ENGINE-246: A solution that works, but the wrong one 2028_fix
authorKrista Bennett <krista@pep-project.org>
Wed, 06 Sep 2017 01:48:08 +0200
branch2028_fix
changeset 203561b05d325adc
parent 2034 b6742bbca2d2
child 2036 81c4285cd4fc
ENGINE-246: A solution that works, but the wrong one
build-config/Linux.conf
doc/readme.md
src/message.h
src/message_api.c
src/message_api.h
src/mime.c
test/revoke_regen_attach_test.cc
     1.1 --- a/build-config/Linux.conf	Tue Sep 05 18:46:05 2017 +0200
     1.2 +++ b/build-config/Linux.conf	Wed Sep 06 01:48:08 2017 +0200
     1.3 @@ -7,7 +7,7 @@
     1.4  TARGET=libpEpEngine.so
     1.5  
     1.6  ######### C #########
     1.7 -CC=gcc -std=c99 -pthread -g -O0
     1.8 +CC=gcc -std=c99 -pthread
     1.9  CFLAGS=-fPIC -fstrict-aliasing -fdiagnostics-color=always
    1.10  ifdef WARN
    1.11      CFLAGS+= -Wall -pedantic -Wstrict-aliasing=3
    1.12 @@ -17,13 +17,13 @@
    1.13  ifdef DEBUG
    1.14      CFLAGS+= -Og -ggdb -DDEBUG_ERRORSTACK
    1.15  else
    1.16 -    CFLAGS+= -DNDEBUG
    1.17 +    CFLAGS+= -O3 -DNDEBUG
    1.18  endif
    1.19  # The '_DEFAULT_SOURCE' feature test macro is required to suppress the warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" otherwise printed during the compilation of every asn1c-generated C file. It's a glibc specific warning, only present in few versions around ~2.19. See https://lwn.net/Articles/590381/ for a discussion.
    1.20  CFLAGS_GENERATED=-D_DEFAULT_SOURCE
    1.21  
    1.22  ######### C++ #########
    1.23 -CXX=g++ -std=gnu++11 -pthread -g -O0
    1.24 +CXX=g++ -std=gnu++11 -pthread
    1.25  CXXFLAGS=-fdiagnostics-color=always -I../src -I../asn.1 $(ETPAN_INC)
    1.26  ifdef WARN
    1.27      CXXFLAGS+=
    1.28 @@ -33,7 +33,7 @@
    1.29  ifdef DEBUG
    1.30      CXXFLAGS+= -Og -ggdb
    1.31  else
    1.32 -    CXXFLAGS+= -DNDEBUG
    1.33 +    CXXFLAGS+= -O3 -DNDEBUG
    1.34  endif
    1.35  
    1.36  ######### C and C++ #########
     2.1 --- a/doc/readme.md	Tue Sep 05 18:46:05 2017 +0200
     2.2 +++ b/doc/readme.md	Wed Sep 06 01:48:08 2017 +0200
     2.3 @@ -10,8 +10,7 @@
     2.4  
     2.5  - run-time dependencies
     2.6    - One of the following OpenPGP implementations:
     2.7 -    - GnuPG version 2.1.17 or later with GPGME (at least version 1.7.0) [https://gnupg.org/](https://gnupg.org/)
     2.8 -    - For platforms not supporting pinentry (e.g. Android) - GnuPG version 2.0.30 with GPGME version 1.6.0 (or later) [https://gnupg.org/](https://gnupg.org/)
     2.9 +    - GnuPG (version 2.0.30 or 2.1.16 or newer) by way of GPGME (version 1.6.0 or newer) [https://gnupg.org/](https://gnupg.org/)
    2.10      - a fork of NetPGP, [https://cacert.pep.foundation/dev/repos/netpgp-et/](https://cacert.pep.foundation/dev/repos/netpgp-et/)
    2.11    - a fork of libetpan, [https://github.com/fdik/libetpan](https://github.com/fdik/libetpan)
    2.12    - zlib, [http://zlib.net/](http://zlib.net/)
     3.1 --- a/src/message.h	Tue Sep 05 18:46:05 2017 +0200
     3.2 +++ b/src/message.h	Wed Sep 06 01:48:08 2017 +0200
     3.3 @@ -163,3 +163,4 @@
     3.4  #ifdef __cplusplus
     3.5  }
     3.6  #endif
     3.7 +
     4.1 --- a/src/message_api.c	Tue Sep 05 18:46:05 2017 +0200
     4.2 +++ b/src/message_api.c	Wed Sep 06 01:48:08 2017 +0200
     4.3 @@ -211,32 +211,6 @@
     4.4      return -1;
     4.5  }
     4.6  
     4.7 -// static void remove_msg_version_field(message* msg) {
     4.8 -//     assert(msg);
     4.9 -// 
    4.10 -//     stringpair_list_t* msg_opt_flds_curr = msg->opt_fields;
    4.11 -//     stringpair_list_t** msg_opt_flds_prev_p = NULL;
    4.12 -//     
    4.13 -//     while (msg_opt_flds_curr) {
    4.14 -//         char* fld_key = msg_opt_flds_curr->value->key;
    4.15 -//         if (fld_key) {
    4.16 -//             if (strcmp(fld_key, "X-pEp-Message-Version") == 0) {
    4.17 -//                 if (!msg_opt_flds_prev_p) {
    4.18 -//                     msg->opt_fields = msg_opt_flds_curr->next;
    4.19 -//                 }
    4.20 -//                 else {
    4.21 -//                     (*msg_opt_flds_prev_p)->next = msg_opt_flds_curr->next;
    4.22 -//                 }
    4.23 -//                 msg_opt_flds_curr->next = NULL;
    4.24 -//                 free_stringpair_list(msg_opt_flds_curr);
    4.25 -//                 break;
    4.26 -//             }
    4.27 -//             *msg_opt_flds_prev_p = msg_opt_flds_curr;
    4.28 -//             msg_opt_flds_curr = msg_opt_flds_curr->next;
    4.29 -//         }
    4.30 -//     }
    4.31 -// }
    4.32 -
    4.33  static PEP_STATUS copy_fields(message *dst, const message *src)
    4.34  {
    4.35      assert(dst);
    4.36 @@ -353,102 +327,6 @@
    4.37      return PEP_STATUS_OK;
    4.38  }
    4.39  
    4.40 -
    4.41 -static message* extract_minimal_envelope(const message* src, 
    4.42 -                                         PEP_msg_direction direct) {
    4.43 -    
    4.44 -    message* envelope = new_message(direct);
    4.45 -    if (!envelope)
    4.46 -        return NULL;
    4.47 -        
    4.48 -    envelope->shortmsg = strdup("pEp");
    4.49 -    if (!envelope->shortmsg)
    4.50 -        return NULL;
    4.51 -
    4.52 -    if (src->from) {
    4.53 -        envelope->from = identity_dup(src->from);
    4.54 -        if (!envelope->from)
    4.55 -            return NULL;
    4.56 -    }
    4.57 -
    4.58 -    if (src->to) {
    4.59 -        envelope->to = identity_list_dup(src->to);
    4.60 -        if (!envelope->to)
    4.61 -            return NULL;
    4.62 -    }
    4.63 -
    4.64 -    if (src->cc) {
    4.65 -        envelope->cc = identity_list_dup(src->cc);
    4.66 -        if (!envelope->cc)
    4.67 -            return NULL;
    4.68 -    }
    4.69 -
    4.70 -    if (src->bcc) {
    4.71 -        envelope->bcc = identity_list_dup(src->bcc);
    4.72 -        if (!envelope->bcc)
    4.73 -            return NULL;
    4.74 -    }
    4.75 -
    4.76 -    /* DO WE WANT TO EXPOSE THIS??? */
    4.77 -    if (src->reply_to) {
    4.78 -        envelope->reply_to = identity_list_dup(src->reply_to);
    4.79 -        if (!envelope->reply_to)
    4.80 -            return NULL;
    4.81 -    }
    4.82 -
    4.83 -    envelope->enc_format = src->enc_format;        
    4.84 -    
    4.85 -    return envelope;
    4.86 -}
    4.87 -
    4.88 -static void add_message_version(
    4.89 -    message* msg,
    4.90 -    int major_version,
    4.91 -    int minor_version
    4.92 -)
    4.93 -{
    4.94 -    assert(msg);
    4.95 -    
    4.96 -    char buf[8]; // xxx.xxx\0
    4.97 -    if (major_version < 1000 && minor_version < 1000) {
    4.98 -        int chars_set = sprintf(buf, "%d.%d", major_version, minor_version);
    4.99 -        if (chars_set >= 3)
   4.100 -            add_opt_field(msg, "X-pEp-Message-Version", buf);
   4.101 -    }
   4.102 -}
   4.103 -
   4.104 -static message* wrap_message_as_attachment(message* envelope, 
   4.105 -    const message* attachment) {
   4.106 -    
   4.107 -    message* _envelope = NULL;
   4.108 -    
   4.109 -    if (!envelope) {
   4.110 -        _envelope = extract_minimal_envelope(attachment, PEP_dir_outgoing);
   4.111 -        if (!_envelope)
   4.112 -            return PEP_UNKNOWN_ERROR;
   4.113 -        envelope = _envelope;
   4.114 -    }
   4.115 -    
   4.116 -    char* message_text = NULL;
   4.117 -    /* Turn message into a MIME-blob */
   4.118 -    PEP_STATUS status = mime_encode_message(attachment, false, &message_text);
   4.119 -    
   4.120 -    if (status != PEP_STATUS_OK || !message_text) {
   4.121 -        free(_envelope);
   4.122 -        return NULL;
   4.123 -    }
   4.124 -    
   4.125 -    size_t message_len = strlen(message_text);
   4.126 -    
   4.127 -    bloblist_t* message_blob = new_bloblist(message_text, message_len,
   4.128 -                                            "message/rfc822", NULL);
   4.129 -    
   4.130 -    envelope->attachments = message_blob;
   4.131 -    add_message_version(envelope, 2, 0);
   4.132 -    
   4.133 -    return envelope;
   4.134 -}
   4.135 -
   4.136  static message * clone_to_empty_message(const message * src)
   4.137  {
   4.138      PEP_STATUS status;
   4.139 @@ -580,8 +458,6 @@
   4.140      return status;
   4.141  }
   4.142  
   4.143 -// N.B. TO BE MOVED TO READ-ONLY
   4.144 -// FIXME: Does this happen concurrent w/ message 2.0 merge?
   4.145  static PEP_STATUS encrypt_PGP_in_pieces(
   4.146      PEP_SESSION session,
   4.147      const message *src,
   4.148 @@ -1244,8 +1120,6 @@
   4.149      PEP_STATUS status = PEP_STATUS_OK;
   4.150      message * msg = NULL;
   4.151      stringlist_t * keys = NULL;
   4.152 -    message* _src = NULL;
   4.153 -    bool no_wrap_message = (flags & PEP_encrypt_flag_dont_raise_headers);
   4.154  
   4.155      assert(session);
   4.156      assert(src);
   4.157 @@ -1373,37 +1247,21 @@
   4.158          return ADD_TO_LOG(PEP_UNENCRYPTED);
   4.159      }
   4.160      else {
   4.161 -        if (no_wrap_message) {
   4.162 -            msg = clone_to_empty_message(src);
   4.163 -            _src = src;
   4.164 -        }
   4.165 -        else {
   4.166 -            // encrypt inner message
   4.167 -            message* inner_message = NULL;
   4.168 -            status = encrypt_message(session, src, extra, &inner_message,
   4.169 -                                     enc_format, flags | PEP_encrypt_flag_dont_raise_headers);                         
   4.170 -            _src = wrap_message_as_attachment(NULL, inner_message);
   4.171 -            if (_src == NULL) {
   4.172 -                status = PEP_UNKNOWN_ERROR;
   4.173 -                goto pep_error;
   4.174 -            }
   4.175 -            msg = clone_to_empty_message(_src);
   4.176 -        }
   4.177 +        msg = clone_to_empty_message(src);
   4.178          if (msg == NULL)
   4.179              goto enomem;
   4.180  
   4.181          if (!(flags & PEP_encrypt_flag_force_no_attached_key))
   4.182 -            attach_own_key(session, _src);
   4.183 +            attach_own_key(session, src);
   4.184  
   4.185          switch (enc_format) {
   4.186          case PEP_enc_PGP_MIME:
   4.187          case PEP_enc_PEP: // BUG: should be implemented extra
   4.188 -            status = encrypt_PGP_MIME(session, _src, keys, msg, flags);
   4.189 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   4.190              break;
   4.191  
   4.192 -        // This actually doesn't really make sense for message 2.0... See function comment below
   4.193          case PEP_enc_pieces:
   4.194 -            status = encrypt_PGP_in_pieces(session, _src, keys, msg, flags);
   4.195 +            status = encrypt_PGP_in_pieces(session, src, keys, msg, flags);
   4.196              break;
   4.197  
   4.198          /* case PEP_enc_PEP:
   4.199 @@ -1434,8 +1292,8 @@
   4.200  
   4.201      if (msg) {
   4.202          decorate_message(msg, PEP_rating_undefined, NULL);
   4.203 -        if (_src->id) {
   4.204 -            msg->id = strdup(_src->id);
   4.205 +        if (src->id) {
   4.206 +            msg->id = strdup(src->id);
   4.207              assert(msg->id);
   4.208              if (msg->id == NULL)
   4.209                  goto enomem;
   4.210 @@ -1443,7 +1301,6 @@
   4.211      }
   4.212  
   4.213      *dst = msg;
   4.214 -//    free_message(wrapped_msg);
   4.215      return ADD_TO_LOG(status);
   4.216  
   4.217  enomem:
   4.218 @@ -1452,8 +1309,7 @@
   4.219  pep_error:
   4.220      free_stringlist(keys);
   4.221      free_message(msg);
   4.222 -    if (!no_wrap_message)
   4.223 -        free_message(_src);
   4.224 +
   4.225      return ADD_TO_LOG(status);
   4.226  }
   4.227  
   4.228 @@ -1515,11 +1371,7 @@
   4.229      switch (enc_format) {
   4.230          case PEP_enc_PGP_MIME:
   4.231          case PEP_enc_PEP: // BUG: should be implemented extra
   4.232 -            // N.B. Don't raise headers, as we want to send a 1.0 message back.
   4.233 -            // If this is a draft, obviously that will change when it's reencrypted
   4.234 -            // for everybody else.
   4.235 -            status = encrypt_PGP_MIME(session, src, keys, msg, 
   4.236 -                                      flags | PEP_encrypt_flag_dont_raise_headers);
   4.237 +            status = encrypt_PGP_MIME(session, src, keys, msg, flags);
   4.238              break;
   4.239  
   4.240          case PEP_enc_pieces:
   4.241 @@ -1580,60 +1432,8 @@
   4.242      return false;
   4.243  }
   4.244  
   4.245 -static const char* pEpmessage_version_str(const message *msg)
   4.246 -{
   4.247 -    char* retval = NULL;
   4.248 -    for (stringpair_list_t *i = msg->opt_fields; i && i->value ; i=i->next) {
   4.249 -        if (strcasecmp(i->value->key, "X-pEp-Message-Version") == 0) {
   4.250 -            retval = i->value->value;
   4.251 -            break;
   4.252 -        }
   4.253 -    }
   4.254 -    return retval;
   4.255 -}
   4.256 -
   4.257 -static int pEpmessage_major_version(const message *msg) {
   4.258 -    const char* version_string = pEpmessage_version_str(msg);
   4.259 -    if (!version_string)
   4.260 -        return -1;
   4.261 -    
   4.262 -    int ver_strlen = strlen(version_string);
   4.263 -    if (ver_strlen < 3)
   4.264 -        return -1;
   4.265 -        
   4.266 -    const short MAX_MAJ_VERSION_DIGITS = 4; // I certainly hope...    
   4.267 -    char version_buf[MAX_MAJ_VERSION_DIGITS + 1];
   4.268 -
   4.269 -    int i = 0;    
   4.270 -    
   4.271 -    for ( ; i < MAX_MAJ_VERSION_DIGITS && i < ver_strlen; i++ ) {
   4.272 -        if (version_string[i] == '.') {
   4.273 -            version_buf[i] = '\0';
   4.274 -            break;
   4.275 -        }
   4.276 -        version_buf[i] = version_string[i];
   4.277 -    }
   4.278 -    
   4.279 -    if (version_string[i] != '.')
   4.280 -        return -1;
   4.281 -    
   4.282 -    // ok, this is some chars + \0, but not necessarily numeric.
   4.283 -    int retval = atoi(version_buf);
   4.284 -    if (retval == 0 && version_buf[0] != 0)
   4.285 -        return -1;
   4.286 -    
   4.287 -    return retval;
   4.288 -}
   4.289 -
   4.290 -// static bool verify_explicit_message_version(const char* desired_version, 
   4.291 -//     const message* msg) {
   4.292 -//     if (!desired_version || !msg)
   4.293 -//         return false;
   4.294 -//     const char* msg_version_str = pEpmessage_version_str(msg);
   4.295 -//     return (msg_version_str && (strcmp(desired_version, msg_version_str) == 0));
   4.296 -// }
   4.297 -
   4.298  // update comm_type to pEp_ct_pEp if needed
   4.299 +
   4.300  static PEP_STATUS _update_identity_for_incoming_message(
   4.301          PEP_SESSION session,
   4.302          const message *src
   4.303 @@ -1861,29 +1661,6 @@
   4.304      return status;
   4.305  }
   4.306  
   4.307 -static void pull_up_longmsg_attachment(message* msg) {
   4.308 -    bloblist_t* matt = msg->attachments;
   4.309 -    if (matt) {
   4.310 -        const char* inner_mime_type = matt->mime_type;
   4.311 -        if (strcasecmp(inner_mime_type, "text/plain") == 0) {
   4.312 -            free(msg->longmsg); /* in case of "" */
   4.313 -            msg->longmsg = strndup(matt->value, matt->size);
   4.314 -            
   4.315 -            bloblist_t* next_node = matt->next;
   4.316 -            if (next_node) {
   4.317 -                inner_mime_type = next_node->mime_type;
   4.318 -                if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.319 -                    free(msg->longmsg_formatted);
   4.320 -                    msg->longmsg_formatted = strndup(next_node->value, next_node->size);
   4.321 -                }
   4.322 -            }
   4.323 -        }
   4.324 -        else if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.325 -            free(msg->longmsg_formatted);
   4.326 -            msg->longmsg_formatted = strndup(matt->value, matt->size);
   4.327 -        }
   4.328 -    }
   4.329 -}
   4.330  
   4.331  DYNAMIC_API PEP_STATUS _decrypt_message(
   4.332          PEP_SESSION session,
   4.333 @@ -1903,7 +1680,6 @@
   4.334      char *ptext = NULL;
   4.335      size_t psize;
   4.336      stringlist_t *_keylist = NULL;
   4.337 -    message *inner_message = NULL; // For version 2.0+ messages
   4.338  
   4.339      assert(session);
   4.340      assert(src);
   4.341 @@ -1964,9 +1740,31 @@
   4.342              
   4.343              char* slong = src->longmsg;
   4.344              char* sform = src->longmsg_formatted;
   4.345 +            bloblist_t* satt = src->attachments;
   4.346              
   4.347 -            if ((!slong || slong[0] == '\0') && (!sform || sform[0] == '\0'))                
   4.348 -                pull_up_longmsg_attachment(src);
   4.349 +            if ((!slong || slong[0] == '\0')
   4.350 +                 && (!sform || sform[0] == '\0')) {
   4.351 +                if (satt) {
   4.352 +                    const char* inner_mime_type = satt->mime_type;
   4.353 +                    if (strcasecmp(inner_mime_type, "text/plain") == 0) {
   4.354 +                        free(slong); /* in case of "" */
   4.355 +                        src->longmsg = strndup(satt->value, satt->size); // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
   4.356 +                        
   4.357 +                        bloblist_t* next_node = satt->next;
   4.358 +                        if (next_node) {
   4.359 +                            inner_mime_type = next_node->mime_type;
   4.360 +                            if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.361 +                                free(sform);
   4.362 +                                src->longmsg_formatted = strndup(next_node->value, next_node->size);  // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
   4.363 +                            }
   4.364 +                        }
   4.365 +                    }
   4.366 +                    else if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.367 +                        free(sform);
   4.368 +                        src->longmsg_formatted = strndup(satt->value, satt->size);  // N.B.: longmsg might be shorter, if attachment contains NUL bytes which are not allowed in text/plain!
   4.369 +                    }
   4.370 +                }
   4.371 +            }
   4.372              
   4.373              return ADD_TO_LOG(PEP_UNENCRYPTED);
   4.374  
   4.375 @@ -2015,44 +1813,32 @@
   4.376                  if (status != PEP_STATUS_OK)
   4.377                      goto pep_error;
   4.378                  
   4.379 -                int msg_major_version = pEpmessage_major_version(src);
   4.380 -                
   4.381 -                if (msg_major_version > 1) {
   4.382 -                    status = mime_decode_message(msg->attachments->value, 
   4.383 -                                                 msg->attachments->size,
   4.384 -                                                 &inner_message);
   4.385 -                    if (status != PEP_STATUS_OK)
   4.386 -                        goto pep_error;
   4.387 -                    
   4.388 -                    int inner_message_version = pEpmessage_major_version(inner_message);
   4.389 -                    
   4.390 -                    /* recurse one level if need be */
   4.391 -                    if (inner_message_version < 2) {
   4.392 -                        status = _decrypt_message(session, inner_message,
   4.393 -                                                  dst, keylist, rating, 
   4.394 -                                                  flags, private_il);
   4.395 -                        
   4.396 -                        free_message(inner_message);
   4.397 -                        return status;
   4.398 -                    }
   4.399 -                    /* 
   4.400 -                       otherwise, we're just going to verify the outer
   4.401 -                       message's keylist etc, and then pull up at the end.
   4.402 -                    */
   4.403 -                }
   4.404 -                                    
   4.405                  char* mlong = msg->longmsg;
   4.406                  char* mform = msg->longmsg_formatted;
   4.407 +                bloblist_t* matt = msg->attachments;
   4.408                  
   4.409 -                /* Note: we don't do this for Version 2.0+ inner messages, as we want to
   4.410 -                   return the whole message, not just the attachment, in that case.
   4.411 -                   (N.B. Version 2.0+ inner messages are themselves compound messages,
   4.412 -                   and the inner message is probably one that needs to be routed
   4.413 -                   elsewhere by the transport) 
   4.414 -                */
   4.415 -                if (!inner_message && (!mlong || mlong[0] == '\0') && (!mform || mform[0] == '\0')) {             
   4.416 -                    pull_up_longmsg_attachment(msg);
   4.417 -                    
   4.418 +                if ((!mlong || mlong[0] == '\0')
   4.419 +                     && (!mform || mform[0] == '\0')) {
   4.420 +                    if (matt) {
   4.421 +                        const char* inner_mime_type = matt->mime_type;
   4.422 +                        if (strcasecmp(inner_mime_type, "text/plain") == 0) {
   4.423 +                            free(mlong); /* in case of "" */
   4.424 +                            msg->longmsg = strndup(matt->value, matt->size);
   4.425 +                            
   4.426 +                            bloblist_t* next_node = matt->next;
   4.427 +                            if (next_node) {
   4.428 +                                inner_mime_type = next_node->mime_type;
   4.429 +                                if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.430 +                                    free(mform);
   4.431 +                                    msg->longmsg_formatted = strndup(next_node->value, next_node->size);
   4.432 +                                }
   4.433 +                            }
   4.434 +                        }
   4.435 +                        else if (strcasecmp(inner_mime_type, "text/html") == 0) {
   4.436 +                            free(mform);
   4.437 +                            msg->longmsg_formatted = strndup(matt->value, matt->size);
   4.438 +                        }
   4.439 +                    }
   4.440                      if (msg->shortmsg) {
   4.441                          free(src->shortmsg);
   4.442                          src->shortmsg = strdup(msg->shortmsg);
   4.443 @@ -2183,45 +1969,43 @@
   4.444                  {
   4.445                      GOTO(pep_error);
   4.446                  }
   4.447 -                
   4.448 -                if (!inner_message) {
   4.449 -                    if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0)
   4.450 -                    {
   4.451 -                        char * shortmsg;
   4.452 -                        char * longmsg;
   4.453 -
   4.454 -                        int r = separate_short_and_long(msg->longmsg, &shortmsg,
   4.455 -                                &longmsg);
   4.456 -                        
   4.457 -                        if (r == -1)
   4.458 -                            goto enomem;
   4.459 -
   4.460 -                        if (shortmsg == NULL) {
   4.461 -                            if (src->shortmsg == NULL)
   4.462 -                                shortmsg = strdup("");
   4.463 -                            else {
   4.464 -                                // FIXME: is msg->shortmsg always a copy of
   4.465 -                                // src->shortmsg already?
   4.466 -                                // if so, we need to change the logic so
   4.467 -                                // that in this case, we don't free msg->shortmsg
   4.468 -                                // and do this strdup, etc.
   4.469 -                                shortmsg = strdup(src->shortmsg);
   4.470 -                            }
   4.471 +
   4.472 +                if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0)
   4.473 +                {
   4.474 +                    char * shortmsg;
   4.475 +                    char * longmsg;
   4.476 +
   4.477 +                    int r = separate_short_and_long(msg->longmsg, &shortmsg,
   4.478 +                            &longmsg);
   4.479 +                    
   4.480 +                    if (r == -1)
   4.481 +                        goto enomem;
   4.482 +
   4.483 +                    if (shortmsg == NULL) {
   4.484 +                        if (src->shortmsg == NULL)
   4.485 +                            shortmsg = strdup("");
   4.486 +                        else {
   4.487 +                            // FIXME: is msg->shortmsg always a copy of
   4.488 +                            // src->shortmsg already?
   4.489 +                            // if so, we need to change the logic so
   4.490 +                            // that in this case, we don't free msg->shortmsg
   4.491 +                            // and do this strdup, etc.
   4.492 +                            shortmsg = strdup(src->shortmsg);
   4.493                          }
   4.494 -
   4.495 -
   4.496 -                        free(msg->shortmsg);
   4.497 -                        free(msg->longmsg);
   4.498 -
   4.499 -                        msg->shortmsg = shortmsg;
   4.500 -                        msg->longmsg = longmsg;
   4.501                      }
   4.502 -                    else {
   4.503 -                        msg->shortmsg = strdup(src->shortmsg);
   4.504 -                        assert(msg->shortmsg);
   4.505 -                        if (msg->shortmsg == NULL)
   4.506 -                            goto enomem;
   4.507 -                    }
   4.508 +
   4.509 +
   4.510 +                    free(msg->shortmsg);
   4.511 +                    free(msg->longmsg);
   4.512 +
   4.513 +                    msg->shortmsg = shortmsg;
   4.514 +                    msg->longmsg = longmsg;
   4.515 +                }
   4.516 +                else {
   4.517 +                    msg->shortmsg = strdup(src->shortmsg);
   4.518 +                    assert(msg->shortmsg);
   4.519 +                    if (msg->shortmsg == NULL)
   4.520 +                        goto enomem;
   4.521                  }
   4.522                  break;
   4.523              default:
   4.524 @@ -2309,10 +2093,6 @@
   4.525          *flags |= PEP_decrypt_flag_own_private_key;
   4.526      }
   4.527  
   4.528 -    // FIXME: To here, we're ok with the separate messages. We need to
   4.529 -    //        specify what clients expect when this is a 2.0 message.
   4.530 -    //        IMHO, we don't need the keylist at that point, just 
   4.531 -    //        the rating and move on.
   4.532      if (msg) {
   4.533          decorate_message(msg, *rating, _keylist);
   4.534          if (imported_keys)
   4.535 @@ -2343,12 +2123,7 @@
   4.536          }
   4.537      }
   4.538  
   4.539 -    if (inner_message)
   4.540 -        *dst = inner_message;
   4.541 -    else
   4.542 -        *dst = msg;
   4.543 -        
   4.544 -    // I think we keep it this way for 2.0 inner messages.
   4.545 +    *dst = msg;
   4.546      *keylist = _keylist;
   4.547  
   4.548      if(decrypt_status == PEP_DECRYPTED_AND_VERIFIED)
   4.549 @@ -2361,8 +2136,6 @@
   4.550  
   4.551  pep_error:
   4.552      free(ptext);
   4.553 -    if (inner_message) // necessary? FIXME: check
   4.554 -        free_message(inner_message);
   4.555      free_message(msg);
   4.556      free_stringlist(_keylist);
   4.557  
     5.1 --- a/src/message_api.h	Tue Sep 05 18:46:05 2017 +0200
     5.2 +++ b/src/message_api.h	Wed Sep 06 01:48:08 2017 +0200
     5.3 @@ -33,11 +33,7 @@
     5.4      // This flag is for special use cases and should not be used
     5.5      // by normal pEp clients!
     5.6      PEP_encrypt_flag_force_unsigned = 0x2,
     5.7 -    PEP_encrypt_flag_force_no_attached_key = 0x4,
     5.8 -    
     5.9 -    // This flag is for when we start wrapping messages in multiple different 
    5.10 -    // sender layers
    5.11 -    PEP_encrypt_flag_dont_raise_headers = 0x8
    5.12 +    PEP_encrypt_flag_force_no_attached_key = 0x4
    5.13  } PEP_encrypt_flags; 
    5.14  
    5.15  typedef unsigned int PEP_encrypt_flags_t;
     6.1 --- a/src/mime.c	Tue Sep 05 18:46:05 2017 +0200
     6.2 +++ b/src/mime.c	Wed Sep 06 01:48:08 2017 +0200
     6.3 @@ -696,13 +696,17 @@
     6.4      assert(msg);
     6.5      assert(result);
     6.6  
     6.7 -    message* duped_msg = message_dup(msg);
     6.8 +    bloblist_t* inlined_attachments = NULL;
     6.9 +    bloblist_t* normal_attachments = NULL;
    6.10  
    6.11 -    if (!duped_msg) {
    6.12 -        status = PEP_OUT_OF_MEMORY;
    6.13 -        goto pep_error;
    6.14 +    if (msg->attachments) {
    6.15 +        normal_attachments = bloblist_dup(msg->attachments);
    6.16 +        if (!normal_attachments) {
    6.17 +            status = PEP_OUT_OF_MEMORY;
    6.18 +            goto pep_error;
    6.19 +        }
    6.20      }
    6.21 -
    6.22 +    
    6.23      //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
    6.24      plaintext = (msg->longmsg) ? msg->longmsg : "";
    6.25      htmltext = msg->longmsg_formatted;
    6.26 @@ -711,10 +715,8 @@
    6.27          /* first, we need to strip out the inlined attachments to ensure this
    6.28             gets set up correctly */
    6.29          
    6.30 -        bloblist_t* inlined_attachments = NULL;
    6.31 -        /* Noooooo... dirk, why do you do this to me? */
    6.32 -                
    6.33 -        split_inlined_and_attached(&inlined_attachments, &duped_msg->attachments);
    6.34 +        /* Noooooo... dirk, why do you do this to me? */                
    6.35 +        split_inlined_and_attached(&inlined_attachments, &normal_attachments);
    6.36  
    6.37          status = mime_html_text(plaintext, htmltext, inlined_attachments, &mime);
    6.38                  
    6.39 @@ -740,7 +742,7 @@
    6.40              goto enomem;
    6.41      }
    6.42  
    6.43 -    if (duped_msg->attachments) {
    6.44 +    if (normal_attachments) {
    6.45          submime = mime;
    6.46          mime = part_multiple_new("multipart/mixed");
    6.47          assert(mime);
    6.48 @@ -758,8 +760,13 @@
    6.49          }
    6.50  
    6.51          bloblist_t *_a;
    6.52 -        for (_a = duped_msg->attachments; _a != NULL; _a = _a->next) {
    6.53 +        for (_a = normal_attachments; _a != NULL; _a = _a->next) {
    6.54  
    6.55 +            // FIXME: As far as I can tell, mime_attachment takes ownership of
    6.56 +            // _a->value, so the shell of this bloblist_t is now lost memory.
    6.57 +            // not a problem if we can free the whole message later, but
    6.58 +            // this solution is bad. Need to make a more fundamental message
    6.59 +            // change somewhere, I guess.
    6.60              status = mime_attachment(_a, &submime);
    6.61              if (status != PEP_STATUS_OK)
    6.62                  goto pep_error;
    6.63 @@ -776,10 +783,6 @@
    6.64          }
    6.65      }
    6.66  
    6.67 -
    6.68 -
    6.69 -    if (duped_msg)
    6.70 -        free_message(duped_msg);
    6.71      *result = mime;
    6.72      return PEP_STATUS_OK;
    6.73  
    6.74 @@ -793,8 +796,11 @@
    6.75      if (submime)
    6.76          mailmime_free(submime);
    6.77  
    6.78 -    if (duped_msg)
    6.79 -        free_message(duped_msg);
    6.80 +    if (inlined_attachments)
    6.81 +        free_bloblist(inlined_attachments);
    6.82 +
    6.83 +    if (normal_attachments)
    6.84 +        free_bloblist(normal_attachments);
    6.85  
    6.86      return status;
    6.87  }
     7.1 --- a/test/revoke_regen_attach_test.cc	Tue Sep 05 18:46:05 2017 +0200
     7.2 +++ b/test/revoke_regen_attach_test.cc	Wed Sep 06 01:48:08 2017 +0200
     7.3 @@ -60,8 +60,7 @@
     7.4      cout << "encrypting message as MIME multipart…\n";
     7.5      message *enc_msg;
     7.6      cout << "calling encrypt_message()\n";
     7.7 -    // We need to keep this as a message 1.0 msg in order to see the attachments
     7.8 -    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME, PEP_encrypt_flag_dont_raise_headers);
     7.9 +    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME, 0);
    7.10      cout << status;
    7.11      assert(status == PEP_STATUS_OK);
    7.12      assert(enc_msg);