aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/DETAILS37
-rw-r--r--g10/build-packet.c102
-rw-r--r--g10/export.c29
-rw-r--r--g10/free-packet.c6
-rw-r--r--g10/import.c20
-rw-r--r--g10/keydb.c6
-rw-r--r--g10/keydb.h13
-rw-r--r--g10/keyring.c61
-rw-r--r--g10/mainproc.c15
-rw-r--r--g10/packet.h41
-rw-r--r--g10/parse-packet.c184
11 files changed, 377 insertions, 137 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index 83d9fea75..1624315ff 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1311,6 +1311,43 @@ CREATE TABLE signatures (
S2K Specifier with an offset of 1000.
+* Format of the OpenPGP TRUST packet
+
+ According to RFC4880 (5.10), the trust packet (aka ring trust) is
+ only used within keyrings and contains data that records the user's
+ specifications of which key holds trusted introducers. The RFC also
+ states that the format of this packet is implementation defined and
+ SHOULD NOT be emitted to output streams or should be ignored on
+ import. GnuPG uses this packet in several additional ways:
+
+ - 1 octet :: Trust-Value (only used by Subtype SIG)
+ - 1 octet :: Signature-Cache (only used by Subtype SIG; value must
+ be less than 128)
+ - 3 octets :: Fixed value: "gpg"
+ - 1 octet :: Subtype
+ - 0 :: Signature cache (SIG)
+ - 1 :: Key source on the primary key (KEY)
+ - 2 :: Key source on a user id (UID)
+ - 1 octet :: Key Source; i.e. the origin of the key:
+ - 0 :: Unknown source.
+ - 1 :: Direct import from a file.
+ - 2 :: Public keyserver.
+ - 3 :: Preferred keysrver.
+ - 4 :: Web Key Directory.
+ - 5 :: Web Key Directory via sub-domain.
+ - 6 :: OpenPGP DANE.
+ - 4 octets :: Time of last update. This is a a four-octet scalar
+ with the seconds since Epoch.
+ - 1 octet :: Scalar with the length of the following field.
+ - N octets :: String with the URL of the source. This may be a
+ zero-length string.
+
+ If the packets contains only two octets a Subtype of 0 is assumed;
+ this is the only format recognized by GnuPG versions < 2.1.18.
+ Trust-Value and Signature-Cache must be zero for all subtypes other
+ than SIG.
+
+
* Keyserver helper message format
*This information is obsolete*
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 512e55c57..60e7d45e8 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -33,6 +33,7 @@
#include "options.h"
#include "../common/host2net.h"
+static gpg_error_t do_ring_trust (iobuf_t out, PKT_ring_trust *rt);
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
static int do_key (iobuf_t out, int ctb, PKT_public_key *pk);
static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
@@ -76,14 +77,11 @@ ctb_pkttype (int ctb)
return (ctb & ((1 << 6) - 1)) >> 2;
}
-/****************
- * Build a packet and write it to INP
- * Returns: 0 := okay
- * >0 := error
- * Note: Caller must free the packet
- */
+
+/* Build a packet and write it to the stream OUT.
+ * Returns: 0 on success or on an error code. */
int
-build_packet( IOBUF out, PACKET *pkt )
+build_packet (IOBUF out, PACKET *pkt)
{
int rc = 0;
int new_ctb = 0;
@@ -170,7 +168,7 @@ build_packet( IOBUF out, PACKET *pkt )
rc = do_onepass_sig (out, ctb, pkt->pkt.onepass_sig);
break;
case PKT_RING_TRUST:
- /* Ignore it (keyring.c does write it directly) */
+ /* Ignore it (only written by build_packet_and_meta) */
break;
case PKT_MDC:
/* We write it directly, so we should never see it here. */
@@ -183,6 +181,62 @@ build_packet( IOBUF out, PACKET *pkt )
}
+/* Build a packet and write it to the stream OUT. This variant also
+ * writes the meta data using ring tyrust packets. Returns: 0 on
+ * success or on aerror code. */
+gpg_error_t
+build_packet_and_meta (iobuf_t out, PACKET *pkt)
+{
+ gpg_error_t err;
+ PKT_ring_trust rt = {0};
+
+ err = build_packet (out, pkt);
+ if (err)
+ ;
+ else if (pkt->pkttype == PKT_SIGNATURE)
+ {
+ PKT_signature *sig = pkt->pkt.signature;
+
+ rt.subtype = RING_TRUST_SIG;
+ /* Note: trustval is not yet used. */
+ if (sig->flags.checked)
+ {
+ rt.sigcache = 1;
+ if (sig->flags.valid)
+ rt.sigcache |= 2;
+ }
+ err = do_ring_trust (out, &rt);
+ }
+ else if (pkt->pkttype == PKT_USER_ID
+ || pkt->pkttype == PKT_ATTRIBUTE)
+ {
+ PKT_user_id *uid = pkt->pkt.user_id;
+
+ rt.subtype = RING_TRUST_UID;
+ rt.keysrc = uid->keysrc;
+ rt.keyupdate = uid->keyupdate;
+ rt.url = uid->updateurl;
+ err = do_ring_trust (out, &rt);
+ rt.url = NULL;
+ }
+ else if (pkt->pkttype == PKT_PUBLIC_KEY
+ || pkt->pkttype == PKT_SECRET_KEY)
+ {
+ PKT_public_key *pk = pkt->pkt.public_key;
+
+ rt.subtype = RING_TRUST_KEY;
+ rt.keysrc = pk->keysrc;
+ rt.keyupdate = pk->keyupdate;
+ rt.url = pk->updateurl;
+ err = do_ring_trust (out, &rt);
+ rt.url = NULL;
+
+ }
+
+ return err;
+}
+
+
/*
* Write the mpi A to OUT.
*/
@@ -320,6 +374,38 @@ write_fake_data (IOBUF out, gcry_mpi_t a)
}
+/* Write a ring trust meta packet. */
+static gpg_error_t
+do_ring_trust (iobuf_t out, PKT_ring_trust *rt)
+{
+ unsigned int namelen = 0;
+ unsigned int pktlen = 6;
+
+ if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
+ {
+ if (rt->url)
+ namelen = strlen (rt->url);
+ pktlen += 1 + 4 + 1 + namelen;
+ }
+
+ write_header (out, (0x80 | ((PKT_RING_TRUST & 15)<<2)), pktlen);
+ iobuf_put (out, rt->trustval);
+ iobuf_put (out, rt->sigcache);
+ iobuf_write (out, "gpg", 3);
+ iobuf_put (out, rt->subtype);
+ if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
+ {
+ iobuf_put (out, rt->keysrc);
+ write_32 (out, rt->keyupdate);
+ iobuf_put (out, namelen);
+ if (namelen)
+ iobuf_write (out, rt->url, namelen);
+ }
+
+ return 0;
+}
+
+
/* Serialize the user id (RFC 4880, Section 5.11) or the user
* attribute UID (Section 5.12) and write it to OUT.
*
diff --git a/g10/export.c b/g10/export.c
index 5b0c81ded..e2adcc4ab 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1284,14 +1284,17 @@ write_keyblock_to_output (kbnode_t keyblock, int with_armor,
{
if (is_deleted_kbnode (node))
continue;
- if (node->pkt->pkttype == PKT_RING_TRUST && !(options & EXPORT_BACKUP))
- continue;
+ if (node->pkt->pkttype == PKT_RING_TRUST)
+ continue; /* Skip - they should not be here anyway. */
if (!pk && (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY))
pk = node->pkt->pkt.public_key;
- err = build_packet (out_help? out_help : out, node->pkt);
+ if ((options & EXPORT_BACKUP))
+ err = build_packet_and_meta (out_help? out_help : out, node->pkt);
+ else
+ err = build_packet (out_help? out_help : out, node->pkt);
if (err)
{
log_error ("build_packet(%d) failed: %s\n",
@@ -1555,9 +1558,8 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
if (node->pkt->pkttype == PKT_COMMENT)
continue;
- /* Make sure that ring_trust packets are only exported in backup
- * mode. */
- if (node->pkt->pkttype == PKT_RING_TRUST && !(options & EXPORT_BACKUP))
+ /* Skip ring trust packets - they should not ne here anyway. */
+ if (node->pkt->pkttype == PKT_RING_TRUST)
continue;
/* If exact is set, then we only export what was requested
@@ -1723,7 +1725,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
ski->iv[ski->ivlen] = xtoi_2 (s);
}
- err = build_packet (out, node->pkt);
+ if ((options & EXPORT_BACKUP))
+ err = build_packet_and_meta (out, node->pkt);
+ else
+ err = build_packet (out, node->pkt);
if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
{
stats->exported++;
@@ -1744,7 +1749,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
}
else
{
- err = build_packet (out, node->pkt);
+ if ((options & EXPORT_BACKUP))
+ err = build_packet_and_meta (out, node->pkt);
+ else
+ err = build_packet (out, node->pkt);
if (node->pkt->pkttype == PKT_PUBLIC_KEY)
{
stats->exported++;
@@ -1775,7 +1783,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
}
else /* Not secret or common packets. */
{
- err = build_packet (out, node->pkt);
+ if ((options & EXPORT_BACKUP))
+ err = build_packet_and_meta (out, node->pkt);
+ else
+ err = build_packet (out, node->pkt);
if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
{
stats->exported++;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 535a17fb8..c14424660 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -127,6 +127,11 @@ release_public_key_parts (PKT_public_key *pk)
xfree (pk->serialno);
pk->serialno = NULL;
}
+ if (pk->updateurl)
+ {
+ xfree (pk->updateurl);
+ pk->updateurl = NULL;
+ }
}
@@ -314,6 +319,7 @@ free_user_id (PKT_user_id *uid)
free_attributes(uid);
xfree (uid->prefs);
xfree (uid->namehash);
+ xfree (uid->updateurl);
xfree (uid->mbox);
xfree (uid);
}
diff --git a/g10/import.c b/g10/import.c
index 3321a7eb8..d43b2a8e3 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -97,8 +97,8 @@ static int import (ctrl_t ctrl,
IOBUF inp, const char* fname, struct import_stats_s *stats,
unsigned char **fpr, size_t *fpr_len, unsigned int options,
import_screener_t screener, void *screener_arg);
-static int read_block (IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root,
- int *r_v3keys);
+static int read_block (IOBUF a, int with_meta,
+ PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys);
static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
static int import_one (ctrl_t ctrl,
kbnode_t keyblock,
@@ -333,7 +333,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
}
/* Read the first non-v3 keyblock. */
- while (!(err = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+ while (!(err = read_block (inp, 0, &pending_pkt, &keyblock, &v3keys)))
{
if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
break;
@@ -563,7 +563,8 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
release_armor_context (afx);
}
- while (!(rc = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+ while (!(rc = read_block (inp, !!(options & IMPORT_RESTORE),
+ &pending_pkt, &keyblock, &v3keys)))
{
stats->v3keys += v3keys;
if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
@@ -637,7 +638,7 @@ import_old_secring (ctrl_t ctrl, const char *fname)
getkey_disable_caches();
stats = import_new_stats_handle ();
- while (!(err = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+ while (!(err = read_block (inp, 0, &pending_pkt, &keyblock, &v3keys)))
{
if (keyblock->pkt->pkttype == PKT_SECRET_KEY)
err = import_secret_one (ctrl, keyblock, stats, 1, 0, 1,
@@ -752,14 +753,15 @@ valid_keyblock_packet (int pkttype)
/****************
* Read the next keyblock from stream A.
- * PENDING_PKT should be initialzed to NULL
- * and not changed by the caller.
+ * Meta data (ring trust packets) are only considered of WITH_META is set.
+ * PENDING_PKT should be initialzed to NULL and not changed by the caller.
* Return: 0 = okay, -1 no more blocks or another errorcode.
* The int at at R_V3KEY counts the number of unsupported v3
* keyblocks.
*/
static int
-read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
+read_block( IOBUF a, int with_meta,
+ PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
{
int rc;
struct parse_packet_ctx_s parsectx;
@@ -781,6 +783,8 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
pkt = xmalloc (sizeof *pkt);
init_packet (pkt);
init_parse_packet (&parsectx, a);
+ if (!with_meta)
+ parsectx.skip_meta = 1;
in_v3key = 0;
while ((rc=parse_packet (&parsectx, pkt)) != -1)
{
diff --git a/g10/keydb.c b/g10/keydb.c
index 1bbda35c7..67957f83e 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -1202,6 +1202,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
case PKT_USER_ID:
case PKT_ATTRIBUTE:
case PKT_SIGNATURE:
+ case PKT_RING_TRUST:
break; /* Allowed per RFC. */
default:
@@ -1458,14 +1459,13 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
case PKT_SIGNATURE:
case PKT_USER_ID:
case PKT_ATTRIBUTE:
- /* Note that we don't want the ring trust packets. They are
- not useful. */
+ case PKT_RING_TRUST:
break;
default:
continue;
}
- err = build_packet (iobuf, node->pkt);
+ err = build_packet_and_meta (iobuf, node->pkt);
if (err)
{
iobuf_close (iobuf);
diff --git a/g10/keydb.h b/g10/keydb.h
index 6f57583fd..2de52d504 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -119,6 +119,19 @@ union pref_hint
};
+/* Constants to describe from where a key was fetched or updated. */
+enum
+ {
+ KEYSRC_UNKNOWN = 0,
+ KEYSRC_FILE = 1, /* Direct import from a file. */
+ KEYSRC_KS = 2, /* Public keyserver. */
+ KEYSRC_PREF_KS = 3, /* Preferred keysrver. */
+ KEYSRC_WKD = 4, /* Web Key Directory. */
+ KEYSRC_WKD_SD = 5, /* Web Key Directory but from a sub domain. */
+ KEYSRC_DANE = 6 /* OpenPGP DANE. */
+ };
+
+
/*-- keydb.c --*/
#define KEYDB_RESOURCE_FLAG_PRIMARY 2 /* The primary resource. */
diff --git a/g10/keyring.c b/g10/keyring.c
index 2210df9c0..e7ebbb38b 100644
--- a/g10/keyring.c
+++ b/g10/keyring.c
@@ -473,29 +473,6 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
}
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 following a signature. */
- lastnode = NULL;
- free_packet(pkt, &parsectx);
- init_packet(pkt);
- continue;
- }
-
-
node = lastnode = new_kbnode (pkt);
if (!keyblock)
keyblock = node;
@@ -531,16 +508,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
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;
- sig->flags.checked = 1;
- sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
- }
- *ret_kb = keyblock;
+ *ret_kb = keyblock;
}
free_packet (pkt, &parsectx);
deinit_parse_packet (&parsectx);
@@ -1420,36 +1388,12 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
{
- if (node->pkt->pkttype == PKT_RING_TRUST)
- continue; /* we write it later on our own */
-
- if ( (rc = build_packet (fp, node->pkt) ))
+ if ( (rc = build_packet_and_meta (fp, node->pkt) ))
{
log_error ("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_strerror (rc) );
return rc;
}
- if (node->pkt->pkttype == PKT_SIGNATURE)
- { /* always write a signature cache packet */
- PKT_signature *sig = node->pkt->pkt.signature;
- unsigned int cacheval = 0;
-
- if (sig->flags.checked)
- {
- cacheval |= 1;
- if (sig->flags.valid)
- cacheval |= 2;
- }
- iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
- iobuf_put (fp, 2); /* 2 bytes */
- iobuf_put (fp, 0); /* unused */
- if (iobuf_put (fp, cacheval))
- {
- rc = gpg_error_from_syserror ();
- log_error ("writing sigcache packet failed\n");
- return rc;
- }
- }
}
return 0;
}
@@ -1640,6 +1584,7 @@ keyring_rebuild_cache (void *token,int noisy)
return rc;
}
+
/****************
* Perform insert/delete/update operation.
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 8581104de..7b2c4567c 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1046,13 +1046,6 @@ list_node (CTX c, kbnode_t node)
else if ((pk->flags.primary && opt.fingerprint) || opt.fingerprint > 1)
print_fingerprint (NULL, pk, 0);
- if (opt.with_colons)
- {
- if (node->next && node->next->pkt->pkttype == PKT_RING_TRUST)
- es_printf ("rtv:1:%u:\n",
- node->next->pkt->pkt.ring_trust->trustval);
- }
-
if (pk->flags.primary)
{
int kl = opt.keyid_format == KF_NONE? 0 : keystrlen ();
@@ -1077,14 +1070,6 @@ list_node (CTX c, kbnode_t node)
if (opt.with_colons)
es_putc (':', es_stdout);
es_putc ('\n', es_stdout);
- if (opt.with_colons
- && node->next
- && node->next->pkt->pkttype == PKT_RING_TRUST)
- {
- es_printf ("rtv:2:%u:\n",
- node->next->pkt->pkt.ring_trust?
- node->next->pkt->pkt.ring_trust->trustval : 0);
- }
}
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
diff --git a/g10/packet.h b/g10/packet.h
index ad6f317e7..b23298aac 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -283,20 +283,25 @@ typedef struct
u32 expiredate; /* expires at this date or 0 if not at all */
prefitem_t *prefs; /* list of preferences (may be NULL)*/
u32 created; /* according to the self-signature */
+ u32 keyupdate; /* From the ring trust packet. */
+ char *updateurl; /* NULL or the URL of the last update origin. */
+ byte keysrc; /* From the ring trust packet. */
byte selfsigversion;
struct
{
unsigned int mdc:1;
unsigned int ks_modify:1;
unsigned int compacted:1;
- unsigned int primary:2; /* 2 if set via the primary flag, 1 if calculated */
+ unsigned int primary:2; /* 2 if set via the primary flag, 1 if calculated */
unsigned int revoked:1;
unsigned int expired:1;
} flags;
+
char *mbox; /* NULL or the result of mailbox_from_userid. */
+
/* The text contained in the user id packet, which is normally the
- name and email address of the key holder (See RFC 4880 5.11).
- (Serialized.). For convenience an extra Nul is always appended. */
+ * name and email address of the key holder (See RFC 4880 5.11).
+ * (Serialized.). For convenience an extra Nul is always appended. */
char name[1];
} PKT_user_id;
@@ -402,6 +407,9 @@ typedef struct
u32 trust_timestamp;
byte trust_depth;
byte trust_value;
+ byte keysrc; /* From the ring trust packet. */
+ u32 keyupdate; /* From the ring trust packet. */
+ char *updateurl; /* NULL or the URL of the last update origin. */
const byte *trust_regexp;
char *serialno; /* Malloced hex string or NULL if it is
likely not on a card. See also
@@ -474,11 +482,28 @@ typedef struct {
byte hash[20];
} PKT_mdc;
+
+/* Subtypes for the ring trust packet. */
+#define RING_TRUST_SIG 0 /* The classical signature cache. */
+#define RING_TRUST_KEY 1 /* A KEYSRC on a primary key. */
+#define RING_TRUST_UID 2 /* A KEYSRC on a user id. */
+
+/* The local only ring trust packet which OpenPGP declares as
+ * implementation defined. GnuPG uses this to cache signature
+ * verification status and since 2.1.18 also to convey information
+ * about the origin of a key. Note that this packet is not part
+ * struct packet_struct becuase we use it only local in the packet
+ * parser and builder. */
typedef struct {
- unsigned int trustval;
- unsigned int sigcache;
+ unsigned int trustval;
+ unsigned int sigcache;
+ unsigned char subtype; /* The subtype of this ring trust packet. */
+ unsigned char keysrc; /* The origin of the key (KEYSRC_*). */
+ u32 keyupdate; /* The wall time the key was last updated. */
+ char *url; /* NULL or the URL of the source. */
} PKT_ring_trust;
+
/* A plaintext packet (see RFC 4880, 5.9). */
typedef struct {
/* The length of data in BUF or 0 if unknown. */
@@ -519,7 +544,6 @@ struct packet_struct {
PKT_compressed *compressed; /* PKT_COMPRESSED */
PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */
PKT_mdc *mdc; /* PKT_MDC */
- PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */
PKT_plaintext *plaintext; /* PKT_PLAINTEXT */
PKT_gpg_control *gpg_control; /* PKT_GPG_CONTROL */
} pkt;
@@ -599,6 +623,7 @@ struct parse_packet_ctx_s
iobuf_t inp; /* The input stream with the packets. */
PACKET *last_pkt; /* The last parsed packet. */
int free_last_pkt; /* Indicates that LAST_PKT must be freed. */
+ int skip_meta; /* Skip right trust packets. */
};
typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
@@ -606,6 +631,7 @@ typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
(a)->inp = (i); \
(a)->last_pkt = NULL; \
(a)->free_last_pkt = 0; \
+ (a)->skip_meta = 0; \
} while (0)
#define deinit_parse_packet(a) do { \
@@ -786,7 +812,8 @@ PACKET *create_gpg_control ( ctrlpkttype_t type,
size_t datalen );
/*-- build-packet.c --*/
-int build_packet( iobuf_t inp, PACKET *pkt );
+int build_packet (iobuf_t out, PACKET *pkt);
+gpg_error_t build_packet_and_meta (iobuf_t out, PACKET *pkt);
gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a);
gpg_error_t gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a);
u32 calc_packet_length( PACKET *pkt );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index ab273a5fa..df04fbc8b 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -74,8 +74,8 @@ static int parse_attribute (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet);
static int parse_comment (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet);
-static void parse_trust (IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET * packet);
+static gpg_error_t parse_ring_trust (parse_packet_ctx_t ctx,
+ unsigned long pktlen);
static int parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen,
PACKET * packet, int new_ctb, int partial);
static int parse_compressed (IOBUF inp, int pkttype, unsigned long pktlen,
@@ -542,6 +542,7 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
*skip = 0;
inp = ctx->inp;
+ again:
log_assert (!pkt->pkt.generic);
if (retpos || list_mode)
{
@@ -800,8 +801,11 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
rc = parse_comment (inp, pkttype, pktlen, pkt);
break;
case PKT_RING_TRUST:
- parse_trust (inp, pkttype, pktlen, pkt);
- rc = 0;
+ {
+ rc = parse_ring_trust (ctx, pktlen);
+ if (!rc)
+ goto again; /* Directly read the next packet. */
+ }
break;
case PKT_PLAINTEXT:
rc = parse_plaintext (inp, pkttype, pktlen, pkt, new_ctb, partial);
@@ -2873,42 +2877,164 @@ parse_comment (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet)
}
-static void
-parse_trust (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt)
+/* Parse a ring trust packet RFC4880 (5.10).
+ *
+ * This parser is special in that the packet is not stored as a packet
+ * but its content is merged into the previous packet. */
+static gpg_error_t
+parse_ring_trust (parse_packet_ctx_t ctx, unsigned long pktlen)
{
+ gpg_error_t err;
+ iobuf_t inp = ctx->inp;
+ PKT_ring_trust rt = {0};
int c;
+ int not_gpg = 0;
- (void) pkttype;
+ if (!pktlen)
+ {
+ if (list_mode)
+ es_fprintf (listfp, ":trust packet: empty\n");
+ err = 0;
+ goto leave;
+ }
- pkt->pkt.ring_trust = xmalloc (sizeof *pkt->pkt.ring_trust);
+ c = iobuf_get_noeof (inp);
+ pktlen--;
+ rt.trustval = c;
if (pktlen)
{
- c = iobuf_get_noeof (inp);
+ if (!c)
+ {
+ c = iobuf_get_noeof (inp);
+ /* We require that bit 7 of the sigcache is 0 (easier
+ * eof handling). */
+ if (!(c & 0x80))
+ rt.sigcache = c;
+ }
+ else
+ iobuf_get_noeof (inp); /* Dummy read. */
pktlen--;
- pkt->pkt.ring_trust->trustval = c;
- pkt->pkt.ring_trust->sigcache = 0;
- if (!c && pktlen == 1)
- {
- c = iobuf_get_noeof (inp);
- pktlen--;
- /* We require that bit 7 of the sigcache is 0 (easier eof
- handling). */
- if (!(c & 0x80))
- pkt->pkt.ring_trust->sigcache = c;
- }
- if (list_mode)
- es_fprintf (listfp, ":trust packet: flag=%02x sigcache=%02x\n",
- pkt->pkt.ring_trust->trustval,
- pkt->pkt.ring_trust->sigcache);
}
- else
+
+ /* Next is the optional subtype. */
+ if (pktlen > 3)
{
- pkt->pkt.ring_trust->trustval = 0;
- pkt->pkt.ring_trust->sigcache = 0;
- if (list_mode)
- es_fprintf (listfp, ":trust packet: empty\n");
+ char tmp[4];
+ tmp[0] = iobuf_get_noeof (inp);
+ tmp[1] = iobuf_get_noeof (inp);
+ tmp[2] = iobuf_get_noeof (inp);
+ tmp[3] = iobuf_get_noeof (inp);
+ pktlen -= 4;
+ if (!memcmp (tmp, "gpg", 3))
+ rt.subtype = tmp[3];
+ else
+ not_gpg = 1;
}
+ /* If it is a key or uid subtype read the remaining data. */
+ if ((rt.subtype == RING_TRUST_KEY || rt.subtype == RING_TRUST_UID)
+ && pktlen >= 6 )
+ {
+ int i;
+ unsigned int namelen;
+
+ rt.keysrc = iobuf_get_noeof (inp);
+ pktlen--;
+ rt.keyupdate = read_32 (inp);
+ pktlen -= 4;
+ namelen = iobuf_get_noeof (inp);
+ pktlen--;
+ if (namelen && pktlen)
+ {
+ rt.url = xtrymalloc (namelen + 1);
+ if (rt.url)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ for (i = 0; pktlen && i < namelen; pktlen--, i++)
+ rt.url[i] = iobuf_get_noeof (inp);
+ rt.url[i] = 0;
+ }
+ }
+
+ if (list_mode)
+ {
+ if (rt.subtype == RING_TRUST_SIG)
+ es_fprintf (listfp, ":trust packet: sig flag=%02x sigcache=%02x\n",
+ rt.trustval, rt.sigcache);
+ else if (rt.subtype == RING_TRUST_UID || rt.subtype == RING_TRUST_KEY)
+ {
+ unsigned char *p;
+
+ es_fprintf (listfp, ":trust packet: %s upd=%lu src=%d%s",
+ (rt.subtype == RING_TRUST_UID? "uid" : "key"),
+ (unsigned long)rt.keyupdate,
+ rt.keysrc,
+ (rt.url? " url=":""));
+ if (rt.url)
+ {
+ for (p = rt.url; *p; p++)
+ {
+ if (*p >= ' ' && *p <= 'z')
+ es_putc (*p, listfp);
+ else
+ es_fprintf (listfp, "\\x%02x", *p);
+ }
+ }
+ es_putc ('\n', listfp);
+ }
+ else if (not_gpg)
+ es_fprintf (listfp, ":trust packet: not created by gpg\n");
+ else
+ es_fprintf (listfp, ":trust packet: subtype=%02x\n",
+ rt.subtype);
+ }
+
+ /* Now transfer the data to the respective packet. Do not do this
+ * if SKIP_META is set. */
+ if (!ctx->last_pkt || ctx->skip_meta)
+ ;
+ else if (rt.subtype == RING_TRUST_SIG
+ && ctx->last_pkt->pkttype == PKT_SIGNATURE)
+ {
+ PKT_signature *sig = ctx->last_pkt->pkt.signature;
+
+ if ((rt.sigcache & 1))
+ {
+ sig->flags.checked = 1;
+ sig->flags.valid = !!(rt.sigcache & 2);
+ }
+ }
+ else if (rt.subtype == RING_TRUST_UID
+ && (ctx->last_pkt->pkttype == PKT_USER_ID
+ || ctx->last_pkt->pkttype == PKT_ATTRIBUTE))
+ {
+ PKT_user_id *uid = ctx->last_pkt->pkt.user_id;
+
+ uid->keysrc = rt.keysrc;
+ uid->keyupdate = rt.keyupdate;
+ uid->updateurl = rt.url;
+ rt.url = NULL;
+ }
+ else if (rt.subtype == RING_TRUST_KEY
+ && (ctx->last_pkt->pkttype == PKT_PUBLIC_KEY
+ || ctx->last_pkt->pkttype == PKT_SECRET_KEY))
+ {
+ PKT_public_key *pk = ctx->last_pkt->pkt.public_key;
+
+ pk->keysrc = rt.keysrc;
+ pk->keyupdate = rt.keyupdate;
+ pk->updateurl = rt.url;
+ rt.url = NULL;
+ }
+
+ err = 0;
+
+ leave:
+ xfree (rt.url);
+ free_packet (NULL, ctx); /* This sets ctx->last_pkt to NULL. */
iobuf_skip_rest (inp, pktlen, 0);
+ return err;
}