src/message_api.c
author vb
Sat, 03 Jan 2015 16:37:53 +0100
changeset 44 4013b57a6a69
parent 43 816f4ccf84da
child 45 37a80387790d
permissions -rw-r--r--
...
vb@37
     1
#include "message_api.h"
vb@37
     2
#include "keymanagement.h"
vb@37
     3
vb@44
     4
#include <libetpan/mailmime.h>
vb@44
     5
#ifndef mailmime_param_new_with_data
vb@44
     6
#include <libetpan/mailprivacy_tools.h>
vb@44
     7
#endif
vb@37
     8
#include <assert.h>
vb@37
     9
#include <string.h>
vb@39
    10
#include <stdlib.h>
vb@39
    11
vb@39
    12
#define NOT_IMPLEMENTED assert(0);
vb@37
    13
vb@44
    14
PEP_STATUS mime_encode_parts(const message *src, message **dst)
vb@44
    15
{
vb@44
    16
    struct mailmime * mime_body;
vb@44
    17
vb@44
    18
    assert(src);
vb@44
    19
    assert(src->enc_format == PEP_enc_none);
vb@44
    20
    assert(dst);
vb@44
    21
vb@44
    22
    if (src->enc_format != PEP_enc_none)
vb@44
    23
        return PEP_ILLEGAL_VALUE;
vb@44
    24
vb@44
    25
    *dst = NULL;
vb@44
    26
vb@44
    27
    if (src->longmsg && src->longmsg_formatted) {
vb@44
    28
        struct mailmime * mime_text;
vb@44
    29
        struct mailmime * mime_html;
vb@44
    30
        NOT_IMPLEMENTED
vb@44
    31
    }
vb@44
    32
    else if (src->longmsg) {
vb@44
    33
        struct mailmime_fields * mime_fields
vb@44
    34
                = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT);
vb@44
    35
        assert(mime_fields);
vb@44
    36
        if (mime_fields == NULL)
vb@44
    37
            return PEP_OUT_OF_MEMORY;
vb@44
    38
vb@44
    39
        struct mailmime_content * content
vb@44
    40
                = mailmime_content_new_with_str("text/plain");
vb@44
    41
        assert(content);
vb@44
    42
        if (content == NULL) {
vb@44
    43
            mailmime_fields_free(mime_fields);
vb@44
    44
            return PEP_OUT_OF_MEMORY;
vb@44
    45
        }
vb@44
    46
vb@44
    47
        struct mailmime_parameter * param
vb@44
    48
                = mailmime_param_new_with_data("charset", "utf-8");
vb@44
    49
        assert(param);
vb@44
    50
        if (param == NULL) {
vb@44
    51
            mailmime_fields_free(mime_fields);
vb@44
    52
            mailmime_content_free(content);
vb@44
    53
            return PEP_OUT_OF_MEMORY;
vb@44
    54
        }
vb@44
    55
vb@44
    56
        int r = clist_append(content->ct_parameters, param);
vb@44
    57
        if (r < 0) {
vb@44
    58
            mailmime_fields_free(mime_fields);
vb@44
    59
            mailmime_content_free(content);
vb@44
    60
            mailmime_parameter_free(param);
vb@44
    61
            return PEP_OUT_OF_MEMORY;
vb@44
    62
        }
vb@44
    63
vb@44
    64
        mime_body = mailmime_new_empty(content, mime_fields);
vb@44
    65
        if (mime_body == NULL) {
vb@44
    66
            mailmime_fields_free(mime_fields);
vb@44
    67
            mailmime_content_free(content);
vb@44
    68
            return PEP_OUT_OF_MEMORY;
vb@44
    69
        }
vb@44
    70
vb@44
    71
        r = mailmime_set_body_text(mime_body, src->longmsg, strlen(src->longmsg));
vb@44
    72
        if (r != MAILIMF_NO_ERROR) {
vb@44
    73
            mailmime_free(mime_body);
vb@44
    74
            return PEP_OUT_OF_MEMORY;
vb@44
    75
        }
vb@44
    76
    }
vb@44
    77
    else if (src->longmsg_formatted) {
vb@44
    78
        NOT_IMPLEMENTED
vb@44
    79
    }
vb@44
    80
 
vb@44
    81
    char *fn = strdup("/tmp/pEp.XXXXXXXXXX");
vb@44
    82
    assert(fn);
vb@44
    83
    if (fn == NULL) {
vb@44
    84
        mailmime_free(mime_body);
vb@44
    85
        return PEP_OUT_OF_MEMORY;
vb@44
    86
    }
vb@44
    87
vb@44
    88
    int f = mkstemp(fn);
vb@44
    89
    assert(f != -1);
vb@44
    90
    free(fn);
