1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-11-10 21:38:50 +01:00

dirmngr: For KS_SEARCH return the fingerprint also with LDAP.

* dirmngr/ks-engine-ldap.c (extract_keys): Return the fingerprint if
available.
(ks_ldap_search): Ditto.
(extract_keys): Make sure to free the ldap values also in corner
cases.
(my_ldap_value_free): New.
(ks_ldap_get): Ditto.
(ks_ldap_search): Ditto.
(my_ldap_connect): Ditto.
--

For background see these comments from gpgme:

/* The output for external keylistings in GnuPG is different from all
   the other key listings.  We catch this here with a special
   preprocessor that reformats the colon handler lines.  */
/* The format is:

   pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>

   as defined in 5.2. Machine Readable Indexes of the OpenPGP
   HTTP Keyserver Protocol (draft).  Modern versions of the SKS
   keyserver return the fingerprint instead of the keyid.  We
   detect this here and use the v4 fingerprint format to convert
   it to a key id.

   We want:
   pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
*/

Regarding the freeing of values: I was not able to find a
specification stating it is okay to pass NULL to ldap_value_free, thus
the new wrapper.  Also add robustness measures in case ldap_get_value
returns an empty array.

GnuPG-bug-id: 5441
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2021-05-19 17:18:15 +02:00
parent cf9a0bc2ec
commit f0e538619d
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B

View File

