src/message_api.c
author vb
Tue, 24 Feb 2015 02:19:11 +0100
changeset 74 c94f9b9cb7f2
parent 73 075aa4eaeb4f
child 76 6da29caa5dae
permissions -rw-r--r--
...
vb@37
     1
#include "message_api.h"
vb@37
     2
#include "keymanagement.h"
vb@62
     3
#include "mime.h"
vb@37
     4
vb@37
     5
#include <assert.h>
vb@37
     6
#include <string.h>
vb@39
     7
#include <stdlib.h>
vb@39
     8
vb@39
     9
#define NOT_IMPLEMENTED assert(0);
vb@37
    10
vb@62
    11
static char * combine_short_and_long(const message * src)
vb@62
    12
{
vb@62
    13
    char * ptext;
vb@63
    14
    char * longmsg;
vb@62
    15
    assert(src);
vb@63
    16
    assert(src->shortmsg && strcmp(src->shortmsg, "pEp") != 0);
vb@62
    17
vb@63
    18
    if (src->longmsg)
vb@63
    19
        longmsg = src->longmsg;
vb@63
    20
    else
vb@63
    21
        longmsg = "";
vb@63
    22
vb@63
    23
    ptext = calloc(1, strlen(src->shortmsg) + strlen(longmsg) + 12);
vb@62
    24
    if (ptext == NULL)
vb@62
    25
        return NULL;
vb@62
    26
vb@62
    27
    strcpy(ptext, "subject: ");
vb@62
    28
    strcat(ptext, src->shortmsg);
vb@62
    29
    strcat(ptext, "\n\n");
vb@63
    30
    strcat(ptext, longmsg);
vb@62
    31
vb@62
    32
    return ptext;
vb@62
    33
}
vb@44
    34
vb@48
    35
DYNAMIC_API PEP_STATUS encrypt_message(
vb@37
    36
        PEP_SESSION session,
vb@37
    37
        const message *src,
vb@37
    38
        stringlist_t * extra,
vb@38
    39
        message **dst,
vb@38
    40
        PEP_enc_format format
vb@37
    41
    )
