Merging ENGINE-40 feature impl w/ default
authorKrista Grothoff <krista@pep-project.org>
Wed, 10 Aug 2016 15:56:16 +0200
changeset 997ce5ec8007bf2
parent 989 3f47e6bba3db
parent 996 1f0b5160cbe5
child 999 2c9ed75a67af
Merging ENGINE-40 feature impl w/ default
     1.1 --- a/src/message_api.c	Mon Aug 08 16:43:37 2016 +0200
     1.2 +++ b/src/message_api.c	Wed Aug 10 15:56:16 2016 +0200
     1.3 @@ -1210,6 +1210,103 @@
     1.4      return status;
     1.5  }
     1.6  
     1.7 +DYNAMIC_API PEP_STATUS encrypt_message_for_self(
     1.8 +        PEP_SESSION session,
     1.9 +        pEp_identity* target_id,
    1.10 +        message *src,
    1.11 +        message **dst,
    1.12 +        PEP_enc_format enc_format
    1.13 +    )
    1.14 +{
    1.15 +    PEP_STATUS status = PEP_STATUS_OK;
    1.16 +    message * msg = NULL;
    1.17 +    stringlist_t * keys = NULL;
    1.18 +
    1.19 +    assert(session);
    1.20 +    assert(src);
    1.21 +    assert(dst);
    1.22 +    assert(enc_format != PEP_enc_none);
    1.23 +
    1.24 +    if (!(session && src && dst && enc_format != PEP_enc_none))
    1.25 +        return PEP_ILLEGAL_VALUE;
    1.26 +
    1.27 +    if (src->dir == PEP_dir_incoming)
    1.28 +        return PEP_ILLEGAL_VALUE;
    1.29 +    
    1.30 +    determine_encryption_format(src);
    1.31 +    if (src->enc_format != PEP_enc_none)
    1.32 +        return PEP_ILLEGAL_VALUE;
    1.33 +
    1.34 +    status = myself(session, target_id);
    1.35 +    if (status != PEP_STATUS_OK)
    1.36 +        goto pep_error;
    1.37 +
    1.38 +    *dst = NULL;
    1.39 +
    1.40 +    
    1.41 +    PEP_STATUS _status = update_identity(session, target_id);
    1.42 +    if (_status != PEP_STATUS_OK) {
    1.43 +        status = _status;
    1.44 +        goto pep_error;
    1.45 +    }
    1.46 +
    1.47 +    char* target_fpr = target_id->fpr;
    1.48 +    if (!target_fpr)
    1.49 +        return PEP_KEY_NOT_FOUND; // FIXME: Error condition
    1.50 +        
    1.51 +    keys = new_stringlist(target_fpr);
    1.52 +
    1.53 +    
    1.54 +    msg = clone_to_empty_message(src);
    1.55 +    if (msg == NULL)
    1.56 +        goto enomem;
    1.57 +
    1.58 +    switch (enc_format) {
    1.59 +        case PEP_enc_PGP_MIME:
    1.60 +        case PEP_enc_PEP: // BUG: should be implemented extra
    1.61 +            status = encrypt_PGP_MIME(session, src, keys, msg);
    1.62 +            break;
    1.63 +
    1.64 +        case PEP_enc_pieces:
    1.65 +            status = encrypt_PGP_in_pieces(session, src, keys, msg);
    1.66 +            break;
    1.67 +
    1.68 +        /* case PEP_enc_PEP:
    1.69 +            // TODO: implement
    1.70 +            NOT_IMPLEMENTED */
    1.71 +
    1.72 +        default:
    1.73 +            assert(0);
    1.74 +            status = PEP_ILLEGAL_VALUE;
    1.75 +            goto pep_error;
    1.76 +    }
    1.77 +        
    1.78 +    if (status == PEP_OUT_OF_MEMORY)
    1.79 +        goto enomem;
    1.80 +    
    1.81 +    if (status != PEP_STATUS_OK)
    1.82 +        goto pep_error;
    1.83 +
    1.84 +     if (msg && msg->shortmsg == NULL) {
    1.85 +         msg->shortmsg = strdup("pEp");
    1.86 +         assert(msg->shortmsg);
    1.87 +         if (msg->shortmsg == NULL)
    1.88 +             goto enomem;
    1.89 +     }
    1.90 +
    1.91 +    *dst = msg;
    1.92 +    return status;
    1.93 +
    1.94 +enomem:
    1.95 +    status = PEP_OUT_OF_MEMORY;
    1.96 +
    1.97 +pep_error:
    1.98 +    free_stringlist(keys);
    1.99 +    free_message(msg);
   1.100 +
   1.101 +    return status;
   1.102 +}
   1.103 +
   1.104  static bool is_a_pEpmessage(const message *msg)
   1.105  {
   1.106      for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
     2.1 --- a/src/message_api.h	Mon Aug 08 16:43:37 2016 +0200
     2.2 +++ b/src/message_api.h	Wed Aug 10 15:56:16 2016 +0200
     2.3 @@ -47,6 +47,39 @@
     2.4          PEP_enc_format enc_format
     2.5      );
     2.6  
     2.7 +// encrypt_message_for_identity() - encrypt message for one particular identity in memory
     2.8 +//                     (to be used, for example, to save message drafts
     2.9 +//                      encrypted with owner ID)
    2.10 +//
    2.11 +//  parameters:
    2.12 +//      session (in)        session handle
    2.13 +//      target_id (in)      self identity this message should be encrypted for
    2.14 +//      src (in)            message to encrypt
    2.15 +//      dst (out)           pointer to new encrypted message or NULL on failure
    2.16 +//      enc_format (in)     encrypted format
    2.17 +//
    2.18 +//  return value:       (FIXME: This may not be correct or complete)
    2.19 +//      PEP_STATUS_OK                   on success
    2.20 +//		PEP_KEY_NOT_FOUND	            at least one of the receipient keys
    2.21 +//		                                could not be found
    2.22 +//		PEP_KEY_HAS_AMBIG_NAME          at least one of the receipient keys has
    2.23 +//		                                an ambiguous name
    2.24 +//		PEP_GET_KEY_FAILED		        cannot retrieve key
    2.25 +//
    2.26 +//	caveat:
    2.27 +//	    the ownership of src remains with the caller
    2.28 +//      the ownership of target_id remains w/ caller            
    2.29 +//	    the ownership of dst goes to the caller
    2.30 +//      message is NOT encrypted for identities other than the target_id (and then,
    2.31 +//          only if the target_id refers to self!)
    2.32 +
    2.33 +DYNAMIC_API PEP_STATUS encrypt_message_for_self(
    2.34 +        PEP_SESSION session,
    2.35 +        pEp_identity* target_id,
    2.36 +        message *src,
    2.37 +        message **dst,
    2.38 +        PEP_enc_format enc_format
    2.39 +    );
    2.40  
    2.41  typedef enum _PEP_color {
    2.42      PEP_rating_undefined = 0,
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/encrypt_for_identity_test.cc	Wed Aug 10 15:56:16 2016 +0200
     3.3 @@ -0,0 +1,107 @@
     3.4 +#include <stdlib.h>
     3.5 +#include <string.h>
     3.6 +#include "platform.h"
     3.7 +#include <iostream>
     3.8 +#include <fstream>
     3.9 +#include <assert.h>
    3.10 +#include "mime.h"
    3.11 +#include "message_api.h"
    3.12 +
    3.13 +using namespace std;
    3.14 +
    3.15 +int main() {
    3.16 +    cout << "\n*** encrypt_for_identity_test ***\n\n";
    3.17 +
    3.18 +    PEP_SESSION session;
    3.19 +    
    3.20 +    cout << "calling init()\n";
    3.21 +    PEP_STATUS status1 = init(&session);
    3.22 +    assert(status1 == PEP_STATUS_OK);
    3.23 +    assert(session);
    3.24 +    cout << "init() completed.\n";
    3.25 +
    3.26 +    // message_api test code
    3.27 +
    3.28 +    cout << "creating message…\n";
    3.29 +    pEp_identity* alice = new_identity("pep.test.alice@pep-project.org", NULL, PEP_OWN_USERID, "Alice Test");
    3.30 +    pEp_identity* bob = new_identity("pep.test.bob@pep-project.org", NULL, "42", "Bob Test");
    3.31 +    alice->me = true;
    3.32 +    identity_list* to_list = new_identity_list(bob); // to bob
    3.33 +    message* outgoing_message = new_message(PEP_dir_outgoing);
    3.34 +    assert(outgoing_message);
    3.35 +    outgoing_message->from = alice;
    3.36 +    outgoing_message->to = to_list;
    3.37 +    outgoing_message->shortmsg = strdup("Greetings, humans!");
    3.38 +    outgoing_message->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
    3.39 +    cout << "message created.\n";
    3.40 +
    3.41 +    char* encoded_text = nullptr;
    3.42 +    PEP_STATUS status = mime_encode_message(outgoing_message, false, &encoded_text);
    3.43 +    assert(status == PEP_STATUS_OK);
    3.44 +    assert(encoded_text);
    3.45 +
    3.46 +    cout << "decrypted:\n\n";
    3.47 +    cout << encoded_text << "\n";
    3.48 +
    3.49 +    free(encoded_text);
    3.50 +
    3.51 +    cout << "encrypting message as MIME multipart…\n";
    3.52 +    message* encrypted_msg = nullptr;
    3.53 +    cout << "calling encrypt_message_for_identity()\n";
    3.54 +    status = encrypt_message_for_self(session, alice, outgoing_message, &encrypted_msg, PEP_enc_PGP_MIME);
    3.55 +    cout << "encrypt_message() returns " << std::hex << status << '.' << endl;
    3.56 +    assert(status == PEP_STATUS_OK);
    3.57 +    assert(encrypted_msg);
    3.58 +    cout << "message encrypted.\n";
    3.59 +    
    3.60 +    status = mime_encode_message(encrypted_msg, false, &encoded_text);
    3.61 +    assert(status == PEP_STATUS_OK);
    3.62 +    assert(encoded_text);
    3.63 +
    3.64 +    cout << "encrypted:\n\n";
    3.65 +    cout << encoded_text << "\n";
    3.66 +
    3.67 +    message* decoded_msg = nullptr;
    3.68 +    status = mime_decode_message(encoded_text, strlen(encoded_text), &decoded_msg);
    3.69 +    assert(status == PEP_STATUS_OK);
    3.70 +    const string string3 = encoded_text;
    3.71 +
    3.72 +    unlink("msg_encrypt_for_self.asc");
    3.73 +    ofstream outFile3("msg_encrypt_for_self.asc");
    3.74 +    outFile3.write(string3.c_str(), string3.size());
    3.75 +    outFile3.close();
    3.76 +
    3.77 +    message* decrypted_msg = nullptr;
    3.78 +    stringlist_t* keylist_used = nullptr;
    3.79 +
    3.80 +    PEP_color color;
    3.81 +    PEP_decrypt_flags_t flags;
    3.82 +
    3.83 +    status = decrypt_message(session, encrypted_msg, &decrypted_msg, &keylist_used, &color, &flags);
    3.84 +    assert(status == PEP_STATUS_OK);
    3.85 +    assert(decrypted_msg);
    3.86 +    assert(keylist_used);
    3.87 +    assert(color);
    3.88 +    PEP_comm_type ct = encrypted_msg->from->comm_type;
    3.89 +    assert(ct == PEP_ct_pEp || ct == PEP_ct_pEp_unconfirmed || ct == PEP_ct_OpenPGP || ct == PEP_ct_OpenPGP_unconfirmed );
    3.90 +
    3.91 +    cout << "keys used:\n";
    3.92 +
    3.93 +    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next)
    3.94 +    {
    3.95 +        cout << "\t " << kl4->value << endl;
    3.96 +        assert(strcmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
    3.97 +        cout << "Encrypted for Alice! Yay! It worked!" << endl;
    3.98 +    }
    3.99 +    cout << "Encrypted ONLY for Alice! Test passed. Move along. These are not the bugs you are looking for." << endl;
   3.100 + 
   3.101 +    cout << "freeing messages…\n";
   3.102 +    free_message(encrypted_msg);
   3.103 +    free_message(decrypted_msg);
   3.104 +    free_message(outgoing_message);
   3.105 +    cout << "done.\n";
   3.106 +
   3.107 +    cout << "calling release()\n";
   3.108 +    release(session);
   3.109 +    return 0;
   3.110 +}