src/message_api.c
branchENGINE-214
changeset 2078 12571364b016
parent 2048 4612060c1d49
child 2092 926e2e53967d
     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)