diff --git a/dirmngr/ks-engine-ldap.c b/dirmngr/ks-engine-ldap.c index 7d61313d9..e8257fdbc 100644 --- a/dirmngr/ks-engine-ldap.c +++ b/dirmngr/ks-engine-ldap.c @@ -1,7 +1,7 @@ /* ks-engine-ldap.c - talk to a LDAP keyserver * Copyright (C) 2001, 2002, 2004, 2005, 2006 * 2007 Free Software Foundation, Inc. - * Copyright (C) 2015 g10 Code GmbH + * Copyright (C) 2015, 2020 g10 Code GmbH * * This file is part of GnuPG. * @@ -49,6 +49,15 @@ #include "ks-engine.h" #include "ldap-parse-uri.h" + +/* Flags with infos from the connected server. */ +#define SERVERINFO_REALLDAP 1 /* This is not the PGP keyserver. */ +#define SERVERINFO_PGPKEYV2 2 /* Needs "pgpeyV2" instead of "pgpKey" */ +#define SERVERINFO_SCHEMAV2 4 /* Version 2 of the Schema. */ +#define SERVERINFO_NTDS 8 /* Server is an Active Directory. */ + + + #ifndef HAVE_TIMEGM time_t timegm(struct tm *tm); #endif @@ -427,40 +436,42 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact) The values are returned in the passed variables. If you pass NULL, then the value won't be returned. It is the caller's responsibility to release *LDAP_CONNP with ldap_unbind and xfree - *BASEDNP and *PGPKEYATTRP. + *BASEDNP. If this function successfully interrogated the server, it returns 0. If there was an LDAP error, it returns the LDAP error code. If an error occurred, *basednp, etc., are undefined (and don't need to be freed.) + R_SERVERINFO receives information about the server. + If no LDAP error occurred, you still need to check that *basednp is valid. If it is NULL, then the server does not appear to be an - OpenPGP Keyserver. In this case, you also do not need to xfree - *pgpkeyattrp. */ + OpenPGP Keyserver. */ static int my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, - char **basednp, char **pgpkeyattrp, int *real_ldapp) + char **basednp, unsigned int *r_serverinfo) { int err = 0; - LDAP *ldap_conn = NULL; - char *user = uri->auth; - struct uri_tuple_s *password_param = uri_query_lookup (uri, "password"); - char *password = password_param ? password_param->value : NULL; - + struct uri_tuple_s *password_param; + char *password; char *basedn = NULL; - /* Whether to look for the pgpKey or pgpKeyv2 attribute. */ - char *pgpkeyattr = "pgpKey"; - int real_ldap = 0; - log_debug ("my_ldap_connect(%s:%d/%s????%s%s%s%s%s)\n", - uri->host, uri->port, - uri->path ?: "", - uri->auth ? "bindname=" : "", uri->auth ?: "", - uri->auth && password ? "," : "", - password ? "password=" : "", password ?: ""); + *r_serverinfo = 0; + + password_param = uri_query_lookup (uri, "password"); + password = password_param ? password_param->value : NULL; + + if (opt.debug) + log_debug ("my_ldap_connect(%s:%d/%s????%s%s%s%s%s)\n", + uri->host, uri->port, + uri->path ?: "", + uri->auth ? "bindname=" : "", uri->auth ?: "", + uri->auth && password ? "," : "", + password ? "password=" : "", + password ? ">not shown<": ""); /* If the uri specifies a secure connection and we don't support TLS, then fail; don't silently revert to an insecure @@ -490,7 +501,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, err = ldap_set_option (ldap_conn, LDAP_OPT_PROTOCOL_VERSION, &ver); if (err != LDAP_SUCCESS) { - log_error ("gpgkeys: unable to go to LDAP 3: %s\n", + log_error ("ks-ldap: unable to go to LDAP 3: %s\n", ldap_err2string (err)); goto out; } @@ -553,8 +564,9 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, /* By default we don't bind as there is usually no need to. */ if (uri->auth) { - log_debug ("LDAP bind to %s, password %s\n", - user, password ? ">not shown<" : ">none<"); + if (opt.debug) + log_debug ("LDAP bind to %s, password %s\n", + user, password ? ">not shown<" : ">none<"); err = ldap_simple_bind_s (ldap_conn, user, password); if (err != LDAP_SUCCESS) @@ -566,18 +578,17 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, } if (uri->path && *uri->path) - /* User specified base DN. */ { + /* User specified base DN. */ basedn = xstrdup (uri->path); /* If the user specifies a base DN, then we know the server is a - real LDAP server. */ - real_ldap = 1; + * real LDAP server. */ + *r_serverinfo |= SERVERINFO_REALLDAP; } else - { + { /* Look for namingContexts. */ LDAPMessage *res = NULL; - /* Look for namingContexts. */ char *attr[] = { "namingContexts", NULL }; err = ldap_search_s (ldap_conn, "", LDAP_SCOPE_BASE, @@ -586,21 +597,22 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, { char **context = ldap_get_values (ldap_conn, res, "namingContexts"); if (context) - /* We found some, so try each namingContext as the search - base and look for pgpBaseKeySpaceDN. Because we found - this, we know we're talking to a regular-ish LDAP - server and not an LDAP keyserver. */ { + /* We found some, so try each namingContext as the + * search base and look for pgpBaseKeySpaceDN. Because + * we found this, we know we're talking to a regular-ish + * LDAP server and not an LDAP keyserver. */ int i; char *attr2[] = { "pgpBaseKeySpaceDN", "pgpVersion", "pgpSoftware", NULL }; - real_ldap = 1; + *r_serverinfo |= SERVERINFO_REALLDAP; for (i = 0; context[i] && ! basedn; i++) { char **vals; LDAPMessage *si_res; + int is_gnupg = 0; { char *object = xasprintf ("cn=pgpServerInfo,%s", @@ -624,7 +636,10 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, "pgpSoftware"); if (vals) { - log_debug ("Server: \t%s\n", vals[0]); + if (opt.debug) + log_debug ("Server: \t%s\n", vals[0]); + if (!ascii_strcasecmp (vals[0], "GnuPG")) + is_gnupg = 1; ldap_value_free (vals); } @@ -632,7 +647,20 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, "pgpVersion"); if (vals) { - log_debug ("Version:\t%s\n", vals[0]); + if (opt.debug) + log_debug ("Version:\t%s\n", vals[0]); + if (is_gnupg) + { + const char *fields[2]; + int nfields; + nfields = split_fields (vals[0], + fields, DIM(fields)); + if (nfields > 0 && atoi(fields[0]) > 1) + *r_serverinfo |= SERVERINFO_SCHEMAV2; + if (nfields > 1 + && !ascii_strcasecmp (fields[1], "ntds")) + *r_serverinfo |= SERVERINFO_NTDS; + } ldap_value_free (vals); } } @@ -650,7 +678,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, else { /* We don't have an answer yet, which means the server might - be an LDAP keyserver. */ + be a PGP.com keyserver. */ char **vals; LDAPMessage *si_res = NULL; @@ -660,9 +688,9 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, "(objectClass=*)", attr2, 0, &si_res); if (err == LDAP_SUCCESS) { - /* For the LDAP keyserver, this is always - "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not be - in the future. */ + /* For the PGP LDAP keyserver, this is always + * "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not be + * in the future. */ vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN"); if (vals) @@ -674,14 +702,16 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, vals = ldap_get_values (ldap_conn, si_res, "software"); if (vals) { - log_debug ("ldap: Server: \t%s\n", vals[0]); + if (opt.debug) + log_debug ("ks-ldap: PGP Server: \t%s\n", vals[0]); ldap_value_free (vals); } vals = ldap_get_values (ldap_conn, si_res, "version"); if (vals) { - log_debug ("ldap: Version:\t%s\n", vals[0]); + if (opt.debug) + log_debug ("ks-ldap: PGP Server Version:\t%s\n", vals[0]); /* If the version is high enough, use the new pgpKeyV2 attribute. This design is iffy at best, @@ -690,7 +720,7 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, keyserver vendor with a different numbering scheme. */ if (atoi (vals[0]) > 1) - pgpkeyattr = "pgpKeyV2"; + *r_serverinfo |= SERVERINFO_PGPKEYV2; ldap_value_free (vals); } @@ -706,29 +736,20 @@ my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp, } out: - if (! err) + if (!err && opt.debug) { log_debug ("ldap_conn: %p\n", ldap_conn); - log_debug ("real_ldap: %d\n", real_ldap); + log_debug ("server_type: %s\n", ((*r_serverinfo & SERVERINFO_REALLDAP) + ? "LDAP" : "PGP.com keyserver") ); log_debug ("basedn: %s\n", basedn); - log_debug ("pgpkeyattr: %s\n", pgpkeyattr); + log_debug ("pgpkeyattr: %s\n", + (*r_serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2":"pgpKey"); } - if (! err && real_ldapp) - *real_ldapp = real_ldap; - if (err) xfree (basedn); else { - if (pgpkeyattrp) - { - if (basedn) - *pgpkeyattrp = xstrdup (pgpkeyattr); - else - *pgpkeyattrp = NULL; - } - if (basednp) *basednp = basedn; else @@ -834,16 +855,11 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, { gpg_error_t err = 0; int ldap_err; - + unsigned int serverinfo; char *filter = NULL; - LDAP *ldap_conn = NULL; - char *basedn = NULL; - char *pgpkeyattr = NULL; - estream_t fp = NULL; - LDAPMessage *message = NULL; (void) ctrl; @@ -863,7 +879,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, return (err); /* Make sure we are talking to an OpenPGP LDAP server. */ - ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL); + ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &serverinfo); if (ldap_err || !basedn) { if (ldap_err) @@ -879,24 +895,26 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, may be discarded we aren't in verbose mode. */ char *attrs[] = { - pgpkeyattr, + "dummy", "pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled", "pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype", NULL }; /* 1 if we want just attribute types; 0 if we want both attribute - types and values. */ + * types and values. */ int attrsonly = 0; - int count; + /* Replace "dummy". */ + attrs[0] = (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2" : "pgpKey"; + ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, attrsonly, &message); if (ldap_err) { err = ldap_err_to_gpg_err (ldap_err); - log_error ("gpgkeys: LDAP search error: %s\n", + log_error ("ks-ldap: LDAP search error: %s\n", ldap_err2string (ldap_err)); goto out; } @@ -904,7 +922,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, count = ldap_count_entries (ldap_conn, message); if (count < 1) { - log_error ("gpgkeys: key %s not found on keyserver\n", keyspec); + log_info ("ks-ldap: key %s not found on keyserver\n", keyspec); if (count == -1) err = ldap_to_gpg_err (ldap_conn); @@ -954,11 +972,11 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, extract_keys (fp, ldap_conn, certid[0], each); - vals = ldap_get_values (ldap_conn, each, pgpkeyattr); + vals = ldap_get_values (ldap_conn, each, attrs[0]); if (! vals) { err = ldap_to_gpg_err (ldap_conn); - log_error("gpgkeys: unable to retrieve key %s " + log_error("ks-ldap: unable to retrieve key %s " "from keyserver\n", certid[0]); goto out; } @@ -1001,7 +1019,6 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, *r_fp = fp; } - xfree (pgpkeyattr); xfree (basedn); if (ldap_conn) @@ -1012,6 +1029,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, return err; } + /* Search the keyserver identified by URI for keys matching PATTERN. On success R_FP has an open stream to read the data. */ gpg_error_t @@ -1020,13 +1038,10 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, { gpg_error_t err; int ldap_err; - + unsigned int serverinfo; char *filter = NULL; - LDAP *ldap_conn = NULL; - char *basedn = NULL; - estream_t fp = NULL; (void) ctrl; @@ -1049,7 +1064,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, } /* Make sure we are talking to an OpenPGP LDAP server. */ - ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL); + ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &serverinfo); if (ldap_err || !basedn) { if (ldap_err) @@ -1082,7 +1097,8 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, "pgpkeysize", "pgpkeytype", NULL }; - log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter); + if (opt.debug) + log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter); ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res); @@ -1095,7 +1111,7 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, err = ldap_err_to_gpg_err (ldap_err); log_error ("SEARCH %s FAILED %d\n", pattern, err); - log_error ("gpgkeys: LDAP search error: %s\n", + log_error ("ks-ldap: LDAP search error: %s\n", ldap_err2string (err)); goto out; } @@ -1117,10 +1133,10 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, if (ldap_err == LDAP_SIZELIMIT_EXCEEDED) { if (count == 1) - log_error ("gpgkeys: search results exceeded server limit." + log_error ("ks-ldap: search results exceeded server limit." " First 1 result shown.\n"); else - log_error ("gpgkeys: search results exceeded server limit." + log_error ("ks-ldap: search results exceeded server limit." " First %d results shown.\n", count); } @@ -1272,7 +1288,8 @@ ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, free_strlist (dupelist); } - log_debug ("SEARCH %s END\n", pattern); + if (opt.debug) + log_debug ("SEARCH %s END\n", pattern); out: if (err) @@ -1865,15 +1882,11 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, { gpg_error_t err = 0; int ldap_err; - + unsigned int serverinfo; LDAP *ldap_conn = NULL; char *basedn = NULL; - char *pgpkeyattr = NULL; - int real_ldap; - LDAPMod **modlist = NULL; LDAPMod **addlist = NULL; - char *data_armored = NULL; /* The last byte of the info block. */ @@ -1898,8 +1911,7 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, return gpg_error (GPG_ERR_NOT_SUPPORTED); } - ldap_err = my_ldap_connect (uri, - &ldap_conn, &basedn, &pgpkeyattr, &real_ldap); + ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &serverinfo); if (ldap_err || !basedn) { if (ldap_err) @@ -1909,22 +1921,31 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, goto out; } - if (! real_ldap) - /* We appear to have an OpenPGP Keyserver, which can unpack the key - on its own (not just a dumb LDAP server). */ + if (!(serverinfo & SERVERINFO_REALLDAP)) { - LDAPMod mod, *attrs[2]; - char *key[] = { data, NULL }; + /* We appear to have a PGP.com Keyserver, which can unpack the + * key on its own (not just a dump LDAP server). This will + * rarely be the case these days. */ + LDAPMod mod; + LDAPMod *attrs[2]; + char *key[2]; char *dn; + key[0] = data; + key[1] = NULL; memset (&mod, 0, sizeof (mod)); mod.mod_op = LDAP_MOD_ADD; - mod.mod_type = pgpkeyattr; + mod.mod_type = (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2":"pgpKey"; mod.mod_values = key; attrs[0] = &mod; attrs[1] = NULL; - dn = xasprintf ("pgpCertid=virtual,%s", basedn); + dn = xtryasprintf ("pgpCertid=virtual,%s", basedn); + if (!dn) + { + err = gpg_error_from_syserror (); + goto out; + } ldap_err = ldap_add_s (ldap_conn, dn, attrs); xfree (dn); @@ -1937,7 +1958,12 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, goto out; } - modlist = xmalloc (sizeof (LDAPMod *)); + modlist = xtrymalloc (sizeof (LDAPMod *)); + if (!modlist) + { + err = gpg_error_from_syserror (); + goto out; + } *modlist = NULL; if (dump_modlist) @@ -1996,10 +2022,10 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, /* Sanity check. */ if (! temp) - assert ((char *) info + infolen - 1 == infoend); + log_assert ((char *) info + infolen - 1 == infoend); else { - assert (infolen == -1); + log_assert (infolen == -1); xfree (temp); } } @@ -2010,7 +2036,9 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, if (err) goto out; - modlist_add (&addlist, pgpkeyattr, data_armored); + modlist_add (&addlist, + (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2":"pgpKey", + data_armored); /* Now append addlist onto modlist. */ modlists_join (&modlist, addlist); @@ -2037,17 +2065,25 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, char *dn; certid = modlist_lookup (addlist, "pgpCertID"); - if (/* We should have a value. */ - ! certid - /* Exactly one. */ - || !(certid[0] && !certid[1])) + /* We should have exactly one value. */ + if (!certid || !(certid[0] && !certid[1])) { - log_error ("Bad certid.\n"); + log_error ("ks-ldap: bad pgpCertID provided\n"); err = GPG_ERR_GENERAL; goto out; } - dn = xasprintf ("pgpCertID=%s,%s", certid[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 (); + goto out; + } + if (opt.debug) + log_debug ("ks-ldap: using DN: %s\n", dn); err = ldap_modify_s (ldap_conn, dn, modlist); if (err == LDAP_NO_SUCH_OBJECT) @@ -2057,7 +2093,7 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, if (err != LDAP_SUCCESS) { - log_error ("gpgkeys: error adding key to keyserver: %s\n", + log_error ("ks-ldap: error adding key to keyserver: %s\n", ldap_err2string (err)); err = ldap_err_to_gpg_err (err); } @@ -2071,7 +2107,6 @@ ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri, ldap_unbind (ldap_conn); xfree (basedn); - xfree (pgpkeyattr); modlist_free (modlist); xfree (addlist); diff --git a/doc/ldap/gnupg-ldap-ad-init.ldif b/doc/ldap/gnupg-ldap-ad-init.ldif new file mode 100644 index 000000000..f9de238d4 --- /dev/null +++ b/doc/ldap/gnupg-ldap-ad-init.ldif @@ -0,0 +1,17 @@ +# gnupg-ldap-ad-init.ldif -*- conf -*- +# +# Entries connecting the schema specified in gnupg-ldap-ad-schema.ldif. +# Revision: 2020-12-08 + +dn: cn=GnuPG Keys,dc=w32demo,dc=g10code,dc=de +changetype: add +objectClass: container +cn: GnuPG Keys + +dn: cn=PGPServerInfo,dc=w32demo,dc=g10code,dc=de +changetype: add +objectClass: pgpServerInfo +cn: PGPServerInfo +pgpBaseKeySpaceDN: cn=GnuPG Keys,dc=w32demo,dc=g10code,dc=de +pgpSoftware: GnuPG +pgpVersion: 2 ntds diff --git a/doc/ldap/gnupg-ldap-ad-schema.ldif b/doc/ldap/gnupg-ldap-ad-schema.ldif new file mode 100644 index 000000000..6c4d19f15 --- /dev/null +++ b/doc/ldap/gnupg-ldap-ad-schema.ldif @@ -0,0 +1,353 @@ +# gnupg-ldap-scheme.ldif -*- conf -*- +# +# Schema for an OpenPGP LDAP keyserver. This is a slighly enhanced +# version of the original LDAP schema used for PGP keyservers as +# installed at quite some sites. +# Revision: 2020-12-08 + +# Some notes: +# - Backup your AD! It is not possible to revert changes of the schema. +# - Try it first on a test system. +# - To import the new attributes and classes use: +# ldifde -i -vv -f gnupg-ldap-ad-schema.ldif +# -c "DC=EXAMPLEDC" "DC=example,DC=org" +# (the above command is given as one line) +# - The schema does not get its own distingished name as done with OpenLDAP. +# - The first GUID we use is f406e7a5-a5ea-411e-9ddd-2e4e66899800 +# and incremented for each attribute. +# +# - Some OIDs, oMSyntax, and original OIDs: +# 2.5.5.1 (127) Object (DS-DN) (1.3.6.1.4.1.1466.115.121.1.12) +# 2.5.5.3 (27) Case-sensitive string +# 2.5.5.9 (2) 32 bit signed integer +# 2.5.5.10 (4) Octet string (1.3.6.1.4.1.1466.115.121.1.26) +# 2.5.5.11 (23) UTC-Time string +# 2.5.5.12 (64) Case-insensitive Unicode string +# 2.5.5.12 (64) Directory String in UTF-8 (1.3.6.1.4.1.1466.115.121.1.15) +# 2.5.5.16 (65) 64 bit signed integer + +# The base DN for the PGP key space by querying the +# pgpBaseKeySpaceDN attribute (This is normally +# 'ou=PGP Keys,dc=example,dc=com'). +dn: CN=pgpBaseKeySpaceDN,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.8 +lDAPDisplayName: pgpBaseKeySpaceDN +description: Points to DN of the object that will store the PGP keys. +attributeSyntax: 2.5.5.1 +oMSyntax: 127 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYAA== + +# See gnupg-ldap-init.ldif for a description of this attribute +dn: CN=pgpSoftware,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.9 +lDAPDisplayName: pgpSoftware +description: 'Origin of the GnuPG keyserver schema' +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYAQ== + +# See gnupg-ldap-init.ldif for a description of this attribute +dn: CN=pgpVersion,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.10 +lDAPDisplayName: pgpVersion +description: Version of this schema +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYAg== + + +# The attribute holding the OpenPGP keyblock. +# The legacy PGP LDAP server used pgpKeyV2 instead. +dn: CN=pgpKey,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.11 +lDAPDisplayName: pgpKey +description: OpenPGP public key block +attributeSyntax: 2.5.5.10 +oMSyntax: 4 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYAw== + +# The long key-ID +dn: CN=pgpCertID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.12 +lDAPDisplayName: pgpCertID +description: OpenPGP long key id +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYBA== + +# A flag to temporary disable a keyblock +dn: CN=pgpDisabled,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.13 +lDAPDisplayName: pgpDisabled +description: pgpDisabled attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYBQ== + +# The short key id. This is actually not required and should thus not +# be used by client software. +dn: CN=pgpKeyID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.14 +lDAPDisplayName: pgpKeyID +description: OpenPGP short key id +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYBg== + +# The algorithm of the key. Used to be "RSA" or "DSS/DH". +dn: CN=pgpKeyType,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.15 +lDAPDisplayName: pgpKeyType +description: pgpKeyType attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYBw== + +# The User-ID. GnuPG maps its user-ID classes this way: +# exact: (pgpUserID=%s) +# substr: (pgpUserID=*%s*) +# mail: (pgpUserID=*<%s>*) +# mailsub: (pgpUserID=*<*%s*>*) +# mailend: (pgpUserID=*<*%s>*) +dn: CN=pgpUserID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.16 +lDAPDisplayName: pgpUserID +description: User ID(s) associated with the key +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYCA== + +# The creation time of the primary key. +# Stored in ISO format: "20201231 120000" +dn: CN=pgpKeyCreateTime,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.17 +lDAPDisplayName: pgpKeyCreateTime +description: Primary key creation time +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYCQ== + +# SignerIDs are not used +dn: CN=pgpSignerID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.18 +lDAPDisplayName: pgpSignerID +description: pgpSignerID attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYCg== + +# A value of 1 indicates that the keyblock has been revoked +dn: CN=pgpRevoked,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.19 +lDAPDisplayName: pgpRevoked +description: pgpRevoked attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYCw== + +# The Subkey key ids +dn: CN=pgpSubKeyID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.20 +lDAPDisplayName: pgpSubKeyID +description: Sub-key ID(s) of the PGP key +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYDA== + +# A hint on the keysize. +dn: CN=pgpKeySize,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.21 +lDAPDisplayName: pgpKeySize +description: pgpKeySize attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYDQ== + +# Expiration time of the primary key. +# Stored in ISO format: "20201231 120000" +dn: CN=pgpKeyExpireTime,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.3401.8.2.22 +lDAPDisplayName: pgpKeyExpireTime +description: pgpKeyExpireTime attribute for PGP +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYDg== + +# The hex encoded fingerprint of the primary key. +dn: CN=gpgFingerprint,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11591.2.4.1.1 +lDAPDisplayName: gpgFingerprint +description: Fingerprint of the primary key +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: TRUE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYDw== + +# A list of hex encoded fingerprints of the subkeys. +dn: CN=gpgSubFingerprint,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11591.2.4.1.2 +lDAPDisplayName: gpgSubFingerprint +description: Fingerprints of the secondary keys +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYEA== + +# A list of utf8 encoded addr-spec used instead of mail/rfc822Mailbox +dn: CN=gpgMailbox,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11591.2.4.1.3 +lDAPDisplayName: gpgMailbox +description: The utf8 encoded addr-spec of a mailbox +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYEQ== + +# A list of hex encoded long keyids of all subkeys. +dn: CN=gpgSubCertID,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: attributeSchema +attributeID: 1.3.6.1.4.1.11591.2.4.1.4 +lDAPDisplayName: gpgSubCertID +description: OpenPGP long subkey id +attributeSyntax: 2.5.5.12 +oMSyntax: 64 +isSingleValued: FALSE +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYEg== + +# Unused GUIDs: +# 9AbnpaXqQR6d3S5OZomYEw== +# 9AbnpaXqQR6d3S5OZomYFA== +# 9AbnpaXqQR6d3S5OZomYFQ== +# 9AbnpaXqQR6d3S5OZomYFg== +# 9AbnpaXqQR6d3S5OZomYFw== +# 9AbnpaXqQR6d3S5OZomYGA== +# 9AbnpaXqQR6d3S5OZomYGQ== +# 9AbnpaXqQR6d3S5OZomYGg== +# 9AbnpaXqQR6d3S5OZomYGw== +# 9AbnpaXqQR6d3S5OZomYHA== +# 9AbnpaXqQR6d3S5OZomYHQ== +# 9AbnpaXqQR6d3S5OZomYHg== +# 9AbnpaXqQR6d3S5OZomYHw== + + +# Sync the schema cache +DN: +changetype: modify +add: schemaUpdateNow +schemaUpdateNow: 1 +- + + +# +# Used by regular LDAP servers to indicate pgp support. +# (structural class) +# +dn: CN=pgpServerInfo,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: classSchema +governsID: 1.3.6.1.4.1.3401.8.2.23 +lDAPDisplayName: pgpServerInfo +description: An OpenPGP public keyblock store +subClassOf: top +objectClassCategory: 1 +mustContain: cn +mustContain: pgpBaseKeySpaceDN +mayContain: pgpSoftware +mayContain: pgpVersion +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYIA== + +# The original PGP key object extended with a few extra attributes. +# All new software should set them but this is not enforced for +# backward compatibility of client software. +# (structural class, writable) +dn: CN=pgpKeyInfo,CN=Schema,CN=Configuration,DC=EXAMPLEDC +changetype: ntdsSchemaAdd +objectClass: classSchema +governsID: 1.3.6.1.4.1.3401.8.2.24 +lDAPDisplayName: pgpKeyInfo +description: An OpenPGP public keyblock +subClassOf: top +objectClassCategory: 1 +instanceType: 4 +mustContain: pgpCertID +mustContain: pgpKey +mayContain: pgpDisabled +mayContain: pgpKeyID +mayContain: pgpKeyType +mayContain: pgpUserID +mayContain: pgpKeyCreateTime +mayContain: pgpSignerID +mayContain: pgpRevoked +mayContain: pgpSubKeyID +mayContain: pgpKeySize +mayContain: pgpKeyExpireTime +mayContain: gpgFingerprint +mayContain: gpgSubFingerprint +mayContain: gpgSubCertID +mayContain: gpgMailbox +schemaIDGUID:: 9AbnpaXqQR6d3S5OZomYIQ== + + +# Sync the schema cache +DN: +changetype: modify +add: schemaUpdateNow +schemaUpdateNow: 1 +- + + +# +# end-of-file +# diff --git a/doc/ldap/gnupg-ldap-init.ldif b/doc/ldap/gnupg-ldap-init.ldif index f184f9ee2..8f62c5c61 100644 --- a/doc/ldap/gnupg-ldap-init.ldif +++ b/doc/ldap/gnupg-ldap-init.ldif @@ -12,10 +12,18 @@ pgpBaseKeySpaceDN: ou=GnuPG Keys,dc=example,dc=com # Using the value GnuPG here indicates that pgpVersion below has a # well-defined meaning. pgpSoftware: GnuPG -# Currently used values: -# 1 :: Classic PGP schema -# 2 :: The attributes gpgFingerprint, gpgSubFingerprint, -# gpgSubCertID, and gpgMailbox are part of the schema. +# pgpVersion is a string with space delimited items: +# +# Item 1 - Implemented schema version. This is an integer with one +# of these values: +# 1 = Classic PGP schema (default) +# 2 = The attributes gpgFingerprint, gpgSubFingerprint, +# gpgSubCertID, and gpgMailbox are part of the schema. +# Item 2 - A string with the used LDAP server +# "-" = Unknown (default) +# "ntds" = Windows Directory Service (AD DS) +# "openldap" = OpenLDAP +# pgpVersion: 2 dn: ou=GnuPG Keys,dc=example,dc=com