From d1e174344cb2d8d3681cd3c3d6dfe0c70d60da20 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Sun, 4 Mar 2007 16:37:52 +0000 Subject: [PATCH] Allow checking for signature times and use in merging Add support for pulling out the creation time of a signature, then use this information when we're merging key signatures. This allows for updating of signatures (eg key preferences) or adding new signatures eg with later expiry dates. As reported in Debian bug #410796 --- decodekey.c | 126 ++++++++++++++++++++++++++++++++++------------------ decodekey.h | 12 +++++ merge.c | 8 +++- 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/decodekey.c b/decodekey.c index efffad7..3a6e075 100644 --- a/decodekey.c +++ b/decodekey.c @@ -22,13 +22,15 @@ /* * parse_subpackets - Parse the subpackets of a Type 4 signature. * @data: The subpacket data. - * @keyid: A pointer to where we should return the keyid. + * @keyid: A pointer to where we should return the keyid. + * @creationtime: A pointer to where we should return the creation time. * * This function parses the subkey data of a Type 4 signature and fills * in the supplied variables. It also returns the length of the data - * processed. + * processed. If the value of any piece of data is not desired a NULL + * can be passed instead of a pointer to a storage area for that value. */ -int parse_subpackets(unsigned char *data, uint64_t *keyid) +int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation) { int offset = 0; int length = 0; @@ -56,8 +58,17 @@ int parse_subpackets(unsigned char *data, uint64_t *keyid) switch (data[offset] & 0x7F) { case 2: /* - * Signature creation time. Might want to output this? + * Signature creation time. */ + if (creation != NULL) { + *creation = data[offset + packetlen - 4]; + *creation <<= 8; + *creation = data[offset + packetlen - 3]; + *creation <<= 8; + *creation = data[offset + packetlen - 2]; + *creation <<= 8; + *creation = data[offset + packetlen - 1]; + } break; case 3: /* @@ -65,21 +76,23 @@ int parse_subpackets(unsigned char *data, uint64_t *keyid) */ break; case 16: - *keyid = data[offset+packetlen - 8]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 7]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 6]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 5]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 4]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 3]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 2]; - *keyid <<= 8; - *keyid += data[offset+packetlen - 1]; + if (keyid != NULL) { + *keyid = data[offset+packetlen - 8]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 7]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 6]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 5]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 4]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 3]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 2]; + *keyid <<= 8; + *keyid += data[offset+packetlen - 1]; + } break; case 20: /* @@ -138,42 +151,55 @@ struct ll *keysigs(struct ll *curll, } /** - * sig_keyid - Return the keyid for a given OpenPGP signature packet. - * @packet: The signature packet. + * sig_info - Get info on a given OpenPGP signature packet + * @packet: The signature packet + * @keyid: A pointer for where to return the signature keyid + * @creation: A pointer for where to return the signature creation time * - * Returns the keyid for the supplied signature packet. + * Gets any info about a signature packet; parses the subpackets for a v4 + * key or pulls the data directly from v2/3. NULL can be passed for any + * values which aren't cared about. */ -uint64_t sig_keyid(struct openpgp_packet *packet) +void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation) { int length = 0; - uint64_t keyid = 0; if (packet != NULL) { - keyid = 0; switch (packet->data[0]) { case 2: case 3: - keyid = packet->data[7]; - keyid <<= 8; - keyid += packet->data[8]; - keyid <<= 8; - keyid += packet->data[9]; - keyid <<= 8; - keyid += packet->data[10]; - keyid <<= 8; - keyid += packet->data[11]; - keyid <<= 8; - keyid += packet->data[12]; - keyid <<= 8; - keyid += packet->data[13]; - keyid <<= 8; - keyid += packet->data[14]; + if (keyid != NULL) { + *keyid = packet->data[7]; + *keyid <<= 8; + *keyid += packet->data[8]; + *keyid <<= 8; + *keyid += packet->data[9]; + *keyid <<= 8; + *keyid += packet->data[10]; + *keyid <<= 8; + *keyid += packet->data[11]; + *keyid <<= 8; + *keyid += packet->data[12]; + *keyid <<= 8; + *keyid += packet->data[13]; + *keyid <<= 8; + *keyid += packet->data[14]; + } + if (creation != NULL) { + *creation = packet->data[3]; + *creation <<= 8; + *creation = packet->data[4]; + *creation <<= 8; + *creation = packet->data[5]; + *creation <<= 8; + *creation = packet->data[6]; + } break; case 4: length = parse_subpackets(&packet->data[4], - &keyid); + keyid, creation); parse_subpackets(&packet->data[length + 4], - &keyid); + keyid, creation); /* * Don't bother to look at the unsigned packets. */ @@ -183,9 +209,25 @@ uint64_t sig_keyid(struct openpgp_packet *packet) } } + return; +} + +/** + * sig_keyid - Return the keyid for a given OpenPGP signature packet. + * @packet: The signature packet. + * + * Returns the keyid for the supplied signature packet. + */ +uint64_t sig_keyid(struct openpgp_packet *packet) +{ + uint64_t keyid = 0; + + sig_info(packet, &keyid, NULL); + return keyid; } + /* * TODO: Abstract out; all our linked lists should be generic and then we can * llsize them. diff --git a/decodekey.h b/decodekey.h index 57bf680..987c3fc 100644 --- a/decodekey.h +++ b/decodekey.h @@ -23,6 +23,18 @@ struct ll *keysigs(struct ll *curll, struct openpgp_packet_list *sigs); +/** + * sig_info - Get info on a given OpenPGP signature packet + * @packet: The signature packet + * @keyid: A pointer for where to return the signature keyid + * @creation: A pointer for where to return the signature creation time + * + * Gets any info about a signature packet; parses the subpackets for a v4 + * key or pulls the data directly from v2/3. NULL can be passed for any + * values which aren't cared about. + */ +void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation); + /** * sig_keyid - Return the keyid for a given OpenPGP signature packet. * @packet: The signature packet. diff --git a/merge.c b/merge.c index 87f45fc..be97eb4 100644 --- a/merge.c +++ b/merge.c @@ -43,15 +43,19 @@ bool compare_packets(struct openpgp_packet *a, struct openpgp_packet *b) */ bool compare_signatures(struct openpgp_packet *a, struct openpgp_packet *b) { + uint64_t a_keyid, b_keyid; + time_t a_creation, b_creation; + if (a->data[0] != b->data[0]) { /* Different signature versions, so not the same */ return false; } else if (a->data[0] == 4 && a->data[1] != b->data[1]) { /* Type 4 signature, but different types */ return false; - /* TODO: Check signature time? */ } else { - return (sig_keyid(a) == sig_keyid(b)); + sig_info(a, &a_keyid, &a_creation); + sig_info(b, &b_keyid, &b_creation); + return (a_creation == b_creation) && (a_keyid == b_keyid); } } -- 2.39.2