vb@37
    42
{
vb@37
    43
    PEP_STATUS status = PEP_STATUS_OK;
vb@63
    44
    message * msg = NULL;
vb@63
    45
    stringlist_t * keys = NULL;
vb@37
    46
vb@37
    47
    assert(session);
vb@37
    48
    assert(src);
vb@37
    49
    assert(dst);
vb@37
    50
    *dst = NULL;
vb@67
    51
    assert(format != PEP_enc_none && format != PEP_enc_none_MIME);
vb@67
    52
vb@67
    53
    // TODO: we don't yet support re-encrypting already encrypted messages
vb@67
    54
    if ((int) src->format >= (int) PEP_enc_pieces) {
vb@67
    55
        NOT_IMPLEMENTED   
vb@67
    56
    }
vb@37
    57
vb@40
    58
    pEp_identity *from = identity_dup(src->from);
vb@40
    59
    if (from == NULL)
vb@63
    60
        goto enomem;
vb@63
    61
    from->me = true;
vb@40
    62
vb@40
    63
    identity_list *to = identity_list_dup(src->to);
vb@40
    64
    if (to == NULL) {
vb@40
    65
        free_identity(from);
vb@63
    66
        goto enomem;
vb@40
    67
    }
vb@40
    68
vb@63
    69
    msg = new_message(src->dir, from, to, NULL);
vb@56
    70
    if (msg == NULL) {
vb@56
    71
        free_identity(from);
vb@56
    72
        free_identity_list(to);
vb@63
    73
        goto enomem;
vb@56
    74
    }
vb@48
    75
    msg->enc_format = PEP_enc_pieces;
vb@37
    76
vb@63
    77
    status = myself(session, from);
vb@63
    78
    if (status != PEP_STATUS_OK)
vb@63
    79
        goto pep_error;
vb@37
    80
vb@63
    81
    keys = new_stringlist(from->fpr);
vb@63
    82
    if (keys == NULL)
vb@63
    83
        goto enomem;
vb@37
    84
vb@39
    85
    stringlist_t *_k = keys;
vb@39
    86
vb@39
    87
    if (extra) {
vb@39
    88
        _k = stringlist_append(_k, extra);
vb@63
    89
        if (_k == NULL)
vb@63
    90
            goto enomem;
vb@37
    91
    }
vb@39
    92
vb@39
    93
    bool dest_keys_found = false;
vb@37
    94
    identity_list * _il;
vb@40
    95
    for (_il = to; _il && _il->ident; _il = _il->next) {
vb@63
    96
        PEP_STATUS status = update_identity(session, _il->ident);
vb@63
    97
        if (status != PEP_STATUS_OK)
vb@63
    98
            goto pep_error;
vb@63
    99
vb@37
   100
        if (_il->ident->fpr) {
vb@39
   101
            dest_keys_found = true;
vb@39
   102
            _k = stringlist_add(_k, _il->ident->fpr);
vb@63
   103
            if (_k == NULL)
vb@63
   104
                goto enomem;
vb@37
   105
        }
vb@37
   106
        else
vb@37
   107
            status = PEP_KEY_NOT_FOUND;
vb@37
   108
    }
vb@37
   109
vb@39
   110
    if (dest_keys_found) {
vb@38
   111
        char *ptext;
vb@37
   112
        char *ctext = NULL;
vb@37
   113
        size_t csize = 0;
vb@37
   114
vb@38
   115
        switch (format) {
vb@44
   116
        case PEP_enc_MIME_multipart: {
vb@62
   117
            bool free_ptext = false;
vb@64
   118
vb@48
   119
            msg->enc_format = PEP_enc_MIME_multipart;
vb@37
   120
vb@63
   121
            if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0) {
vb@62
   122
                ptext = combine_short_and_long(src);
vb@63
   123
                if (ptext == NULL)
vb@63
   124
                    goto enomem;
vb@62
   125
                free_ptext = true;
vb@62
   126
            }
vb@62
   127
            else if (src->longmsg) {
vb@62
   128
                ptext = src->longmsg;
vb@62
   129
            }
vb@62
   130
vb@67
   131
            if (src->format == PEP_enc_none) {
vb@67
   132
                char *_ptext = ptext;
vb@67
   133
                status = mime_encode_text(_ptext, src->longmsg_formatted,
vb@67
   134
                        src->attachments, &ptext);
vb@67
   135
                assert(status == PEP_STATUS_OK);
vb@67
   136
                if (free_ptext)
vb@67
   137
                    free(_ptext);
vb@67
   138
                assert(ptext);
vb@67
   139
                if (ptext == NULL)
vb@67
   140
                    goto pep_error;
vb@67
   141
                free_ptext = true;
vb@67
   142
            }
vb@67
   143
            else if (src->format == PEP_enc_none_MIME) {
vb@67
   144
                assert(src->longmsg);
vb@67
   145
                if (src->longmsg == NULL) {
vb@67
   146
                    status = PEP_ILLEGAL_VALUE;
vb@67
   147
                    goto pep_error;
vb@67
   148
                }
vb@67
   149
                ptext = src->longmsg;
vb@67
   150
            }
vb@67
   151
vb@67
   152
            status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@67
   153
                    &ctext, &csize);
vb@62
   154
            if (free_ptext)
vb@62
   155
                free(ptext);
vb@62
   156
            if (ctext) {
vb@62
   157
                msg->longmsg = strdup(ctext);
vb@64
   158
                if (msg->longmsg == NULL)
vb@63
   159
                    goto enomem;
vb@63
   160
            }
vb@63
   161
            else {
vb@63
   162
                goto pep_error;
vb@62
   163
            }
vb@62
   164
        }
vb@63
   165
        break;
vb@62
   166
vb@62
   167
        case PEP_enc_pieces:
vb@64
   168
            msg->enc_format = PEP_enc_pieces;
vb@64
   169
vb@67
   170
            // TODO: decoding MIME
vb@67
   171
            if (src->format == PEP_enc_none_MIME) {
vb@67
   172
                NOT_IMPLEMENTED
vb@67
   173
            }
vb@67
   174
vb@63
   175
            if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0) {
vb@62
   176
                ptext = combine_short_and_long(src);
vb@63
   177
                if (ptext == NULL)
vb@63
   178
                    goto enomem;
vb@63
   179
vb@39
   180
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   181
                        &ctext, &csize);
vb@40
   182
                free(ptext);
vb@38
   183
                if (ctext) {
vb@40
   184
                    msg->longmsg = strdup(ctext);
vb@64
   185
                    if (msg->longmsg == NULL)
vb@63
   186
                        goto enomem;
vb@38
   187
                }
vb@38
   188
                else {
vb@63
   189
                    goto pep_error;
vb@38
   190
                }
vb@38
   191
            }
vb@38
   192
            else if (src->longmsg) {
vb@38
   193
                ptext = src->longmsg;
vb@39
   194
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   195
                        &ctext, &csize);
