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