aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-12-15 08:55:36 +0100
committerWerner Koch <wk@gnupg.org>2020-12-15 13:36:19 +0100
commita2434ccabdd1956876b44e05e07c3c3630c50f8f (patch)
tree219da778f6b652d44611a977750943e9af03c4ed
parent2c6bb03cfb56b99acf5136e5143de336a82b7402 (diff)
downloadgnupg-a2434ccabdd1956876b44e05e07c3c3630c50f8f.tar.gz
dirmngr: Store all version 2 schema attributes.
* g10/call-dirmngr.c (ks_put_inq_cb): Emit "fpr" records. * dirmngr/ks-engine-ldap.c (extract_attributes): Add args extract-state and schemav2. Add data for the new schema version. remove the legacy code to handle UIDs in the "pub" line. (ks_ldap_put): Set new attributes for NTDS use the fingerprint as CN. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--dirmngr/ks-engine-ldap.c130
-rw-r--r--g10/call-dirmngr.c3
2 files changed, 88 insertions, 45 deletions
diff --git a/dirmngr/ks-engine-ldap.c b/dirmngr/ks-engine-ldap.c
index e8257fdbc..49d389266 100644
--- a/dirmngr/ks-engine-ldap.c
+++ b/dirmngr/ks-engine-ldap.c
@@ -46,6 +46,7 @@
#include "dirmngr.h"
#include "misc.h"
#include "../common/userids.h"
+#include "../common/mbox-util.h"
#include "ks-engine.h"
#include "ldap-parse-uri.h"
@@ -1629,15 +1630,16 @@ uncescape (char *str)
/* Given one line from an info block (`gpg --list-{keys,sigs}
--with-colons KEYID'), pull it apart and fill in the modlist with
- the relevant (for the LDAP schema) attributes. */
+ the relevant (for the LDAP schema) attributes. EXTRACT_STATE
+ should initally be set to 0 by the caller. SCHEMAV2 is set if the
+ server supports the version 2 schema. */
static void
-extract_attributes (LDAPMod ***modlist, char *line)
+extract_attributes (LDAPMod ***modlist, int *extract_state,
+ char *line, int schemav2)
{
int field_count;
char **fields;
-
char *keyid;
-
int is_pub, is_sub, is_uid, is_sig;
/* Remove trailing whitespace */
@@ -1652,24 +1654,42 @@ extract_attributes (LDAPMod ***modlist, char *line)
if (field_count < 7)
goto out;
- is_pub = strcasecmp ("pub", fields[0]) == 0;
- is_sub = strcasecmp ("sub", fields[0]) == 0;
- is_uid = strcasecmp ("uid", fields[0]) == 0;
- is_sig = strcasecmp ("sig", fields[0]) == 0;
+ is_pub = !ascii_strcasecmp ("pub", fields[0]);
+ is_sub = !ascii_strcasecmp ("sub", fields[0]);
+ is_uid = !ascii_strcasecmp ("uid", fields[0]);
+ is_sig = !ascii_strcasecmp ("sig", fields[0]);
+ if (!ascii_strcasecmp ("fpr", fields[0]))
+ {
+ /* Special treatment for a fingerprint. */
+ if (!(*extract_state & 1))
+ goto out; /* Stray fingerprint line - ignore. */
+ *extract_state &= ~1;
+ if (field_count >= 10 && schemav2)
+ {
+ if ((*extract_state & 2))
+ modlist_add (modlist, "gpgFingerprint", fields[9]);
+ else
+ modlist_add (modlist, "gpgSubFingerprint", fields[9]);
+ }
+ goto out;
+ }
+
+ *extract_state &= ~(1|2);
+ if (is_pub)
+ *extract_state |= (1|2);
+ else if (is_sub)
+ *extract_state |= 1;
if (!is_pub && !is_sub && !is_uid && !is_sig)
- /* Not a relevant line. */
- goto out;
+ goto out; /* Not a relevant line. */
keyid = fields[4];
if (is_uid && strlen (keyid) == 0)
- /* The uid record type can have an empty keyid. */
- ;
+ ; /* The uid record type can have an empty keyid. */
else if (strlen (keyid) == 16
&& strspn (keyid, "0123456789aAbBcCdDeEfF") == 16)
- /* Otherwise, we expect exactly 16 hex characters. */
- ;
+ ; /* Otherwise, we expect exactly 16 hex characters. */
else
{
log_error ("malformed record!\n");
@@ -1748,12 +1768,12 @@ extract_attributes (LDAPMod ***modlist, char *line)
{
if (is_pub)
{
- modlist_add (modlist, "pgpCertID", keyid);
- modlist_add (modlist, "pgpKeyID", &keyid[8]);
+ modlist_add (modlist, "pgpCertID", keyid); /* Long keyid(!) */
+ modlist_add (modlist, "pgpKeyID", &keyid[8]); /* Short keyid */
}
if (is_sub)
- modlist_add (modlist, "pgpSubKeyID", keyid);
+ modlist_add (modlist, "pgpSubKeyID", keyid); /* Long keyid(!) */
}
if (is_pub)
@@ -1851,25 +1871,22 @@ extract_attributes (LDAPMod ***modlist, char *line)
}
}
- if ((is_uid || is_pub) && field_count >= 10)
+ if (is_uid && field_count >= 10)
{
char *uid = fields[9];
+ char *mbox;
- if (is_pub && strlen (uid) == 0)
- /* When using gpg --list-keys, the uid is included. When
- passed via gpg, it is not. It is important to process it
- when it is present, because gpg 1 won't print a UID record
- if there is only one key. */
- ;
- else
- {
- uncescape (uid);
- modlist_add (modlist, "pgpUserID", uid);
- }
+ uncescape (uid);
+ modlist_add (modlist, "pgpUserID", uid);
+ if (schemav2 && (mbox = mailbox_from_userid (uid, 0)))
+ {
+ modlist_add (modlist, "gpgMailbox", mbox);
+ xfree (mbox);
+ }
}
out:
- free (fields);
+ xfree (fields);
}
/* Send the key in {KEY,KEYLEN} with the metadata {INFO,INFOLEN} to
@@ -1888,12 +1905,13 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
LDAPMod **modlist = NULL;
LDAPMod **addlist = NULL;
char *data_armored = NULL;
+ int extract_state;
/* The last byte of the info block. */
const char *infoend = (const char *) info + infolen - 1;
/* Enable this code to dump the modlist to /tmp/modlist.txt. */
-#if 0
+#if 1
# warning Disable debug code before checking in.
const int dump_modlist = 1;
#else
@@ -1995,9 +2013,15 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
modlist_add (&modlist, "pgpKeySize", NULL);
modlist_add (&modlist, "pgpKeyExpireTime", NULL);
modlist_add (&modlist, "pgpCertID", NULL);
+ if ((serverinfo & SERVERINFO_SCHEMAV2))
+ {
+ modlist_add (&modlist, "gpgFingerprint", NULL);
+ modlist_add (&modlist, "gpgSubFingerprint", NULL);
+ modlist_add (&modlist, "gpgMailbox", NULL);
+ }
/* Assemble the INFO stuff into LDAP attributes */
-
+ extract_state = 0;
while (infolen > 0)
{
char *temp = NULL;
@@ -2015,7 +2039,8 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
*newline = '\0';
- extract_attributes (&addlist, info);
+ extract_attributes (&addlist, &extract_state, info,
+ (serverinfo & SERVERINFO_SCHEMAV2));
infolen = infolen - ((uintptr_t) newline - (uintptr_t) info + 1);
info = newline + 1;
@@ -2061,22 +2086,37 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
keyserver) this does NOT merge signatures, but replaces the whole
key. This should make some people very happy. */
{
- char **certid;
+ char **attrval;
char *dn;
- certid = modlist_lookup (addlist, "pgpCertID");
- /* We should have exactly one value. */
- if (!certid || !(certid[0] && !certid[1]))
+ if ((serverinfo & SERVERINFO_NTDS))
{
- log_error ("ks-ldap: bad pgpCertID provided\n");
- err = GPG_ERR_GENERAL;
- goto out;
+ /* The modern way using a CN RDN with the fingerprint. This
+ * has the advantage that we won't have duplicate 64 bit
+ * keyids in the store. In particular NTDS requires the
+ * DN to be unique. */
+ attrval = modlist_lookup (addlist, "gpgFingerprint");
+ /* We should have exactly one value. */
+ if (!attrval || !(attrval[0] && !attrval[1]))
+ {
+ log_error ("ks-ldap: bad gpgFingerprint provided\n");
+ err = GPG_ERR_GENERAL;
+ goto out;
+ }
+ dn = xtryasprintf ("CN=%s,%s", attrval[0], basedn);
+ }
+ else /* The old style way. */
+ {
+ attrval = modlist_lookup (addlist, "pgpCertID");
+ /* We should have exactly one value. */
+ if (!attrval || !(attrval[0] && !attrval[1]))
+ {
+ log_error ("ks-ldap: bad pgpCertID provided\n");
+ err = GPG_ERR_GENERAL;
+ goto out;
+ }
+ dn = xtryasprintf ("pgpCertID=%s,%s", attrval[0], basedn);
}
-
- if ((serverinfo & SERVERINFO_NTDS))
- dn = xtryasprintf ("CN=%s,%s", certid[0], basedn);
- else
- dn = xtryasprintf ("pgpCertID=%s,%s", certid[0], basedn);
if (!dn)
{
err = gpg_error_from_syserror ();
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 1a4d896c6..17f5fdcf3 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -931,6 +931,7 @@ ks_put_inq_cb (void *opaque, const char *line)
{
kbnode_t node;
estream_t fp;
+ char hexfpr[2*MAX_FINGERPRINT_LEN+1];
/* Parse the keyblock and send info lines back to the server. */
fp = es_fopenmem (0, "rw,samethread");
@@ -988,6 +989,8 @@ ks_put_inq_cb (void *opaque, const char *line)
nbits_from_pk (pk), pk->pubkey_algo,
pk->keyid, pk->timestamp, pk->expiredate,
NULL);
+ es_fprintf (fp, "fpr:::::::::%s:\n",
+ hexfingerprint (pk, hexfpr, sizeof hexfpr));
}
break;