vb@44
    91
    if (f == -1) {
vb@44
    92
        mailmime_free(mime_body);
vb@44
    93
        return PEP_CANNOT_CREATE_TEMP_FILE;
vb@44
    94
    }
vb@44
    95
vb@44
    96
    FILE *fp = fdopen(f, "w+");
vb@44
    97
    assert(fp);
vb@44
    98
    if (fp == NULL) {
vb@44
    99
        return PEP_CANNOT_CREATE_TEMP_FILE;
vb@44
   100
    }
vb@44
   101
vb@44
   102
    int col = 0;
vb@44
   103
    int r = mailmime_write_file(fp, &col, mime_body);
vb@44
   104
    assert(r == MAILIMF_NO_ERROR);
vb@44
   105
    mailmime_free(mime_body);
vb@44
   106
    if (r != MAILIMF_NO_ERROR) {
vb@44
   107
        fclose(fp);
vb@44
   108
        return PEP_CANNOT_CREATE_TEMP_FILE;
vb@44
   109
    }
vb@44
   110
vb@44
   111
    rewind(fp);
vb@44
   112
vb@44
   113
    char *buf = (char *) calloc(1, col + 1);
vb@44
   114
    assert(buf);
vb@44
   115
    if (buf == NULL) {
vb@44
   116
        fclose(fp);
vb@44
   117
        return PEP_OUT_OF_MEMORY;
vb@44
   118
    }
vb@44
   119
vb@44
   120
    size_t size = fread(buf, col, 1, fp);
vb@44
   121
    assert(size);
vb@44
   122
    fclose(fp);
vb@44
   123
    if (size == 0L) {
vb@44
   124
        free(buf);
vb@44
   125
        return PEP_CANNOT_CREATE_TEMP_FILE;
vb@44
   126
    }
vb@44
   127
vb@44
   128
    message *msg = new_message(src->dir, src->from, src->to, src->shortmsg);
vb@44
   129
    if (msg == NULL) {
vb@44
   130
        free(buf);
vb@44
   131
        return PEP_OUT_OF_MEMORY;
vb@44
   132
    }
vb@44
   133
    msg->longmsg = buf;
vb@44
   134
vb@44
   135
    *dst = msg;
vb@44
   136
    return PEP_STATUS_OK;
vb@44
   137
}
vb@44
   138
vb@44
   139
PEP_STATUS mime_decode_parts(const message *src, message **dst)
vb@44
   140
{
vb@44
   141
    PEP_STATUS status = PEP_STATUS_OK;
vb@44
   142
vb@44
   143
    assert(src);
vb@44
   144
    assert(src->enc_format == PEP_enc_none_MIME);
vb@44
   145
    assert(dst);
vb@44
   146
vb@44
   147
    if (src->enc_format != PEP_enc_none_MIME)
vb@44
   148
        return PEP_ILLEGAL_VALUE;
vb@44
   149
vb@44
   150
    *dst = NULL;
vb@44
   151
vb@44
   152
    return status;
vb@44
   153
}
vb@44
   154
vb@37
   155
PEP_STATUS encrypt_message(
vb@37
   156
        PEP_SESSION session,
vb@37
   157
        const message *src,
vb@37
   158
        stringlist_t * extra,
vb@38
   159
        message **dst,
vb@38
   160
        PEP_enc_format format
vb@37
   161
    )
