ENGINE-214: actually works, but will need to be changed due to need to encapsulate message version in protected part of message. Infrastructure to do that comes in with this commit, but we need to refactor _decrypt_message in order to do everything cleanly. Branching for ENGINE-262 and will return to this branch once done with refactor. ENGINE-214
authorKrista Bennett <krista@pep-project.org>
Tue, 19 Sep 2017 15:59:42 +0200
branchENGINE-214
changeset 207812571364b016
parent 2077 d6ea1827e4e3
child 2079 1e94912983c5
ENGINE-214: actually works, but will need to be changed due to need to encapsulate message version in protected part of message. Infrastructure to do that comes in with this commit, but we need to refactor _decrypt_message in order to do everything cleanly. Branching for ENGINE-262 and will return to this branch once done with refactor.
src/message_api.c
src/pEp_internal.h
     1.1 --- a/src/message_api.c	Tue Sep 19 12:38:55 2017 +0200
     1.2 +++ b/src/message_api.c	Tue Sep 19 15:59:42 2017 +0200
     1.3 @@ -100,6 +100,41 @@
     1.4      }
     1.5  }
     1.6  
     1.7 +static char * encapsulate_message_version(const char *msg_version, const char *longmsg)
     1.8 +{
     1.9 +    assert(msg_version);
    1.10 +    
    1.11 +    if (!msg_version) {
    1.12 +        if (!longmsg)
    1.13 +            return NULL;
    1.14 +        else {
    1.15 +            char *result = strdup(longmsg);
    1.16 +            assert(result);
    1.17 +            return result;            
    1.18 +        }    
    1.19 +    }
    1.20 +    
    1.21 +    if (longmsg == NULL)
    1.22 +        longmsg = "";
    1.23 +        
    1.24 +    const char * const newlines = "\n\n";
    1.25 +    const size_t NL_LEN = 2;
    1.26 +        
    1.27 +    const size_t bufsize = PEP_MSG_VERSION_KEY_LEN + strlen(msg_version) + NL_LEN + strlen(longmsg) + 1;
    1.28 +    char * ptext = calloc(1, bufsize);
    1.29 +    assert(ptext);
    1.30 +    if (ptext == NULL)
    1.31 +        return NULL;
    1.32 +
    1.33 +    strlcpy(ptext, PEP_MSG_VERSION_KEY, bufsize);
    1.34 +    strlcat(ptext, msg_version, bufsize);
    1.35 +    strlcat(ptext, newlines, bufsize);
    1.36 +    strlcat(ptext, longmsg, bufsize);
    1.37 +
    1.38 +    return ptext;
    1.39 +}
    1.40 +
    1.41 +
    1.42  static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
    1.43  {
    1.44      assert(shortmsg);
    1.45 @@ -122,18 +157,16 @@
    1.46      if (longmsg == NULL)
    1.47          longmsg = "";
    1.48  
    1.49 -    const char * const subject = "Subject: ";
    1.50 -    const size_t SUBJ_LEN = 9;
    1.51      const char * const newlines = "\n\n";
    1.52      const size_t NL_LEN = 2;
    1.53  
    1.54 -    const size_t bufsize = SUBJ_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
    1.55 +    const size_t bufsize = PEP_SUBJ_KEY_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
    1.56      char * ptext = calloc(1, bufsize);
    1.57      assert(ptext);
    1.58      if (ptext == NULL)
    1.59          return NULL;
    1.60  
    1.61 -    strlcpy(ptext, subject, bufsize);
    1.62 +    strlcpy(ptext, PEP_SUBJ_KEY, bufsize);
    1.63      strlcat(ptext, shortmsg, bufsize);
    1.64      strlcat(ptext, newlines, bufsize);
    1.65      strlcat(ptext, longmsg, bufsize);
    1.66 @@ -141,62 +174,106 @@
    1.67      return ptext;
    1.68  }
    1.69  
    1.70 -static int separate_short_and_long(const char *src, char **shortmsg, char **longmsg)
    1.71 +/* 
    1.72 +   WARNING: For the moment, this only works for the first line of decrypted
    1.73 +   plaintext because we don't need more. IF WE DO, THIS MUST BE EXPANDED, or
    1.74 +   we need a delineated section to parse separately
    1.75 +   
    1.76 +   Does case-insensitive compare of keys, so sending in a lower-cased
    1.77 +   string constant saves a bit of computation
    1.78 + */
    1.79 +static PEP_STATUS get_data_from_encapsulated_line(const char* plaintext, const char* key, 
    1.80 +                                                  const size_t keylen, char** data, 
    1.81 +                                                  char** modified_msg) {
    1.82 +    char* _data = NULL;
    1.83 +    char* _modified = NULL;
    1.84 +    
    1.85 +    if (strncasecmp(plaintext, key, keylen) == 0) {
    1.86 +        const char *line_end = strchr(plaintext, '\n');
    1.87 +
    1.88 +        if (line_end == NULL) {
    1.89 +            _data = strdup(plaintext + keylen);
    1.90 +            assert(_data);
    1.91 +            if (_data == NULL)
    1.92 +                return PEP_OUT_OF_MEMORY;
    1.93 +        }
    1.94 +        else {
    1.95 +            size_t n = line_end - plaintext;
    1.96 +
    1.97 +            if (*(line_end - 1) == '\r')
    1.98 +                _data = strndup(plaintext + keylen, n - (keylen + 1));
    1.99 +            else
   1.100 +                _data = strndup(plaintext + keylen, n - keylen);
   1.101 +            assert(_data);
   1.102 +            if (_data == NULL)
   1.103 +                return PEP_OUT_OF_MEMORY;
   1.104 +
   1.105 +            while (*(plaintext + n) && (*(plaintext + n) == '\n' || *(plaintext + n) == '\r'))
   1.106 +                ++n;
   1.107 +
   1.108 +            if (*(plaintext + n)) {
   1.109 +                _modified = strdup(plaintext + n);
   1.110 +                assert(_modified);
   1.111 +                if (_modified == NULL)
   1.112 +                    return PEP_OUT_OF_MEMORY;
   1.113 +            }
   1.114 +        }
   1.115 +    }
   1.116 +    *data = _data;
   1.117 +    *modified_msg = _modified;
   1.118 +    return PEP_STATUS_OK;
   1.119 +}
   1.120 +
   1.121 +
   1.122 +static int separate_short_and_long(const char *src, char **shortmsg, char** msg_version, char **longmsg)
   1.123  {
   1.124      char *_shortmsg = NULL;
   1.125 +    char *_msg_version = NULL;
   1.126      char *_longmsg = NULL;
   1.127  
   1.128      assert(src);
   1.129      assert(shortmsg);
   1.130 +    assert(msg_version);
   1.131      assert(longmsg);
   1.132  
   1.133 -    if (src == NULL || shortmsg == NULL || longmsg == NULL)
   1.134 +    if (src == NULL || shortmsg == NULL || msg_version == NULL || longmsg == NULL)
   1.135          return -1;
   1.136  
   1.137      *shortmsg = NULL;
   1.138      *longmsg = NULL;
   1.139 -
   1.140 -    if (strncasecmp(src, "subject: ", 9) == 0) {
   1.141 -        char *line_end = strchr(src, '\n');
   1.142 -
   1.143 -        if (line_end == NULL) {
   1.144 -            _shortmsg = strdup(src + 9);
   1.145 -            assert(_shortmsg);
   1.146 -            if (_shortmsg == NULL)
   1.147 -                goto enomem;
   1.148 -            // _longmsg = NULL;
   1.149 -        }
   1.150 -        else {
   1.151 -            size_t n = line_end - src;
   1.152 -
   1.153 -            if (*(line_end - 1) == '\r')
   1.154 -                _shortmsg = strndup(src + 9, n - 10);
   1.155 -            else
   1.156 -                _shortmsg = strndup(src + 9, n - 9);
   1.157 -            assert(_shortmsg);
   1.158 -            if (_shortmsg == NULL)
   1.159 -                goto enomem;
   1.160 -
   1.161 -            while (*(src + n) && (*(src + n) == '\n' || *(src + n) == '\r'))
   1.162 -                ++n;
   1.163 -
   1.164 -            if (*(src + n)) {
   1.165 -                _longmsg = strdup(src + n);
   1.166 -                assert(_longmsg);
   1.167 -                if (_longmsg == NULL)
   1.168 -                    goto enomem;
   1.169 -            }
   1.170 -        }
   1.171 -        *shortmsg = _shortmsg;
   1.172 +    *msg_version = NULL;
   1.173 +
   1.174 +    // We generated the input here. If we ever need more than one header value to be
   1.175 +    // encapsulated and hidden in the encrypted text, we will have to modify this.
   1.176 +    // As is, we're either doing this with a version 1.0 client, in which case
   1.177 +    // the only encapsulated header value is subject, or 2.0+, in which the
   1.178 +    // message version is the only encapsulated header value. If we need this
   1.179 +    // to be more complex, we're going to have to do something more elegant
   1.180 +    // and efficient.    
   1.181 +    PEP_STATUS status = get_data_from_encapsulated_line(src, PEP_SUBJ_KEY_LC, 
   1.182 +                                                        PEP_SUBJ_KEY_LEN, 
   1.183 +                                                        &_shortmsg, &_longmsg);
   1.184 +                                                        
   1.185 +    if (_shortmsg) {
   1.186 +        if (status == PEP_STATUS_OK)
   1.187 +            *shortmsg = _shortmsg;
   1.188 +        else
   1.189 +            goto enomem;
   1.190      }
   1.191      else {
   1.192 -        // If there's no "Subject: " and the shortmsg is
   1.193 -        // pEp (or anything else), then we shouldn't be replacing it.
   1.194 -        // Chances are that the message wasn't encrypted
   1.195 -        // using pEp and that the actually subject IS pEp. In any event,
   1.196 -        // erasing the subject line when we don't have one in the plaintext
   1.197 -        // isn't the right behaviour.
   1.198 -        // _shortmsg = strdup("");
   1.199 +        status = get_data_from_encapsulated_line(src, PEP_MSG_VERSION_KEY_LC, 
   1.200 +                                                 PEP_MSG_VERSION_KEY_LEN, 
   1.201 +                                                 &_msg_version, &_longmsg);
   1.202 +        if (_msg_version) {
   1.203 +            if (status == PEP_STATUS_OK)
   1.204 +                *msg_version = _msg_version;
   1.205 +            else
   1.206 +                goto enomem;
   1.207 +        }
   1.208 +    }
   1.209 +    
   1.210 +    // If there was no secret data hiding in the first line...
   1.211 +    if (!_shortmsg && !_msg_version) {
   1.212          _longmsg = strdup(src);
   1.213          assert(_longmsg);
   1.214          if (_longmsg == NULL)
   1.215 @@ -209,6 +286,7 @@
   1.216  
   1.217  enomem:
   1.218      free(_shortmsg);
   1.219 +    free(_msg_version);
   1.220      free(_longmsg);
   1.221  
   1.222      return -1;
   1.223 @@ -1985,8 +2063,8 @@
   1.224                  {
   1.225                      char * shortmsg;
   1.226                      char * longmsg;
   1.227 -
   1.228 -                    int r = separate_short_and_long(msg->longmsg, &shortmsg,
   1.229 +                    char * msg_version; // This is incorrect, but just here to get things compiling for the moment
   1.230 +                    int r = separate_short_and_long(msg->longmsg, &shortmsg, &msg_version,
   1.231                              &longmsg);
   1.232                      
   1.233                      if (r == -1)
     2.1 --- a/src/pEp_internal.h	Tue Sep 19 12:38:55 2017 +0200
     2.2 +++ b/src/pEp_internal.h	Tue Sep 19 15:59:42 2017 +0200
     2.3 @@ -37,6 +37,19 @@
     2.4  #define PEP_SUBJ_BYTELEN 5
     2.5  #endif
     2.6  
     2.7 +#ifndef PEP_SUBJ_KEY
     2.8 +#define PEP_SUBJ_KEY "Subject: "
     2.9 +#define PEP_SUBJ_KEY_LC "subject: "
    2.10 +#define PEP_SUBJ_KEY_LEN 9
    2.11 +#endif
    2.12 +
    2.13 +#ifndef PEP_MSG_VERSION_KEY
    2.14 +#define PEP_MSG_VERSION_KEY "pEp-Message-Version: "
    2.15 +#define PEP_MSG_VERSION_KEY_LC "pep-message-version: "
    2.16 +#define PEP_MSG_VERSION_KEY_LEN 21
    2.17 +#endif
    2.18 +
    2.19 +
    2.20  #include "platform.h"
    2.21  
    2.22  #ifdef WIN32