1.1 --- a/src/message_api.c Fri Feb 02 11:03:20 2018 +0100
1.2 +++ b/src/message_api.c Fri Feb 02 17:15:33 2018 +0100
1.3 @@ -1823,31 +1823,31 @@
1.4 return ADD_TO_LOG(status);
1.5 }
1.6
1.7 -static PEP_STATUS _update_identity_for_incoming_message(
1.8 - PEP_SESSION session,
1.9 - const message *src
1.10 - )
1.11 -{
1.12 - PEP_STATUS status;
1.13 -
1.14 - if (src->from && src->from->address) {
1.15 - if (!is_me(session, src->from))
1.16 - status = update_identity(session, src->from);
1.17 - else
1.18 - status = myself(session, src->from);
1.19 - if (status == PEP_STATUS_OK
1.20 - && is_a_pEpmessage(src)
1.21 - && src->from->comm_type >= PEP_ct_OpenPGP_unconfirmed
1.22 - && src->from->comm_type != PEP_ct_pEp_unconfirmed
1.23 - && src->from->comm_type != PEP_ct_pEp)
1.24 - {
1.25 - src->from->comm_type |= PEP_ct_pEp_unconfirmed;
1.26 - status = set_identity(session, src->from);
1.27 - }
1.28 - return status;
1.29 - }
1.30 - return PEP_ILLEGAL_VALUE;
1.31 -}
1.32 +// static PEP_STATUS _update_identity_for_incoming_message(
1.33 +// PEP_SESSION session,
1.34 +// const message *src
1.35 +// )
1.36 +// {
1.37 +// PEP_STATUS status;
1.38 +//
1.39 +// if (src->from && src->from->address) {
1.40 +// if (!is_me(session, src->from))
1.41 +// status = update_identity(session, src->from);
1.42 +// else
1.43 +// status = myself(session, src->from);
1.44 +// if (status == PEP_STATUS_OK
1.45 +// && is_a_pEpmessage(src)
1.46 +// && src->from->comm_type >= PEP_ct_OpenPGP_unconfirmed
1.47 +// && src->from->comm_type != PEP_ct_pEp_unconfirmed
1.48 +// && src->from->comm_type != PEP_ct_pEp)
1.49 +// {
1.50 +// src->from->comm_type |= PEP_ct_pEp_unconfirmed;
1.51 +// status = set_identity(session, src->from);
1.52 +// }
1.53 +// return status;
1.54 +// }
1.55 +// return PEP_ILLEGAL_VALUE;
1.56 +// }
1.57
1.58
1.59 static PEP_STATUS _get_detached_signature(message* msg,
1.60 @@ -2037,7 +2037,7 @@
1.61 }
1.62 else {
1.63 pEp_identity *_sender = new_identity(sender->address, fpr,
1.64 - sender->user_id, sender->username);
1.65 + sender->user_id, sender->username);
1.66 if (_sender == NULL)
1.67 return PEP_OUT_OF_MEMORY;
1.68
1.69 @@ -2426,6 +2426,58 @@
1.70 return status;
1.71 }
1.72
1.73 +static PEP_STATUS update_sender_to_pep_trust(
1.74 + PEP_SESSION session,
1.75 + pEp_identity* sender,
1.76 + stringlist_t* keylist)
1.77 +{
1.78 + assert(session);
1.79 + assert(sender);
1.80 + assert(keylist && !EMPTYSTR(keylist->value));
1.81 +
1.82 + if (!session || !sender || !keylist || EMPTYSTR(keylist->value))
1.83 + return PEP_ILLEGAL_VALUE;
1.84 +
1.85 + free(sender->fpr);
1.86 + sender->fpr = NULL;
1.87 +
1.88 + PEP_STATUS status =
1.89 + is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
1.90 +
1.91 + if (EMPTYSTR(sender->fpr) || strcmp(sender->fpr, keylist->value) != 0) {
1.92 + free(sender->fpr);
1.93 + sender->fpr = strdup(keylist->value);
1.94 + if (!sender->fpr)
1.95 + return PEP_OUT_OF_MEMORY;
1.96 + status = get_trust(session, sender);
1.97 +
1.98 + if (status == PEP_CANNOT_FIND_IDENTITY || sender->comm_type == PEP_ct_unknown) {
1.99 + PEP_comm_type ct = PEP_ct_unknown;
1.100 + status = get_key_rating(session, sender->fpr, &ct);
1.101 + if (status != PEP_STATUS_OK)
1.102 + return status;
1.103 +
1.104 + sender->comm_type = ct;
1.105 + }
1.106 + }
1.107 +
1.108 + // Could be done elegantly, but we do this explicitly here for readability.
1.109 + // This file's code is difficult enough to parse. But change at will.
1.110 + switch (sender->comm_type) {
1.111 + case PEP_ct_OpenPGP_unconfirmed:
1.112 + status = set_trust(session, sender->user_id, sender->fpr, PEP_ct_pEp_unconfirmed);
1.113 + break;
1.114 + case PEP_ct_OpenPGP:
1.115 + status = set_trust(session, sender->user_id, sender->fpr, PEP_ct_pEp);
1.116 + break;
1.117 + default:
1.118 + break;
1.119 + }
1.120 +
1.121 + return status;
1.122 +}
1.123 +
1.124 +
1.125 DYNAMIC_API PEP_STATUS _decrypt_message(
1.126 PEP_SESSION session,
1.127 message *src,
1.128 @@ -2456,36 +2508,58 @@
1.129 char *ptext = NULL;
1.130 size_t psize;
1.131 stringlist_t *_keylist = NULL;
1.132 + char* signer_fpr = NULL;
1.133 + bool is_pep_msg = is_a_pEpmessage(src);
1.134
1.135 *dst = NULL;
1.136 *keylist = NULL;
1.137 *rating = PEP_rating_undefined;
1.138
1.139 *flags = 0;
1.140 +
1.141 /*** End init ***/
1.142
1.143 + // Ok, before we do anything, if it's a pEp message, regardless of whether it's
1.144 + // encrypted or not, we set the sender as a pEp user. This has NOTHING to do
1.145 + // with the key.
1.146 + if (src->from && !(is_me(session, src->from))) {
1.147 + if (is_pep_msg) {
1.148 + pEp_identity* tmp_from = src->from;
1.149 +
1.150 + // Ensure there's a user id
1.151 + if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
1.152 + status = update_identity(session, tmp_from);
1.153 + if (status == PEP_CANNOT_FIND_IDENTITY) {
1.154 + tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
1.155 + if (!tmp_from->user_id)
1.156 + return PEP_OUT_OF_MEMORY;
1.157 + snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
1.158 + "TOFU_%s", tmp_from->address);
1.159 + status = PEP_STATUS_OK;
1.160 + }
1.161 + }
1.162 + if (status == PEP_STATUS_OK) {
1.163 + // Now set user as PEP (may also create an identity if none existed yet)
1.164 + status = set_as_pep_user(session, tmp_from);
1.165 + }
1.166 + }
1.167 + }
1.168 + // We really need key used in signing to do anything further on the pEp comm_type.
1.169 + // So we can't adjust the rating of the sender just yet.
1.170 +
1.171 /*** Begin Import any attached public keys and update identities accordingly ***/
1.172 -
1.173 // Private key in unencrypted mail are ignored -> NULL
1.174 bool imported_keys = import_attached_keys(session, src, NULL);
1.175
1.176 - // Update src->from in case we just imported a key
1.177 - // we would need to check signature
1.178 - status = _update_identity_for_incoming_message(session, src);
1.179 -
1.180 - if (status == PEP_ILLEGAL_VALUE && src->from && is_me(session, src->from)) {
1.181 - // the above function should fail if it's us.
1.182 - // We don't need to update, as any revocations or expirations
1.183 - // of our own key imported above, which are all that we
1.184 - // would care about for anything imported,
1.185 - // SHOULD get caught when they matter later.
1.186 - // (Private keys imported above are not stored in the trust DB)
1.187 - status = PEP_STATUS_OK;
1.188 - }
1.189 + // FIXME: is this really necessary here?
1.190 + if (!is_me(session, src->from))
1.191 + status = update_identity(session, src->from);
1.192 + else
1.193 + status = myself(session, src->from);
1.194
1.195 if (status != PEP_STATUS_OK)
1.196 return ADD_TO_LOG(status);
1.197 -
1.198 +
1.199 /*** End Import any attached public keys and update identities accordingly ***/
1.200
1.201 /*** Begin get detached signatures that are attached to the encrypted message ***/
1.202 @@ -2519,7 +2593,7 @@
1.203 status = get_crypto_text(src, &ctext, &csize);
1.204 if (status != PEP_STATUS_OK)
1.205 return status;
1.206 -
1.207 +
1.208 /** Ok, we should be ready to decrypt. Try decrypt and verify first! **/
1.209 status = cryptotech[crypto].decrypt_and_verify(session, ctext,
1.210 csize, dsig_text, dsig_size,
1.211 @@ -2677,12 +2751,17 @@
1.212 }
1.213
1.214 *rating = decrypt_rating(decrypt_status);
1.215 +
1.216 + // Ok, so if it was signed and it's all verified, we can update
1.217 + // eligible signer comm_types to PEP_ct_pEp_*
1.218 + if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_pep_msg)
1.219 + status = update_sender_to_pep_trust(session, src->from, _keylist);
1.220
1.221 /* Ok, now we have a keylist used for decryption/verification.
1.222 now we need to update the message rating with the
1.223 sender and recipients in mind */
1.224 status = amend_rating_according_to_sender_and_recipients(session,
1.225 - rating, src->from, _keylist);
1.226 + rating, src->from, _keylist);
1.227
1.228 if (status != PEP_STATUS_OK)
1.229 GOTO(pep_error);
1.230 @@ -2741,6 +2820,7 @@
1.231
1.232 pep_error:
1.233 free(ptext);
1.234 + free(signer_fpr);
1.235 free_message(msg);
1.236 free_stringlist(_keylist);
1.237