vb@37
   162
{
vb@37
   163
    PEP_STATUS status = PEP_STATUS_OK;
vb@37
   164
vb@37
   165
    assert(session);
vb@37
   166
    assert(src);
vb@37
   167
    assert(dst);
vb@37
   168
    *dst = NULL;
vb@38
   169
    assert(format != PEP_enc_none);
vb@37
   170
vb@40
   171
    pEp_identity *from = identity_dup(src->from);
vb@40
   172
    if (from == NULL)
vb@40
   173
        return PEP_OUT_OF_MEMORY;
vb@40
   174
vb@40
   175
    identity_list *to = identity_list_dup(src->to);
vb@40
   176
    if (to == NULL) {
vb@40
   177
        free_identity(from);
vb@40
   178
        return PEP_OUT_OF_MEMORY;
vb@40
   179
    }
vb@40
   180
vb@40
   181
    message *msg = new_message(src->dir, from, to, NULL);
vb@37
   182
    if (msg == NULL)
vb@37
   183
        return PEP_OUT_OF_MEMORY;
vb@37
   184
vb@40
   185
    from->me = true;
vb@37
   186
vb@40
   187
    status = myself(session, from);
vb@37
   188
    if (status != PEP_STATUS_OK) {
vb@37
   189
        free_message(msg);
vb@37
   190
        return status;
vb@37
   191
    }
vb@37
   192
vb@40
   193
    stringlist_t * keys = new_stringlist(from->fpr);
vb@37
   194
    if (keys == NULL) {
vb@37
   195
        free_message(msg);
vb@37
   196
        return PEP_OUT_OF_MEMORY;
vb@37
   197
    }
vb@37
   198
vb@39
   199
    stringlist_t *_k = keys;
vb@39
   200
vb@39
   201
    if (extra) {
vb@39
   202
        _k = stringlist_append(_k, extra);
vb@39
   203
        if (_k == NULL) {
vb@39
   204
            free_stringlist(keys);
vb@37
   205
            free_message(msg);
vb@37
   206
            return PEP_OUT_OF_MEMORY;
vb@37
   207
        }
vb@37
   208
    }
vb@39
   209
vb@39
   210
    bool dest_keys_found = false;
vb@37
   211
    identity_list * _il;
vb@40
   212
    for (_il = to; _il && _il->ident; _il = _il->next) {
vb@39
   213
        PEP_STATUS _status = update_identity(session, _il->ident);
vb@39
   214
        if (_status != PEP_STATUS_OK) {
vb@37
   215
            free_message(msg);
vb@37
   216
            free_stringlist(keys);
vb@39
   217
            return _status;
vb@37
   218
        }
vb@37
   219
        if (_il->ident->fpr) {
vb@39
   220
            dest_keys_found = true;
vb@39
   221
            _k = stringlist_add(_k, _il->ident->fpr);
vb@39
   222
            if (_k == NULL) {
vb@37
   223
                free_message(msg);
vb@37
   224
                free_stringlist(keys);
vb@37
   225
                return PEP_OUT_OF_MEMORY;
vb@37
   226
            }
vb@37
   227
        }
vb@37
   228
        else
vb@37
   229
            status = PEP_KEY_NOT_FOUND;
vb@37
   230
    }
vb@37
   231
vb@39
   232
    if (dest_keys_found) {
vb@38
   233
        char *ptext;
vb@37
   234
        char *ctext = NULL;
vb@37
   235
        size_t csize = 0;
vb@37
   236
vb@38
   237
        switch (format) {
vb@44
   238
        case PEP_enc_MIME_multipart: {
vb@44
   239
            *dst = msg;
vb@38
   240
            break;
vb@44
   241
        }
vb@37
   242
vb@38
   243
        case PEP_enc_pieces:
vb@38
   244
            if (src->shortmsg && src->longmsg) {
vb@39
   245
                ptext = calloc(1, strlen(src->shortmsg) + strlen(src->longmsg)
vb@39
   246
                        + 12);
vb@38
   247
                if (ptext == NULL) {
vb@38
   248
                    free_message(msg);
vb@38
   249
                    free_stringlist(keys);
vb@38
   250
                    return PEP_OUT_OF_MEMORY;
vb@38
   251
                }
vb@38
   252
                strcpy(ptext, "subject: ");
vb@38
   253
                strcat(ptext, src->shortmsg);
vb@38
   254
                strcat(ptext, "\n\n");
vb@38
   255
                strcat(ptext, src->longmsg);
vb@39
   256
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   257
                        &ctext, &csize);
vb@40
   258
                free(ptext);
vb@38
   259
                if (ctext) {
vb@40
   260
                    msg->longmsg = strdup(ctext);
vb@38
   261
                    msg->shortmsg = strdup("pEp");
vb@40
   262
                    if (!(msg->longmsg && msg->shortmsg)) {
vb@40
   263
                        free_message(msg);
vb@40
   264
                        return PEP_OUT_OF_MEMORY;
vb@40
   265
                    }
vb@38
   266
                }
vb@38
   267
                else {
vb@38
   268
                    free_message(msg);
vb@38
   269
                    msg = NULL;
vb@38
   270
                }
vb@38
   271
            }
vb@38
   272
            else if (src->shortmsg) {
vb@43
   273
                ptext = calloc(1, strlen(src->shortmsg) + 12);
vb@43
   274
                if (ptext == NULL) {
vb@43
   275
                    free_message(msg);
vb@43
   276
                    free_stringlist(keys);
vb@43
   277
                    return PEP_OUT_OF_MEMORY;
vb@43
   278
                }
vb@43
   279
                strcpy(ptext, "subject: ");
vb@43
   280
                strcat(ptext, src->shortmsg);
vb@43
   281
                strcat(ptext, "\n\n");
vb@39
   282
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   283
                        &ctext, &csize);
vb@43
   284
                free(ptext);
vb@38
   285
                if (ctext) {
vb@40
   286
                    msg->longmsg = strdup(ctext);
vb@40
   287
                    msg->shortmsg = strdup("pEp");
vb@40
   288
                    if (!(msg->longmsg && msg->shortmsg)) {
vb@40
   289
                        free_message(msg);
vb@40
   290
                        return PEP_OUT_OF_MEMORY;
vb@40
   291
                    }
vb@38
   292
                }
vb@38
   293
                else {
vb@38
   294
                    free_message(msg);
vb@38
   295
                    msg = NULL;
vb@38
   296
                }
vb@38
   297
            }
vb@38
   298
            else if (src->longmsg) {
vb@38
   299
                ptext = src->longmsg;
vb@39
   300
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   301
                        &ctext, &csize);
vb@38
   302
                if (ctext) {
vb@40
   303
                    msg->longmsg = strdup(ctext);
vb@38
   304
                    msg->shortmsg = strdup("pEp");
vb@40
   305
                    if (!(msg->longmsg && msg->shortmsg)) {
vb@40
   306
                        free_message(msg);
vb@40
   307
                        return PEP_OUT_OF_MEMORY;
vb@40
   308
                    }
vb@38
   309
                }
vb@38
   310
                else {
vb@38
   311
                    free_message(msg);
vb@38
   312
                    msg = NULL;
vb@38
   313
                }
vb@38
   314
            }