vb@38
   196
                if (ctext) {
vb@40
   197
                    msg->longmsg = strdup(ctext);
vb@64
   198
                    if (msg->longmsg == NULL)
vb@63
   199
                        goto enomem;
vb@38
   200
                }
vb@38
   201
                else {
vb@63
   202
                    goto pep_error;
vb@38
   203
                }
vb@38
   204
            }
vb@63
   205
vb@63
   206
            if (msg->longmsg_formatted) {
vb@38
   207
                ptext = src->longmsg_formatted;
vb@39
   208
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   209
                        &ctext, &csize);
vb@38
   210
                if (ctext) {
vb@40
   211
                    msg->longmsg_formatted = strdup(ctext);
vb@63
   212
                    if (msg->longmsg_formatted == NULL)
vb@63
   213
                        goto enomem;
vb@63
   214
                }
vb@63
   215
                else {
vb@63
   216
                    goto pep_error;
vb@63
   217
                }
vb@63
   218
            }
vb@63
   219
vb@63
   220
            if (src->attachments) {
vb@63
   221
                bloblist_t *_s;
vb@63
   222
                bloblist_t *_d = new_bloblist(NULL, 0, NULL, NULL);
vb@63
   223
                if (_d == NULL)
vb@63
   224
                    goto enomem;
vb@63
   225
vb@63
   226
                msg->attachments = _d;
vb@63
   227
                for (_s = src->attachments; _s && _s->data; _s = _s->next) {
vb@63
   228
                    int psize = _s->size;
vb@63
   229
                    ptext = _s->data;
vb@63
   230
                    status = encrypt_and_sign(session, keys, ptext, psize,
vb@63
   231
                            &ctext, &csize);
vb@63
   232
                    if (ctext) {
vb@63
   233
                        char * _c = strdup(ctext);
vb@63
   234
                        if (_c == NULL)
vb@63
   235
                            goto enomem;
vb@63
   236
vb@63
   237
                        _d = bloblist_add(_d, _c, csize, _s->mime_type,
vb@63
   238
                                _s->file_name);
vb@63
   239
                        if (_d == NULL)
vb@63
   240
                            goto enomem;
vb@63
   241
                    }
vb@63
   242
                    else {
vb@63
   243
                        goto pep_error;
vb@40
   244
                    }
vb@38
   245
                }
vb@38
   246
            }
vb@38
   247
            break;
vb@38
   248
vb@38
   249
        default:
vb@38
   250
            assert(0);
vb@63
   251
            status = PEP_ILLEGAL_VALUE;
vb@63
   252
            goto pep_error;
vb@37
   253
        }
vb@37
   254
    }
vb@37
   255
vb@37
   256
    free_stringlist(keys);
vb@63
   257
vb@64
   258
    if (msg->shortmsg == NULL)
vb@64
   259
        msg->shortmsg = strdup("pEp");
vb@64
   260
vb@63
   261
    *dst = msg;
vb@63
   262
    return PEP_STATUS_OK;
vb@63
   263
vb@63
   264
enomem:
vb@63
   265
    status = PEP_OUT_OF_MEMORY;
vb@63
   266
vb@63
   267
pep_error:
vb@63
   268
    free_stringlist(keys);
vb@63
   269
    free_message(msg);
vb@63
   270
vb@37
   271
    return status;
vb@37
   272
}
vb@37
   273
vb@48
   274
DYNAMIC_API PEP_STATUS decrypt_message(
vb@37
   275
        PEP_SESSION session,
vb@37
   276
        const message *src,
vb@37
   277
        message **dst
vb@37
   278
    )
vb@37
   279
{
vb@37
   280
    PEP_STATUS status = PEP_STATUS_OK;
vb@73
   281
    message *msg = NULL;
vb@37
   282
vb@74
   283
    assert(session);
vb@74
   284
    assert(src);
vb@74
   285
    assert(dst);
vb@73
   286
vb@74
   287
    *dst = NULL;
vb@74
   288
    
vb@74
   289
    // msg = new_message(src->dir, from, to, NULL);
vb@74
   290
vb@74
   291
    *dst = msg;
vb@74
   292
    return PEP_STATUS_OK;
vb@73
   293
vb@73
   294
enomem:
vb@73
   295
    status = PEP_OUT_OF_MEMORY;
vb@73
   296
vb@73
   297
pep_error:
vb@73
   298
    free_message(msg);
vb@39
   299
vb@37
   300
    return status;
vb@37
   301
}
vb@37
   302