@ -295,6 +295,16 @@ epoch2ldaptime (time_t stamp)
return xstrdup ("INVALID TIME"); return xstrdup ("INVALID TIME");
} }
#endif #endif
static void
my_ldap_value_free (char **vals)
{
if (vals)
ldap_value_free (vals);
}
/* Print a help output for the schemata supported by this module. */ /* Print a help output for the schemata supported by this module. */
gpg_error_t gpg_error_t
@ -697,26 +707,26 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
{ {
vals = ldap_get_values (ldap_conn, si_res, vals = ldap_get_values (ldap_conn, si_res,
"pgpBaseKeySpaceDN"); "pgpBaseKeySpaceDN");
if (vals) if (vals && vals[0])
{ {
basedn = xtrystrdup (vals[0]); basedn = xtrystrdup (vals[0]);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, si_res, vals = ldap_get_values (ldap_conn, si_res,
"pgpSoftware"); "pgpSoftware");
if (vals) if (vals && vals[0])
{ {
if (opt.debug) if (opt.debug)
log_debug ("Server: \t%s\n", vals[0]); log_debug ("Server: \t%s\n", vals[0]);
if (!ascii_strcasecmp (vals[0], "GnuPG")) if (!ascii_strcasecmp (vals[0], "GnuPG"))
is_gnupg = 1; is_gnupg = 1;
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, si_res, vals = ldap_get_values (ldap_conn, si_res,
"pgpVersion"); "pgpVersion");
if (vals) if (vals && vals[0])
{ {
if (opt.debug) if (opt.debug)
log_debug ("Version:\t%s\n", vals[0]); log_debug ("Version:\t%s\n", vals[0]);
@ -732,8 +742,8 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
&& !ascii_strcasecmp (fields[1], "ntds")) && !ascii_strcasecmp (fields[1], "ntds"))
*r_serverinfo |= SERVERINFO_NTDS; *r_serverinfo |= SERVERINFO_NTDS;
} }
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
} }
/* From man ldap_search_s: "res parameter of /* From man ldap_search_s: "res parameter of
@ -766,22 +776,22 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
* in the future. */ * in the future. */
vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN"); vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN");
if (vals) if (vals && vals[0])
{ {
basedn = xtrystrdup (vals[0]); basedn = xtrystrdup (vals[0]);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, si_res, "software"); vals = ldap_get_values (ldap_conn, si_res, "software");
if (vals) if (vals && vals[0])
{ {
if (opt.debug) if (opt.debug)
log_debug ("ks-ldap: PGP Server: \t%s\n", vals[0]); log_debug ("ks-ldap: PGP Server: \t%s\n", vals[0]);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, si_res, "version"); vals = ldap_get_values (ldap_conn, si_res, "version");
if (vals) if (vals && vals[0])
{ {
if (opt.debug) if (opt.debug)
log_debug ("ks-ldap: PGP Server Version:\t%s\n", vals[0]); log_debug ("ks-ldap: PGP Server Version:\t%s\n", vals[0]);
@ -795,8 +805,8 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
if (atoi (vals[0]) > 1) if (atoi (vals[0]) > 1)
*r_serverinfo |= SERVERINFO_PGPKEYV2; *r_serverinfo |= SERVERINFO_PGPKEYV2;
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
} }
ldap_msgfree (si_res); ldap_msgfree (si_res);
@ -850,10 +860,17 @@ extract_keys (estream_t output,
char **vals; char **vals;
es_fprintf (output, "INFO %s BEGIN\n", certid); es_fprintf (output, "INFO %s BEGIN\n", certid);
es_fprintf (output, "pub:%s:", certid);
/* Note: ldap_get_values returns a NULL terminated array of /* Note: ldap_get_values returns a NULL terminated array of
strings. */ strings. */
vals = ldap_get_values (ldap_conn, message, "gpgfingerprint");
if (vals && vals[0] && vals[0][0])
es_fprintf (output, "pub:%s:", vals[0]);
else
es_fprintf (output, "pub:%s:", certid);
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, message, "pgpkeytype"); vals = ldap_get_values (ldap_conn, message, "pgpkeytype");
if (vals && vals[0]) if (vals && vals[0])
{ {
@ -861,8 +878,8 @@ extract_keys (estream_t output,
es_fprintf (output, "1"); es_fprintf (output, "1");
else if (strcmp (vals[0],"DSS/DH") == 0) else if (strcmp (vals[0],"DSS/DH") == 0)
es_fprintf (output, "17"); es_fprintf (output, "17");
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, ":"); es_fprintf (output, ":");
@ -872,8 +889,8 @@ extract_keys (estream_t output,
int v = atoi (vals[0]); int v = atoi (vals[0]);
if (v > 0) if (v > 0)
es_fprintf (output, "%d", v); es_fprintf (output, "%d", v);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, ":"); es_fprintf (output, ":");
@ -882,8 +899,8 @@ extract_keys (estream_t output,
{ {
if (strlen (vals[0]) == 15) if (strlen (vals[0]) == 15)
es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0])); es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, ":"); es_fprintf (output, ":");
@ -892,8 +909,8 @@ extract_keys (estream_t output,
{ {
if (strlen (vals[0]) == 15) if (strlen (vals[0]) == 15)
es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0])); es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, ":"); es_fprintf (output, ":");
@ -902,8 +919,8 @@ extract_keys (estream_t output,
{ {
if (atoi (vals[0]) == 1) if (atoi (vals[0]) == 1)
es_fprintf (output, "r"); es_fprintf (output, "r");
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, "\n"); es_fprintf (output, "\n");
@ -913,8 +930,8 @@ extract_keys (estream_t output,
int i; int i;
for (i = 0; vals[i]; i++) for (i = 0; vals[i]; i++)
es_fprintf (output, "uid:%s\n", vals[i]); es_fprintf (output, "uid:%s\n", vals[i]);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fprintf (output, "INFO %s END\n", certid); es_fprintf (output, "INFO %s END\n", certid);
} }
@ -973,6 +990,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
"dummy", "dummy",
"pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled", "pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
"pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype", "pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
"gpgfingerprint",
NULL NULL
}; };
/* 1 if we want just attribute types; 0 if we want both attribute /* 1 if we want just attribute types; 0 if we want both attribute
@ -1075,7 +1093,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
} }
} }
ldap_value_free (certid); my_ldap_value_free (certid);
} }
free_strlist (seen); free_strlist (seen);
@ -1180,7 +1198,8 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
{ {
"pgpcertid", "pgpuserid", "pgprevoked", "pgpdisabled", "pgpcertid", "pgpuserid", "pgprevoked", "pgpdisabled",
"pgpkeycreatetime", "pgpkeyexpiretime", "modifytimestamp", "pgpkeycreatetime", "pgpkeyexpiretime", "modifytimestamp",
"pgpkeysize", "pgpkeytype", NULL "pgpkeysize", "pgpkeytype", "gpgfingerprint",
NULL
}; };
if (opt.debug) if (opt.debug)
@ -1220,6 +1239,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
add_to_strlist (&dupelist, certid[0]); add_to_strlist (&dupelist, certid[0]);
count++; count++;
} }
my_ldap_value_free (certid);
} }
if (ldap_err == LDAP_SIZELIMIT_EXCEEDED) if (ldap_err == LDAP_SIZELIMIT_EXCEEDED)
@ -1249,18 +1269,26 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
LDAPMessage *uids; LDAPMessage *uids;
certid = ldap_get_values (ldap_conn, each, "pgpcertid"); certid = ldap_get_values (ldap_conn, each, "pgpcertid");
if (! certid || ! certid[0]) if (!certid || !certid[0])
continue; {
my_ldap_value_free (certid);
continue;
}
/* Have we seen this certid before? */ /* Have we seen this certid before? */
if (! strlist_find (dupelist, certid[0])) if (! strlist_find (dupelist, certid[0]))
{ {
add_to_strlist (&dupelist, certid[0]); add_to_strlist (&dupelist, certid[0]);
es_fprintf (fp, "pub:%s:",certid[0]); vals = ldap_get_values (ldap_conn, each, "gpgfingerprint");
if (vals && vals[0] && vals[0][0])
es_fprintf (fp, "pub:%s:", vals[0]);
else
es_fprintf (fp, "pub:%s:", certid[0]);
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, each, "pgpkeytype"); vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
if (vals) if (vals && vals[0])
{ {
/* The LDAP server doesn't exactly handle this /* The LDAP server doesn't exactly handle this
well. */ well. */
@ -1268,60 +1296,60 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
es_fputs ("1", fp); es_fputs ("1", fp);
else if (strcasecmp (vals[0], "DSS/DH") == 0) else if (strcasecmp (vals[0], "DSS/DH") == 0)
es_fputs ("17", fp); es_fputs ("17", fp);
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fputc (':', fp); es_fputc (':', fp);
vals = ldap_get_values (ldap_conn, each, "pgpkeysize"); vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
if (vals) if (vals && vals[0])
{ {
/* Not sure why, but some keys are listed with a /* Not sure why, but some keys are listed with a
key size of 0. Treat that like an unknown. */ key size of 0. Treat that like an unknown. */
if (atoi (vals[0]) > 0) if (atoi (vals[0]) > 0)
es_fprintf (fp, "%d", atoi (vals[0])); es_fprintf (fp, "%d", atoi (vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fputc (':', fp); es_fputc (':', fp);
/* YYYYMMDDHHmmssZ */ /* YYYYMMDDHHmmssZ */
vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime"); vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
if(vals && strlen (vals[0]) == 15) if(vals && vals[0] && strlen (vals[0]) == 15)
{ {
es_fprintf (fp, "%u", es_fprintf (fp, "%u",
(unsigned int) ldap2epochtime(vals[0])); (unsigned int) ldap2epochtime(vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fputc (':', fp); es_fputc (':', fp);
vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime"); vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
if (vals && strlen (vals[0]) == 15) if (vals && vals[0] && strlen (vals[0]) == 15)
{ {
es_fprintf (fp, "%u", es_fprintf (fp, "%u",
(unsigned int) ldap2epochtime (vals[0])); (unsigned int) ldap2epochtime (vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
es_fputc (':', fp); es_fputc (':', fp);
vals = ldap_get_values (ldap_conn, each, "pgprevoked"); vals = ldap_get_values (ldap_conn, each, "pgprevoked");
if (vals) if (vals && vals[0])
{ {
if (atoi (vals[0]) == 1) if (atoi (vals[0]) == 1)
es_fprintf (fp, "r"); es_fprintf (fp, "r");
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
vals = ldap_get_values (ldap_conn, each, "pgpdisabled"); vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
if (vals) if (vals && vals[0])
{ {
if (atoi (vals[0]) ==1) if (atoi (vals[0]) ==1)
es_fprintf (fp, "d"); es_fprintf (fp, "d");
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
#if 0 #if 0
/* This is not yet specified in the keyserver /* This is not yet specified in the keyserver
@ -1329,12 +1357,12 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
es_fputc (':', fp); es_fputc (':', fp);
vals = ldap_get_values (ldap_conn, each, "modifytimestamp"); vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
if(vals && strlen (vals[0]) == 15) if(vals && vals[0] strlen (vals[0]) == 15)
{ {
es_fprintf (fp, "%u", es_fprintf (fp, "%u",
(unsigned int) ldap2epochtime (vals[0])); (unsigned int) ldap2epochtime (vals[0]));
ldap_value_free (vals);
} }
my_ldap_value_free (vals);
#endif #endif
es_fprintf (fp, "\n"); es_fprintf (fp, "\n");
@ -1345,10 +1373,13 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
uids = ldap_next_entry (ldap_conn, uids)) uids = ldap_next_entry (ldap_conn, uids))
{ {
vals = ldap_get_values (ldap_conn, uids, "pgpcertid"); vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
if (! vals) if (!vals || !vals[0])
continue; {
my_ldap_value_free (vals);
continue;
}
if (strcasecmp (certid[0], vals[0]) == 0) if (!ascii_strcasecmp (certid[0], vals[0]))
{ {
char **uidvals; char **uidvals;
@ -1358,12 +1389,14 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
uids, "pgpuserid"); uids, "pgpuserid");
if (uidvals) if (uidvals)
{ {
/* Need to escape any colons */ /* Need to percent escape any colons */
char *quoted = percent_escape (uidvals[0], NULL); char *quoted = try_percent_escape (uidvals[0],
es_fputs (quoted, fp); NULL);
if (quoted)
es_fputs (quoted, fp);
xfree (quoted); xfree (quoted);
ldap_value_free (uidvals);
} }
my_ldap_value_free (uidvals);
es_fprintf (fp, "\n"); es_fprintf (fp, "\n");
} }
@ -1372,7 +1405,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
} }
} }
ldap_value_free (certid); my_ldap_value_free (certid);
} }
} }
@ -1386,8 +1419,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
out: out:
if (err) if (err)
{ {
if (fp) es_fclose (fp);
es_fclose (fp);
} }
else else
{ {