merged in default ENGINE-174
authorKrista Grothoff <krista@pep-project.org>
Mon, 13 Mar 2017 14:21:31 +0100
branchENGINE-174
changeset 1649a06807cad94d
parent 1637 4078d6ed8b3b
parent 1645 5f5d81b05b0e
child 1652 5aefca53abee
merged in default
src/message_api.c
test/apple_mail_test.cc
     1.1 --- a/src/cryptotech.c	Thu Mar 09 12:41:34 2017 +0100
     1.2 +++ b/src/cryptotech.c	Mon Mar 13 14:21:31 2017 +0100
     1.3 @@ -36,6 +36,7 @@
     1.4          cryptotech[PEP_crypt_OpenPGP].confirmed_comm_type = PEP_ct_OpenPGP;
     1.5          cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify = pgp_decrypt_and_verify;
     1.6          cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign = pgp_encrypt_and_sign;
     1.7 +        cryptotech[PEP_crypt_OpenPGP].encrypt_only = pgp_encrypt_only;
     1.8          cryptotech[PEP_crypt_OpenPGP].verify_text = pgp_verify_text;
     1.9          cryptotech[PEP_crypt_OpenPGP].delete_keypair = pgp_delete_keypair;
    1.10          cryptotech[PEP_crypt_OpenPGP].export_key = pgp_export_keydata;
     2.1 --- a/src/cryptotech.h	Thu Mar 09 12:41:34 2017 +0100
     2.2 +++ b/src/cryptotech.h	Mon Mar 13 14:21:31 2017 +0100
     2.3 @@ -32,6 +32,11 @@
     2.4          size_t psize, char **ctext, size_t *csize
     2.5      );
     2.6  
     2.7 +typedef PEP_STATUS (*encrypt_only_t)(
     2.8 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     2.9 +        size_t psize, char **ctext, size_t *csize
    2.10 +    );
    2.11 +
    2.12  typedef PEP_STATUS (*delete_keypair_t)(PEP_SESSION session, const char *fpr);
    2.13  
    2.14  typedef PEP_STATUS (*export_key_t)(
    2.15 @@ -92,6 +97,7 @@
    2.16      decrypt_and_verify_t decrypt_and_verify;
    2.17      verify_text_t verify_text;
    2.18      encrypt_and_sign_t encrypt_and_sign;
    2.19 +    encrypt_only_t encrypt_only;
    2.20      delete_keypair_t delete_keypair;
    2.21      export_key_t export_key;
    2.22      find_keys_t find_keys;
     3.1 --- a/src/message_api.c	Thu Mar 09 12:41:34 2017 +0100
     3.2 +++ b/src/message_api.c	Mon Mar 13 14:21:31 2017 +0100
     3.3 @@ -340,7 +340,8 @@
     3.4      PEP_SESSION session,
     3.5      const message *src,
     3.6      stringlist_t *keys,
     3.7 -    message *dst
     3.8 +    message *dst,
     3.9 +    PEP_encrypt_flags_t flags
    3.10      )
    3.11  {
    3.12      PEP_STATUS status = PEP_STATUS_OK;
    3.13 @@ -396,8 +397,12 @@
    3.14      if (mimetext == NULL)
    3.15          goto pep_error;
    3.16  
    3.17 -    status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
    3.18 -        &ctext, &csize);
    3.19 +    if (flags & PEP_encrypt_flag_force_unsigned)
    3.20 +        status = encrypt_only(session, keys, mimetext, strlen(mimetext),
    3.21 +            &ctext, &csize);
    3.22 +    else
    3.23 +        status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
    3.24 +            &ctext, &csize);
    3.25      free(mimetext);
    3.26      if (ctext == NULL)
    3.27          goto pep_error;
    3.28 @@ -439,7 +444,8 @@
    3.29      PEP_SESSION session,
    3.30      const message *src,
    3.31      stringlist_t *keys,
    3.32 -    message *dst
    3.33 +    message *dst,
    3.34 +    PEP_encrypt_flags_t flags
    3.35      )
    3.36  {
    3.37      PEP_STATUS status = PEP_STATUS_OK;
    3.38 @@ -453,6 +459,8 @@
    3.39  
    3.40      dst->enc_format = PEP_enc_pieces;
    3.41  
    3.42 +    bool nosign = (flags & PEP_encrypt_flag_force_unsigned);
    3.43 +
    3.44      if (src->shortmsg && src->shortmsg[0] && strcmp(src->shortmsg, "pEp") != 0) {
    3.45          if (session->unencrypted_subject) {
    3.46              dst->shortmsg = strdup(src->shortmsg);
    3.47 @@ -468,8 +476,12 @@
    3.48              free_ptext = true;
    3.49          }
    3.50  
    3.51 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.52 -            &csize);
    3.53 +        if (nosign)
    3.54 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    3.55 +                &csize);
    3.56 +        else 
    3.57 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.58 +                &csize);
    3.59          if (free_ptext)
    3.60              free(ptext);
    3.61          free_ptext = false;
    3.62 @@ -482,8 +494,12 @@
    3.63      }
    3.64      else if (src->longmsg && src->longmsg[0]) {
    3.65          ptext = src->longmsg;
    3.66 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.67 -            &csize);
    3.68 +        if (nosign)
    3.69 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    3.70 +                &csize);
    3.71 +        else 
    3.72 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.73 +                &csize);
    3.74          if (ctext) {
    3.75              dst->longmsg = ctext;
    3.76          }
    3.77 @@ -500,8 +516,12 @@
    3.78  
    3.79      if (src->longmsg_formatted && src->longmsg_formatted[0]) {
    3.80          ptext = src->longmsg_formatted;
    3.81 -        status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.82 -            &csize);
    3.83 +        if (nosign)
    3.84 +            status = encrypt_only(session, keys, ptext, strlen(ptext), &ctext,
    3.85 +                &csize);
    3.86 +        else 
    3.87 +            status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
    3.88 +                &csize);
    3.89          if (ctext) {
    3.90  
    3.91              bloblist_t *_a = bloblist_add(dst->attachments, ctext, csize,
    3.92 @@ -535,8 +555,12 @@
    3.93              else {
    3.94                  size_t psize = _s->size;
    3.95                  ptext = _s->value;
    3.96 -                status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
    3.97 -                    &csize);
    3.98 +                if (nosign)
    3.99 +                    status = encrypt_only(session, keys, ptext, psize, &ctext,
   3.100 +                        &csize);
   3.101 +                else 
   3.102 +                    status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
   3.103 +                        &csize);
   3.104                  if (ctext) {
   3.105                      char *filename = NULL;
   3.106  
   3.107 @@ -1184,12 +1208,12 @@
   3.108      }
   3.109  
   3.110      if (!dest_keys_found ||
   3.111 -        stringlist_length(keys) == 0 ||
   3.112 +        stringlist_length(keys)  == 0 ||
   3.113          _rating(max_comm_type,
   3.114                  PEP_rating_undefined) < PEP_rating_reliable)
   3.115      {
   3.116          free_stringlist(keys);
   3.117 -        if (!session->passive_mode)
   3.118 +        if (!session->passive_mode && !(flags & PEP_encrypt_flag_force_no_attached_key))
   3.119              attach_own_key(session, src);
   3.120          return PEP_UNENCRYPTED;
   3.121      }
   3.122 @@ -1198,16 +1222,17 @@
   3.123          if (msg == NULL)
   3.124              goto enomem;
   3.125  
   3.126 -        attach_own_key(session, src);
   3.127 +        if (!(flags & PEP_encrypt_flag_force_no_attached_key))
   3.128 +            attach_own_key(session, src);
   3.129  
   3.130          switch (enc_format) {
   3.131          case PEP_enc_PGP_MIME:
   3.132          case PEP_enc_PEP: // BUG: should be implemented extra
   3.133 -            status = encrypt_PGP_MIME(session, src, keys, msg);
   3.134 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   3.135              break;
   3.136  
   3.137          case PEP_enc_pieces:
   3.138 -            status = encrypt_PGP_in_pieces(session, src, keys, msg);
   3.139 +            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
   3.140              break;
   3.141  
   3.142          /* case PEP_enc_PEP:
   3.143 @@ -1264,7 +1289,8 @@
   3.144          pEp_identity* target_id,
   3.145          message *src,
   3.146          message **dst,
   3.147 -        PEP_enc_format enc_format
   3.148 +        PEP_enc_format enc_format,
   3.149 +        PEP_encrypt_flags_t flags
   3.150      )
   3.151  {
   3.152      PEP_STATUS status = PEP_STATUS_OK;
   3.153 @@ -1305,6 +1331,9 @@
   3.154  
   3.155      keys = new_stringlist(target_fpr);
   3.156  
   3.157 +    /* KG: did we ever do this??? */
   3.158 +    if (!(flags & PEP_encrypt_flag_force_no_attached_key))
   3.159 +        attach_own_key(session, src);
   3.160  
   3.161      msg = clone_to_empty_message(src);
   3.162      if (msg == NULL)
   3.163 @@ -1313,16 +1342,16 @@
   3.164      switch (enc_format) {
   3.165          case PEP_enc_PGP_MIME:
   3.166          case PEP_enc_PEP: // BUG: should be implemented extra
   3.167 -            status = encrypt_PGP_MIME(session, src, keys, msg);
   3.168 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   3.169              break;
   3.170  
   3.171          case PEP_enc_pieces:
   3.172 -            status = encrypt_PGP_in_pieces(session, src, keys, msg);
   3.173 +            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
   3.174              break;
   3.175  
   3.176          /* case PEP_enc_PEP:
   3.177 +            NOT_IMPLEMENTED */
   3.178              // TODO: implement
   3.179 -            NOT_IMPLEMENTED */
   3.180  
   3.181          default:
   3.182              assert(0);
   3.183 @@ -2529,17 +2558,18 @@
   3.184      if (status != PEP_STATUS_OK)
   3.185          goto pep_error;
   3.186  
   3.187 -    status = decrypt_message(session,
   3.188 -                             tmp_msg,
   3.189 -                             &dec_msg,
   3.190 -                             keylist,
   3.191 -                             rating,
   3.192 -                             flags);
   3.193 -    if (status != PEP_STATUS_OK)
   3.194 -        goto pep_error;
   3.195 -
   3.196 +    PEP_STATUS decrypt_status = decrypt_message(session,
   3.197 +                                                tmp_msg,
   3.198 +                                                &dec_msg,
   3.199 +                                                keylist,
   3.200 +                                                rating,
   3.201 +                                                flags);
   3.202 +                                                
   3.203      status = mime_encode_message(dec_msg, false, mime_plaintext);
   3.204  
   3.205 +    if (status == PEP_STATUS_OK)
   3.206 +        return decrypt_status;
   3.207 +        
   3.208  pep_error:
   3.209      free_message(tmp_msg);
   3.210      free_message(dec_msg);
   3.211 @@ -2547,6 +2577,7 @@
   3.212      return status;
   3.213  }
   3.214  
   3.215 +
   3.216  DYNAMIC_API PEP_STATUS MIME_encrypt_message(
   3.217      PEP_SESSION session,
   3.218      const char *mimetext,
   3.219 @@ -2585,3 +2616,41 @@
   3.220      return status;
   3.221  
   3.222  }
   3.223 +
   3.224 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
   3.225 +    PEP_SESSION session,
   3.226 +    pEp_identity* target_id,
   3.227 +    const char *mimetext,
   3.228 +    size_t size,
   3.229 +    char** mime_ciphertext,
   3.230 +    PEP_enc_format enc_format,
   3.231 +    PEP_encrypt_flags_t flags
   3.232 +)
   3.233 +{
   3.234 +    PEP_STATUS status = PEP_STATUS_OK;
   3.235 +    message* tmp_msg = NULL;
   3.236 +    message* enc_msg = NULL;
   3.237 +
   3.238 +    status = mime_decode_message(mimetext, size, &tmp_msg);
   3.239 +    if (status != PEP_STATUS_OK)
   3.240 +        goto pep_error;
   3.241 +
   3.242 +    // This isn't incoming, though... so we need to reverse the direction
   3.243 +    tmp_msg->dir = PEP_dir_outgoing;
   3.244 +    status = encrypt_message_for_self(session,
   3.245 +                                      target_id,
   3.246 +                                      tmp_msg,
   3.247 +                                      &enc_msg,
   3.248 +                                      enc_format,
   3.249 +                                      flags);
   3.250 +    if (status != PEP_STATUS_OK)
   3.251 +        goto pep_error;
   3.252 +
   3.253 +    status = mime_encode_message(enc_msg, false, mime_ciphertext);
   3.254 +
   3.255 +pep_error:
   3.256 +    free_message(tmp_msg);
   3.257 +    free_message(enc_msg);
   3.258 +
   3.259 +    return status;
   3.260 +}
     4.1 --- a/src/message_api.h	Thu Mar 09 12:41:34 2017 +0100
     4.2 +++ b/src/message_api.h	Mon Mar 13 14:21:31 2017 +0100
     4.3 @@ -23,7 +23,14 @@
     4.4  void add_opt_field(message *msg, const char *name, const char *value);
     4.5  
     4.6  typedef enum _PEP_encrypt_flags {
     4.7 -    PEP_encrypt_flag_force_encryption = 0x1
     4.8 +    // "default" means whatever the default behaviour for the function is.
     4.9 +    PEP_encrypt_flag_default = 0x0,
    4.10 +    PEP_encrypt_flag_force_encryption = 0x1,
    4.11 +
    4.12 +    // This flag is for special use cases and should not be used
    4.13 +    // by normal pEp clients!
    4.14 +    PEP_encrypt_flag_force_unsigned = 0x2,
    4.15 +    PEP_encrypt_flag_force_no_attached_key = 0x4
    4.16  } PEP_encrypt_flags; 
    4.17  
    4.18  typedef unsigned int PEP_encrypt_flags_t;
    4.19 @@ -68,6 +75,7 @@
    4.20  //      src (in)            message to encrypt
    4.21  //      dst (out)           pointer to new encrypted message or NULL on failure
    4.22  //      enc_format (in)     encrypted format
    4.23 +//      flags (in)          flags to set special encryption features
    4.24  //
    4.25  //  return value:       (FIXME: This may not be correct or complete)
    4.26  //      PEP_STATUS_OK                   on success
    4.27 @@ -89,7 +97,8 @@
    4.28          pEp_identity* target_id,
    4.29          message *src,
    4.30          message **dst,
    4.31 -        PEP_enc_format enc_format
    4.32 +        PEP_enc_format enc_format,
    4.33 +        PEP_encrypt_flags_t flags
    4.34      );
    4.35  
    4.36  // MIME_encrypt_message() - encrypt a MIME message, with MIME output
    4.37 @@ -126,6 +135,43 @@
    4.38      PEP_encrypt_flags_t flags
    4.39  );
    4.40  
    4.41 +// MIME_encrypt_message_for_self() - encrypt MIME message for user's identity only,
    4.42 +//                              ignoring recipients and other identities from
    4.43 +//                              the message, with MIME output
    4.44 +//  parameters:
    4.45 +//      session (in)            session handle
    4.46 +//      target_id (in)      self identity this message should be encrypted for
    4.47 +//      mimetext (in)           MIME encoded text to encrypt
    4.48 +//      size (in)               size of input mime text
    4.49 +//      mime_ciphertext (out)   encrypted, encoded message
    4.50 +//      enc_format (in)         encrypted format
    4.51 +//      flags (in)              flags to set special encryption features
    4.52 +//
    4.53 +//  return value:
    4.54 +//      PEP_STATUS_OK           if everything worked
    4.55 +//      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
    4.56 +//      PEP_CANNOT_CREATE_TEMP_FILE
    4.57 +//                              if there are issues with temp files; in
    4.58 +//                              this case errno will contain the underlying
    4.59 +//                              error
    4.60 +//      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
    4.61 +//
    4.62 +//  caveat:
    4.63 +//      the encrypted, encoded mime text will go to the ownership of the caller; mimetext
    4.64 +//      will remain in the ownership of the caller
    4.65 +
    4.66 +DYNAMIC_API PEP_STATUS MIME_encrypt_message_for_self(
    4.67 +    PEP_SESSION session,
    4.68 +    pEp_identity* target_id,
    4.69 +    const char *mimetext,
    4.70 +    size_t size,
    4.71 +    char** mime_ciphertext,
    4.72 +    PEP_enc_format enc_format,
    4.73 +    PEP_encrypt_flags_t flags
    4.74 +);
    4.75 +
    4.76 +
    4.77 +
    4.78  typedef enum _PEP_rating {
    4.79      PEP_rating_undefined = 0,
    4.80      PEP_rating_cannot_decrypt,
    4.81 @@ -208,7 +254,9 @@
    4.82  //      flags (out)             flags to signal special decryption features
    4.83  //
    4.84  //  return value:
    4.85 -//      PEP_STATUS_OK           if everything worked
    4.86 +//      decrypt status          if everything worked with MIME encode/decode, 
    4.87 +//                              the status of the decryption is returned 
    4.88 +//                              (PEP_STATUS_OK or decryption error status)
    4.89  //      PEP_BUFFER_TOO_SMALL    if encoded message size is too big to handle
    4.90  //      PEP_CANNOT_CREATE_TEMP_FILE
    4.91  //                              if there are issues with temp files; in
    4.92 @@ -377,4 +425,3 @@
    4.93  #ifdef __cplusplus
    4.94  }
    4.95  #endif
    4.96 -
     5.1 --- a/src/pEpEngine.c	Thu Mar 09 12:41:34 2017 +0100
     5.2 +++ b/src/pEpEngine.c	Mon Mar 13 14:21:31 2017 +0100
     5.3 @@ -1477,6 +1477,26 @@
     5.4              keylist, ptext, psize, ctext, csize);
     5.5  }
     5.6  
     5.7 +PEP_STATUS encrypt_only(
     5.8 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     5.9 +    size_t psize, char **ctext, size_t *csize
    5.10 +    )
    5.11 +{
    5.12 +    assert(session);
    5.13 +    assert(keylist);
    5.14 +    assert(ptext);
    5.15 +    assert(psize);
    5.16 +    assert(ctext);
    5.17 +    assert(csize);
    5.18 +
    5.19 +    if (!(session && keylist && ptext && psize && ctext && csize))
    5.20 +        return PEP_ILLEGAL_VALUE;
    5.21 +
    5.22 +    return session->cryptotech[PEP_crypt_OpenPGP].encrypt_only(session,
    5.23 +            keylist, ptext, psize, ctext, csize);
    5.24 +}
    5.25 +
    5.26 +
    5.27  DYNAMIC_API PEP_STATUS verify_text(
    5.28      PEP_SESSION session, const char *text, size_t size,
    5.29      const char *signature, size_t sig_size, stringlist_t **keylist
     6.1 --- a/src/pEp_internal.h	Thu Mar 09 12:41:34 2017 +0100
     6.2 +++ b/src/pEp_internal.h	Mon Mar 13 14:21:31 2017 +0100
     6.3 @@ -167,6 +167,12 @@
     6.4  PEP_STATUS init_transport_system(PEP_SESSION session, bool in_first);
     6.5  void release_transport_system(PEP_SESSION session, bool out_last);
     6.6  
     6.7 +/* NOT to be exposed to the outside!!! */
     6.8 +PEP_STATUS encrypt_only(
     6.9 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    6.10 +        size_t psize, char **ctext, size_t *csize
    6.11 +);
    6.12 +
    6.13  #ifdef NDEBUG
    6.14  #define DEBUG_LOG(TITLE, ENTITY, DESC)
    6.15  #define  LOGD(...)
     7.1 --- a/src/pgp_gpg.c	Thu Mar 09 12:41:34 2017 +0100
     7.2 +++ b/src/pgp_gpg.c	Mon Mar 13 14:21:31 2017 +0100
     7.3 @@ -250,6 +250,11 @@
     7.4              "gpgme_op_encrypt_sign");
     7.5          assert(gpg.gpgme_op_encrypt_sign);
     7.6  
     7.7 +        gpg.gpgme_op_encrypt
     7.8 +            = (gpgme_op_encrypt_t) (intptr_t) dlsym(gpgme,
     7.9 +            "gpgme_op_encrypt");
    7.10 +        assert(gpg.gpgme_op_encrypt);
    7.11 +
    7.12          gpg.gpgme_op_verify_result
    7.13              = (gpgme_op_verify_result_t) (intptr_t) dlsym(gpgme,
    7.14              "gpgme_op_verify_result");
    7.15 @@ -873,11 +878,12 @@
    7.16      return result;
    7.17  }
    7.18  
    7.19 -PEP_STATUS pgp_encrypt_and_sign(
    7.20 +
    7.21 +static PEP_STATUS pgp_encrypt_sign_optional(    
    7.22      PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    7.23 -    size_t psize, char **ctext, size_t *csize
    7.24 -    )
    7.25 -{
    7.26 +    size_t psize, char **ctext, size_t *csize, bool sign
    7.27 +)
    7.28 +{    
    7.29      PEP_STATUS result;
    7.30      gpgme_error_t gpgme_error;
    7.31      gpgme_data_t plain, cipher;
    7.32 @@ -943,7 +949,7 @@
    7.33              gpg.gpgme_data_release(cipher);
    7.34              return PEP_OUT_OF_MEMORY;
    7.35          case GPG_ERR_NO_ERROR:
    7.36 -            if (i == 0) {
    7.37 +            if (i == 0 && sign) {
    7.38                  gpgme_error_t _gpgme_error = gpg.gpgme_signers_add(session->ctx, rcpt[0]);
    7.39                  _gpgme_error = _GPGERR(_gpgme_error);
    7.40                  assert(_gpgme_error == GPG_ERR_NO_ERROR);
    7.41 @@ -976,9 +982,16 @@
    7.42  
    7.43      // TODO: remove that and replace with proper key management
    7.44      flags = GPGME_ENCRYPT_ALWAYS_TRUST;
    7.45 -
    7.46 -    gpgme_error = gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
    7.47 -        plain, cipher);
    7.48 +    
    7.49 +    if (sign) {
    7.50 +        gpgme_error = gpg.gpgme_op_encrypt_sign(session->ctx, rcpt, flags,
    7.51 +            plain, cipher);
    7.52 +    }
    7.53 +    else {
    7.54 +        gpgme_error = gpg.gpgme_op_encrypt(session->ctx, rcpt, flags,
    7.55 +            plain, cipher);
    7.56 +    }
    7.57 +    
    7.58      gpgme_error = _GPGERR(gpgme_error);
    7.59      switch (gpgme_error) {
    7.60      case GPG_ERR_NO_ERROR:
    7.61 @@ -1024,6 +1037,24 @@
    7.62      return result;
    7.63  }
    7.64  
    7.65 +PEP_STATUS pgp_encrypt_only(
    7.66 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    7.67 +    size_t psize, char **ctext, size_t *csize
    7.68 +    )
    7.69 +{
    7.70 +    return pgp_encrypt_sign_optional(session, keylist, ptext,
    7.71 +        psize, ctext, csize, false);
    7.72 +}
    7.73 +
    7.74 +PEP_STATUS pgp_encrypt_and_sign(
    7.75 +    PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
    7.76 +    size_t psize, char **ctext, size_t *csize
    7.77 +    )
    7.78 +{
    7.79 +    return pgp_encrypt_sign_optional(session, keylist, ptext,
    7.80 +        psize, ctext, csize, true);
    7.81 +}
    7.82 +
    7.83  PEP_STATUS pgp_generate_keypair(
    7.84      PEP_SESSION session, pEp_identity *identity
    7.85      )
     8.1 --- a/src/pgp_gpg.h	Thu Mar 09 12:41:34 2017 +0100
     8.2 +++ b/src/pgp_gpg.h	Mon Mar 13 14:21:31 2017 +0100
     8.3 @@ -19,6 +19,12 @@
     8.4          size_t psize, char **ctext, size_t *csize
     8.5      );
     8.6  
     8.7 +PEP_STATUS pgp_encrypt_only(
     8.8 +        PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
     8.9 +        size_t psize, char **ctext, size_t *csize
    8.10 +    );
    8.11 +
    8.12 +
    8.13  PEP_STATUS pgp_verify_text(
    8.14          PEP_SESSION session, const char *text, size_t size,
    8.15          const char *signature, size_t sig_size, stringlist_t **keylist
    8.16 @@ -100,4 +106,3 @@
    8.17  
    8.18  PEP_STATUS pgp_binary(const char **path);
    8.19  #define PGP_BINARY_PATH pgp_binary
    8.20 -
     9.1 --- a/src/pgp_gpg_internal.h	Thu Mar 09 12:41:34 2017 +0100
     9.2 +++ b/src/pgp_gpg_internal.h	Mon Mar 13 14:21:31 2017 +0100
     9.3 @@ -43,6 +43,9 @@
     9.4  typedef gpgme_error_t(*gpgme_op_encrypt_sign_t)(gpgme_ctx_t CTX,
     9.5      gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
     9.6      gpgme_data_t CIPHER);
     9.7 +typedef gpgme_error_t(*gpgme_op_encrypt_t)(gpgme_ctx_t CTX,
     9.8 +        gpgme_key_t RECP[], gpgme_encrypt_flags_t FLAGS, gpgme_data_t PLAIN,
     9.9 +        gpgme_data_t CIPHER);
    9.10  typedef gpgme_verify_result_t(*gpgme_op_verify_result_t)(gpgme_ctx_t CTX);
    9.11  typedef void(*gpgme_signers_clear_t)(gpgme_ctx_t CTX);
    9.12  typedef gpgme_error_t(*gpgme_signers_add_t)(gpgme_ctx_t CTX, const gpgme_key_t KEY);
    9.13 @@ -102,6 +105,7 @@
    9.14      gpgme_op_decrypt_verify_t gpgme_op_decrypt_verify;
    9.15      gpgme_op_decrypt_result_t gpgme_op_decrypt_result;
    9.16      gpgme_op_encrypt_sign_t gpgme_op_encrypt_sign;
    9.17 +    gpgme_op_encrypt_t gpgme_op_encrypt;
    9.18      gpgme_op_verify_result_t gpgme_op_verify_result;
    9.19      gpgme_signers_clear_t gpgme_signers_clear;
    9.20      gpgme_signers_add_t gpgme_signers_add;
    9.21 @@ -125,4 +129,3 @@
    9.22      gpgme_op_edit_t gpgme_op_edit;
    9.23      gpgme_io_write_t gpgme_io_write;
    9.24  };
    9.25 -
    10.1 --- a/test/encrypt_for_identity_test.cc	Thu Mar 09 12:41:34 2017 +0100
    10.2 +++ b/test/encrypt_for_identity_test.cc	Mon Mar 13 14:21:31 2017 +0100
    10.3 @@ -35,6 +35,7 @@
    10.4      outgoing_message->from = alice;
    10.5      outgoing_message->to = to_list;
    10.6      outgoing_message->shortmsg = strdup("Greetings, humans!");
    10.7 +    outgoing_message->longmsg = strdup("This is a test of the emergency message system. This is only a test. BEEP.");
    10.8      outgoing_message->attachments = new_bloblist(NULL, 0, "application/octet-stream", NULL);
    10.9      cout << "message created.\n";
   10.10  
   10.11 @@ -51,7 +52,7 @@
   10.12      cout << "encrypting message as MIME multipart…\n";
   10.13      message* encrypted_msg = nullptr;
   10.14      cout << "calling encrypt_message_for_identity()\n";
   10.15 -    status = encrypt_message_for_self(session, alice, outgoing_message, &encrypted_msg, PEP_enc_PGP_MIME);
   10.16 +    status = encrypt_message_for_self(session, alice, outgoing_message, &encrypted_msg, PEP_enc_PGP_MIME, PEP_encrypt_flag_force_unsigned | PEP_encrypt_flag_force_no_attached_key);
   10.17      cout << "encrypt_message() returns " << std::hex << status << '.' << endl;
   10.18      assert(status == PEP_STATUS_OK);
   10.19      assert(encrypted_msg);
   10.20 @@ -81,20 +82,27 @@
   10.21      PEP_decrypt_flags_t flags;
   10.22  
   10.23      status = decrypt_message(session, encrypted_msg, &decrypted_msg, &keylist_used, &rating, &flags);
   10.24 -    assert(status == PEP_STATUS_OK);
   10.25      assert(decrypted_msg);
   10.26      assert(keylist_used);
   10.27      assert(rating);
   10.28 +    assert(status == PEP_DECRYPTED && rating == PEP_rating_unreliable);
   10.29      PEP_comm_type ct = encrypted_msg->from->comm_type;
   10.30      assert(ct == PEP_ct_pEp || ct == PEP_ct_pEp_unconfirmed || ct == PEP_ct_OpenPGP || ct == PEP_ct_OpenPGP_unconfirmed );
   10.31  
   10.32      cout << "keys used:\n";
   10.33  
   10.34 -    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next)
   10.35 +    int i = 0;
   10.36 +
   10.37 +    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next, i++)
   10.38      {
   10.39 -        cout << "\t " << kl4->value << endl;
   10.40 -        assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
   10.41 -        cout << "Encrypted for Alice! Yay! It worked!" << endl;
   10.42 +        if (i == 0)
   10.43 +            assert(strcasecmp("",kl4->value) == 0);
   10.44 +        else {
   10.45 +            cout << "\t " << kl4->value << endl;
   10.46 +            assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
   10.47 +            cout << "Encrypted for Alice! Yay! It worked!" << endl;
   10.48 +        }
   10.49 +        assert(i < 2);
   10.50      }
   10.51      cout << "Encrypted ONLY for Alice! Test passed. Move along. These are not the bugs you are looking for." << endl;
   10.52   
   10.53 @@ -104,6 +112,82 @@
   10.54      free_message(outgoing_message);
   10.55      cout << "done.\n";
   10.56  
   10.57 +    cout << "*** Now testing MIME_encrypt_for_self ***" << endl;
   10.58 +
   10.59 +    alice = new_identity("pep.test.alice@pep-project.org", NULL, PEP_OWN_USERID, "Alice Test");
   10.60 +    bob = new_identity("pep.test.bob@pep-project.org", NULL, "42", "Bob Test");
   10.61 +
   10.62 +    cout << "Reading in alice_bob_encrypt_test_plaintext_mime.eml..." << endl;
   10.63 +    
   10.64 +    ifstream inFile("test_mails/alice_bob_encrypt_test_plaintext_mime.eml");
   10.65 +    assert(inFile.is_open());
   10.66 +
   10.67 +    string mimetext;
   10.68 +
   10.69 +    cout << "reading mime mail\n";
   10.70 +    while (!inFile.eof()) {
   10.71 +        static string line;
   10.72 +        getline(inFile, line);
   10.73 +        mimetext += line + "\n";
   10.74 +    }
   10.75 +    inFile.close();
   10.76 +
   10.77 +    cout << "Text read:" << endl;
   10.78 +    cout << mimetext.c_str() << endl;
   10.79 +    char* encrypted_mimetext = nullptr;
   10.80 +    
   10.81 +    cout << "Calling MIME_encrypt_message_for_self" << endl;
   10.82 +    status = MIME_encrypt_message_for_self(session, alice, mimetext.c_str(),
   10.83 +                                           mimetext.size(), 
   10.84 +                                           &encrypted_mimetext, 
   10.85 +                                           PEP_enc_PGP_MIME, 
   10.86 +                                           PEP_encrypt_flag_force_unsigned | PEP_encrypt_flag_force_no_attached_key);
   10.87 +    
   10.88 +    cout << "Encrypted message:" << endl;
   10.89 +    cout << encrypted_mimetext << endl;
   10.90 +
   10.91 +    cout << "Calling MIME_decrypt_message" << endl;
   10.92 +    
   10.93 +    char* decrypted_mimetext = nullptr;
   10.94 +    free_stringlist(keylist_used);
   10.95 +    keylist_used = nullptr;
   10.96 +    PEP_decrypt_flags_t mimeflags;
   10.97 +    PEP_rating mimerating;
   10.98 +
   10.99 +    status = MIME_decrypt_message(session,
  10.100 +                                  encrypted_mimetext,
  10.101 +                                  strlen(encrypted_mimetext),
  10.102 +                                  &decrypted_mimetext,
  10.103 +                                  &keylist_used,
  10.104 +                                  &mimerating,
  10.105 +                                  &mimeflags);
  10.106 +
  10.107 +    assert(decrypted_msg);
  10.108 +    assert(keylist_used);
  10.109 +    assert(mimerating);
  10.110 +                             
  10.111 +    assert(status == PEP_DECRYPTED && mimerating == PEP_rating_unreliable);
  10.112 +
  10.113 +    cout << "Decrypted message:" << endl;
  10.114 +    cout << decrypted_mimetext << endl;
  10.115 +
  10.116 +    cout << "keys used:\n";
  10.117 +
  10.118 +    i = 0;
  10.119 +
  10.120 +    for (stringlist_t* kl4 = keylist_used; kl4 && kl4->value; kl4 = kl4->next, i++)
  10.121 +    {
  10.122 +        if (i == 0)
  10.123 +            assert(strcasecmp("",kl4->value) == 0);
  10.124 +        else {
  10.125 +            cout << "\t " << kl4->value << endl;
  10.126 +            assert(strcasecmp("4ABE3AAF59AC32CFE4F86500A9411D176FF00E97", kl4->value) == 0);
  10.127 +            cout << "Encrypted for Alice! Yay! It worked!" << endl;
  10.128 +        }
  10.129 +        assert(i < 2);
  10.130 +    }
  10.131 +    cout << "Encrypted ONLY for Alice! Test passed. Move along. These are not the bugs you are looking for." << endl;
  10.132 +    
  10.133      cout << "calling release()\n";
  10.134      release(session);
  10.135      return 0;