/* * Return the last found keyring. Caller must free it. * The returned keyblock has the kbode flag bit 0 set for the node with * the public key used to locate the keyblock or flag bit 1 set for * the user ID node. */ int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) { PACKET *pkt; int rc; KBNODE keyblock = NULL, node, lastnode; IOBUF a; int in_cert = 0; int pk_no = 0; int uid_no = 0; int save_mode; if (ret_kb) *ret_kb = NULL; if (!hd->found.kr) return -1; /* no successful search */ a = iobuf_open (hd->found.kr->fname); if (!a) { log_error(_("can't open `%s'\n"), hd->found.kr->fname); return G10ERR_KEYRING_OPEN; } if (iobuf_seek (a, hd->found.offset) ) { log_error ("can't seek `%s'\n", hd->found.kr->fname); iobuf_close(a); return G10ERR_KEYRING_OPEN; } pkt = xmalloc (sizeof *pkt); init_packet (pkt); hd->found.n_packets = 0;; lastnode = NULL; save_mode = set_packet_list_mode(0); while ((rc=parse_packet (a, pkt)) != -1) { hd->found.n_packets++; if (rc == G10ERR_UNKNOWN_PACKET) { free_packet (pkt); init_packet (pkt); continue; } if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", g10_errstr(rc) ); rc = G10ERR_INV_KEYRING; break; } /* Filter allowed packets. */ switch (pkt->pkttype){ case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: case PKT_USER_ID: case PKT_ATTRIBUTE: case PKT_SIGNATURE: break; /* Allowed per RFC. */ case PKT_RING_TRUST: case PKT_OLD_COMMENT: case PKT_COMMENT: case PKT_GPG_CONTROL: break; /* Allowed by us. */ default: log_error ("skipped packet of type %d in keyring\n", (int)pkt->pkttype); free_packet(pkt); init_packet(pkt); continue; } if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_SECRET_KEY)) { hd->found.n_packets--; /* fix counter */ break; /* ready */ } in_cert = 1; if (pkt->pkttype == PKT_RING_TRUST) { /*(this code is duplicated after the loop)*/ if ( lastnode && lastnode->pkt->pkttype == PKT_SIGNATURE && (pkt->pkt.ring_trust->sigcache & 1) ) { /* This is a ring trust packet with a checked signature * status cache following directly a signature paket. * Set the cache status into that signature packet. * * We do not use cached signatures made with MD5 to * avoid using a cached status created with an older * version of gpg. */ PKT_signature *sig = lastnode->pkt->pkt.signature; if (sig->digest_algo != DIGEST_ALGO_MD5) { sig->flags.checked = 1; sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); } } /* Reset LASTNODE, so that we set the cache status only from * the ring trust packet immediately following a signature. */ lastnode = NULL; free_packet(pkt); init_packet(pkt); continue; } node = lastnode = new_kbnode (pkt); if (!keyblock) keyblock = node; else add_kbnode (keyblock, node); switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: if (++pk_no == hd->found.pk_no) node->flag |= 1; break; case PKT_USER_ID: if (++uid_no == hd->found.uid_no) node->flag |= 2; break; default: break; } pkt = xmalloc (sizeof *pkt); init_packet(pkt); } set_packet_list_mode(save_mode); if (rc == -1 && keyblock) rc = 0; /* got the entire keyblock */ if (rc || !ret_kb) release_kbnode (keyblock); else { /*(duplicated from the loop body)*/ if ( pkt && pkt->pkttype == PKT_RING_TRUST && lastnode && lastnode->pkt->pkttype == PKT_SIGNATURE && (pkt->pkt.ring_trust->sigcache & 1) ) { PKT_signature *sig = lastnode->pkt->pkt.signature; if (sig->digest_algo != DIGEST_ALGO_MD5) { sig->flags.checked = 1; sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); } } *ret_kb = keyblock; } free_packet (pkt); xfree (pkt); iobuf_close(a); /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ if (rc == G10ERR_INV_KEYRING) hd->current.error = rc; return rc; }
/* * Return the last found keyring. Caller must free it. * The returned keyblock has the kbode flag bit 0 set for the node with * the public key used to locate the keyblock or flag bit 1 set for * the user ID node. */ int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) { PACKET *pkt; int rc; KBNODE keyblock = NULL, node, lastnode; IOBUF a; int in_cert = 0; int pk_no = 0; int uid_no = 0; int save_mode; if (ret_kb) *ret_kb = NULL; if (!hd->found.kr) return -1; /* no successful search */ a = iobuf_open (hd->found.kr->fname); if (!a) { log_error(_("can't open `%s'\n"), hd->found.kr->fname); return G10ERR_KEYRING_OPEN; } if (iobuf_seek (a, hd->found.offset) ) { log_error ("can't seek `%s'\n", hd->found.kr->fname); iobuf_close(a); return G10ERR_KEYRING_OPEN; } pkt = xmalloc (sizeof *pkt); init_packet (pkt); hd->found.n_packets = 0;; lastnode = NULL; save_mode = set_packet_list_mode(0); while ((rc=parse_packet (a, pkt)) != -1) { hd->found.n_packets++; if (rc == G10ERR_UNKNOWN_PACKET) { free_packet (pkt); init_packet (pkt); continue; } if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", g10_errstr(rc) ); rc = G10ERR_INV_KEYRING; break; } if (pkt->pkttype == PKT_COMPRESSED) { log_error ("skipped compressed packet in keyring\n"); free_packet(pkt); init_packet(pkt); continue; } if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_SECRET_KEY)) { hd->found.n_packets--; /* fix counter */ break; /* ready */ } in_cert = 1; if (pkt->pkttype == PKT_RING_TRUST) { /*(this code is duplicated after the loop)*/ if ( lastnode && lastnode->pkt->pkttype == PKT_SIGNATURE && (pkt->pkt.ring_trust->sigcache & 1) ) { /* this is a ring trust packet with a checked signature * status cache following directly a signature paket. * Set the cache status into that signature packet */ PKT_signature *sig = lastnode->pkt->pkt.signature; sig->flags.checked = 1; sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); } /* reset lastnode, so that we set the cache status only from * the ring trust packet immediately folling a signature */ lastnode = NULL; } else { node = lastnode = new_kbnode (pkt); if (!keyblock) keyblock = node; else add_kbnode (keyblock, node); if ( pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_PUBLIC_SUBKEY || pkt->pkttype == PKT_SECRET_KEY || pkt->pkttype == PKT_SECRET_SUBKEY) { if (++pk_no == hd->found.pk_no) node->flag |= 1; } else if ( pkt->pkttype == PKT_USER_ID) { if (++uid_no == hd->found.uid_no) node->flag |= 2; } } pkt = xmalloc (sizeof *pkt); init_packet(pkt); } set_packet_list_mode(save_mode); if (rc == -1 && keyblock) rc = 0; /* got the entire keyblock */ if (rc || !ret_kb) release_kbnode (keyblock); else { /*(duplicated form the loop body)*/ if ( pkt && pkt->pkttype == PKT_RING_TRUST && lastnode && lastnode->pkt->pkttype == PKT_SIGNATURE && (pkt->pkt.ring_trust->sigcache & 1) ) { PKT_signature *sig = lastnode->pkt->pkt.signature; sig->flags.checked = 1; sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); } *ret_kb = keyblock; } free_packet (pkt); xfree (pkt); iobuf_close(a); /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ if (rc == G10ERR_INV_KEYRING) hd->current.error = rc; return rc; }
/* * Return the last found keyblock. Caller must free it. * The returned keyblock has the kbode flag bit 0 set for the node with * the public key used to locate the keyblock or flag bit 1 set for * the user ID node. */ int keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) { PACKET *pkt; struct parse_packet_ctx_s parsectx; int rc; KBNODE keyblock = NULL, node, lastnode; IOBUF a; int in_cert = 0; int pk_no = 0; int uid_no = 0; int save_mode; if (ret_kb) *ret_kb = NULL; if (!hd->found.kr) return -1; /* no successful search */ a = iobuf_open (hd->found.kr->fname); if (!a) { log_error(_("can't open '%s'\n"), hd->found.kr->fname); return GPG_ERR_KEYRING_OPEN; } if (iobuf_seek (a, hd->found.offset) ) { log_error ("can't seek '%s'\n", hd->found.kr->fname); iobuf_close(a); return GPG_ERR_KEYRING_OPEN; } pkt = xmalloc (sizeof *pkt); init_packet (pkt); init_parse_packet (&parsectx, a); hd->found.n_packets = 0; lastnode = NULL; save_mode = set_packet_list_mode(0); while ((rc=parse_packet (&parsectx, pkt)) != -1) { hd->found.n_packets = parsectx.n_parsed_packets; if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) { free_packet (pkt, &parsectx); init_packet (pkt); continue; } if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY) { if (in_cert) /* It is not this key that is problematic, but the following key. */ { rc = 0; hd->found.n_packets --; } else /* Upper layer needs to handle this. */ { } break; } if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", gpg_strerror (rc) ); rc = GPG_ERR_INV_KEYRING; break; } /* Filter allowed packets. */ switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: case PKT_USER_ID: case PKT_ATTRIBUTE: case PKT_SIGNATURE: break; /* Allowed per RFC. */ case PKT_RING_TRUST: case PKT_OLD_COMMENT: case PKT_COMMENT: case PKT_GPG_CONTROL: break; /* Allowed by us. */ default: log_info ("skipped packet of type %d in keyring\n", (int)pkt->pkttype); free_packet(pkt, &parsectx); init_packet(pkt); continue; } if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_SECRET_KEY)) { hd->found.n_packets--; /* fix counter */ break; /* ready */ } in_cert = 1; node = lastnode = new_kbnode (pkt); if (!keyblock) keyblock = node; else add_kbnode (keyblock, node); switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: if (++pk_no == hd->found.pk_no) node->flag |= 1; break; case PKT_USER_ID: if (++uid_no == hd->found.uid_no) node->flag |= 2; break; default: break; } pkt = xmalloc (sizeof *pkt); init_packet(pkt); } set_packet_list_mode(save_mode); if (rc == -1 && keyblock) rc = 0; /* got the entire keyblock */ if (rc || !ret_kb) release_kbnode (keyblock); else { *ret_kb = keyblock; } free_packet (pkt, &parsectx); deinit_parse_packet (&parsectx); xfree (pkt); iobuf_close(a); /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING) hd->current.error = rc; return rc; }