|
|
@ -173,17 +173,15 @@ int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b) |
|
|
|
pgp_packet_t a_userid = pgp_user_id_from_raw (a, a_len); |
|
|
|
pgp_packet_t b_userid = pgp_user_id_from_raw (b, b_len); |
|
|
|
|
|
|
|
T("(%.*s, %.*s)", a_len, (const char *) a, b_len, (const char *) b); |
|
|
|
char *a_email = NULL; |
|
|
|
pgp_user_id_email_normalized(NULL, a_userid, &a_email); |
|
|
|
if (!a_email) |
|
|
|
pgp_user_id_uri(NULL, a_userid, &a_email); |
|
|
|
|
|
|
|
char *a_address = NULL; |
|
|
|
pgp_user_id_address_normalized(NULL, a_userid, &a_address); |
|
|
|
if (!a_address) |
|
|
|
pgp_user_id_other(NULL, a_userid, &a_address); |
|
|
|
|
|
|
|
char *b_address = NULL; |
|
|
|
pgp_user_id_address_normalized(NULL, b_userid, &b_address); |
|
|
|
if (!b_address) |
|
|
|
pgp_user_id_other(NULL, b_userid, &b_address); |
|
|
|
char *b_email = NULL; |
|
|
|
pgp_user_id_email_normalized(NULL, b_userid, &b_email); |
|
|
|
if (!b_email) |
|
|
|
pgp_user_id_uri(NULL, b_userid, &b_email); |
|
|
|
|
|
|
|
pgp_packet_free(a_userid); |
|
|
|
pgp_packet_free(b_userid); |
|
|
@ -192,24 +190,24 @@ int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b) |
|
|
|
// first string is less than, equal to, or greater than the |
|
|
|
// second, respectively. |
|
|
|
int result; |
|
|
|
if (!a_address && !b_address) |
|
|
|
if (!a_email && !b_email) |
|
|
|
result = 0; |
|
|
|
else if (!a_address) |
|
|
|
else if (!a_email) |
|
|
|
result = -1; |
|
|
|
else if (!b_address) |
|
|
|
else if (!b_email) |
|
|
|
result = 1; |
|
|
|
else |
|
|
|
result = strcmp(a_address, b_address); |
|
|
|
result = strcmp(a_email, b_email); |
|
|
|
|
|
|
|
if (true) { |
|
|
|
T("'%s' %s '%s'", |
|
|
|
a_address, |
|
|
|
a_email, |
|
|
|
result == 0 ? "==" : result < 0 ? "<" : ">", |
|
|
|
b_address); |
|
|
|
b_email); |
|
|
|
} |
|
|
|
|
|
|
|
free(a_address); |
|
|
|
free(b_address); |
|
|
|
free(a_email); |
|
|
|
free(b_email); |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
@ -792,7 +790,7 @@ static PEP_STATUS tpk_save(PEP_SESSION session, pgp_tpk_t tpk, |
|
|
|
pgp_tsk_t tsk = pgp_tpk_as_tsk(tpk); |
|
|
|
pgp_status = pgp_tsk_serialize(&err, tsk, writer); |
|
|
|
pgp_tsk_free(tsk); |
|
|
|
//pgp_writer_free(writer); |
|
|
|
pgp_writer_free(writer); |
|
|
|
if (pgp_status != 0) |
|
|
|
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Serializing TPK"); |
|
|
|
|
|
|
@ -858,7 +856,12 @@ static PEP_STATUS tpk_save(PEP_SESSION session, pgp_tpk_t tpk, |
|
|
|
|
|
|
|
pgp_packet_t userid = pgp_user_id_new (user_id_value); |
|
|
|
pgp_user_id_name(NULL, userid, &name); |
|
|
|
pgp_user_id_address_or_other(NULL, userid, &email); |
|
|
|
// Try to get the normalized address. |
|
|
|
pgp_user_id_email_normalized(NULL, userid, &email); |
|
|
|
if (! email) |
|
|
|
// Ok, it's not a proper RFC 2822 name-addr. Perhaps it |
|
|
|
// is a URI. |
|
|
|
pgp_user_id_uri(NULL, userid, &email); |
|
|
|
pgp_packet_free(userid); |
|
|
|
free(user_id_value); |
|
|
|
|
|
|
@ -1240,7 +1243,7 @@ check_signatures_cb(void *cookie_opaque, pgp_message_structure_t structure) |
|
|
|
// Make sure the TPK is not revoked, it's |
|
|
|
// creation time is <= now, and it hasn't |
|
|
|
// expired. |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk); |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revoked(tpk, 0); |
|
|
|
bool revoked = (pgp_revocation_status_variant(rs) |
|
|
|
== PGP_REVOCATION_STATUS_REVOKED); |
|
|
|
pgp_revocation_status_free(rs); |
|
|
@ -1248,7 +1251,7 @@ check_signatures_cb(void *cookie_opaque, pgp_message_structure_t structure) |
|
|
|
T("TPK %s is revoked.", primary_fpr_str); |
|
|
|
good = false; |
|
|
|
cookie->good_but_revoked ++; |
|
|
|
} else if (! pgp_tpk_alive(tpk)) { |
|
|
|
} else if (! pgp_tpk_alive(tpk, 0)) { |
|
|
|
T("TPK %s is not alive.", primary_fpr_str); |
|
|
|
good = false; |
|
|
|
cookie->good_but_expired ++; |
|
|
@ -1273,7 +1276,7 @@ check_signatures_cb(void *cookie_opaque, pgp_message_structure_t structure) |
|
|
|
primary_fpr_str, keyid_str); |
|
|
|
good = false; |
|
|
|
cookie->good_but_revoked ++; |
|
|
|
} else if (! pgp_signature_key_alive(sig, key)) { |
|
|
|
} else if (! pgp_signature_key_alive(sig, key, 0)) { |
|
|
|
T("TPK %s's signing key %s is expired.", |
|
|
|
primary_fpr_str, keyid_str); |
|
|
|
good = false; |
|
|
@ -1671,6 +1674,8 @@ PEP_STATUS pgp_sign_only( |
|
|
|
ws = pgp_signer_new_detached(&err, ws, &signer, 1, 0); |
|
|
|
if (!ws) |
|
|
|
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Setting up signer"); |
|
|
|
// pgp_signer_new_detached consumes signer. |
|
|
|
signer = NULL; |
|
|
|
|
|
|
|
pgp_status_t write_status = |
|
|
|
pgp_writer_stack_write_all (&err, ws, |
|
|
@ -1692,7 +1697,11 @@ PEP_STATUS pgp_sign_only( |
|
|
|
|
|
|
|
out: |
|
|
|
pgp_signer_free (signer); |
|
|
|
pgp_key_pair_free (signing_keypair); |
|
|
|
// XXX: pgp_key_pair_as_signer is only supposed to reference |
|
|
|
// signing_keypair, but it consumes it. If this is fixed, this |
|
|
|
// will become a leak. |
|
|
|
// |
|
|
|
//pgp_key_pair_free (signing_keypair); |
|
|
|
pgp_tpk_key_iter_free (iter); |
|
|
|
pgp_tpk_free(signer_tpk); |
|
|
|
|
|
|
@ -1706,8 +1715,16 @@ static PEP_STATUS pgp_encrypt_sign_optional( |
|
|
|
{ |
|
|
|
PEP_STATUS status = PEP_STATUS_OK; |
|
|
|
pgp_error_t err = NULL; |
|
|
|
int keys_count = 0; |
|
|
|
pgp_tpk_t *keys = NULL; |
|
|
|
|
|
|
|
int recipient_tpk_count = 0; |
|
|
|
pgp_tpk_t *recipient_tpks = NULL; |
|
|
|
|
|
|
|
int recipient_count = 0; |
|
|
|
int recipient_alloc = 0; |
|
|
|
pgp_recipient_t *recipients = NULL; |
|
|
|
int recipient_keys_count = 0; |
|
|
|
pgp_key_t *recipient_keys = NULL; |
|
|
|
|
|
|
|
pgp_tpk_t signer_tpk = NULL; |
|
|
|
pgp_writer_stack_t ws = NULL; |
|
|
|
pgp_tpk_key_iter_t iter = NULL; |
|
|
@ -1724,18 +1741,82 @@ static PEP_STATUS pgp_encrypt_sign_optional( |
|
|
|
*ctext = NULL; |
|
|
|
*csize = 0; |
|
|
|
|
|
|
|
keys = calloc(stringlist_length(keylist), sizeof(*keys)); |
|
|
|
if (keys == NULL) |
|
|
|
int keylist_len = stringlist_length(keylist); |
|
|
|
|
|
|
|
// We don't need to worry about extending recipient_tpks, because |
|
|
|
// there will be at most KEYLIST_LEN tpks, which we allocate up |
|
|
|
// front. |
|
|
|
recipient_tpks = calloc(keylist_len, sizeof(*recipient_tpks)); |
|
|
|
if (recipient_tpks == NULL) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
|
|
|
|
// Because there may be multiple encryption keys per TPK, we may |
|
|
|
// need to extend recipient_keys and recipients. |
|
|
|
recipient_alloc = keylist_len; |
|
|
|
recipient_keys = calloc(recipient_alloc, sizeof(*recipient_keys)); |
|
|
|
if (recipient_keys == NULL) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
|
|
|
|
recipients = calloc(recipient_alloc, sizeof(*recipients)); |
|
|
|
if (recipients == NULL) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
|
|
|
|
|
|
|
|
// Get the keys for the recipients. |
|
|
|
const stringlist_t *_keylist; |
|
|
|
for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) { |
|
|
|
assert(_keylist->value); |
|
|
|
pgp_fingerprint_t pgp_fpr = pgp_fingerprint_from_hex(_keylist->value); |
|
|
|
status = tpk_find_by_fpr(session, pgp_fpr, false, &keys[keys_count ++], NULL); |
|
|
|
pgp_fingerprint_free(pgp_fpr); |
|
|
|
ERROR_OUT(NULL, status, "Looking up key for recipient '%s'", _keylist->value); |
|
|
|
|
|
|
|
pgp_tpk_t tpk; |
|
|
|
status = tpk_find_by_fpr_hex(session, _keylist->value, |
|
|
|
false, &tpk, NULL); |
|
|
|
// We couldn't find a key for this recipient. |
|
|
|
ERROR_OUT(NULL, status, |
|
|
|
"Looking up key for recipient '%s'", _keylist->value); |
|
|
|
|
|
|
|
recipient_tpks[recipient_tpk_count ++] = tpk; |
|
|
|
|
|
|
|
// Collect all of the keys that have the encryption for |
|
|
|
// transport capability. |
|
|
|
pgp_tpk_key_iter_t iter = pgp_tpk_key_iter_valid(tpk); |
|
|
|
if (! iter) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
pgp_tpk_key_iter_encrypting_capable_for_transport(iter); |
|
|
|
|
|
|
|
pgp_key_t key; |
|
|
|
while ((key = pgp_tpk_key_iter_next (iter, NULL, NULL))) { |
|
|
|
assert(recipient_count == recipient_keys_count); |
|
|
|
if (recipient_count == recipient_alloc) { |
|
|
|
assert(recipient_alloc > 0); |
|
|
|
recipient_alloc *= 2; |
|
|
|
|
|
|
|
void *t = reallocarray(recipient_keys, recipient_alloc, |
|
|
|
sizeof(*recipient_keys)); |
|
|
|
if (! t) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
recipient_keys = t; |
|
|
|
|
|
|
|
t = reallocarray(recipients, recipient_alloc, |
|
|
|
sizeof(*recipients)); |
|
|
|
if (! t) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
recipients = t; |
|
|
|
} |
|
|
|
|
|
|
|
// pgp_recipient_new consumes the passed key id, but it |
|
|
|
// only references key (i.e., we still have to free key). |
|
|
|
pgp_keyid_t keyid = pgp_key_keyid(key); |
|
|
|
if (! key) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
|
|
|
|
key = pgp_key_clone(key); |
|
|
|
if (! key) |
|
|
|
ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory"); |
|
|
|
recipient_keys[recipient_keys_count++] = key; |
|
|
|
|
|
|
|
recipients[recipient_count++] = pgp_recipient_new(keyid, key); |
|
|
|
} |
|
|
|
pgp_tpk_key_iter_free(iter); |
|
|
|
} |
|
|
|
|
|
|
|
if (sign) { |
|
|
@ -1752,11 +1833,14 @@ static PEP_STATUS pgp_encrypt_sign_optional( |
|
|
|
|
|
|
|
ws = pgp_writer_stack_message(writer); |
|
|
|
ws = pgp_encryptor_new (&err, ws, |
|
|
|
NULL, 0, keys, keys_count, |
|
|
|
PGP_ENCRYPTION_MODE_FOR_TRANSPORT, 0); |
|
|
|
NULL, 0, recipients, recipient_count, |
|
|
|
0, 0); |
|
|
|
if (!ws) |
|
|
|
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Setting up encryptor"); |
|
|
|
|
|
|
|
// pgp_encrypt_new consumes the recipients (but not the keys). |
|
|
|
recipient_count = 0; |
|
|
|
|
|
|
|
if (sign) { |
|
|
|
iter = pgp_tpk_key_iter_valid(signer_tpk); |
|
|
|
pgp_tpk_key_iter_signing_capable (iter); |
|
|
@ -1780,6 +1864,8 @@ static PEP_STATUS pgp_encrypt_sign_optional( |
|
|
|
ws = pgp_signer_new(&err, ws, &signer, 1, 0); |
|
|
|
if (!ws) |
|
|
|
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Setting up signer"); |
|
|
|
// pgp_signer_new consumes signer. |
|
|
|
signer = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
ws = pgp_literal_writer_new (&err, ws); |
|
|
@ -1811,13 +1897,23 @@ static PEP_STATUS pgp_encrypt_sign_optional( |
|
|
|
|
|
|
|
out: |
|
|
|
pgp_signer_free (signer); |
|
|
|
pgp_key_pair_free (signing_keypair); |
|
|
|
// XXX: pgp_key_pair_as_signer is only supposed to reference |
|
|
|
// signing_keypair, but it consumes it. If this is fixed, this |
|
|
|
// will become a leak. |
|
|
|
// |
|
|
|
// pgp_key_pair_free (signing_keypair); |
|
|
|
pgp_tpk_key_iter_free (iter); |
|
|
|
pgp_tpk_free(signer_tpk); |
|
|
|
|
|
|
|
for (int i = 0; i < keys_count; i ++) |
|
|
|
pgp_tpk_free(keys[i]); |
|
|
|
free(keys); |
|
|
|
for (int i = 0; i < recipient_count; i ++) |
|
|
|
pgp_recipient_free(recipients[i]); |
|
|
|
free(recipients); |
|
|
|
for (int i = 0; i < recipient_keys_count; i ++) |
|
|
|
pgp_key_free(recipient_keys[i]); |
|
|
|
free(recipient_keys); |
|
|
|
for (int i = 0; i < recipient_tpk_count; i ++) |
|
|
|
pgp_tpk_free(recipient_tpks[i]); |
|
|
|
free(recipient_tpks); |
|
|
|
|
|
|
|
T("-> %s", pEp_status_to_string(status)); |
|
|
|
return status; |
|
|
@ -2269,7 +2365,7 @@ static stringpair_list_t *add_key(PEP_SESSION session, |
|
|
|
bool revoked = false; |
|
|
|
// Don't add revoked keys to the keyinfo_list. |
|
|
|
if (keyinfo_list) { |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk); |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revoked(tpk, 0); |
|
|
|
pgp_revocation_status_variant_t rsv = pgp_revocation_status_variant(rs); |
|
|
|
pgp_revocation_status_free(rs); |
|
|
|
if (rsv == PGP_REVOCATION_STATUS_REVOKED) |
|
|
@ -2471,7 +2567,7 @@ PEP_STATUS pgp_renew_key( |
|
|
|
status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL); |
|
|
|
ERROR_OUT(NULL, status, "Looking up '%s'", fpr); |
|
|
|
|
|
|
|
uint32_t creation_time = pgp_key_creation_time(pgp_tpk_primary(tpk)); |
|
|
|
uint32_t creation_time = pgp_key_creation_time(pgp_tpk_primary_key(tpk)); |
|
|
|
if (creation_time > t) |
|
|
|
// The creation time is after the expiration time! |
|
|
|
ERROR_OUT(NULL, PEP_UNKNOWN_ERROR, |
|
|
@ -2509,6 +2605,10 @@ PEP_STATUS pgp_renew_key( |
|
|
|
|
|
|
|
out: |
|
|
|
pgp_signer_free (signer); |
|
|
|
// XXX: pgp_key_pair_as_signer is only supposed to reference |
|
|
|
// signing_keypair, but it consumes it. If this is fixed, this |
|
|
|
// will become a leak. |
|
|
|
// |
|
|
|
pgp_key_pair_free (keypair); |
|
|
|
pgp_tpk_key_iter_free (iter); |
|
|
|
pgp_tpk_free(tpk); |
|
|
@ -2557,7 +2657,7 @@ PEP_STATUS pgp_revoke_key( |
|
|
|
if (! tpk) |
|
|
|
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration"); |
|
|
|
|
|
|
|
assert(pgp_revocation_status_variant(pgp_tpk_revocation_status(tpk)) |
|
|
|
assert(pgp_revocation_status_variant(pgp_tpk_revoked(tpk, 0)) |
|
|
|
== PGP_REVOCATION_STATUS_REVOKED); |
|
|
|
|
|
|
|
status = tpk_save(session, tpk, NULL); |
|
|
@ -2577,7 +2677,7 @@ PEP_STATUS pgp_revoke_key( |
|
|
|
static void _pgp_key_expired(pgp_tpk_t tpk, const time_t when, bool* expired) |
|
|
|
{ |
|
|
|
// Is the TPK live? |
|
|
|
*expired = !pgp_tpk_alive_at(tpk, when); |
|
|
|
*expired = !pgp_tpk_alive(tpk, when); |
|
|
|
|
|
|
|
#ifdef TRACING |
|
|
|
{ |
|
|
@ -2635,7 +2735,7 @@ static void _pgp_key_expired(pgp_tpk_t tpk, const time_t when, bool* expired) |
|
|
|
|
|
|
|
out: |
|
|
|
// Er, this might be problematic in terms of internal vs. external in log. FIXME? |
|
|
|
T("(%s) -> %s (expired: %d)", fpr, pEp_status_to_string(status), *expired); |
|
|
|
T(" -> expired: %d", *expired); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -2682,7 +2782,7 @@ PEP_STATUS pgp_key_revoked(PEP_SESSION session, const char *fpr, bool *revoked) |
|
|
|
pgp_fingerprint_free(pgp_fpr); |
|
|
|
ERROR_OUT(NULL, status, "Looking up %s", fpr); |
|
|
|
|
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk); |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revoked(tpk, 0); |
|
|
|
*revoked = pgp_revocation_status_variant(rs) == PGP_REVOCATION_STATUS_REVOKED; |
|
|
|
pgp_revocation_status_free (rs); |
|
|
|
pgp_tpk_free(tpk); |
|
|
@ -2726,7 +2826,7 @@ PEP_STATUS pgp_get_key_rating( |
|
|
|
// goto out; |
|
|
|
// } |
|
|
|
|
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revocation_status(tpk); |
|
|
|
pgp_revocation_status_t rs = pgp_tpk_revoked(tpk, 0); |
|
|
|
pgp_revocation_status_variant_t rsv = pgp_revocation_status_variant(rs); |
|
|
|
pgp_revocation_status_free(rs); |
|
|
|
if (rsv == PGP_REVOCATION_STATUS_REVOKED) { |
|
|
@ -2800,7 +2900,7 @@ PEP_STATUS pgp_key_created(PEP_SESSION session, const char *fpr, time_t *created |
|
|
|
pgp_fingerprint_free(pgp_fpr); |
|
|
|
ERROR_OUT(NULL, status, "Looking up %s", fpr); |
|
|
|
|
|
|
|
pgp_key_t k = pgp_tpk_primary(tpk); |
|
|
|
pgp_key_t k = pgp_tpk_primary_key(tpk); |
|
|
|
*created = pgp_key_creation_time(k); |
|
|
|
pgp_tpk_free(tpk); |
|
|
|
|
|
|
|