|
|
@ -236,8 +236,7 @@ pgp_cb_ret_t |
|
|
|
pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) |
|
|
|
{ |
|
|
|
const pgp_contents_t *content = &pkt->u; |
|
|
|
const pgp_key_t *signer; |
|
|
|
validate_key_cb_t *key; |
|
|
|
validate_key_cb_t *vdata; |
|
|
|
pgp_pubkey_t *sigkey; |
|
|
|
pgp_error_t **errors; |
|
|
|
pgp_io_t *io; |
|
|
@ -249,119 +248,174 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) |
|
|
|
(void) fprintf(io->errs, "%s\n", |
|
|
|
pgp_show_packet_tag(pkt->tag)); |
|
|
|
} |
|
|
|
key = pgp_callback_arg(cbinfo); |
|
|
|
vdata = pgp_callback_arg(cbinfo); |
|
|
|
errors = pgp_callback_errors(cbinfo); |
|
|
|
switch (pkt->tag) { |
|
|
|
case PGP_PTAG_CT_PUBLIC_KEY: |
|
|
|
if (key->pubkey.version != 0) { |
|
|
|
if (vdata->pubkey.version != 0) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: version bad\n"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
key->pubkey = content->pubkey; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
vdata->pubkey = content->pubkey; |
|
|
|
pgp_keyid(vdata->pubkeyid, PGP_KEY_ID_SIZE, |
|
|
|
&vdata->pubkey, PGP_HASH_SHA1); /* TODO v3*/ |
|
|
|
|
|
|
|
case PGP_PTAG_CT_PUBLIC_SUBKEY: |
|
|
|
if (key->subkey.version) { |
|
|
|
pgp_pubkey_free(&key->subkey); |
|
|
|
} |
|
|
|
key->subkey = content->pubkey; |
|
|
|
vdata->last_seen = PRIMARYKEY; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
|
|
|
|
case PGP_PTAG_CT_SECRET_KEY: |
|
|
|
key->seckey = content->seckey; |
|
|
|
key->pubkey = key->seckey.pubkey; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
case PGP_PTAG_CT_PUBLIC_SUBKEY: |
|
|
|
if(vdata->last_seen == ID || |
|
|
|
vdata->last_seen == ATTRIBUTE){ |
|
|
|
if (vdata->subkey.version) { |
|
|
|
pgp_pubkey_free(&vdata->subkey); |
|
|
|
} |
|
|
|
vdata->subkey = content->pubkey; |
|
|
|
vdata->last_seen = SUBKEY; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
}else{ |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: unexpected subkey\n"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
|
|
|
|
case PGP_PTAG_CT_USER_ID: |
|
|
|
if (key->userid) { |
|
|
|
pgp_userid_free(&key->userid); |
|
|
|
} |
|
|
|
key->userid = content->userid; |
|
|
|
key->last_seen = ID; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
if(vdata->last_seen == PRIMARYKEY || |
|
|
|
vdata->last_seen == ATTRIBUTE || |
|
|
|
vdata->last_seen == ID){ |
|
|
|
if (vdata->userid) { |
|
|
|
pgp_userid_free(&vdata->userid); |
|
|
|
} |
|
|
|
vdata->userid = content->userid; |
|
|
|
vdata->last_seen = ID; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
}else{ |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: unexpected userID\n"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
|
|
|
|
case PGP_PTAG_CT_USER_ATTR: |
|
|
|
if (content->userattr.len == 0) { |
|
|
|
if(vdata->last_seen == PRIMARYKEY || |
|
|
|
vdata->last_seen == ATTRIBUTE || |
|
|
|
vdata->last_seen == ID){ |
|
|
|
if (content->userattr.len == 0) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: user attribute length 0"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
(void) fprintf(io->outs, "user attribute, length=%d\n", |
|
|
|
(int) content->userattr.len); |
|
|
|
if (vdata->userattr.len) { |
|
|
|
pgp_data_free(&vdata->userattr); |
|
|
|
} |
|
|
|
vdata->userattr = content->userattr; |
|
|
|
vdata->last_seen = ATTRIBUTE; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
}else{ |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: user attribute length 0"); |
|
|
|
"pgp_validate_key_cb: unexpected user attribute\n"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
(void) fprintf(io->outs, "user attribute, length=%d\n", |
|
|
|
(int) content->userattr.len); |
|
|
|
if (key->userattr.len) { |
|
|
|
pgp_data_free(&key->userattr); |
|
|
|
} |
|
|
|
key->userattr = content->userattr; |
|
|
|
key->last_seen = ATTRIBUTE; |
|
|
|
return PGP_KEEP_MEMORY; |
|
|
|
|
|
|
|
} |
|
|
|
case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */ |
|
|
|
case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ |
|
|
|
from = 0; |
|
|
|
signer = pgp_getkeybyid(io, key->keyring, |
|
|
|
content->sig.info.signer_id, |
|
|
|
&from, &sigkey); |
|
|
|
if (!signer) { |
|
|
|
if (!add_sig_to_list(&content->sig.info, |
|
|
|
&key->result->unknown_sigs, |
|
|
|
&key->result->unknownc)) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: user attribute length 0"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
if (sigkey == &signer->enckey) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"WARNING: signature made with encryption key\n"); |
|
|
|
} |
|
|
|
sigkey = NULL; |
|
|
|
if(vdata->keyring){ |
|
|
|
const pgp_key_t *signer; |
|
|
|
signer = pgp_getkeybyid(io, vdata->keyring, |
|
|
|
content->sig.info.signer_id, |
|
|
|
&from, &sigkey); |
|
|
|
if (signer && sigkey == &signer->enckey) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"WARNING: signature made with encryption key\n"); |
|
|
|
} |
|
|
|
} else { |
|
|
|
/* If no keyring is given to check against |
|
|
|
* then this is a self certification check. |
|
|
|
* First ensure signature issuer ID is pubkey's ID*/ |
|
|
|
if(memcmp(vdata->pubkeyid, |
|
|
|
content->sig.info.signer_id, |
|
|
|
PGP_KEY_ID_SIZE) == 0){ |
|
|
|
sigkey = &vdata->pubkey; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!sigkey) { |
|
|
|
if (!add_sig_to_list(&content->sig.info, |
|
|
|
&vdata->result->unknown_sigs, |
|
|
|
&vdata->result->unknownc)) { |
|
|
|
(void) fprintf(io->errs, |
|
|
|
"pgp_validate_key_cb: out of memory"); |
|
|
|
return PGP_FINISHED; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
switch (content->sig.info.type) { |
|
|
|
case PGP_CERT_GENERIC: |
|
|
|
case PGP_CERT_PERSONA: |
|
|
|
case PGP_CERT_CASUAL: |
|
|
|
case PGP_CERT_POSITIVE: |
|
|
|
case PGP_SIG_REV_CERT: |
|
|
|
valid = (key->last_seen == ID) ? |
|
|
|
pgp_check_useridcert_sig(&key->pubkey, |
|
|
|
key->userid, |
|
|
|
if(vdata->last_seen == ID){ |
|
|
|
valid = pgp_check_useridcert_sig(&vdata->pubkey, |
|
|
|
vdata->userid, |
|
|
|
&content->sig, |
|
|
|
pgp_get_pubkey(signer), |
|
|
|
key->reader->key->packets[ |
|
|
|
key->reader->packet].raw) : |
|
|
|
pgp_check_userattrcert_sig(&key->pubkey, |
|
|
|
&key->userattr, |
|
|
|
sigkey, |
|
|
|
vdata->reader->key->packets[ |
|
|
|
vdata->reader->packet].raw); |
|
|
|
/* XXX TODO if valid : pgp_update_key_userid |
|
|
|
* - id expiration |
|
|
|
* - revocation |
|
|
|
* - is primary |
|
|
|
* */ |
|
|
|
} else if(vdata->last_seen == ATTRIBUTE) { |
|
|
|
valid = pgp_check_userattrcert_sig(&vdata->pubkey, |
|
|
|
&vdata->userattr, |
|
|
|
&content->sig, |
|
|
|
pgp_get_pubkey(signer), |
|
|
|
key->reader->key->packets[ |
|
|
|
key->reader->packet].raw); |
|
|
|
sigkey, |
|
|
|
vdata->reader->key->packets[ |
|
|
|
vdata->reader->packet].raw); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case PGP_SIG_SUBKEY: |
|
|
|
/* |
|
|
|
* XXX: we should also check that the signer is the |
|
|
|
* key we are validating, I think. |
|
|
|
* we ensure that the signing key is the |
|
|
|
* primary key we are validating, "vdata->pubkey". |
|
|
|
*/ |
|
|
|
valid = pgp_check_subkey_sig(&key->pubkey, |
|
|
|
&key->subkey, |
|
|
|
&content->sig, |
|
|
|
pgp_get_pubkey(signer), |
|
|
|
key->reader->key->packets[ |
|
|
|
key->reader->packet].raw); |
|
|
|
if(vdata->last_seen == SUBKEY && |
|
|
|
memcmp(vdata->pubkeyid, |
|
|
|
content->sig.info.signer_id, |
|
|
|
PGP_KEY_ID_SIZE) == 0 ){ |
|
|
|
valid = pgp_check_subkey_sig(&vdata->pubkey, |
|
|
|
&vdata->subkey, |
|
|
|
&content->sig, |
|
|
|
&vdata->pubkey, |
|
|
|
vdata->reader->key->packets[ |
|
|
|
vdata->reader->packet].raw); |
|
|
|
/* XXX TODO if valid : pgp_update_key_subkey |
|
|
|
* with expiration and flags from sig info */ |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case PGP_SIG_DIRECT: |
|
|
|
valid = pgp_check_direct_sig(&key->pubkey, |
|
|
|
&content->sig, |
|
|
|
pgp_get_pubkey(signer), |
|
|
|
key->reader->key->packets[ |
|
|
|
key->reader->packet].raw); |
|
|
|
if(vdata->last_seen == PRIMARYKEY){ |
|
|
|
valid = pgp_check_direct_sig(&vdata->pubkey, |
|
|
|
&content->sig, |
|
|
|
sigkey, |
|
|
|
vdata->reader->key->packets[ |
|
|
|
vdata->reader->packet].raw); |
|
|
|
/* XXX TODO if valid : pgp_update_key |
|
|
|
* with expiration and flags from sig info */ |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case PGP_SIG_STANDALONE: |
|
|
|
case PGP_SIG_PRIMARY: |
|
|
|
case PGP_SIG_REV_KEY: |
|
|
|
/* TODO */ |
|
|
|
case PGP_SIG_REV_SUBKEY: |
|
|
|
/* TODO */ |
|
|
|
case PGP_SIG_TIMESTAMP: |
|
|
|
case PGP_SIG_3RD_PARTY: |
|
|
|
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, |
|
|
@ -377,17 +431,20 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) |
|
|
|
|
|
|
|
if (valid) { |
|
|
|
if (!add_sig_to_list(&content->sig.info, |
|
|
|
&key->result->valid_sigs, |
|
|
|
&key->result->validc)) { |
|
|
|
&vdata->result->valid_sigs, |
|
|
|
&vdata->result->validc)) { |
|
|
|
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", |
|
|
|
"Can't add good sig to list\n"); |
|
|
|
} |
|
|
|
if(vdata->on_valid){ |
|
|
|
return vdata->on_valid(vdata,&content->sig); |
|
|
|
} |
|
|
|
} else { |
|
|
|
PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s", |
|
|
|
"Bad Sig"); |
|
|
|
if (!add_sig_to_list(&content->sig.info, |
|
|
|
&key->result->invalid_sigs, |
|
|
|
&key->result->invalidc)) { |
|
|
|
&vdata->result->invalid_sigs, |
|
|
|
&vdata->result->invalidc)) { |
|
|
|
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", |
|
|
|
"Can't add good sig to list\n"); |
|
|
|
} |
|
|
@ -401,8 +458,8 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) |
|
|
|
break; |
|
|
|
|
|
|
|
case PGP_GET_PASSPHRASE: |
|
|
|
if (key->getpassphrase) { |
|
|
|
return key->getpassphrase(pkt, cbinfo); |
|
|
|
if (vdata->getpassphrase) { |
|
|
|
return vdata->getpassphrase(pkt, cbinfo); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
@ -412,7 +469,7 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) |
|
|
|
printf("Got trust\n"); |
|
|
|
//hexdump(stdout, (const uint8_t *)content->trust.data, 10, " "); |
|
|
|
//hexdump(stdout, (const uint8_t *)&content->ss_trust, 2, " "); |
|
|
|
//printf("Trust level %d, amount %d\n", key->trust.level, key->trust.amount); |
|
|
|
//printf("Trust level %d, amount %d\n", vdata->trust.level, vdata->trust.amount); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
@ -686,7 +743,8 @@ pgp_validate_key_sigs(pgp_validation_t *result, |
|
|
|
const pgp_key_t *key, |
|
|
|
const pgp_keyring_t *keyring, |
|
|
|
pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, |
|
|
|
pgp_cbdata_t *)) |
|
|
|
pgp_cbdata_t *) |
|
|
|
) |
|
|
|
{ |
|
|
|
pgp_stream_t *stream; |
|
|
|
validate_key_cb_t keysigs; |
|
|
@ -701,6 +759,9 @@ pgp_validate_key_sigs(pgp_validation_t *result, |
|
|
|
|
|
|
|
keysigs.keyring = keyring; |
|
|
|
|
|
|
|
keysigs.on_valid = NULL; |
|
|
|
keysigs.on_valid_args = NULL; |
|
|
|
|
|
|
|
pgp_set_callback(stream, pgp_validate_key_cb, &keysigs); |
|
|
|
stream->readinfo.accumulate = 1; |
|
|
|
pgp_keydata_reader_set(stream, key); |
|
|
|