vb@38
   315
            if (msg && msg->longmsg_formatted) {
vb@38
   316
                ptext = src->longmsg_formatted;
vb@39
   317
                status = encrypt_and_sign(session, keys, ptext, strlen(ptext),
vb@39
   318
                        &ctext, &csize);
vb@38
   319
                if (ctext) {
vb@40
   320
                    msg->longmsg_formatted = strdup(ctext);
vb@40
   321
                    if (msg->longmsg_formatted == NULL) {
vb@40
   322
                        free_message(msg);
vb@40
   323
                        return PEP_OUT_OF_MEMORY;
vb@40
   324
                    }
vb@38
   325
                }
vb@38
   326
                else {
vb@38
   327
                    free_message(msg);
vb@38
   328
                    msg = NULL;
vb@38
   329
                }
vb@38
   330
            }
vb@38
   331
            if (msg) {
vb@42
   332
                if (src->attachments) {
vb@42
   333
                    bloblist_t *_s;
vb@42
   334
                    bloblist_t *_d = new_bloblist(NULL, 0, NULL, NULL);
vb@42
   335
                    if (_d == NULL) {
vb@42
   336
                        free_message(msg);
vb@42
   337
                        free_stringlist(keys);
vb@42
   338
                        return PEP_OUT_OF_MEMORY;
vb@42
   339
                    }
vb@42
   340
                    msg->attachments = _d;
vb@42
   341
                    for (_s = src->attachments; _s && _s->data; _s = _s->next) {
vb@42
   342
                        int psize = _s->size;
vb@42
   343
                        ptext = _s->data;
vb@42
   344
                        status = encrypt_and_sign(session, keys, ptext, psize,
vb@42
   345
                                &ctext, &csize);
vb@42
   346
                        if (ctext) {
vb@42
   347
                            char * _c = strdup(ctext);
vb@42
   348
                            if (_c == NULL) {
vb@42
   349
                                free_message(msg);
vb@42
   350
                                free_stringlist(keys);
vb@42
   351
                                return PEP_OUT_OF_MEMORY;
vb@42
   352
                            }
vb@42
   353
                            _d = bloblist_add(_d, _c, csize, _s->mime_type,
vb@42
   354
                                    _s->file_name);
vb@42
   355
                            if (_d == NULL) {
vb@42
   356
                                free_message(msg);
vb@42
   357
                                free_stringlist(keys);
vb@42
   358
                                return PEP_OUT_OF_MEMORY;
vb@42
   359
                            }
vb@42
   360
                        }
vb@42
   361
                        else {
vb@40
   362
                            free_message(msg);
vb@42
   363
                            msg = NULL;
vb@42
   364
                            break;
vb@40
   365
                        }
vb@38
   366
                    }
vb@38
   367
                }
vb@39
   368
                msg->enc_format = PEP_enc_pieces;
vb@38
   369
                *dst = msg;
vb@38
   370
            }
vb@38
   371
            break;
vb@38
   372
vb@38
   373
        default:
vb@38
   374
            assert(0);
vb@37
   375
        }
vb@37
   376
    }
vb@37
   377
    else
vb@37
   378
        free_message(msg);
vb@37
   379
vb@37
   380
    free_stringlist(keys);
vb@37
   381
    return status;
vb@37
   382
}
vb@37
   383
vb@37
   384
PEP_STATUS decrypt_message(
vb@37
   385
        PEP_SESSION session,
vb@37
   386
        const message *src,
vb@37
   387
        message **dst
vb@37
   388
    )
vb@37
   389
{
vb@37
   390
    PEP_STATUS status = PEP_STATUS_OK;
vb@37
   391
vb@39
   392
    NOT_IMPLEMENTED
vb@39
   393
vb@37
   394
    return status;
vb@37
   395
}
vb@37
   396