ENGINE-74: first successful version. ENGINE-74
authorKrista Grothoff <krista@pep-project.org>
Wed, 23 Nov 2016 15:37:45 +0100
branchENGINE-74
changeset 142772c2539b14e7
parent 1426 7a1d5065841b
child 1428 aefb57561f8e
ENGINE-74: first successful version.
src/message_api.c
src/pgp_gpg.c
     1.1 --- a/src/message_api.c	Thu Nov 17 13:10:26 2016 +0100
     1.2 +++ b/src/message_api.c	Wed Nov 23 15:37:45 2016 +0100
     1.3 @@ -44,7 +44,7 @@
     1.4  static bool is_fileending(const bloblist_t *bl, const char *fe)
     1.5  {
     1.6      assert(fe);
     1.7 -    
     1.8 +
     1.9      if (bl == NULL || bl->filename == NULL || fe == NULL)
    1.10          return false;
    1.11  
    1.12 @@ -99,7 +99,7 @@
    1.13              return result;
    1.14          }
    1.15      }
    1.16 -        
    1.17 +
    1.18      if (longmsg == NULL)
    1.19          longmsg = "";
    1.20  
    1.21 @@ -130,7 +130,7 @@
    1.22      assert(src);
    1.23      assert(shortmsg);
    1.24      assert(longmsg);
    1.25 -    
    1.26 +
    1.27      if (src == NULL || shortmsg == NULL || longmsg == NULL)
    1.28          return -1;
    1.29  
    1.30 @@ -385,7 +385,7 @@
    1.31      assert(status == PEP_STATUS_OK);
    1.32      if (status != PEP_STATUS_OK)
    1.33          goto pep_error;
    1.34 -    
    1.35 +
    1.36      if (free_ptext){
    1.37          free(ptext);
    1.38          free_ptext=0;
    1.39 @@ -652,7 +652,7 @@
    1.40      assert(msg);
    1.41  
    1.42      add_opt_field(msg, "X-pEp-Version", PEP_VERSION);
    1.43 -    
    1.44 +
    1.45      if (rating != PEP_rating_undefined)
    1.46          add_opt_field(msg, "X-EncStatus", rating_to_string(rating));
    1.47  
    1.48 @@ -667,16 +667,16 @@
    1.49  {
    1.50      if (ct == PEP_ct_unknown)
    1.51          return PEP_rating_undefined;
    1.52 -    
    1.53 +
    1.54      else if (ct == PEP_ct_key_not_found)
    1.55          return PEP_rating_have_no_key;
    1.56 -        
    1.57 +
    1.58      else if (ct == PEP_ct_compromized)
    1.59          return PEP_rating_under_attack;
    1.60  
    1.61      else if (ct == PEP_ct_mistrusted)
    1.62          return PEP_rating_mistrust;
    1.63 -    
    1.64 +
    1.65      if (rating == PEP_rating_unencrypted_for_some)
    1.66          return PEP_rating_unencrypted_for_some;
    1.67  
    1.68 @@ -712,7 +712,7 @@
    1.69  
    1.70      if (blob == NULL || blob->filename == NULL)
    1.71          return false;
    1.72 -    
    1.73 +
    1.74      ext = strrchr(blob->filename, '.');
    1.75      if (ext == NULL)
    1.76          return false;
    1.77 @@ -751,7 +751,7 @@
    1.78      assert(filename);
    1.79      if (filename == NULL)
    1.80          return NULL;
    1.81 -    
    1.82 +
    1.83      char *ext = strrchr(filename, '.');
    1.84      if (ext == NULL)
    1.85          return NULL;
    1.86 @@ -794,7 +794,7 @@
    1.87  
    1.88      assert(session);
    1.89      assert(fpr);
    1.90 -    
    1.91 +
    1.92      if (session == NULL || fpr == NULL)
    1.93          return PEP_rating_undefined;
    1.94  
    1.95 @@ -857,7 +857,7 @@
    1.96  
    1.97      if (max_comm_type == PEP_ct_compromized)
    1.98          return PEP_ct_compromized;
    1.99 -    
   1.100 +
   1.101      if (max_comm_type == PEP_ct_mistrusted)
   1.102          return PEP_ct_mistrusted;
   1.103  
   1.104 @@ -894,7 +894,7 @@
   1.105                is_mime_type(bl, "application/octet-stream")) &&
   1.106               (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
   1.107                      is_fileending(bl, ".key") || is_fileending(bl, ".asc"))) ||
   1.108 -            // explicit mime type 
   1.109 +            // explicit mime type
   1.110              is_mime_type(bl, "application/pgp-keys") ||
   1.111              // as text, by file name
   1.112              (is_mime_type(bl, "text/plain") &&
   1.113 @@ -928,14 +928,14 @@
   1.114  }
   1.115  
   1.116  bool import_attached_keys(
   1.117 -        PEP_SESSION session, 
   1.118 +        PEP_SESSION session,
   1.119          const message *msg,
   1.120          identity_list **private_idents
   1.121      )
   1.122  {
   1.123      assert(session);
   1.124      assert(msg);
   1.125 -    
   1.126 +
   1.127      if (session == NULL || msg == NULL)
   1.128          return false;
   1.129  
   1.130 @@ -944,10 +944,10 @@
   1.131      bloblist_t *bl;
   1.132      int i = 0;
   1.133      for (bl = msg->attachments; i < MAX_KEYS_TO_IMPORT && bl && bl->value;
   1.134 -            bl = bl->next, i++) 
   1.135 +            bl = bl->next, i++)
   1.136      {
   1.137          if (bl && bl->value && bl->size && bl->size < MAX_KEY_SIZE
   1.138 -                && is_key(bl)) 
   1.139 +                && is_key(bl))
   1.140          {
   1.141              import_key(session, bl->value, bl->size, private_idents);
   1.142              remove = true;
   1.143 @@ -968,10 +968,10 @@
   1.144      if (status != PEP_STATUS_OK)
   1.145          return status;
   1.146      assert(size);
   1.147 -    
   1.148 +
   1.149      bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
   1.150                        "pEpkey.asc");
   1.151 -    
   1.152 +
   1.153      if (msg->attachments == NULL && bl)
   1.154          msg->attachments = bl;
   1.155  
   1.156 @@ -984,7 +984,7 @@
   1.157  {
   1.158      assert(session);
   1.159      assert(msg);
   1.160 -    
   1.161 +
   1.162      if (msg->dir == PEP_dir_incoming)
   1.163          return;
   1.164  
   1.165 @@ -994,16 +994,16 @@
   1.166  
   1.167      if(_attach_key(session, msg->from->fpr, msg) != PEP_STATUS_OK)
   1.168          return;
   1.169 -    
   1.170 +
   1.171      char *revoked_fpr = NULL;
   1.172      uint64_t revocation_date = 0;
   1.173 -    
   1.174 +
   1.175      if(get_revoked(session, msg->from->fpr,
   1.176                     &revoked_fpr, &revocation_date) == PEP_STATUS_OK &&
   1.177         revoked_fpr != NULL)
   1.178      {
   1.179          time_t now = time(NULL);
   1.180 -        
   1.181 +
   1.182          if (now < (time_t)revocation_date + ONE_WEEK)
   1.183          {
   1.184              _attach_key(session, revoked_fpr, msg);
   1.185 @@ -1015,7 +1015,7 @@
   1.186  PEP_cryptotech determine_encryption_format(message *msg)
   1.187  {
   1.188      assert(msg);
   1.189 -    
   1.190 +
   1.191      if (is_PGP_message_text(msg->longmsg)) {
   1.192          msg->enc_format = PEP_enc_pieces;
   1.193          return PEP_crypt_OpenPGP;
   1.194 @@ -1056,7 +1056,7 @@
   1.195  
   1.196      if (src->dir == PEP_dir_incoming)
   1.197          return PEP_ILLEGAL_VALUE;
   1.198 -    
   1.199 +
   1.200      determine_encryption_format(src);
   1.201      if (src->enc_format != PEP_enc_none)
   1.202          return PEP_ILLEGAL_VALUE;
   1.203 @@ -1083,25 +1083,25 @@
   1.204      PEP_comm_type max_comm_type = PEP_ct_pEp;
   1.205  
   1.206      identity_list * _il;
   1.207 -    
   1.208 +
   1.209      if ((_il = src->bcc) && _il->ident)
   1.210      {
   1.211          // BCC limited support:
   1.212          //     - App splits mails with BCC in multiple mails.
   1.213          //     - Each email is encrypted separately
   1.214 -        
   1.215 +
   1.216          if(_il->next || (src->to && src->to->ident) || (src->cc && src->cc->ident))
   1.217          {
   1.218              // Only one Bcc with no other recipient allowed for now
   1.219              return PEP_ILLEGAL_VALUE;
   1.220          }
   1.221 -        
   1.222 +
   1.223          PEP_STATUS _status = update_identity(session, _il->ident);
   1.224          if (_status != PEP_STATUS_OK) {
   1.225              status = _status;
   1.226              goto pep_error;
   1.227          }
   1.228 -        
   1.229 +
   1.230          if (_il->ident->fpr && _il->ident->fpr[0]) {
   1.231              _k = stringlist_add(_k, _il->ident->fpr);
   1.232              if (_k == NULL)
   1.233 @@ -1112,7 +1112,7 @@
   1.234          else {
   1.235              dest_keys_found = false;
   1.236              status = PEP_KEY_NOT_FOUND;
   1.237 -        }        
   1.238 +        }
   1.239      }
   1.240      else
   1.241      {
   1.242 @@ -1157,7 +1157,7 @@
   1.243              }
   1.244          }
   1.245      }
   1.246 -    
   1.247 +
   1.248      if (!dest_keys_found ||
   1.249          stringlist_length(keys) == 0 ||
   1.250          _rating(max_comm_type,
   1.251 @@ -1194,10 +1194,10 @@
   1.252              status = PEP_ILLEGAL_VALUE;
   1.253              goto pep_error;
   1.254          }
   1.255 -        
   1.256 +
   1.257          if (status == PEP_OUT_OF_MEMORY)
   1.258              goto enomem;
   1.259 -        
   1.260 +
   1.261          if (status != PEP_STATUS_OK)
   1.262              goto pep_error;
   1.263      }
   1.264 @@ -1249,7 +1249,7 @@
   1.265  
   1.266      if (src->dir == PEP_dir_incoming)
   1.267          return PEP_ILLEGAL_VALUE;
   1.268 -    
   1.269 +
   1.270      determine_encryption_format(src);
   1.271      if (src->enc_format != PEP_enc_none)
   1.272          return PEP_ILLEGAL_VALUE;
   1.273 @@ -1260,7 +1260,7 @@
   1.274  
   1.275      *dst = NULL;
   1.276  
   1.277 -    
   1.278 +
   1.279      PEP_STATUS _status = update_identity(session, target_id);
   1.280      if (_status != PEP_STATUS_OK) {
   1.281          status = _status;
   1.282 @@ -1270,10 +1270,10 @@
   1.283      char* target_fpr = target_id->fpr;
   1.284      if (!target_fpr)
   1.285          return PEP_KEY_NOT_FOUND; // FIXME: Error condition
   1.286 -        
   1.287 +
   1.288      keys = new_stringlist(target_fpr);
   1.289  
   1.290 -    
   1.291 +
   1.292      msg = clone_to_empty_message(src);
   1.293      if (msg == NULL)
   1.294          goto enomem;
   1.295 @@ -1297,10 +1297,10 @@
   1.296              status = PEP_ILLEGAL_VALUE;
   1.297              goto pep_error;
   1.298      }
   1.299 -        
   1.300 +
   1.301      if (status == PEP_OUT_OF_MEMORY)
   1.302          goto enomem;
   1.303 -    
   1.304 +
   1.305      if (status != PEP_STATUS_OK)
   1.306          goto pep_error;
   1.307  
   1.308 @@ -1360,18 +1360,75 @@
   1.309  
   1.310  PEP_STATUS _get_detached_signature(message* msg, bloblist_t** signature_blob) {
   1.311      bloblist_t* attach_curr = msg->attachments;
   1.312 -    
   1.313 +
   1.314 +    *signature_blob = NULL;
   1.315 +
   1.316      while (attach_curr) {
   1.317 -        if (strcasecmp(attach_curr->mime_type, "application/pgp-signature")) {
   1.318 -            // TODO: deal with filenames. Is that sending-client-specific?
   1.319 -            // In any event, presume the first one signs the plaintext. Hopefully
   1.320 -            // that's sufficient?
   1.321 +        if (strcasecmp(attach_curr->mime_type, "application/pgp-signature") == 0) {
   1.322              *signature_blob = attach_curr;
   1.323              break;
   1.324          }
   1.325          attach_curr = attach_curr->next;
   1.326      }
   1.327 -    
   1.328 +
   1.329 +    return PEP_STATUS_OK;
   1.330 +}
   1.331 +
   1.332 +PEP_STATUS _get_signed_text(const char* ptext, const size_t psize,
   1.333 +                            char** stext, size_t* ssize) {
   1.334 +
   1.335 +    char* signed_boundary = NULL;
   1.336 +    char* signpost = strstr(ptext, "Content-Type: multipart/signed");
   1.337 +
   1.338 +    *ssize = 0;
   1.339 +    *stext = NULL;
   1.340 +
   1.341 +    if (!signpost)
   1.342 +        return PEP_UNKNOWN_ERROR;
   1.343 +
   1.344 +    char* curr_line = signpost;
   1.345 +//    const char* end_text = ptext + psize;
   1.346 +    const char* boundary_key = "boundary=\"";
   1.347 +    const size_t BOUNDARY_KEY_SIZE = 10;
   1.348 +
   1.349 +    char* start_boundary = strstr(curr_line, boundary_key);
   1.350 +    if (!start_boundary)
   1.351 +        return PEP_UNKNOWN_ERROR;
   1.352 +
   1.353 +    start_boundary += BOUNDARY_KEY_SIZE;
   1.354 +
   1.355 +    char* end_boundary = strstr(start_boundary, "\"");
   1.356 +
   1.357 +    if (!end_boundary)
   1.358 +        return PEP_UNKNOWN_ERROR;
   1.359 +
   1.360 +    size_t boundary_strlen = (end_boundary - start_boundary) + 2;
   1.361 +
   1.362 +    signed_boundary = calloc(1, boundary_strlen + 1);
   1.363 +    strlcpy(signed_boundary, "--", boundary_strlen + 1);
   1.364 +    strlcat(signed_boundary, start_boundary, boundary_strlen + 1);
   1.365 +
   1.366 +    start_boundary = strstr(end_boundary, signed_boundary);
   1.367 +
   1.368 +    if (!start_boundary)
   1.369 +        return PEP_UNKNOWN_ERROR;
   1.370 +
   1.371 +    start_boundary += boundary_strlen;
   1.372 +
   1.373 +    while (*start_boundary == '\n')
   1.374 +        start_boundary++;
   1.375 +
   1.376 +    end_boundary = strstr(start_boundary + boundary_strlen, signed_boundary);
   1.377 +
   1.378 +    if (!end_boundary)
   1.379 +        return PEP_UNKNOWN_ERROR;
   1.380 +
   1.381 +    end_boundary--; // See RFC3156 section 5...
   1.382 +
   1.383 +    *ssize = end_boundary - start_boundary;
   1.384 +    *stext = start_boundary;
   1.385 +    free(signed_boundary);
   1.386 +
   1.387      return PEP_STATUS_OK;
   1.388  }
   1.389  
   1.390 @@ -1381,7 +1438,7 @@
   1.391          message **dst,
   1.392          stringlist_t **keylist,
   1.393          PEP_rating *rating,
   1.394 -        PEP_decrypt_flags_t *flags, 
   1.395 +        PEP_decrypt_flags_t *flags,
   1.396          identity_list **private_il
   1.397      )
   1.398  {
   1.399 @@ -1418,8 +1475,8 @@
   1.400      // IF longmsg and longmsg_formatted are empty, we MAY have an encrypted body
   1.401      // that's an attachment instead.
   1.402      // Check for encryption stuck in the first 2 attachments instead of the body
   1.403 -    // (This is currently based on AppleMail and a couple of other things
   1.404 -    //  which were broken for us - we may find a more general case to deal with)
   1.405 +    // (RFC3156)
   1.406 +    //
   1.407      if (!src->longmsg && !src->longmsg_formatted) {
   1.408          bloblist_t* attached_head = src->attachments;
   1.409          if (attached_head && strcasecmp(attached_head->mime_type, "application/pgp-encrypted")) {
   1.410 @@ -1429,12 +1486,12 @@
   1.411                  char* newlongmsg = calloc(1, enc_att_len + 1);
   1.412                  if (newlongmsg == NULL)
   1.413                      goto enomem;
   1.414 -                
   1.415 +
   1.416                  memcpy(newlongmsg, enc_att_txt, enc_att_len);
   1.417                  newlongmsg[enc_att_len] = '\0';
   1.418 -                
   1.419 +
   1.420                  src->longmsg = newlongmsg;
   1.421 -                
   1.422 +
   1.423                  // delete attachments here
   1.424                  src->attachments = enc_att_txt->next;
   1.425                  consume_bloblist_head(attached_head);
   1.426 @@ -1442,7 +1499,7 @@
   1.427              }
   1.428          }
   1.429      }
   1.430 -    
   1.431 +
   1.432      // Get detached signature, if any
   1.433      bloblist_t* detached_sig = NULL;
   1.434      char* dsig_text = NULL;
   1.435 @@ -1452,13 +1509,13 @@
   1.436          dsig_text = detached_sig->value;
   1.437          dsig_size = detached_sig->size;
   1.438      }
   1.439 -    
   1.440 +
   1.441      PEP_cryptotech crypto = determine_encryption_format(src);
   1.442  
   1.443      *dst = NULL;
   1.444      *keylist = NULL;
   1.445      *rating = PEP_rating_undefined;
   1.446 - 
   1.447 +
   1.448      switch (src->enc_format) {
   1.449          case PEP_enc_none:
   1.450              *rating = PEP_rating_unencrypted;
   1.451 @@ -1466,7 +1523,7 @@
   1.452                  remove_attached_keys(src);
   1.453              if(session->inject_sync_msg){
   1.454                  status = receive_DeviceState_msg(session, src, *rating, *keylist);
   1.455 -                if (status == PEP_MESSAGE_CONSUME || 
   1.456 +                if (status == PEP_MESSAGE_CONSUME ||
   1.457                      status == PEP_MESSAGE_IGNORE) {
   1.458                      free_message(msg);
   1.459                      msg = NULL;
   1.460 @@ -1494,7 +1551,7 @@
   1.461              NOT_IMPLEMENTED
   1.462      }
   1.463      status = cryptotech[crypto].decrypt_and_verify(session, ctext,
   1.464 -                                                   csize, dsig_text, dsig_size, 
   1.465 +                                                   csize, dsig_text, dsig_size,
   1.466                                                     &ptext, &psize, &_keylist);
   1.467      if (status > PEP_CANNOT_DECRYPT_UNKNOWN){
   1.468          goto pep_error;
   1.469 @@ -1510,7 +1567,7 @@
   1.470          }
   1.471      }
   1.472  
   1.473 -    bool imported_private_key_address = false; 
   1.474 +    bool imported_private_key_address = false;
   1.475  
   1.476      if (ptext) {
   1.477          switch (src->enc_format) {
   1.478 @@ -1518,6 +1575,26 @@
   1.479                  status = mime_decode_message(ptext, psize, &msg);
   1.480                  if (status != PEP_STATUS_OK)
   1.481                      goto pep_error;
   1.482 +                status = _get_detached_signature(msg, &detached_sig);
   1.483 +                if (decrypt_status == PEP_DECRYPTED && detached_sig) {
   1.484 +                    dsig_text = detached_sig->value;
   1.485 +                    dsig_size = detached_sig->size;
   1.486 +                    size_t ssize = 0;
   1.487 +                    char* stext = NULL;
   1.488 +
   1.489 +                    status = _get_signed_text(ptext, psize, &stext, &ssize);
   1.490 +                    stringlist_t *_verify_keylist = NULL;
   1.491 +
   1.492 +                    if (ssize > 0 && stext) {
   1.493 +                        status = cryptotech[crypto].verify_text(session, stext,
   1.494 +                                                                ssize, dsig_text, dsig_size,
   1.495 +                                                                &_verify_keylist);
   1.496 +
   1.497 +                        if (status == PEP_VERIFIED || status == PEP_VERIFIED_AND_TRUSTED)
   1.498 +                            decrypt_status = PEP_DECRYPTED_AND_VERIFIED;
   1.499 +                    }
   1.500 +                }
   1.501 +
   1.502                  break;
   1.503  
   1.504              case PEP_enc_pieces:
   1.505 @@ -1609,7 +1686,7 @@
   1.506                  // BUG: must implement more
   1.507                  NOT_IMPLEMENTED
   1.508          }
   1.509 -        
   1.510 +
   1.511          switch (src->enc_format) {
   1.512              case PEP_enc_PGP_MIME:
   1.513              case PEP_enc_pieces:
   1.514 @@ -1645,11 +1722,11 @@
   1.515                  // BUG: must implement more
   1.516                  NOT_IMPLEMENTED
   1.517          }
   1.518 -       
   1.519 +
   1.520          // check for private key in decrypted message attachement while inporting
   1.521          identity_list *_private_il = NULL;
   1.522          imported_keys = import_attached_keys(session, msg, &_private_il);
   1.523 -        if (_private_il && 
   1.524 +        if (_private_il &&
   1.525              identity_list_length(_private_il) == 1 &&
   1.526              _private_il->ident->address)
   1.527          {
   1.528 @@ -1661,11 +1738,11 @@
   1.529          }else{
   1.530              free_identity_list(_private_il);
   1.531          }
   1.532 -         
   1.533 +
   1.534          if(decrypt_status == PEP_DECRYPTED){
   1.535  
   1.536              // TODO optimize if import_attached_keys didn't import any key
   1.537 -            
   1.538 +
   1.539              // In case message did decrypt, but no valid signature could be found
   1.540              // then retry decrypt+verify after importing key.
   1.541  
   1.542 @@ -1675,32 +1752,32 @@
   1.543              status = _update_identity_for_incoming_message(session, src);
   1.544              if(status != PEP_STATUS_OK)
   1.545                  goto pep_error;
   1.546 -            
   1.547 +
   1.548              char *re_ptext = NULL;
   1.549              size_t re_psize;
   1.550 -            
   1.551 +
   1.552              free_stringlist(_keylist);
   1.553              _keylist = NULL;
   1.554  
   1.555              status = cryptotech[crypto].decrypt_and_verify(session, ctext,
   1.556                  csize, dsig_text, dsig_size, &re_ptext, &re_psize, &_keylist);
   1.557 -            
   1.558 +
   1.559              free(re_ptext);
   1.560 -            
   1.561 +
   1.562              if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
   1.563                  goto pep_error;
   1.564 -            
   1.565 +
   1.566              decrypt_status = status;
   1.567          }
   1.568 -        
   1.569 +
   1.570          *rating = decrypt_rating(decrypt_status);
   1.571 -        
   1.572 +
   1.573          if (*rating > PEP_rating_mistrust) {
   1.574              PEP_rating kl_rating = PEP_rating_undefined;
   1.575 -            
   1.576 +
   1.577              if (_keylist)
   1.578                  kl_rating = keylist_rating(session, _keylist);
   1.579 -            
   1.580 +
   1.581              if (kl_rating <= PEP_rating_mistrust) {
   1.582                  *rating = kl_rating;
   1.583              }
   1.584 @@ -1738,13 +1815,13 @@
   1.585      }
   1.586  
   1.587      // Case of own key imported from own trusted message
   1.588 -    if (// Message have been reliably decrypted 
   1.589 +    if (// Message have been reliably decrypted
   1.590          msg &&
   1.591          *rating >= PEP_rating_trusted &&
   1.592          imported_private_key_address &&
   1.593          // to is [own]
   1.594          msg->to->ident->user_id &&
   1.595 -        strcmp(msg->to->ident->user_id, PEP_OWN_USERID) == 0 
   1.596 +        strcmp(msg->to->ident->user_id, PEP_OWN_USERID) == 0
   1.597          )
   1.598      {
   1.599          *flags |= PEP_decrypt_flag_own_private_key;
   1.600 @@ -1756,7 +1833,7 @@
   1.601              remove_attached_keys(msg);
   1.602          if (*rating >= PEP_rating_reliable && session->inject_sync_msg) {
   1.603              status = receive_DeviceState_msg(session, msg, *rating, _keylist);
   1.604 -            if (status == PEP_MESSAGE_CONSUME || 
   1.605 +            if (status == PEP_MESSAGE_CONSUME ||
   1.606                  status == PEP_MESSAGE_IGNORE) {
   1.607                  free_message(msg);
   1.608                  msg = NULL;
   1.609 @@ -1794,7 +1871,7 @@
   1.610          message **dst,
   1.611          stringlist_t **keylist,
   1.612          PEP_rating *rating,
   1.613 -        PEP_decrypt_flags_t *flags 
   1.614 +        PEP_decrypt_flags_t *flags
   1.615      )
   1.616  {
   1.617      return _decrypt_message( session, src, dst, keylist, rating, flags, NULL );
   1.618 @@ -1803,7 +1880,7 @@
   1.619  DYNAMIC_API PEP_STATUS own_message_private_key_details(
   1.620          PEP_SESSION session,
   1.621          message *msg,
   1.622 -        pEp_identity **ident 
   1.623 +        pEp_identity **ident
   1.624      )
   1.625  {
   1.626      assert(session);
   1.627 @@ -1813,10 +1890,10 @@
   1.628      if (!(session && msg && ident))
   1.629          return PEP_ILLEGAL_VALUE;
   1.630  
   1.631 -    message *dst = NULL; 
   1.632 +    message *dst = NULL;
   1.633      stringlist_t *keylist = NULL;
   1.634      PEP_rating rating;
   1.635 -    PEP_decrypt_flags_t flags; 
   1.636 +    PEP_decrypt_flags_t flags;
   1.637  
   1.638      *ident = NULL;
   1.639  
   1.640 @@ -1839,7 +1916,7 @@
   1.641  }
   1.642  
   1.643  static void _max_comm_type_from_identity_list(
   1.644 -        identity_list *identities, 
   1.645 +        identity_list *identities,
   1.646          PEP_SESSION session,
   1.647          PEP_comm_type *max_comm_type,
   1.648          bool *comm_type_determined
   1.649 @@ -1888,7 +1965,7 @@
   1.650  
   1.651      _max_comm_type_from_identity_list(msg->cc, session,
   1.652                                        &max_comm_type, &comm_type_determined);
   1.653 -        
   1.654 +
   1.655      _max_comm_type_from_identity_list(msg->bcc, session,
   1.656                                        &max_comm_type, &comm_type_determined);
   1.657  
   1.658 @@ -1968,46 +2045,46 @@
   1.659  static bool _is_valid_hex(const char* hexstr) {
   1.660      if (!hexstr)
   1.661          return false;
   1.662 -    
   1.663 +
   1.664      const char* curr = hexstr;
   1.665      char currchar;
   1.666 -    
   1.667 +
   1.668      for (currchar = *curr; currchar != '\0'; currchar = *(++curr)) {
   1.669          if ((currchar >= '0' && currchar <= '9') ||
   1.670              (currchar >= 'a' && currchar <= 'f') ||
   1.671 -            (currchar >= 'A' && currchar <= 'F')) 
   1.672 +            (currchar >= 'A' && currchar <= 'F'))
   1.673          {
   1.674              continue;
   1.675          }
   1.676          return false;
   1.677      }
   1.678 -    return true;        
   1.679 +    return true;
   1.680  }
   1.681  
   1.682  // Returns, in comparison: 1 if fpr1 > fpr2, 0 if equal, -1 if fpr1 < fpr2
   1.683  static PEP_STATUS _compare_fprs(const char* fpr1, const char* fpr2, int* comparison) {
   1.684 -    
   1.685 +
   1.686      const int _FULL_FINGERPRINT_LENGTH = 40;
   1.687      const int _ASCII_LOWERCASE_OFFSET = 32;
   1.688  
   1.689      size_t fpr1_len = strlen(fpr1);
   1.690      size_t fpr2_len = strlen(fpr2);
   1.691 -    
   1.692 +
   1.693      if (fpr1_len != _FULL_FINGERPRINT_LENGTH || fpr2_len != _FULL_FINGERPRINT_LENGTH)
   1.694          return PEP_TRUSTWORDS_FPR_WRONG_LENGTH;
   1.695 -    
   1.696 +
   1.697      if (!_is_valid_hex(fpr1) || !_is_valid_hex(fpr2))
   1.698          return PEP_ILLEGAL_VALUE;
   1.699 -    
   1.700 +
   1.701      const char* fpr1_curr = fpr1;
   1.702      const char* fpr2_curr = fpr2;
   1.703 -    
   1.704 +
   1.705      char current;
   1.706  
   1.707      // Advance past leading zeros.
   1.708      for (current = *fpr1_curr; current != '0' && current != '\0'; current = *(++fpr1_curr), fpr1_len--);
   1.709      for (current = *fpr2_curr; current != '0' && current != '\0'; current = *(++fpr2_curr), fpr2_len--);
   1.710 -    
   1.711 +
   1.712      if (fpr1_len == fpr2_len) {
   1.713          char digit1;
   1.714          char digit2;
   1.715 @@ -2021,7 +2098,7 @@
   1.716                  digit1 -= _ASCII_LOWERCASE_OFFSET;
   1.717              if (digit2 >= 'a' && digit2 <= 'f')
   1.718                  digit2 -= _ASCII_LOWERCASE_OFFSET;
   1.719 -                        
   1.720 +
   1.721              // We take advantage of the fact that 'a'-'f' are larger
   1.722              // integer values in the ASCII table than '0'-'9'.
   1.723              // This allows us to compare digits directly.
   1.724 @@ -2032,7 +2109,7 @@
   1.725                  *comparison = -1;
   1.726                  return PEP_STATUS_OK;
   1.727              }
   1.728 -            
   1.729 +
   1.730              // pointers already advanced above. Keep going.
   1.731          }
   1.732          *comparison = 0;
   1.733 @@ -2059,28 +2136,28 @@
   1.734      assert(id2->fpr);
   1.735      assert(words);
   1.736      assert(wsize);
   1.737 -    
   1.738 +
   1.739      if (!(session && id1 && id2 && words && wsize) ||
   1.740          !(id1->fpr) || (!id2->fpr))
   1.741          return PEP_ILLEGAL_VALUE;
   1.742 -    
   1.743 +
   1.744      const char *source1 = id1->fpr;
   1.745      const char *source2 = id2->fpr;
   1.746 -    
   1.747 +
   1.748      *words = NULL;
   1.749      *wsize = 0;
   1.750  
   1.751      const size_t SHORT_NUM_TWORDS = 5;
   1.752 -    
   1.753 +
   1.754      // N.B. THIS will have to be changed once we start checking trustword entropy.
   1.755      // For now, full is ALL, and otherwise it's 5-per-id.
   1.756      size_t max_words_per_id = (full ? 0 : SHORT_NUM_TWORDS);
   1.757 -    
   1.758 +
   1.759      char* first_set = NULL;
   1.760      char* second_set = NULL;
   1.761      size_t first_wsize = 0;
   1.762      size_t second_wsize = 0;
   1.763 -    
   1.764 +
   1.765      int fpr_comparison = -255;
   1.766      PEP_STATUS status = _compare_fprs(source1, source2, &fpr_comparison);
   1.767      if (status != PEP_STATUS_OK)
   1.768 @@ -2093,32 +2170,32 @@
   1.769              status = trustwords(session, source2, lang, &first_set, &first_wsize, max_words_per_id);
   1.770              if (status != PEP_STATUS_OK)
   1.771                  goto error_release;
   1.772 -            status = trustwords(session, source1, lang, &second_set, &second_wsize, max_words_per_id); 
   1.773 +            status = trustwords(session, source1, lang, &second_set, &second_wsize, max_words_per_id);
   1.774              if (status != PEP_STATUS_OK)
   1.775                  goto error_release;
   1.776              break;
   1.777 -        case 0: 
   1.778 +        case 0:
   1.779          case -1: // source1 <= source2
   1.780              status = trustwords(session, source1, lang, &first_set, &first_wsize, max_words_per_id);
   1.781              if (status != PEP_STATUS_OK)
   1.782                  goto error_release;
   1.783 -            status = trustwords(session, source2, lang, &second_set, &second_wsize, max_words_per_id); 
   1.784 +            status = trustwords(session, source2, lang, &second_set, &second_wsize, max_words_per_id);
   1.785              if (status != PEP_STATUS_OK)
   1.786                  goto error_release;
   1.787              break;
   1.788          default:
   1.789              return PEP_UNKNOWN_ERROR; // shouldn't be possible
   1.790      }
   1.791 -    
   1.792 +
   1.793      size_t _wsize = first_wsize + second_wsize;
   1.794 -    
   1.795 +
   1.796      bool needs_space = (first_set[first_wsize - 1] != ' ');
   1.797 -    
   1.798 +
   1.799      if (needs_space)
   1.800          _wsize++;
   1.801 -    
   1.802 +
   1.803      _retstr = calloc(1, _wsize + 1);
   1.804 -    
   1.805 +
   1.806      size_t len = strlcpy(_retstr, first_set, _wsize);
   1.807      if (len >= _wsize) {
   1.808          status = PEP_UNKNOWN_ERROR;
   1.809 @@ -2136,16 +2213,16 @@
   1.810          status = PEP_UNKNOWN_ERROR;
   1.811          goto error_release;
   1.812      }
   1.813 -    
   1.814 +
   1.815      *words = _retstr;
   1.816      *wsize = _wsize;
   1.817      status = PEP_STATUS_OK;
   1.818 -    
   1.819 +
   1.820      goto the_end;
   1.821 -    
   1.822 +
   1.823      error_release:
   1.824      free(_retstr);
   1.825 -    
   1.826 +
   1.827      the_end:
   1.828      free(first_set);
   1.829      free(second_set);
   1.830 @@ -2161,16 +2238,16 @@
   1.831      stringlist_t **keylist,
   1.832      PEP_rating *rating,
   1.833      PEP_decrypt_flags_t *flags
   1.834 -) 
   1.835 +)
   1.836  {
   1.837      PEP_STATUS status = PEP_STATUS_OK;
   1.838      message* tmp_msg = NULL;
   1.839      message* dec_msg = NULL;
   1.840 -    
   1.841 +
   1.842      status = mime_decode_message(mimetext, size, &tmp_msg);
   1.843      if (status != PEP_STATUS_OK)
   1.844          goto pep_error;
   1.845 -    
   1.846 +
   1.847      status = decrypt_message(session,
   1.848                               tmp_msg,
   1.849                               &dec_msg,
   1.850 @@ -2179,13 +2256,13 @@
   1.851                               flags);
   1.852      if (status != PEP_STATUS_OK)
   1.853          goto pep_error;
   1.854 -    
   1.855 +
   1.856      status = mime_encode_message(dec_msg, false, mime_plaintext);
   1.857 -    
   1.858 +
   1.859  pep_error:
   1.860      free_message(tmp_msg);
   1.861      free_message(dec_msg);
   1.862 -    
   1.863 +
   1.864      return status;
   1.865  }
   1.866  
   1.867 @@ -2197,16 +2274,16 @@
   1.868      char** mime_ciphertext,
   1.869      PEP_enc_format enc_format,
   1.870      PEP_encrypt_flags_t flags
   1.871 -) 
   1.872 +)
   1.873  {
   1.874      PEP_STATUS status = PEP_STATUS_OK;
   1.875      message* tmp_msg = NULL;
   1.876      message* enc_msg = NULL;
   1.877 -    
   1.878 +
   1.879      status = mime_decode_message(mimetext, size, &tmp_msg);
   1.880      if (status != PEP_STATUS_OK)
   1.881          goto pep_error;
   1.882 -    
   1.883 +
   1.884      // This isn't incoming, though... so we need to reverse the direction
   1.885      tmp_msg->dir = PEP_dir_outgoing;
   1.886      status = encrypt_message(session,
   1.887 @@ -2217,9 +2294,9 @@
   1.888                               flags);
   1.889      if (status != PEP_STATUS_OK)
   1.890          goto pep_error;
   1.891 -        
   1.892 +
   1.893      status = mime_encode_message(enc_msg, false, mime_ciphertext);
   1.894 -    
   1.895 +
   1.896  pep_error:
   1.897      free_message(tmp_msg);
   1.898      free_message(enc_msg);
   1.899 @@ -2227,5 +2304,3 @@
   1.900      return status;
   1.901  
   1.902  }
   1.903 -
   1.904 -
     2.1 --- a/src/pgp_gpg.c	Thu Nov 17 13:10:26 2016 +0100
     2.2 +++ b/src/pgp_gpg.c	Wed Nov 23 15:37:45 2016 +0100
     2.3 @@ -433,7 +433,7 @@
     2.4      switch (dt) {
     2.5      case GPGME_DATA_TYPE_PGP_SIGNED:
     2.6      case GPGME_DATA_TYPE_PGP_OTHER:
     2.7 - //   case GPGME_DATA_TYPE_PGP_ENCRYPTED:
     2.8 +    case GPGME_DATA_TYPE_PGP_ENCRYPTED:
     2.9          if (dsigtext) {
    2.10              gpgme_error = gpg.gpgme_op_decrypt(session->ctx, cipher, plain);
    2.11          }
    2.12 @@ -448,12 +448,6 @@
    2.13          switch (gpgme_error) {
    2.14              case GPG_ERR_NO_ERROR:
    2.15              {
    2.16 -                if (dsigtext) {
    2.17 -                    gpgme_data_t sigdata;
    2.18 -                    gpg.gpgme_data_new_from_mem(&sigdata, dsigtext,
    2.19 -                                                dsigsize, 0);
    2.20 -                    gpgme_op_verify(session->ctx, sigdata, plain, NULL);
    2.21 -                }
    2.22                  gpgme_verify_result_t gpgme_verify_result;
    2.23                  char *_buffer = NULL;
    2.24                  size_t reading;
    2.25 @@ -478,28 +472,29 @@
    2.26                  reading = gpg.gpgme_data_read(plain, _buffer, length);
    2.27                  assert(length == reading);
    2.28  
    2.29 -//                 if (dsigtext) {  // Is this safe to do?
    2.30 -//                     gpgme_data_t sigdata;
    2.31 -//                     gpg.gpgme_data_new_from_mem(&sigdata, dsigtext,
    2.32 -//                                                 dsigsize, 0);
    2.33 -//                     gpgme_op_verify(session->ctx, sigdata, plain, NULL);
    2.34 -//                 }
    2.35 +                if (dsigtext) {  // Is this safe to do?
    2.36 +                    gpgme_data_t sigdata;
    2.37 +                    // FIXME: replace with verify_text?
    2.38 +                    gpg.gpgme_data_new_from_mem(&sigdata, dsigtext,
    2.39 +                                                dsigsize, 0);
    2.40 +                    gpgme_op_verify(session->ctx, sigdata, plain, NULL);
    2.41 +                }
    2.42  
    2.43                  gpgme_verify_result =
    2.44                      gpg.gpgme_op_verify_result(session->ctx);
    2.45                  assert(gpgme_verify_result);
    2.46                  gpgme_signature = gpgme_verify_result->signatures;
    2.47  
    2.48 -//                 if (!gpgme_signature && dsigtext) {
    2.49 -//                     gpgme_data_t sigdata;
    2.50 -//                     gpg.gpgme_data_new_from_mem(&sigdata, dsigtext,
    2.51 -//                                                 dsigsize, 0);
    2.52 -//                     gpgme_op_verify(session->ctx, sigdata, plain, NULL);
    2.53 -//                     gpgme_verify_result =
    2.54 -//                         gpg.gpgme_op_verify_result(session->ctx);
    2.55 -//                     assert(gpgme_verify_result);
    2.56 -//                     gpgme_signature = gpgme_verify_result->signatures;
    2.57 -//                 }
    2.58 +                // if (!gpgme_signature && dsigtext) {
    2.59 +                //     gpgme_data_t sigdata;
    2.60 +                //     gpg.gpgme_data_new_from_mem(&sigdata, dsigtext,
    2.61 +                //                                 dsigsize, 0);
    2.62 +                //     gpgme_op_verify(session->ctx, sigdata, plain, NULL);
    2.63 +                //     gpgme_verify_result_t result2 =
    2.64 +                //         gpg.gpgme_op_verify_result(session->ctx);
    2.65 +                //     assert(result2);
    2.66 +                //     gpgme_signature = result2->signatures;
    2.67 +                // }
    2.68  
    2.69                  if (gpgme_signature) {
    2.70                      stringlist_t *k;
    2.71 @@ -514,6 +509,7 @@
    2.72                      k = _keylist;
    2.73  
    2.74                      result = PEP_DECRYPTED_AND_VERIFIED;
    2.75 +                    gpg.gpgme_check(NULL);
    2.76                      do {
    2.77                          switch (_GPGERR(gpgme_signature->status)) {
    2.78                          case GPG_ERR_NO_ERROR: