diff options
author | Werner Koch <[email protected]> | 2011-01-20 13:12:53 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2011-01-20 13:12:53 +0000 |
commit | 7f32d88ed1b81719e0cda11710fc66745deee6e2 (patch) | |
tree | 569ba918414268e5cee2eebaa7de3e23b6bbe277 /g10/call-dirmngr.c | |
parent | Keyserver search and get basically works again. (diff) | |
download | gnupg-7f32d88ed1b81719e0cda11710fc66745deee6e2.tar.gz gnupg-7f32d88ed1b81719e0cda11710fc66745deee6e2.zip |
All standard keyserver commands are now using dirmngr.
Diffstat (limited to 'g10/call-dirmngr.c')
-rw-r--r-- | g10/call-dirmngr.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index 1816a72d3..f34b94b60 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -59,6 +59,16 @@ struct ks_get_parm_s }; +/* Parameter structure used with the KS_PUT command. */ +struct ks_put_parm_s +{ + assuan_context_t ctx; + kbnode_t keyblock; /* The optional keyblock. */ + const void *data; /* The key in OpenPGP binary format. */ + size_t datalen; /* The length of DATA. */ +}; + + /* Data used to associate an session with dirmngr contexts. We can't use a simple one to one mapping because we sometimes need two connection s to the dirmngr; for example while doing a listing and @@ -436,3 +446,166 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, estream_t *r_fp) close_context (ctrl, ctx); return err; } + + + +/* Handle the KS_PUT inquiries. */ +static gpg_error_t +ks_put_inq_cb (void *opaque, const char *line) +{ + struct ks_put_parm_s *parm = opaque; + gpg_error_t err = 0; + + if (!strncmp (line, "KEYBLOCK", 8) && (line[8] == ' ' || !line[8])) + { + if (parm->data) + err = assuan_send_data (parm->ctx, parm->data, parm->datalen); + } + else if (!strncmp (line, "KEYBLOCK_INFO", 13) && (line[13]==' ' || !line[13])) + { + kbnode_t node; + estream_t fp; + + /* Parse the keyblock and send info lines back to the server. */ + fp = es_fopenmem (0, "rw"); + if (!fp) + err = gpg_error_from_syserror (); + + for (node = parm->keyblock; !err && node; node=node->next) + { + switch(node->pkt->pkttype) + { + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + { + PKT_public_key *pk = node->pkt->pkt.public_key; + + keyid_from_pk (pk, NULL); + + es_fprintf (fp, "%s:%08lX%08lX:%u:%u:%u:%u:%s%s:\n", + node->pkt->pkttype==PKT_PUBLIC_KEY? "pub" : "sub", + (ulong)pk->keyid[0], (ulong)pk->keyid[1], + pk->pubkey_algo, + nbits_from_pk (pk), + pk->timestamp, + pk->expiredate, + pk->flags.revoked? "r":"", + pk->has_expired? "e":""); + } + break; + + case PKT_USER_ID: + { + PKT_user_id *uid = node->pkt->pkt.user_id; + int r; + + if (!uid->attrib_data) + { + es_fprintf (fp, "uid:"); + + /* Quote ':', '%', and any 8-bit characters. */ + for (r=0; r < uid->len; r++) + { + if (uid->name[r] == ':' + || uid->name[r]== '%' + || (uid->name[r]&0x80)) + es_fprintf (fp, "%%%02X", (byte)uid->name[r]); + else + es_putc (uid->name[r], fp); + } + + es_fprintf (fp, ":%u:%u:%s%s:\n", + uid->created,uid->expiredate, + uid->is_revoked? "r":"", + uid->is_expired? "e":""); + } + } + break; + + /* This bit is really for the benefit of people who + store their keys in LDAP servers. It makes it easy + to do queries for things like "all keys signed by + Isabella". */ + case PKT_SIGNATURE: + { + PKT_signature *sig = node->pkt->pkt.signature; + + if (IS_UID_SIG (sig)) + { + es_fprintf (fp, "sig:%08lX%08lX:%X:%u:%u:\n", + (ulong)sig->keyid[0],(ulong)sig->keyid[1], + sig->sig_class, sig->timestamp, + sig->expiredate); + } + } + break; + + default: + continue; + } + /* Given that the last operation was an es_fprintf we should + get the correct ERRNO if ferror indicates an error. */ + if (es_ferror (fp)) + err = gpg_error_from_syserror (); + } + + /* Without an error and if we have an keyblock at all, send the + data back. */ + if (!err && parm->keyblock) + { + int rc; + char buffer[512]; + size_t nread; + + es_rewind (fp); + while (!(rc=es_read (fp, buffer, sizeof buffer, &nread)) && nread) + { + err = assuan_send_data (parm->ctx, buffer, nread); + if (err) + break; + } + if (!err && rc) + err = gpg_error_from_syserror (); + } + es_fclose (fp); + } + else + return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE); + + return err; +} + + +/* Send a key to the configured server. {DATA,DATLEN} contains the + key in OpenPGP binary transport format. If KEYBLOCK is not NULL it + has the internal representaion of that key; this is for example + used to convey meta data to LDAP keyservers. */ +gpg_error_t +gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock) +{ + gpg_error_t err; + assuan_context_t ctx; + struct ks_put_parm_s parm; + + memset (&parm, 0, sizeof parm); + + /* We are going to parse the keyblock, thus we better make sure the + all information is readily available. */ + if (keyblock) + merge_keys_and_selfsig (keyblock); + + err = open_context (ctrl, &ctx); + if (err) + return err; + + parm.ctx = ctx; + parm.keyblock = keyblock; + parm.data = data; + parm.datalen = datalen; + + err = assuan_transact (ctx, "KS_PUT", NULL, NULL, + ks_put_inq_cb, &parm, NULL, NULL); + + close_context (ctrl, ctx); + return err; +} |