Line data Source code
1 : /* ks-engine-ldap.c - talk to a LDAP keyserver
2 : * Copyright (C) 2001, 2002, 2004, 2005, 2006
3 : * 2007 Free Software Foundation, Inc.
4 : * Copyright (C) 2015 g10 Code GmbH
5 : *
6 : * This file is part of GnuPG.
7 : *
8 : * GnuPG is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 3 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * GnuPG is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <config.h>
23 : #include <stdio.h>
24 : #include <string.h>
25 : #include <time.h>
26 : #include <unistd.h>
27 : #ifdef HAVE_GETOPT_H
28 : # include <getopt.h>
29 : #endif
30 : #include <stdlib.h>
31 : #include <errno.h>
32 : #include <assert.h>
33 :
34 : #ifdef _WIN32
35 : # include <winsock2.h>
36 : # include <winldap.h>
37 : #else
38 : # ifdef NEED_LBER_H
39 : # include <lber.h>
40 : # endif
41 : /* For OpenLDAP, to enable the API that we're using. */
42 : # define LDAP_DEPRECATED 1
43 : # include <ldap.h>
44 : #endif
45 :
46 : #include "dirmngr.h"
47 : #include "misc.h"
48 : #include "userids.h"
49 : #include "ks-engine.h"
50 : #include "ldap-parse-uri.h"
51 :
52 : #ifndef HAVE_TIMEGM
53 : time_t timegm(struct tm *tm);
54 : #endif
55 :
56 : /* Convert an LDAP error to a GPG error. */
57 : static int
58 0 : ldap_err_to_gpg_err (int code)
59 : {
60 : gpg_err_code_t ec;
61 :
62 0 : switch (code)
63 : {
64 : #ifdef LDAP_X_CONNECTING
65 0 : case LDAP_X_CONNECTING: ec = GPG_ERR_LDAP_X_CONNECTING; break;
66 : #endif
67 :
68 0 : case LDAP_REFERRAL_LIMIT_EXCEEDED: ec = GPG_ERR_LDAP_REFERRAL_LIMIT; break;
69 0 : case LDAP_CLIENT_LOOP: ec = GPG_ERR_LDAP_CLIENT_LOOP; break;
70 0 : case LDAP_NO_RESULTS_RETURNED: ec = GPG_ERR_LDAP_NO_RESULTS; break;
71 0 : case LDAP_CONTROL_NOT_FOUND: ec = GPG_ERR_LDAP_CONTROL_NOT_FOUND; break;
72 0 : case LDAP_NOT_SUPPORTED: ec = GPG_ERR_LDAP_NOT_SUPPORTED; break;
73 0 : case LDAP_CONNECT_ERROR: ec = GPG_ERR_LDAP_CONNECT; break;
74 0 : case LDAP_NO_MEMORY: ec = GPG_ERR_LDAP_NO_MEMORY; break;
75 0 : case LDAP_PARAM_ERROR: ec = GPG_ERR_LDAP_PARAM; break;
76 0 : case LDAP_USER_CANCELLED: ec = GPG_ERR_LDAP_USER_CANCELLED; break;
77 0 : case LDAP_FILTER_ERROR: ec = GPG_ERR_LDAP_FILTER; break;
78 0 : case LDAP_AUTH_UNKNOWN: ec = GPG_ERR_LDAP_AUTH_UNKNOWN; break;
79 0 : case LDAP_TIMEOUT: ec = GPG_ERR_LDAP_TIMEOUT; break;
80 0 : case LDAP_DECODING_ERROR: ec = GPG_ERR_LDAP_DECODING; break;
81 0 : case LDAP_ENCODING_ERROR: ec = GPG_ERR_LDAP_ENCODING; break;
82 0 : case LDAP_LOCAL_ERROR: ec = GPG_ERR_LDAP_LOCAL; break;
83 0 : case LDAP_SERVER_DOWN: ec = GPG_ERR_LDAP_SERVER_DOWN; break;
84 :
85 0 : case LDAP_SUCCESS: ec = GPG_ERR_LDAP_SUCCESS; break;
86 :
87 0 : case LDAP_OPERATIONS_ERROR: ec = GPG_ERR_LDAP_OPERATIONS; break;
88 0 : case LDAP_PROTOCOL_ERROR: ec = GPG_ERR_LDAP_PROTOCOL; break;
89 0 : case LDAP_TIMELIMIT_EXCEEDED: ec = GPG_ERR_LDAP_TIMELIMIT; break;
90 0 : case LDAP_SIZELIMIT_EXCEEDED: ec = GPG_ERR_LDAP_SIZELIMIT; break;
91 0 : case LDAP_COMPARE_FALSE: ec = GPG_ERR_LDAP_COMPARE_FALSE; break;
92 0 : case LDAP_COMPARE_TRUE: ec = GPG_ERR_LDAP_COMPARE_TRUE; break;
93 0 : case LDAP_AUTH_METHOD_NOT_SUPPORTED: ec=GPG_ERR_LDAP_UNSUPPORTED_AUTH;break;
94 0 : case LDAP_STRONG_AUTH_REQUIRED: ec = GPG_ERR_LDAP_STRONG_AUTH_RQRD; break;
95 0 : case LDAP_PARTIAL_RESULTS: ec = GPG_ERR_LDAP_PARTIAL_RESULTS; break;
96 0 : case LDAP_REFERRAL: ec = GPG_ERR_LDAP_REFERRAL; break;
97 :
98 : #ifdef LDAP_ADMINLIMIT_EXCEEDED
99 0 : case LDAP_ADMINLIMIT_EXCEEDED: ec = GPG_ERR_LDAP_ADMINLIMIT; break;
100 : #endif
101 :
102 : #ifdef LDAP_UNAVAILABLE_CRITICAL_EXTENSION
103 : case LDAP_UNAVAILABLE_CRITICAL_EXTENSION:
104 0 : ec = GPG_ERR_LDAP_UNAVAIL_CRIT_EXTN; break;
105 : #endif
106 :
107 0 : case LDAP_CONFIDENTIALITY_REQUIRED: ec = GPG_ERR_LDAP_CONFIDENT_RQRD; break;
108 0 : case LDAP_SASL_BIND_IN_PROGRESS: ec = GPG_ERR_LDAP_SASL_BIND_INPROG; break;
109 0 : case LDAP_NO_SUCH_ATTRIBUTE: ec = GPG_ERR_LDAP_NO_SUCH_ATTRIBUTE; break;
110 0 : case LDAP_UNDEFINED_TYPE: ec = GPG_ERR_LDAP_UNDEFINED_TYPE; break;
111 0 : case LDAP_INAPPROPRIATE_MATCHING: ec = GPG_ERR_LDAP_BAD_MATCHING; break;
112 0 : case LDAP_CONSTRAINT_VIOLATION: ec = GPG_ERR_LDAP_CONST_VIOLATION; break;
113 :
114 : #ifdef LDAP_TYPE_OR_VALUE_EXISTS
115 0 : case LDAP_TYPE_OR_VALUE_EXISTS: ec = GPG_ERR_LDAP_TYPE_VALUE_EXISTS; break;
116 : #endif
117 :
118 0 : case LDAP_INVALID_SYNTAX: ec = GPG_ERR_LDAP_INV_SYNTAX; break;
119 0 : case LDAP_NO_SUCH_OBJECT: ec = GPG_ERR_LDAP_NO_SUCH_OBJ; break;
120 0 : case LDAP_ALIAS_PROBLEM: ec = GPG_ERR_LDAP_ALIAS_PROBLEM; break;
121 0 : case LDAP_INVALID_DN_SYNTAX: ec = GPG_ERR_LDAP_INV_DN_SYNTAX; break;
122 0 : case LDAP_IS_LEAF: ec = GPG_ERR_LDAP_IS_LEAF; break;
123 0 : case LDAP_ALIAS_DEREF_PROBLEM: ec = GPG_ERR_LDAP_ALIAS_DEREF; break;
124 :
125 : #ifdef LDAP_X_PROXY_AUTHZ_FAILURE
126 0 : case LDAP_X_PROXY_AUTHZ_FAILURE: ec = GPG_ERR_LDAP_X_PROXY_AUTH_FAIL; break;
127 : #endif
128 :
129 0 : case LDAP_INAPPROPRIATE_AUTH: ec = GPG_ERR_LDAP_BAD_AUTH; break;
130 0 : case LDAP_INVALID_CREDENTIALS: ec = GPG_ERR_LDAP_INV_CREDENTIALS; break;
131 :
132 : #ifdef LDAP_INSUFFICIENT_ACCESS
133 0 : case LDAP_INSUFFICIENT_ACCESS: ec = GPG_ERR_LDAP_INSUFFICIENT_ACC; break;
134 : #endif
135 :
136 0 : case LDAP_BUSY: ec = GPG_ERR_LDAP_BUSY; break;
137 0 : case LDAP_UNAVAILABLE: ec = GPG_ERR_LDAP_UNAVAILABLE; break;
138 0 : case LDAP_UNWILLING_TO_PERFORM: ec = GPG_ERR_LDAP_UNWILL_TO_PERFORM; break;
139 0 : case LDAP_LOOP_DETECT: ec = GPG_ERR_LDAP_LOOP_DETECT; break;
140 0 : case LDAP_NAMING_VIOLATION: ec = GPG_ERR_LDAP_NAMING_VIOLATION; break;
141 0 : case LDAP_OBJECT_CLASS_VIOLATION: ec = GPG_ERR_LDAP_OBJ_CLS_VIOLATION; break;
142 0 : case LDAP_NOT_ALLOWED_ON_NONLEAF: ec=GPG_ERR_LDAP_NOT_ALLOW_NONLEAF;break;
143 0 : case LDAP_NOT_ALLOWED_ON_RDN: ec = GPG_ERR_LDAP_NOT_ALLOW_ON_RDN; break;
144 0 : case LDAP_ALREADY_EXISTS: ec = GPG_ERR_LDAP_ALREADY_EXISTS; break;
145 0 : case LDAP_NO_OBJECT_CLASS_MODS: ec = GPG_ERR_LDAP_NO_OBJ_CLASS_MODS; break;
146 0 : case LDAP_RESULTS_TOO_LARGE: ec = GPG_ERR_LDAP_RESULTS_TOO_LARGE; break;
147 0 : case LDAP_AFFECTS_MULTIPLE_DSAS: ec = GPG_ERR_LDAP_AFFECTS_MULT_DSAS; break;
148 :
149 : #ifdef LDAP_VLV_ERROR
150 0 : case LDAP_VLV_ERROR: ec = GPG_ERR_LDAP_VLV; break;
151 : #endif
152 :
153 0 : case LDAP_OTHER: ec = GPG_ERR_LDAP_OTHER; break;
154 :
155 : #ifdef LDAP_CUP_RESOURCES_EXHAUSTED
156 0 : case LDAP_CUP_RESOURCES_EXHAUSTED: ec=GPG_ERR_LDAP_CUP_RESOURCE_LIMIT;break;
157 0 : case LDAP_CUP_SECURITY_VIOLATION: ec=GPG_ERR_LDAP_CUP_SEC_VIOLATION; break;
158 0 : case LDAP_CUP_INVALID_DATA: ec = GPG_ERR_LDAP_CUP_INV_DATA; break;
159 0 : case LDAP_CUP_UNSUPPORTED_SCHEME: ec = GPG_ERR_LDAP_CUP_UNSUP_SCHEME; break;
160 0 : case LDAP_CUP_RELOAD_REQUIRED: ec = GPG_ERR_LDAP_CUP_RELOAD; break;
161 : #endif
162 :
163 : #ifdef LDAP_CANCELLED
164 0 : case LDAP_CANCELLED: ec = GPG_ERR_LDAP_CANCELLED; break;
165 : #endif
166 :
167 : #ifdef LDAP_NO_SUCH_OPERATION
168 0 : case LDAP_NO_SUCH_OPERATION: ec = GPG_ERR_LDAP_NO_SUCH_OPERATION; break;
169 : #endif
170 :
171 : #ifdef LDAP_TOO_LATE
172 0 : case LDAP_TOO_LATE: ec = GPG_ERR_LDAP_TOO_LATE; break;
173 : #endif
174 :
175 : #ifdef LDAP_CANNOT_CANCEL
176 0 : case LDAP_CANNOT_CANCEL: ec = GPG_ERR_LDAP_CANNOT_CANCEL; break;
177 : #endif
178 :
179 : #ifdef LDAP_ASSERTION_FAILED
180 0 : case LDAP_ASSERTION_FAILED: ec = GPG_ERR_LDAP_ASSERTION_FAILED; break;
181 : #endif
182 :
183 : #ifdef LDAP_PROXIED_AUTHORIZATION_DENIED
184 : case LDAP_PROXIED_AUTHORIZATION_DENIED:
185 0 : ec = GPG_ERR_LDAP_PROX_AUTH_DENIED; break;
186 : #endif
187 :
188 : default:
189 : #if defined(LDAP_E_ERROR) && defined(LDAP_X_ERROR)
190 0 : if (LDAP_E_ERROR (code))
191 0 : ec = GPG_ERR_LDAP_E_GENERAL;
192 0 : else if (LDAP_X_ERROR (code))
193 0 : ec = GPG_ERR_LDAP_X_GENERAL;
194 : else
195 : #endif
196 0 : ec = GPG_ERR_LDAP_GENERAL;
197 0 : break;
198 : }
199 :
200 0 : return ec;
201 : }
202 :
203 : /* Retrieve an LDAP error and return it's GPG equivalent. */
204 : static int
205 0 : ldap_to_gpg_err (LDAP *ld)
206 : {
207 : #if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER)
208 : int err;
209 :
210 0 : if (ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &err) == 0)
211 0 : return ldap_err_to_gpg_err (err);
212 : else
213 0 : return GPG_ERR_GENERAL;
214 : #elif defined(HAVE_LDAP_LD_ERRNO)
215 : return ldap_err_to_gpg_err (ld->ld_errno);
216 : #else
217 : /* We should never get here since the LDAP library should always
218 : have either ldap_get_option or ld_errno, but just in case... */
219 : return GPG_ERR_INTERNAL;
220 : #endif
221 : }
222 :
223 : static time_t
224 0 : ldap2epochtime (const char *timestr)
225 : {
226 : struct tm pgptime;
227 : time_t answer;
228 :
229 0 : memset (&pgptime, 0, sizeof(pgptime));
230 :
231 : /* YYYYMMDDHHmmssZ */
232 :
233 0 : sscanf (timestr, "%4d%2d%2d%2d%2d%2d",
234 : &pgptime.tm_year,
235 : &pgptime.tm_mon,
236 : &pgptime.tm_mday,
237 : &pgptime.tm_hour,
238 : &pgptime.tm_min,
239 : &pgptime.tm_sec);
240 :
241 0 : pgptime.tm_year -= 1900;
242 0 : pgptime.tm_isdst = -1;
243 0 : pgptime.tm_mon--;
244 :
245 : /* mktime() takes the timezone into account, so we use timegm() */
246 :
247 0 : answer = timegm (&pgptime);
248 :
249 0 : return answer;
250 : }
251 :
252 : /* Caller must free the result. */
253 : static char *
254 0 : tm2ldaptime (struct tm *tm)
255 : {
256 0 : struct tm tmp = *tm;
257 : char buf[16];
258 :
259 : /* YYYYMMDDHHmmssZ */
260 :
261 0 : tmp.tm_year += 1900;
262 0 : tmp.tm_mon ++;
263 :
264 0 : snprintf (buf, sizeof buf, "%04d%02d%02d%02d%02d%02dZ",
265 : tmp.tm_year,
266 : tmp.tm_mon,
267 : tmp.tm_mday,
268 : tmp.tm_hour,
269 : tmp.tm_min,
270 : tmp.tm_sec);
271 :
272 0 : return xstrdup (buf);
273 : }
274 :
275 : #if 0
276 : /* Caller must free */
277 : static char *
278 : epoch2ldaptime (time_t stamp)
279 : {
280 : struct tm tm;
281 : if (gmtime_r (&stamp, &tm))
282 : return tm2ldaptime (&tm);
283 : else
284 : return xstrdup ("INVALID TIME");
285 : }
286 : #endif
287 :
288 : /* Print a help output for the schemata supported by this module. */
289 : gpg_error_t
290 0 : ks_ldap_help (ctrl_t ctrl, parsed_uri_t uri)
291 : {
292 0 : const char const data[] =
293 : "Handler for LDAP URLs:\n"
294 : " ldap://host:port/[BASEDN]???[bindname=BINDNAME,password=PASSWORD]\n"
295 : "\n"
296 : "Note: basedn, bindname and password need to be percent escaped. In\n"
297 : "particular, spaces need to be replaced with %20 and commas with %2c.\n"
298 : "bindname will typically be of the form:\n"
299 : "\n"
300 : " uid=user%2cou=PGP%20Users%2cdc=EXAMPLE%2cdc=ORG\n"
301 : "\n"
302 : "The ldaps:// and ldapi:// schemes are also supported. If ldaps is used\n"
303 : "then the server's certificate will be checked. If it is not valid, any\n"
304 : "operation will be aborted.\n"
305 : "\n"
306 : "Supported methods: search, get, put\n";
307 : gpg_error_t err;
308 :
309 0 : if(!uri)
310 0 : err = ks_print_help (ctrl, " ldap");
311 0 : else if (strcmp (uri->scheme, "ldap") == 0
312 0 : || strcmp (uri->scheme, "ldaps") == 0
313 0 : || strcmp (uri->scheme, "ldapi") == 0)
314 0 : err = ks_print_help (ctrl, data);
315 : else
316 0 : err = 0;
317 :
318 0 : return err;
319 : }
320 :
321 : /* Convert a keyspec to a filter. Return an error if the keyspec is
322 : bad or is not supported. The filter is escaped and returned in
323 : *filter. It is the caller's responsibility to free *filter.
324 : *filter is only set if this function returns success (i.e., 0). */
325 : static gpg_error_t
326 0 : keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
327 : {
328 : /* Remove search type indicator and adjust PATTERN accordingly.
329 : Note: don't include a preceding 0x when searching by keyid. */
330 :
331 : /* XXX: Should we include disabled / revoke options? */
332 : KEYDB_SEARCH_DESC desc;
333 0 : char *f = NULL;
334 0 : char *freeme = NULL;
335 :
336 0 : gpg_error_t err = classify_user_id (keyspec, &desc, 1);
337 0 : if (err)
338 0 : return err;
339 :
340 0 : switch (desc.mode)
341 : {
342 : case KEYDB_SEARCH_MODE_EXACT:
343 0 : f = xasprintf ("(pgpUserID=%s)",
344 0 : (freeme = ldap_escape_filter (desc.u.name)));
345 0 : break;
346 :
347 : case KEYDB_SEARCH_MODE_SUBSTR:
348 0 : if (! only_exact)
349 0 : f = xasprintf ("(pgpUserID=*%s*)",
350 0 : (freeme = ldap_escape_filter (desc.u.name)));
351 0 : break;
352 :
353 : case KEYDB_SEARCH_MODE_MAIL:
354 0 : if (! only_exact)
355 0 : f = xasprintf ("(pgpUserID=*<%s>*)",
356 0 : (freeme = ldap_escape_filter (desc.u.name)));
357 0 : break;
358 :
359 : case KEYDB_SEARCH_MODE_MAILSUB:
360 0 : if (! only_exact)
361 0 : f = xasprintf ("(pgpUserID=*<*%s*>*)",
362 0 : (freeme = ldap_escape_filter (desc.u.name)));
363 0 : break;
364 :
365 : case KEYDB_SEARCH_MODE_MAILEND:
366 0 : if (! only_exact)
367 0 : f = xasprintf ("(pgpUserID=*<*%s>*)",
368 0 : (freeme = ldap_escape_filter (desc.u.name)));
369 0 : break;
370 :
371 : case KEYDB_SEARCH_MODE_SHORT_KID:
372 0 : f = xasprintf ("(pgpKeyID=%08lX)", (ulong) desc.u.kid[1]);
373 0 : break;
374 : case KEYDB_SEARCH_MODE_LONG_KID:
375 0 : f = xasprintf ("(pgpCertID=%08lX%08lX)",
376 0 : (ulong) desc.u.kid[0], (ulong) desc.u.kid[1]);
377 0 : break;
378 :
379 : case KEYDB_SEARCH_MODE_FPR16:
380 : case KEYDB_SEARCH_MODE_FPR20:
381 : case KEYDB_SEARCH_MODE_FPR:
382 : case KEYDB_SEARCH_MODE_ISSUER:
383 : case KEYDB_SEARCH_MODE_ISSUER_SN:
384 : case KEYDB_SEARCH_MODE_SN:
385 : case KEYDB_SEARCH_MODE_SUBJECT:
386 : case KEYDB_SEARCH_MODE_KEYGRIP:
387 : case KEYDB_SEARCH_MODE_WORDS:
388 : case KEYDB_SEARCH_MODE_FIRST:
389 : case KEYDB_SEARCH_MODE_NEXT:
390 : default:
391 0 : break;
392 : }
393 :
394 0 : xfree (freeme);
395 :
396 0 : if (! f)
397 : {
398 0 : log_error ("Unsupported search mode.\n");
399 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
400 : }
401 :
402 0 : *filter = f;
403 :
404 0 : return 0;
405 : }
406 :
407 :
408 :
409 : /* Connect to an LDAP server and interrogate it.
410 :
411 : - uri describes the server to connect to and various options
412 : including whether to use TLS and the username and password (see
413 : ldap_parse_uri for a description of the various fields).
414 :
415 : This function returns:
416 :
417 : - The ldap connection handle in *LDAP_CONNP.
418 :
419 : - The base DN for the PGP key space by querying the
420 : pgpBaseKeySpaceDN attribute (This is normally
421 : 'ou=PGP Keys,dc=EXAMPLE,dc=ORG').
422 :
423 : - The attribute to lookup to find the pgp key. This is either
424 : 'pgpKey' or 'pgpKeyV2'.
425 :
426 : - Whether this is a real ldap server. (It's unclear what this
427 : exactly means.)
428 :
429 : The values are returned in the passed variables. If you pass NULL,
430 : then the value won't be returned. It is the caller's
431 : responsibility to release *LDAP_CONNP with ldap_unbind and xfree
432 : *BASEDNP and *PGPKEYATTRP.
433 :
434 : If this function successfully interrogated the server, it returns
435 : 0. If there was an LDAP error, it returns the LDAP error code. If
436 : an error occurred, *basednp, etc., are undefined (and don't need to
437 : be freed.)
438 :
439 : If no LDAP error occurred, you still need to check that *basednp is
440 : valid. If it is NULL, then the server does not appear to be an
441 : OpenPGP Keyserver. In this case, you also do not need to xfree
442 : *pgpkeyattrp. */
443 : static int
444 0 : my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
445 : char **basednp, char **pgpkeyattrp, int *real_ldapp)
446 : {
447 0 : int err = 0;
448 :
449 0 : LDAP *ldap_conn = NULL;
450 :
451 0 : char *user = uri->auth;
452 0 : struct uri_tuple_s *password_param = uri_query_lookup (uri, "password");
453 0 : char *password = password_param ? password_param->value : NULL;
454 :
455 0 : char *basedn = NULL;
456 : /* Whether to look for the pgpKey or pgpKeyv2 attribute. */
457 0 : char *pgpkeyattr = "pgpKey";
458 0 : int real_ldap = 0;
459 :
460 0 : log_debug ("my_ldap_connect(%s:%d/%s????%s%s%s%s%s)\n",
461 0 : uri->host, uri->port,
462 0 : uri->path ?: "",
463 0 : uri->auth ? "bindname=" : "", uri->auth ?: "",
464 0 : uri->auth && password ? "," : "",
465 0 : password ? "password=" : "", password ?: "");
466 :
467 : /* If the uri specifies a secure connection and we don't support
468 : TLS, then fail; don't silently revert to an insecure
469 : connection. */
470 0 : if (uri->use_tls)
471 : {
472 : #ifndef HAVE_LDAP_START_TLS_S
473 : log_error ("Can't use LDAP to connect to the server: no TLS support.");
474 : err = GPG_ERR_LDAP_NOT_SUPPORTED;
475 : goto out;
476 : #endif
477 : }
478 :
479 0 : ldap_conn = ldap_init (uri->host, uri->port);
480 0 : if (! ldap_conn)
481 : {
482 0 : err = gpg_err_code_from_syserror ();
483 0 : log_error ("Failed to open connection to LDAP server (%s://%s:%d)\n",
484 0 : uri->scheme, uri->host, uri->port);
485 0 : goto out;
486 : }
487 :
488 : #ifdef HAVE_LDAP_SET_OPTION
489 : {
490 0 : int ver = LDAP_VERSION3;
491 :
492 0 : err = ldap_set_option (ldap_conn, LDAP_OPT_PROTOCOL_VERSION, &ver);
493 0 : if (err != LDAP_SUCCESS)
494 : {
495 0 : log_error ("gpgkeys: unable to go to LDAP 3: %s\n",
496 : ldap_err2string (err));
497 0 : goto out;
498 : }
499 : }
500 : #endif
501 :
502 : /* XXX: It would be nice to have an option to provide the server's
503 : certificate. */
504 : #if 0
505 : #if defined(LDAP_OPT_X_TLS_CACERTFILE) && defined(HAVE_LDAP_SET_OPTION)
506 : err = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, ca_cert_file);
507 : if (err)
508 : {
509 : log_error ("unable to set ca-cert-file to '%s': %s\n",
510 : ca_cert_file, ldap_err2string (err));
511 : goto out;
512 : }
513 : #endif /* LDAP_OPT_X_TLS_CACERTFILE && HAVE_LDAP_SET_OPTION */
514 : #endif
515 :
516 : #ifndef HAVE_LDAP_START_TLS_S
517 : if (uri->use_tls)
518 : {
519 : /* XXX: We need an option to determine whether to abort if the
520 : certificate is bad or not. Right now we conservatively
521 : default to checking the certificate and aborting. */
522 : int check_cert = LDAP_OPT_X_TLS_HARD; /* LDAP_OPT_X_TLS_NEVER */
523 :
524 : err = ldap_set_option (ldap_conn,
525 : LDAP_OPT_X_TLS_REQUIRE_CERT, &check_cert);
526 : if (err)
527 : {
528 : log_error ("Failed to set TLS option on LDAP connection.\n");
529 : goto out;
530 : }
531 :
532 : err = ldap_start_tls_s (ldap_conn, NULL, NULL);
533 : if (err)
534 : {
535 : log_error ("Failed to connect to LDAP server with TLS.\n");
536 : goto out;
537 : }
538 : }
539 : #endif
540 :
541 : /* By default we don't bind as there is usually no need to. */
542 0 : if (uri->auth)
543 : {
544 0 : log_debug ("LDAP bind to %s, password %s\n",
545 : user, password ? ">not shown<" : ">none<");
546 :
547 0 : err = ldap_simple_bind_s (ldap_conn, user, password);
548 0 : if (err != LDAP_SUCCESS)
549 : {
550 0 : log_error ("Internal LDAP bind error: %s\n",
551 : ldap_err2string (err));
552 0 : goto out;
553 : }
554 : }
555 :
556 0 : if (uri->path && *uri->path)
557 : /* User specified base DN. */
558 : {
559 0 : basedn = xstrdup (uri->path);
560 :
561 : /* If the user specifies a base DN, then we know the server is a
562 : real LDAP server. */
563 0 : real_ldap = 1;
564 : }
565 : else
566 : {
567 0 : LDAPMessage *res = NULL;
568 : /* Look for namingContexts. */
569 0 : char *attr[] = { "namingContexts", NULL };
570 :
571 0 : err = ldap_search_s (ldap_conn, "", LDAP_SCOPE_BASE,
572 : "(objectClass=*)", attr, 0, &res);
573 0 : if (err == LDAP_SUCCESS)
574 : {
575 0 : char **context = ldap_get_values (ldap_conn, res, "namingContexts");
576 0 : if (context)
577 : /* We found some, so try each namingContext as the search
578 : base and look for pgpBaseKeySpaceDN. Because we found
579 : this, we know we're talking to a regular-ish LDAP
580 : server and not an LDAP keyserver. */
581 : {
582 : int i;
583 0 : char *attr2[] =
584 : { "pgpBaseKeySpaceDN", "pgpVersion", "pgpSoftware", NULL };
585 :
586 0 : real_ldap = 1;
587 :
588 0 : for (i = 0; context[i] && ! basedn; i++)
589 : {
590 : char **vals;
591 : LDAPMessage *si_res;
592 :
593 : {
594 0 : char *object = xasprintf ("cn=pgpServerInfo,%s",
595 0 : context[i]);
596 0 : err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
597 : "(objectClass=*)", attr2, 0, &si_res);
598 0 : xfree (object);
599 : }
600 :
601 0 : if (err == LDAP_SUCCESS)
602 : {
603 0 : vals = ldap_get_values (ldap_conn, si_res,
604 : "pgpBaseKeySpaceDN");
605 0 : if (vals)
606 : {
607 0 : basedn = xtrystrdup (vals[0]);
608 0 : ldap_value_free (vals);
609 : }
610 :
611 0 : vals = ldap_get_values (ldap_conn, si_res,
612 : "pgpSoftware");
613 0 : if (vals)
614 : {
615 0 : log_debug ("Server: \t%s\n", vals[0]);
616 0 : ldap_value_free (vals);
617 : }
618 :
619 0 : vals = ldap_get_values (ldap_conn, si_res,
620 : "pgpVersion");
621 0 : if (vals)
622 : {
623 0 : log_debug ("Version:\t%s\n", vals[0]);
624 0 : ldap_value_free (vals);
625 : }
626 : }
627 :
628 : /* From man ldap_search_s: "res parameter of
629 : ldap_search_ext_s() and ldap_search_s() should be
630 : freed with ldap_msgfree() regardless of return
631 : value of these functions. */
632 0 : ldap_msgfree (si_res);
633 : }
634 :
635 0 : ldap_value_free (context);
636 : }
637 : }
638 : else
639 : {
640 : /* We don't have an answer yet, which means the server might
641 : be an LDAP keyserver. */
642 : char **vals;
643 0 : LDAPMessage *si_res = NULL;
644 :
645 0 : char *attr2[] = { "pgpBaseKeySpaceDN", "version", "software", NULL };
646 :
647 0 : err = ldap_search_s (ldap_conn, "cn=pgpServerInfo", LDAP_SCOPE_BASE,
648 : "(objectClass=*)", attr2, 0, &si_res);
649 0 : if (err == LDAP_SUCCESS)
650 : {
651 : /* For the LDAP keyserver, this is always
652 : "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not be
653 : in the future. */
654 :
655 0 : vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN");
656 0 : if (vals)
657 : {
658 0 : basedn = xtrystrdup (vals[0]);
659 0 : ldap_value_free (vals);
660 : }
661 :
662 0 : vals = ldap_get_values (ldap_conn, si_res, "software");
663 0 : if (vals)
664 : {
665 0 : log_debug ("ldap: Server: \t%s\n", vals[0]);
666 0 : ldap_value_free (vals);
667 : }
668 :
669 0 : vals = ldap_get_values (ldap_conn, si_res, "version");
670 0 : if (vals)
671 : {
672 0 : log_debug ("ldap: Version:\t%s\n", vals[0]);
673 :
674 : /* If the version is high enough, use the new
675 : pgpKeyV2 attribute. This design is iffy at best,
676 : but it matches how PGP does it. I figure the NAI
677 : folks assumed that there would never be an LDAP
678 : keyserver vendor with a different numbering
679 : scheme. */
680 0 : if (atoi (vals[0]) > 1)
681 0 : pgpkeyattr = "pgpKeyV2";
682 :
683 0 : ldap_value_free (vals);
684 : }
685 : }
686 :
687 0 : ldap_msgfree (si_res);
688 : }
689 :
690 : /* From man ldap_search_s: "res parameter of ldap_search_ext_s()
691 : and ldap_search_s() should be freed with ldap_msgfree()
692 : regardless of return value of these functions. */
693 0 : ldap_msgfree (res);
694 : }
695 :
696 : out:
697 0 : if (! err)
698 : {
699 0 : log_debug ("ldap_conn: %p\n", ldap_conn);
700 0 : log_debug ("real_ldap: %d\n", real_ldap);
701 0 : log_debug ("basedn: %s\n", basedn);
702 0 : log_debug ("pgpkeyattr: %s\n", pgpkeyattr);
703 : }
704 :
705 0 : if (! err && real_ldapp)
706 0 : *real_ldapp = real_ldap;
707 :
708 0 : if (err)
709 0 : xfree (basedn);
710 : else
711 : {
712 0 : if (pgpkeyattrp)
713 : {
714 0 : if (basedn)
715 0 : *pgpkeyattrp = xstrdup (pgpkeyattr);
716 : else
717 0 : *pgpkeyattrp = NULL;
718 : }
719 :
720 0 : if (basednp)
721 0 : *basednp = basedn;
722 : else
723 0 : xfree (basedn);
724 : }
725 :
726 0 : if (err)
727 : {
728 0 : if (ldap_conn)
729 0 : ldap_unbind (ldap_conn);
730 : }
731 : else
732 0 : *ldap_connp = ldap_conn;
733 :
734 0 : return err;
735 : }
736 :
737 : /* Extract keys from an LDAP reply and write them out to the output
738 : stream OUTPUT in a format GnuPG can import (either the OpenPGP
739 : binary format or armored format). */
740 : static void
741 0 : extract_keys (estream_t output,
742 : LDAP *ldap_conn, const char *certid, LDAPMessage *message)
743 : {
744 : char **vals;
745 :
746 0 : es_fprintf (output, "INFO %s BEGIN\n", certid);
747 0 : es_fprintf (output, "pub:%s:", certid);
748 :
749 : /* Note: ldap_get_values returns a NULL terminates array of
750 : strings. */
751 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeytype");
752 0 : if (vals && vals[0])
753 : {
754 0 : if (strcmp (vals[0], "RSA") == 0)
755 0 : es_fprintf (output, "1");
756 0 : else if (strcmp (vals[0],"DSS/DH") == 0)
757 0 : es_fprintf (output, "17");
758 0 : ldap_value_free (vals);
759 : }
760 :
761 0 : es_fprintf (output, ":");
762 :
763 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeysize");
764 0 : if (vals && vals[0])
765 : {
766 0 : int v = atoi (vals[0]);
767 0 : if (v > 0)
768 0 : es_fprintf (output, "%d", v);
769 0 : ldap_value_free (vals);
770 : }
771 :
772 0 : es_fprintf (output, ":");
773 :
774 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeycreatetime");
775 0 : if (vals && vals[0])
776 : {
777 0 : if (strlen (vals[0]) == 15)
778 0 : es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
779 0 : ldap_value_free (vals);
780 : }
781 :
782 0 : es_fprintf (output, ":");
783 :
784 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeyexpiretime");
785 0 : if (vals && vals[0])
786 : {
787 0 : if (strlen (vals[0]) == 15)
788 0 : es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
789 0 : ldap_value_free (vals);
790 : }
791 :
792 0 : es_fprintf (output, ":");
793 :
794 0 : vals = ldap_get_values (ldap_conn, message, "pgprevoked");
795 0 : if (vals && vals[0])
796 : {
797 0 : if (atoi (vals[0]) == 1)
798 0 : es_fprintf (output, "r");
799 0 : ldap_value_free (vals);
800 : }
801 :
802 0 : es_fprintf (output, "\n");
803 :
804 0 : vals = ldap_get_values (ldap_conn, message, "pgpuserid");
805 0 : if (vals && vals[0])
806 : {
807 : int i;
808 0 : for (i = 0; vals[i]; i++)
809 0 : es_fprintf (output, "uid:%s\n", vals[i]);
810 0 : ldap_value_free (vals);
811 : }
812 :
813 0 : es_fprintf (output, "INFO %s END\n", certid);
814 0 : }
815 :
816 : /* Get the key described key the KEYSPEC string from the keyserver
817 : identified by URI. On success R_FP has an open stream to read the
818 : data. */
819 : gpg_error_t
820 0 : ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
821 : estream_t *r_fp)
822 : {
823 0 : gpg_error_t err = 0;
824 : int ldap_err;
825 :
826 0 : char *filter = NULL;
827 :
828 0 : LDAP *ldap_conn = NULL;
829 :
830 0 : char *basedn = NULL;
831 0 : char *pgpkeyattr = NULL;
832 :
833 0 : estream_t fp = NULL;
834 :
835 0 : LDAPMessage *message = NULL;
836 :
837 : (void) ctrl;
838 :
839 0 : if (opt.use_tor)
840 : {
841 : /* For now we do not support LDAP over Tor. */
842 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
843 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
844 : }
845 :
846 : /* Before connecting to the server, make sure we have a sane
847 : keyspec. If not, there is no need to establish a network
848 : connection. */
849 0 : err = keyspec_to_ldap_filter (keyspec, &filter, 1);
850 0 : if (err)
851 0 : return (err);
852 :
853 : /* Make sure we are talking to an OpenPGP LDAP server. */
854 0 : ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL);
855 0 : if (ldap_err || !basedn)
856 : {
857 0 : if (ldap_err)
858 0 : err = ldap_err_to_gpg_err (ldap_err);
859 : else
860 0 : err = GPG_ERR_GENERAL;
861 0 : goto out;
862 : }
863 :
864 : {
865 : /* The ordering is significant. Specifically, "pgpcertid" needs
866 : to be the second item in the list, since everything after it
867 : may be discarded we aren't in verbose mode. */
868 0 : char *attrs[] =
869 : {
870 : pgpkeyattr,
871 : "pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
872 : "pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
873 : NULL
874 : };
875 : /* 1 if we want just attribute types; 0 if we want both attribute
876 : types and values. */
877 0 : int attrsonly = 0;
878 :
879 : int count;
880 :
881 0 : ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
882 : filter, attrs, attrsonly, &message);
883 0 : if (ldap_err)
884 : {
885 0 : err = ldap_err_to_gpg_err (ldap_err);
886 :
887 0 : log_error ("gpgkeys: LDAP search error: %s\n",
888 : ldap_err2string (ldap_err));
889 0 : goto out;
890 : }
891 :
892 0 : count = ldap_count_entries (ldap_conn, message);
893 0 : if (count < 1)
894 : {
895 0 : log_error ("gpgkeys: key %s not found on keyserver\n", keyspec);
896 :
897 0 : if (count == -1)
898 0 : err = ldap_to_gpg_err (ldap_conn);
899 : else
900 0 : err = gpg_error (GPG_ERR_NO_DATA);
901 :
902 0 : goto out;
903 : }
904 :
905 : {
906 : /* There may be more than one unique result for a given keyID,
907 : so we should fetch them all (test this by fetching short key
908 : id 0xDEADBEEF). */
909 :
910 : /* The set of entries that we've seen. */
911 0 : strlist_t seen = NULL;
912 : LDAPMessage *each;
913 :
914 0 : for (each = ldap_first_entry (ldap_conn, message);
915 : each;
916 0 : each = ldap_next_entry (ldap_conn, each))
917 : {
918 : char **vals;
919 : char **certid;
920 :
921 : /* Use the long keyid to remove duplicates. The LDAP
922 : server returns the same keyid more than once if there
923 : are multiple user IDs on the key. Note that this does
924 : NOT mean that a keyid that exists multiple times on the
925 : keyserver will not be fetched. It means that each KEY,
926 : no matter how many user IDs share its keyid, will be
927 : fetched only once. If a keyid that belongs to more
928 : than one key is fetched, the server quite properly
929 : responds with all matching keys. -ds */
930 :
931 0 : certid = ldap_get_values (ldap_conn, each, "pgpcertid");
932 0 : if (certid && certid[0])
933 : {
934 0 : if (! strlist_find (seen, certid[0]))
935 : {
936 : /* It's not a duplicate, add it */
937 :
938 0 : add_to_strlist (&seen, certid[0]);
939 :
940 0 : if (! fp)
941 0 : fp = es_fopenmem(0, "rw");
942 :
943 0 : extract_keys (fp, ldap_conn, certid[0], each);
944 :
945 0 : vals = ldap_get_values (ldap_conn, each, pgpkeyattr);
946 0 : if (! vals)
947 : {
948 0 : err = ldap_to_gpg_err (ldap_conn);
949 0 : log_error("gpgkeys: unable to retrieve key %s "
950 : "from keyserver\n", certid[0]);
951 0 : goto out;
952 : }
953 : else
954 : {
955 : /* We should strip the new lines. */
956 0 : es_fprintf (fp, "KEY 0x%s BEGIN\n", certid[0]);
957 0 : es_fputs (vals[0], fp);
958 0 : es_fprintf (fp, "\nKEY 0x%s END\n", certid[0]);
959 :
960 0 : ldap_value_free (vals);
961 : }
962 : }
963 : }
964 :
965 0 : ldap_value_free (certid);
966 : }
967 :
968 0 : free_strlist (seen);
969 :
970 0 : if (! fp)
971 0 : err = gpg_error (GPG_ERR_NO_DATA);
972 : }
973 : }
974 :
975 : out:
976 0 : if (message)
977 0 : ldap_msgfree (message);
978 :
979 0 : if (err)
980 : {
981 0 : if (fp)
982 0 : es_fclose (fp);
983 : }
984 : else
985 : {
986 0 : if (fp)
987 0 : es_fseek (fp, 0, SEEK_SET);
988 :
989 0 : *r_fp = fp;
990 : }
991 :
992 0 : xfree (pgpkeyattr);
993 0 : xfree (basedn);
994 :
995 0 : if (ldap_conn)
996 0 : ldap_unbind (ldap_conn);
997 :
998 0 : xfree (filter);
999 :
1000 0 : return err;
1001 : }
1002 :
1003 : /* Search the keyserver identified by URI for keys matching PATTERN.
1004 : On success R_FP has an open stream to read the data. */
1005 : gpg_error_t
1006 0 : ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1007 : estream_t *r_fp)
1008 : {
1009 : gpg_error_t err;
1010 : int ldap_err;
1011 :
1012 0 : char *filter = NULL;
1013 :
1014 0 : LDAP *ldap_conn = NULL;
1015 :
1016 0 : char *basedn = NULL;
1017 :
1018 0 : estream_t fp = NULL;
1019 :
1020 : (void) ctrl;
1021 :
1022 0 : if (opt.use_tor)
1023 : {
1024 : /* For now we do not support LDAP over Tor. */
1025 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
1026 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
1027 : }
1028 :
1029 : /* Before connecting to the server, make sure we have a sane
1030 : keyspec. If not, there is no need to establish a network
1031 : connection. */
1032 0 : err = keyspec_to_ldap_filter (pattern, &filter, 0);
1033 0 : if (err)
1034 : {
1035 0 : log_error ("Bad search pattern: '%s'\n", pattern);
1036 0 : return (err);
1037 : }
1038 :
1039 : /* Make sure we are talking to an OpenPGP LDAP server. */
1040 0 : ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL);
1041 0 : if (ldap_err || !basedn)
1042 : {
1043 0 : if (ldap_err)
1044 0 : err = ldap_err_to_gpg_err (ldap_err);
1045 : else
1046 0 : err = GPG_ERR_GENERAL;
1047 0 : goto out;
1048 : }
1049 :
1050 : /* Even if we have no results, we want to return a stream. */
1051 0 : fp = es_fopenmem(0, "rw");
1052 0 : if (!fp)
1053 : {
1054 0 : err = gpg_error_from_syserror ();
1055 0 : goto out;
1056 : }
1057 :
1058 : {
1059 : char **vals;
1060 : LDAPMessage *res, *each;
1061 0 : int count = 0;
1062 0 : strlist_t dupelist = NULL;
1063 :
1064 : /* The maximum size of the search, including the optional stuff
1065 : and the trailing \0 */
1066 0 : char *attrs[] =
1067 : {
1068 : "pgpcertid", "pgpuserid", "pgprevoked", "pgpdisabled",
1069 : "pgpkeycreatetime", "pgpkeyexpiretime", "modifytimestamp",
1070 : "pgpkeysize", "pgpkeytype", NULL
1071 : };
1072 :
1073 0 : log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter);
1074 :
1075 0 : ldap_err = ldap_search_s (ldap_conn, basedn,
1076 : LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res);
1077 :
1078 0 : xfree (filter);
1079 0 : filter = NULL;
1080 :
1081 0 : if (ldap_err != LDAP_SUCCESS && ldap_err != LDAP_SIZELIMIT_EXCEEDED)
1082 : {
1083 0 : err = ldap_err_to_gpg_err (ldap_err);
1084 :
1085 0 : log_error ("SEARCH %s FAILED %d\n", pattern, err);
1086 0 : log_error ("gpgkeys: LDAP search error: %s\n",
1087 : ldap_err2string (err));
1088 0 : goto out;
1089 : }
1090 :
1091 : /* The LDAP server doesn't return a real count of unique keys, so we
1092 : can't use ldap_count_entries here. */
1093 0 : for (each = ldap_first_entry (ldap_conn, res);
1094 : each;
1095 0 : each = ldap_next_entry (ldap_conn, each))
1096 : {
1097 0 : char **certid = ldap_get_values (ldap_conn, each, "pgpcertid");
1098 0 : if (certid && certid[0] && ! strlist_find (dupelist, certid[0]))
1099 : {
1100 0 : add_to_strlist (&dupelist, certid[0]);
1101 0 : count++;
1102 : }
1103 : }
1104 :
1105 0 : if (ldap_err == LDAP_SIZELIMIT_EXCEEDED)
1106 : {
1107 0 : if (count == 1)
1108 0 : log_error ("gpgkeys: search results exceeded server limit."
1109 : " First 1 result shown.\n");
1110 : else
1111 0 : log_error ("gpgkeys: search results exceeded server limit."
1112 : " First %d results shown.\n", count);
1113 : }
1114 :
1115 0 : free_strlist (dupelist);
1116 0 : dupelist = NULL;
1117 :
1118 0 : if (count < 1)
1119 0 : es_fputs ("info:1:0\n", fp);
1120 : else
1121 : {
1122 0 : es_fprintf (fp, "info:1:%d\n", count);
1123 :
1124 0 : for (each = ldap_first_entry (ldap_conn, res);
1125 : each;
1126 0 : each = ldap_next_entry (ldap_conn, each))
1127 : {
1128 : char **certid;
1129 : LDAPMessage *uids;
1130 :
1131 0 : certid = ldap_get_values (ldap_conn, each, "pgpcertid");
1132 0 : if (! certid || ! certid[0])
1133 0 : continue;
1134 :
1135 : /* Have we seen this certid before? */
1136 0 : if (! strlist_find (dupelist, certid[0]))
1137 : {
1138 0 : add_to_strlist (&dupelist, certid[0]);
1139 :
1140 0 : es_fprintf (fp, "pub:%s:",certid[0]);
1141 :
1142 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
1143 0 : if (vals)
1144 : {
1145 : /* The LDAP server doesn't exactly handle this
1146 : well. */
1147 0 : if (strcasecmp (vals[0], "RSA") == 0)
1148 0 : es_fputs ("1", fp);
1149 0 : else if (strcasecmp (vals[0], "DSS/DH") == 0)
1150 0 : es_fputs ("17", fp);
1151 0 : ldap_value_free (vals);
1152 : }
1153 :
1154 0 : es_fputc (':', fp);
1155 :
1156 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
1157 0 : if (vals)
1158 : {
1159 : /* Not sure why, but some keys are listed with a
1160 : key size of 0. Treat that like an unknown. */
1161 0 : if (atoi (vals[0]) > 0)
1162 0 : es_fprintf (fp, "%d", atoi (vals[0]));
1163 0 : ldap_value_free (vals);
1164 : }
1165 :
1166 0 : es_fputc (':', fp);
1167 :
1168 : /* YYYYMMDDHHmmssZ */
1169 :
1170 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
1171 0 : if(vals && strlen (vals[0]) == 15)
1172 : {
1173 0 : es_fprintf (fp, "%u",
1174 0 : (unsigned int) ldap2epochtime(vals[0]));
1175 0 : ldap_value_free (vals);
1176 : }
1177 :
1178 0 : es_fputc (':', fp);
1179 :
1180 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
1181 0 : if (vals && strlen (vals[0]) == 15)
1182 : {
1183 0 : es_fprintf (fp, "%u",
1184 0 : (unsigned int) ldap2epochtime (vals[0]));
1185 0 : ldap_value_free (vals);
1186 : }
1187 :
1188 0 : es_fputc (':', fp);
1189 :
1190 0 : vals = ldap_get_values (ldap_conn, each, "pgprevoked");
1191 0 : if (vals)
1192 : {
1193 0 : if (atoi (vals[0]) == 1)
1194 0 : es_fprintf (fp, "r");
1195 0 : ldap_value_free (vals);
1196 : }
1197 :
1198 0 : vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
1199 0 : if (vals)
1200 : {
1201 0 : if (atoi (vals[0]) ==1)
1202 0 : es_fprintf (fp, "d");
1203 0 : ldap_value_free (vals);
1204 : }
1205 :
1206 : #if 0
1207 : /* This is not yet specified in the keyserver
1208 : protocol, but may be someday. */
1209 : es_fputc (':', fp);
1210 :
1211 : vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
1212 : if(vals && strlen (vals[0]) == 15)
1213 : {
1214 : es_fprintf (fp, "%u",
1215 : (unsigned int) ldap2epochtime (vals[0]));
1216 : ldap_value_free (vals);
1217 : }
1218 : #endif
1219 :
1220 0 : es_fprintf (fp, "\n");
1221 :
1222 : /* Now print all the uids that have this certid */
1223 0 : for (uids = ldap_first_entry (ldap_conn, res);
1224 : uids;
1225 0 : uids = ldap_next_entry (ldap_conn, uids))
1226 : {
1227 0 : vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
1228 0 : if (! vals)
1229 0 : continue;
1230 :
1231 0 : if (strcasecmp (certid[0], vals[0]) == 0)
1232 : {
1233 : char **uidvals;
1234 :
1235 0 : es_fprintf (fp, "uid:");
1236 :
1237 0 : uidvals = ldap_get_values (ldap_conn,
1238 : uids, "pgpuserid");
1239 0 : if (uidvals)
1240 : {
1241 : /* Need to escape any colons */
1242 0 : char *quoted = percent_escape (uidvals[0], NULL);
1243 0 : es_fputs (quoted, fp);
1244 0 : xfree (quoted);
1245 0 : ldap_value_free (uidvals);
1246 : }
1247 :
1248 0 : es_fprintf (fp, "\n");
1249 : }
1250 :
1251 0 : ldap_value_free(vals);
1252 : }
1253 : }
1254 :
1255 0 : ldap_value_free (certid);
1256 : }
1257 : }
1258 :
1259 0 : ldap_msgfree (res);
1260 0 : free_strlist (dupelist);
1261 : }
1262 :
1263 0 : log_debug ("SEARCH %s END\n", pattern);
1264 :
1265 : out:
1266 0 : if (err)
1267 : {
1268 0 : if (fp)
1269 0 : es_fclose (fp);
1270 : }
1271 : else
1272 : {
1273 : /* Return the read stream. */
1274 0 : if (fp)
1275 0 : es_fseek (fp, 0, SEEK_SET);
1276 :
1277 0 : *r_fp = fp;
1278 : }
1279 :
1280 0 : xfree (basedn);
1281 :
1282 0 : if (ldap_conn)
1283 0 : ldap_unbind (ldap_conn);
1284 :
1285 0 : xfree (filter);
1286 :
1287 0 : return err;
1288 : }
1289 :
1290 :
1291 :
1292 : /* A modlist describes a set of changes to an LDAP entry. (An entry
1293 : consists of 1 or more attributes. Attributes are <name, value>
1294 : pairs. Note: an attribute may be multi-valued in which case
1295 : multiple values are associated with a single name.)
1296 :
1297 : A modlist is a NULL terminated array of struct LDAPMod's.
1298 :
1299 : Thus, if we have:
1300 :
1301 : LDAPMod **modlist;
1302 :
1303 : Then:
1304 :
1305 : modlist[i]
1306 :
1307 : Is the ith modification.
1308 :
1309 : Each LDAPMod describes a change to a single attribute. Further,
1310 : there is one modification for each attribute that we want to
1311 : change. The attribute's new value is stored in LDAPMod.mod_values.
1312 : If the attribute is multi-valued, we still only use a single
1313 : LDAPMod structure: mod_values is a NULL-terminated array of
1314 : strings. To delete an attribute from an entry, we set mod_values
1315 : to NULL.
1316 :
1317 : Thus, if:
1318 :
1319 : modlist[i]->mod_values == NULL
1320 :
1321 : then we remove the attribute.
1322 :
1323 : (Using LDAP_MOD_DELETE doesn't work here as we don't know if the
1324 : attribute in question exists or not.)
1325 :
1326 : Note: this function does NOT copy or free ATTR. It does copy
1327 : VALUE. */
1328 : static void
1329 0 : modlist_add (LDAPMod ***modlistp, char *attr, const char *value)
1330 : {
1331 0 : LDAPMod **modlist = *modlistp;
1332 :
1333 : LDAPMod **m;
1334 0 : int nummods = 0;
1335 :
1336 : /* Search modlist for the attribute we're playing with. If modlist
1337 : is NULL, then the list is empty. Recall: modlist is a NULL
1338 : terminated array. */
1339 0 : for (m = modlist; m && *m; m++, nummods ++)
1340 : {
1341 : /* The attribute is already on the list. */
1342 : char **ptr;
1343 0 : int numvalues = 0;
1344 :
1345 0 : if (strcasecmp ((*m)->mod_type, attr) != 0)
1346 0 : continue;
1347 :
1348 : /* We have this attribute already, so when the REPLACE happens,
1349 : the server attributes will be replaced anyway. */
1350 0 : if (! value)
1351 0 : return;
1352 :
1353 : /* Attributes can be multi-valued. See if the value is already
1354 : present. mod_values is a NULL terminated array of pointers.
1355 : Note: mod_values can be NULL. */
1356 0 : for (ptr = (*m)->mod_values; ptr && *ptr; ptr++)
1357 : {
1358 0 : if (strcmp (*ptr, value) == 0)
1359 : /* Duplicate value, we're done. */
1360 0 : return;
1361 0 : numvalues ++;
1362 : }
1363 :
1364 : /* Append the value. */
1365 0 : ptr = xrealloc ((*m)->mod_values, sizeof (char *) * (numvalues + 2));
1366 :
1367 0 : (*m)->mod_values = ptr;
1368 0 : ptr[numvalues] = xstrdup (value);
1369 :
1370 0 : ptr[numvalues + 1] = NULL;
1371 :
1372 0 : return;
1373 : }
1374 :
1375 : /* We didn't find the attr, so make one and add it to the end */
1376 :
1377 : /* Like attribute values, the list of attributes is NULL terminated
1378 : array of pointers. */
1379 0 : modlist = xrealloc (modlist, sizeof (LDAPMod *) * (nummods + 2));
1380 :
1381 0 : *modlistp = modlist;
1382 0 : modlist[nummods] = xmalloc (sizeof (LDAPMod));
1383 :
1384 0 : modlist[nummods]->mod_op = LDAP_MOD_REPLACE;
1385 0 : modlist[nummods]->mod_type = attr;
1386 0 : if (value)
1387 : {
1388 0 : modlist[nummods]->mod_values = xmalloc (sizeof(char *) * 2);
1389 :
1390 0 : modlist[nummods]->mod_values[0] = xstrdup (value);
1391 0 : modlist[nummods]->mod_values[1] = NULL;
1392 : }
1393 : else
1394 0 : modlist[nummods]->mod_values = NULL;
1395 :
1396 0 : modlist[nummods + 1] = NULL;
1397 :
1398 0 : return;
1399 : }
1400 :
1401 : /* Look up the value of an attribute in the specified modlist. If the
1402 : attribute is not on the mod list, returns NULL. The result is a
1403 : NULL-terminated array of strings. Don't change it. */
1404 : static char **
1405 0 : modlist_lookup (LDAPMod **modlist, const char *attr)
1406 : {
1407 : LDAPMod **m;
1408 0 : for (m = modlist; m && *m; m++)
1409 : {
1410 0 : if (strcasecmp ((*m)->mod_type, attr) != 0)
1411 0 : continue;
1412 :
1413 0 : return (*m)->mod_values;
1414 : }
1415 :
1416 0 : return NULL;
1417 : }
1418 :
1419 : /* Dump a modlist to a file. This is useful for debugging. */
1420 : static estream_t modlist_dump (LDAPMod **modlist, estream_t output)
1421 : GPGRT_ATTR_USED;
1422 :
1423 : static estream_t
1424 0 : modlist_dump (LDAPMod **modlist, estream_t output)
1425 : {
1426 : LDAPMod **m;
1427 :
1428 0 : int opened = 0;
1429 :
1430 0 : if (! output)
1431 : {
1432 0 : output = es_fopenmem (0, "rw");
1433 0 : if (!output)
1434 0 : return NULL;
1435 0 : opened = 1;
1436 : }
1437 :
1438 0 : for (m = modlist; m && *m; m++)
1439 : {
1440 0 : es_fprintf (output, " %s:", (*m)->mod_type);
1441 :
1442 0 : if (! (*m)->mod_values)
1443 0 : es_fprintf(output, " delete.\n");
1444 : else
1445 : {
1446 : char **ptr;
1447 : int i;
1448 :
1449 0 : int multi = 0;
1450 0 : if ((*m)->mod_values[0] && (*m)->mod_values[1])
1451 : /* Have at least 2. */
1452 0 : multi = 1;
1453 :
1454 0 : if (multi)
1455 0 : es_fprintf (output, "\n");
1456 :
1457 0 : for ((ptr = (*m)->mod_values), (i = 1); ptr && *ptr; ptr++, i ++)
1458 : {
1459 : /* Assuming terminals are about 80 characters wide,
1460 : display at most most about 10 lines of debugging
1461 : output. If we do trim the buffer, append '...' to
1462 : the end. */
1463 0 : const int max_len = 10 * 70;
1464 0 : size_t value_len = strlen (*ptr);
1465 0 : int elide = value_len > max_len;
1466 :
1467 0 : if (multi)
1468 0 : es_fprintf (output, " %d. ", i);
1469 0 : es_fprintf (output, "`%.*s", max_len, *ptr);
1470 0 : if (elide)
1471 0 : es_fprintf (output, "...' (%zd bytes elided)",
1472 : value_len - max_len);
1473 : else
1474 0 : es_fprintf (output, "'");
1475 0 : es_fprintf (output, "\n");
1476 : }
1477 : }
1478 : }
1479 :
1480 0 : if (opened)
1481 0 : es_fseek (output, 0, SEEK_SET);
1482 :
1483 0 : return output;
1484 : }
1485 :
1486 : /* Free all of the memory allocated by the mod list. This assumes
1487 : that the attribute names don't have to be freed, but the attributes
1488 : values do. (Which is what modlist_add does.) */
1489 : static void
1490 0 : modlist_free (LDAPMod **modlist)
1491 : {
1492 : LDAPMod **ml;
1493 :
1494 0 : if (! modlist)
1495 0 : return;
1496 :
1497 : /* Unwind and free the whole modlist structure */
1498 :
1499 : /* The modlist is a NULL terminated array of pointers. */
1500 0 : for (ml = modlist; *ml; ml++)
1501 : {
1502 0 : LDAPMod *mod = *ml;
1503 : char **ptr;
1504 :
1505 : /* The list of values is a NULL termianted array of pointers.
1506 : If the list is NULL, there are no values. */
1507 :
1508 0 : if (mod->mod_values)
1509 : {
1510 0 : for (ptr = mod->mod_values; *ptr; ptr++)
1511 0 : xfree (*ptr);
1512 :
1513 0 : xfree (mod->mod_values);
1514 : }
1515 :
1516 0 : xfree (mod);
1517 : }
1518 0 : xfree (modlist);
1519 : }
1520 :
1521 : /* Append two onto the end of one. Two is not freed, but its pointers
1522 : are now part of one. Make sure you don't free them both!
1523 :
1524 : As long as you don't add anything to ONE, TWO is still valid.
1525 : After that all bets are off. */
1526 : static void
1527 0 : modlists_join (LDAPMod ***one, LDAPMod **two)
1528 : {
1529 0 : int i, one_count = 0, two_count = 0;
1530 : LDAPMod **grow;
1531 :
1532 0 : if (!*two)
1533 : /* two is empty. Nothing to do. */
1534 0 : return;
1535 :
1536 0 : if (!*one)
1537 : /* one is empty. Just set it equal to *two. */
1538 : {
1539 0 : *one = two;
1540 0 : return;
1541 : }
1542 :
1543 0 : for (grow = *one; *grow; grow++)
1544 0 : one_count ++;
1545 :
1546 0 : for (grow = two; *grow; grow++)
1547 0 : two_count ++;
1548 :
1549 0 : grow = xrealloc (*one, sizeof(LDAPMod *) * (one_count + two_count + 1));
1550 :
1551 0 : for (i = 0; i < two_count; i++)
1552 0 : grow[one_count + i] = two[i];
1553 :
1554 0 : grow[one_count + i] = NULL;
1555 :
1556 0 : *one = grow;
1557 : }
1558 :
1559 : /* Given a string, unescape C escapes. In particular, \xXX. This
1560 : modifies the string in place. */
1561 : static void
1562 0 : uncescape (char *str)
1563 : {
1564 0 : size_t r = 0;
1565 0 : size_t w = 0;
1566 :
1567 0 : char *first = strchr (str, '\\');
1568 0 : if (! first)
1569 : /* No backslashes => no escaping. We're done. */
1570 0 : return;
1571 :
1572 : /* Start at the first '\\'. */
1573 0 : r = w = (uintptr_t) first - (uintptr_t) str;
1574 :
1575 0 : while (str[r])
1576 : {
1577 : /* XXX: What to do about bad escapes?
1578 : XXX: hextobyte already checks the string thus the hexdigitp
1579 : could be removed. */
1580 0 : if (str[r] == '\\' && str[r + 1] == 'x'
1581 0 : && str[r+2] && str[r+3]
1582 0 : && hexdigitp (str + r + 2)
1583 0 : && hexdigitp (str + r + 3))
1584 0 : {
1585 0 : int x = hextobyte (&str[r + 2]);
1586 0 : assert (0 <= x && x <= 0xff);
1587 :
1588 0 : str[w] = x;
1589 :
1590 : /* We consumed 4 characters and wrote 1. */
1591 0 : r += 4;
1592 0 : w ++;
1593 : }
1594 : else
1595 0 : str[w ++] = str[r ++];
1596 : }
1597 :
1598 0 : str[w] = '\0';
1599 : }
1600 :
1601 : /* Given one line from an info block (`gpg --list-{keys,sigs}
1602 : --with-colons KEYID'), pull it apart and fill in the modlist with
1603 : the relevant (for the LDAP schema) attributes. */
1604 : static void
1605 0 : extract_attributes (LDAPMod ***modlist, char *line)
1606 : {
1607 : int field_count;
1608 : char **fields;
1609 :
1610 : char *keyid;
1611 :
1612 : int is_pub, is_sub, is_uid, is_sig;
1613 :
1614 : /* Remove trailing whitespace */
1615 0 : trim_trailing_spaces (line);
1616 :
1617 0 : fields = strsplit (line, ':', '\0', &field_count);
1618 0 : if (field_count == 1)
1619 : /* We only have a single field. There is definitely nothing to
1620 : do. */
1621 0 : goto out;
1622 :
1623 0 : if (field_count < 7)
1624 0 : goto out;
1625 :
1626 0 : is_pub = strcasecmp ("pub", fields[0]) == 0;
1627 0 : is_sub = strcasecmp ("sub", fields[0]) == 0;
1628 0 : is_uid = strcasecmp ("uid", fields[0]) == 0;
1629 0 : is_sig = strcasecmp ("sig", fields[0]) == 0;
1630 :
1631 0 : if (!is_pub && !is_sub && !is_uid && !is_sig)
1632 : /* Not a relevant line. */
1633 0 : goto out;
1634 :
1635 0 : keyid = fields[4];
1636 :
1637 0 : if (is_uid && strlen (keyid) == 0)
1638 : /* The uid record type can have an empty keyid. */
1639 : ;
1640 0 : else if (strlen (keyid) == 16
1641 0 : && strspn (keyid, "0123456789aAbBcCdDeEfF") == 16)
1642 : /* Otherwise, we expect exactly 16 hex characters. */
1643 : ;
1644 : else
1645 : {
1646 0 : log_error ("malformed record!\n");
1647 0 : goto out;
1648 : }
1649 :
1650 0 : if (is_pub)
1651 : {
1652 0 : int disabled = 0;
1653 0 : int revoked = 0;
1654 : char *flags;
1655 0 : for (flags = fields[1]; *flags; flags ++)
1656 0 : switch (*flags)
1657 : {
1658 : case 'r':
1659 : case 'R':
1660 0 : revoked = 1;
1661 0 : break;
1662 :
1663 : case 'd':
1664 : case 'D':
1665 0 : disabled = 1;
1666 0 : break;
1667 : }
1668 :
1669 : /* Note: we always create the pgpDisabled and pgpRevoked
1670 : attributes, regardless of whether the key is disabled/revoked
1671 : or not. This is because a very common search is like
1672 : "(&(pgpUserID=*isabella*)(pgpDisabled=0))" */
1673 :
1674 0 : if (is_pub)
1675 : {
1676 0 : modlist_add (modlist,"pgpDisabled", disabled ? "1" : "0");
1677 0 : modlist_add (modlist,"pgpRevoked", revoked ? "1" : "0");
1678 : }
1679 : }
1680 :
1681 0 : if (is_pub || is_sub)
1682 : {
1683 0 : char *size = fields[2];
1684 0 : int val = atoi (size);
1685 0 : size = NULL;
1686 :
1687 0 : if (val > 0)
1688 : {
1689 : /* We zero pad this on the left to make PGP happy. */
1690 : char padded[6];
1691 0 : if (val < 99999 && val > 0)
1692 : {
1693 0 : snprintf (padded, sizeof padded, "%05u", val);
1694 0 : size = padded;
1695 : }
1696 : }
1697 :
1698 0 : if (size)
1699 : {
1700 0 : if (is_pub || is_sub)
1701 0 : modlist_add (modlist, "pgpKeySize", size);
1702 : }
1703 : }
1704 :
1705 0 : if (is_pub)
1706 : {
1707 0 : char *algo = fields[3];
1708 0 : int val = atoi (algo);
1709 0 : switch (val)
1710 : {
1711 : case 1:
1712 0 : algo = "RSA";
1713 0 : break;
1714 :
1715 : case 17:
1716 0 : algo = "DSS/DH";
1717 0 : break;
1718 :
1719 : default:
1720 0 : algo = NULL;
1721 0 : break;
1722 : }
1723 :
1724 0 : if (algo)
1725 : {
1726 0 : if (is_pub)
1727 0 : modlist_add (modlist, "pgpKeyType", algo);
1728 : }
1729 : }
1730 :
1731 0 : if (is_pub || is_sub || is_sig)
1732 : {
1733 0 : if (is_pub)
1734 : {
1735 0 : modlist_add (modlist, "pgpCertID", keyid);
1736 0 : modlist_add (modlist, "pgpKeyID", &keyid[8]);
1737 : }
1738 :
1739 0 : if (is_sub)
1740 0 : modlist_add (modlist, "pgpSubKeyID", keyid);
1741 :
1742 0 : if (is_sig)
1743 0 : modlist_add (modlist, "pgpSignerID", keyid);
1744 : }
1745 :
1746 0 : if (is_pub)
1747 : {
1748 0 : char *create_time = fields[5];
1749 :
1750 0 : if (strlen (create_time) == 0)
1751 0 : create_time = NULL;
1752 : else
1753 : {
1754 0 : char *create_time_orig = create_time;
1755 : struct tm tm;
1756 : time_t t;
1757 : char *end;
1758 :
1759 0 : memset (&tm, 0, sizeof (tm));
1760 :
1761 : /* parse_timestamp handles both seconds fromt he epoch and
1762 : ISO 8601 format. We also need to handle YYYY-MM-DD
1763 : format (as generated by gpg1 --with-colons --list-key).
1764 : Check that first and then if it fails, then try
1765 : parse_timestamp. */
1766 :
1767 0 : if (!isodate_human_to_tm (create_time, &tm))
1768 0 : create_time = tm2ldaptime (&tm);
1769 0 : else if ((t = parse_timestamp (create_time, &end)) != (time_t) -1
1770 0 : && *end == '\0')
1771 : {
1772 :
1773 0 : if (!gnupg_gmtime (&t, &tm))
1774 0 : create_time = NULL;
1775 : else
1776 0 : create_time = tm2ldaptime (&tm);
1777 : }
1778 : else
1779 0 : create_time = NULL;
1780 :
1781 0 : if (! create_time)
1782 : /* Failed to parse string. */
1783 0 : log_error ("Failed to parse creation time ('%s')",
1784 : create_time_orig);
1785 : }
1786 :
1787 0 : if (create_time)
1788 : {
1789 0 : modlist_add (modlist, "pgpKeyCreateTime", create_time);
1790 0 : xfree (create_time);
1791 : }
1792 : }
1793 :
1794 0 : if (is_pub)
1795 : {
1796 0 : char *expire_time = fields[6];
1797 :
1798 0 : if (strlen (expire_time) == 0)
1799 0 : expire_time = NULL;
1800 : else
1801 : {
1802 0 : char *expire_time_orig = expire_time;
1803 : struct tm tm;
1804 : time_t t;
1805 : char *end;
1806 :
1807 0 : memset (&tm, 0, sizeof (tm));
1808 :
1809 : /* parse_timestamp handles both seconds fromt he epoch and
1810 : ISO 8601 format. We also need to handle YYYY-MM-DD
1811 : format (as generated by gpg1 --with-colons --list-key).
1812 : Check that first and then if it fails, then try
1813 : parse_timestamp. */
1814 :
1815 0 : if (!isodate_human_to_tm (expire_time, &tm))
1816 0 : expire_time = tm2ldaptime (&tm);
1817 0 : else if ((t = parse_timestamp (expire_time, &end)) != (time_t) -1
1818 0 : && *end == '\0')
1819 : {
1820 0 : if (!gnupg_gmtime (&t, &tm))
1821 0 : expire_time = NULL;
1822 : else
1823 0 : expire_time = tm2ldaptime (&tm);
1824 : }
1825 : else
1826 0 : expire_time = NULL;
1827 :
1828 0 : if (! expire_time)
1829 : /* Failed to parse string. */
1830 0 : log_error ("Failed to parse creation time ('%s')",
1831 : expire_time_orig);
1832 : }
1833 :
1834 0 : if (expire_time)
1835 : {
1836 0 : modlist_add (modlist, "pgpKeyExpireTime", expire_time);
1837 0 : xfree (expire_time);
1838 : }
1839 : }
1840 :
1841 0 : if ((is_uid || is_pub) && field_count >= 10)
1842 : {
1843 0 : char *uid = fields[9];
1844 :
1845 0 : if (is_pub && strlen (uid) == 0)
1846 : /* When using gpg --list-keys, the uid is included. When
1847 : passed via gpg, it is not. It is important to process it
1848 : when it is present, because gpg 1 won't print a UID record
1849 : if there is only one key. */
1850 : ;
1851 : else
1852 : {
1853 0 : uncescape (uid);
1854 0 : modlist_add (modlist, "pgpUserID", uid);
1855 : }
1856 : }
1857 :
1858 : out:
1859 0 : free (fields);
1860 0 : }
1861 :
1862 : /* Send the key in {KEY,KEYLEN} with the metadata {INFO,INFOLEN} to
1863 : the keyserver identified by URI. See server.c:cmd_ks_put for the
1864 : format of the data and metadata. */
1865 : gpg_error_t
1866 0 : ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
1867 : void *data, size_t datalen,
1868 : void *info, size_t infolen)
1869 : {
1870 0 : gpg_error_t err = 0;
1871 : int ldap_err;
1872 :
1873 0 : LDAP *ldap_conn = NULL;
1874 0 : char *basedn = NULL;
1875 0 : char *pgpkeyattr = NULL;
1876 : int real_ldap;
1877 :
1878 0 : LDAPMod **modlist = NULL;
1879 0 : LDAPMod **addlist = NULL;
1880 :
1881 0 : char *data_armored = NULL;
1882 :
1883 : /* The last byte of the info block. */
1884 0 : const char *infoend = (const char *) info + infolen - 1;
1885 :
1886 : /* Enable this code to dump the modlist to /tmp/modlist.txt. */
1887 : #if 0
1888 : # warning Disable debug code before checking in.
1889 : const int dump_modlist = 1;
1890 : #else
1891 0 : const int dump_modlist = 0;
1892 : #endif
1893 0 : estream_t dump = NULL;
1894 :
1895 : /* Elide a warning. */
1896 : (void) ctrl;
1897 :
1898 0 : if (opt.use_tor)
1899 : {
1900 : /* For now we do not support LDAP over Tor. */
1901 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
1902 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
1903 : }
1904 :
1905 0 : ldap_err = my_ldap_connect (uri,
1906 : &ldap_conn, &basedn, &pgpkeyattr, &real_ldap);
1907 0 : if (ldap_err || !basedn)
1908 : {
1909 0 : if (ldap_err)
1910 0 : err = ldap_err_to_gpg_err (ldap_err);
1911 : else
1912 0 : err = GPG_ERR_GENERAL;
1913 0 : goto out;
1914 : }
1915 :
1916 0 : if (! real_ldap)
1917 : /* We appear to have an OpenPGP Keyserver, which can unpack the key
1918 : on its own (not just a dumb LDAP server). */
1919 : {
1920 : LDAPMod mod, *attrs[2];
1921 0 : char *key[] = { data, NULL };
1922 : char *dn;
1923 :
1924 0 : memset (&mod, 0, sizeof (mod));
1925 0 : mod.mod_op = LDAP_MOD_ADD;
1926 0 : mod.mod_type = pgpkeyattr;
1927 0 : mod.mod_values = key;
1928 0 : attrs[0] = &mod;
1929 0 : attrs[1] = NULL;
1930 :
1931 0 : dn = xasprintf ("pgpCertid=virtual,%s", basedn);
1932 0 : ldap_err = ldap_add_s (ldap_conn, dn, attrs);
1933 0 : xfree (dn);
1934 :
1935 0 : if (ldap_err != LDAP_SUCCESS)
1936 : {
1937 0 : err = ldap_err_to_gpg_err (err);
1938 0 : goto out;
1939 : }
1940 :
1941 0 : goto out;
1942 : }
1943 :
1944 0 : modlist = xmalloc (sizeof (LDAPMod *));
1945 0 : *modlist = NULL;
1946 :
1947 0 : if (dump_modlist)
1948 : {
1949 0 : dump = es_fopen("/tmp/modlist.txt", "w");
1950 0 : if (! dump)
1951 0 : log_error ("Failed to open /tmp/modlist.txt: %s\n",
1952 0 : strerror (errno));
1953 :
1954 0 : if (dump)
1955 : {
1956 0 : es_fprintf(dump, "data (%zd bytes)\n", datalen);
1957 0 : es_fprintf(dump, "info (%zd bytes): '\n", infolen);
1958 0 : es_fwrite(info, infolen, 1, dump);
1959 0 : es_fprintf(dump, "'\n");
1960 : }
1961 : }
1962 :
1963 : /* Start by nulling out all attributes. We try and do a modify
1964 : operation first, so this ensures that we don't leave old
1965 : attributes lying around. */
1966 0 : modlist_add (&modlist, "pgpDisabled", NULL);
1967 0 : modlist_add (&modlist, "pgpKeyID", NULL);
1968 0 : modlist_add (&modlist, "pgpKeyType", NULL);
1969 0 : modlist_add (&modlist, "pgpUserID", NULL);
1970 0 : modlist_add (&modlist, "pgpKeyCreateTime", NULL);
1971 0 : modlist_add (&modlist, "pgpSignerID", NULL);
1972 0 : modlist_add (&modlist, "pgpRevoked", NULL);
1973 0 : modlist_add (&modlist, "pgpSubKeyID", NULL);
1974 0 : modlist_add (&modlist, "pgpKeySize", NULL);
1975 0 : modlist_add (&modlist, "pgpKeyExpireTime", NULL);
1976 0 : modlist_add (&modlist, "pgpCertID", NULL);
1977 :
1978 : /* Assemble the INFO stuff into LDAP attributes */
1979 :
1980 0 : while (infolen > 0)
1981 : {
1982 0 : char *temp = NULL;
1983 :
1984 0 : char *newline = memchr (info, '\n', infolen);
1985 0 : if (! newline)
1986 : /* The last line is not \n terminated! Make a copy so we can
1987 : add a NUL terminator. */
1988 : {
1989 0 : temp = xmalloc (infolen + 1);
1990 0 : memcpy (temp, info, infolen);
1991 0 : info = temp;
1992 0 : newline = (char *) info + infolen;
1993 : }
1994 :
1995 0 : *newline = '\0';
1996 :
1997 0 : extract_attributes (&modlist, info);
1998 :
1999 0 : infolen = infolen - ((uintptr_t) newline - (uintptr_t) info + 1);
2000 0 : info = newline + 1;
2001 :
2002 : /* Sanity check. */
2003 0 : if (! temp)
2004 0 : assert ((char *) info + infolen - 1 == infoend);
2005 : else
2006 : {
2007 0 : assert (infolen == -1);
2008 0 : xfree (temp);
2009 : }
2010 : }
2011 :
2012 0 : modlist_add (&addlist, "objectClass", "pgpKeyInfo");
2013 :
2014 0 : err = armor_data (&data_armored, data, datalen);
2015 0 : if (err)
2016 0 : goto out;
2017 :
2018 0 : modlist_add (&addlist, pgpkeyattr, data_armored);
2019 :
2020 : /* Now append addlist onto modlist. */
2021 0 : modlists_join (&modlist, addlist);
2022 :
2023 0 : if (dump)
2024 : {
2025 0 : estream_t input = modlist_dump (modlist, NULL);
2026 0 : if (input)
2027 : {
2028 0 : copy_stream (input, dump);
2029 0 : es_fclose (input);
2030 : }
2031 : }
2032 :
2033 : /* Going on the assumption that modify operations are more frequent
2034 : than adds, we try a modify first. If it's not there, we just
2035 : turn around and send an add command for the same key. Otherwise,
2036 : the modify brings the server copy into compliance with our copy.
2037 : Note that unlike the LDAP keyserver (and really, any other
2038 : keyserver) this does NOT merge signatures, but replaces the whole
2039 : key. This should make some people very happy. */
2040 : {
2041 : char **certid;
2042 : char *dn;
2043 :
2044 0 : certid = modlist_lookup (modlist, "pgpCertID");
2045 0 : if (/* We should have a value. */
2046 : ! certid
2047 : /* Exactly one. */
2048 0 : || !(certid[0] && !certid[1]))
2049 : {
2050 0 : log_error ("Bad certid.\n");
2051 0 : err = GPG_ERR_GENERAL;
2052 0 : goto out;
2053 : }
2054 :
2055 0 : dn = xasprintf ("pgpCertID=%s,%s", certid[0], basedn);
2056 :
2057 0 : err = ldap_modify_s (ldap_conn, dn, modlist);
2058 0 : if (err == LDAP_NO_SUCH_OBJECT)
2059 0 : err = ldap_add_s (ldap_conn, dn, addlist);
2060 :
2061 0 : xfree (dn);
2062 :
2063 0 : if (err != LDAP_SUCCESS)
2064 : {
2065 0 : log_error ("gpgkeys: error adding key to keyserver: %s\n",
2066 : ldap_err2string (err));
2067 0 : err = ldap_err_to_gpg_err (err);
2068 : }
2069 : }
2070 :
2071 : out:
2072 0 : if (dump)
2073 0 : es_fclose (dump);
2074 :
2075 0 : if (ldap_conn)
2076 0 : ldap_unbind (ldap_conn);
2077 :
2078 0 : xfree (basedn);
2079 0 : xfree (pgpkeyattr);
2080 :
2081 0 : modlist_free (modlist);
2082 0 : xfree (addlist);
2083 :
2084 0 : xfree (data_armored);
2085 :
2086 0 : return err;
2087 : }
|