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 <https://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 : #ifdef HAVE_LDAP_START_TLS_S
517 0 : 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 : #ifndef HAVE_W32_SYSTEM
523 0 : int check_cert = LDAP_OPT_X_TLS_HARD; /* LDAP_OPT_X_TLS_NEVER */
524 :
525 0 : err = ldap_set_option (ldap_conn,
526 : LDAP_OPT_X_TLS_REQUIRE_CERT, &check_cert);
527 0 : if (err)
528 : {
529 0 : log_error ("Failed to set TLS option on LDAP connection.\n");
530 0 : goto out;
531 : }
532 : #else
533 : /* On Windows, the certificates are checked by default. If the
534 : option to disable checking mentioned above is ever
535 : implemented, the way to do that on Windows is to install a
536 : callback routine using ldap_set_option (..,
537 : LDAP_OPT_SERVER_CERTIFICATE, ..); */
538 : #endif
539 :
540 0 : err = ldap_start_tls_s (ldap_conn,
541 : #ifdef HAVE_W32_SYSTEM
542 : /* ServerReturnValue, result */
543 : NULL, NULL,
544 : #endif
545 : /* ServerControls, ClientControls */
546 : NULL, NULL);
547 0 : if (err)
548 : {
549 0 : log_error ("Failed to connect to LDAP server with TLS.\n");
550 0 : goto out;
551 : }
552 : }
553 : #endif
554 :
555 : /* By default we don't bind as there is usually no need to. */
556 0 : if (uri->auth)
557 : {
558 0 : log_debug ("LDAP bind to %s, password %s\n",
559 : user, password ? ">not shown<" : ">none<");
560 :
561 0 : err = ldap_simple_bind_s (ldap_conn, user, password);
562 0 : if (err != LDAP_SUCCESS)
563 : {
564 0 : log_error ("Internal LDAP bind error: %s\n",
565 : ldap_err2string (err));
566 0 : goto out;
567 : }
568 : }
569 :
570 0 : if (uri->path && *uri->path)
571 : /* User specified base DN. */
572 : {
573 0 : basedn = xstrdup (uri->path);
574 :
575 : /* If the user specifies a base DN, then we know the server is a
576 : real LDAP server. */
577 0 : real_ldap = 1;
578 : }
579 : else
580 : {
581 0 : LDAPMessage *res = NULL;
582 : /* Look for namingContexts. */
583 0 : char *attr[] = { "namingContexts", NULL };
584 :
585 0 : err = ldap_search_s (ldap_conn, "", LDAP_SCOPE_BASE,
586 : "(objectClass=*)", attr, 0, &res);
587 0 : if (err == LDAP_SUCCESS)
588 : {
589 0 : char **context = ldap_get_values (ldap_conn, res, "namingContexts");
590 0 : if (context)
591 : /* We found some, so try each namingContext as the search
592 : base and look for pgpBaseKeySpaceDN. Because we found
593 : this, we know we're talking to a regular-ish LDAP
594 : server and not an LDAP keyserver. */
595 : {
596 : int i;
597 0 : char *attr2[] =
598 : { "pgpBaseKeySpaceDN", "pgpVersion", "pgpSoftware", NULL };
599 :
600 0 : real_ldap = 1;
601 :
602 0 : for (i = 0; context[i] && ! basedn; i++)
603 : {
604 : char **vals;
605 : LDAPMessage *si_res;
606 :
607 : {
608 0 : char *object = xasprintf ("cn=pgpServerInfo,%s",
609 0 : context[i]);
610 0 : err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
611 : "(objectClass=*)", attr2, 0, &si_res);
612 0 : xfree (object);
613 : }
614 :
615 0 : if (err == LDAP_SUCCESS)
616 : {
617 0 : vals = ldap_get_values (ldap_conn, si_res,
618 : "pgpBaseKeySpaceDN");
619 0 : if (vals)
620 : {
621 0 : basedn = xtrystrdup (vals[0]);
622 0 : ldap_value_free (vals);
623 : }
624 :
625 0 : vals = ldap_get_values (ldap_conn, si_res,
626 : "pgpSoftware");
627 0 : if (vals)
628 : {
629 0 : log_debug ("Server: \t%s\n", vals[0]);
630 0 : ldap_value_free (vals);
631 : }
632 :
633 0 : vals = ldap_get_values (ldap_conn, si_res,
634 : "pgpVersion");
635 0 : if (vals)
636 : {
637 0 : log_debug ("Version:\t%s\n", vals[0]);
638 0 : ldap_value_free (vals);
639 : }
640 : }
641 :
642 : /* From man ldap_search_s: "res parameter of
643 : ldap_search_ext_s() and ldap_search_s() should be
644 : freed with ldap_msgfree() regardless of return
645 : value of these functions. */
646 0 : ldap_msgfree (si_res);
647 : }
648 :
649 0 : ldap_value_free (context);
650 : }
651 : }
652 : else
653 : {
654 : /* We don't have an answer yet, which means the server might
655 : be an LDAP keyserver. */
656 : char **vals;
657 0 : LDAPMessage *si_res = NULL;
658 :
659 0 : char *attr2[] = { "pgpBaseKeySpaceDN", "version", "software", NULL };
660 :
661 0 : err = ldap_search_s (ldap_conn, "cn=pgpServerInfo", LDAP_SCOPE_BASE,
662 : "(objectClass=*)", attr2, 0, &si_res);
663 0 : if (err == LDAP_SUCCESS)
664 : {
665 : /* For the LDAP keyserver, this is always
666 : "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not be
667 : in the future. */
668 :
669 0 : vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN");
670 0 : if (vals)
671 : {
672 0 : basedn = xtrystrdup (vals[0]);
673 0 : ldap_value_free (vals);
674 : }
675 :
676 0 : vals = ldap_get_values (ldap_conn, si_res, "software");
677 0 : if (vals)
678 : {
679 0 : log_debug ("ldap: Server: \t%s\n", vals[0]);
680 0 : ldap_value_free (vals);
681 : }
682 :
683 0 : vals = ldap_get_values (ldap_conn, si_res, "version");
684 0 : if (vals)
685 : {
686 0 : log_debug ("ldap: Version:\t%s\n", vals[0]);
687 :
688 : /* If the version is high enough, use the new
689 : pgpKeyV2 attribute. This design is iffy at best,
690 : but it matches how PGP does it. I figure the NAI
691 : folks assumed that there would never be an LDAP
692 : keyserver vendor with a different numbering
693 : scheme. */
694 0 : if (atoi (vals[0]) > 1)
695 0 : pgpkeyattr = "pgpKeyV2";
696 :
697 0 : ldap_value_free (vals);
698 : }
699 : }
700 :
701 0 : ldap_msgfree (si_res);
702 : }
703 :
704 : /* From man ldap_search_s: "res parameter of ldap_search_ext_s()
705 : and ldap_search_s() should be freed with ldap_msgfree()
706 : regardless of return value of these functions. */
707 0 : ldap_msgfree (res);
708 : }
709 :
710 : out:
711 0 : if (! err)
712 : {
713 0 : log_debug ("ldap_conn: %p\n", ldap_conn);
714 0 : log_debug ("real_ldap: %d\n", real_ldap);
715 0 : log_debug ("basedn: %s\n", basedn);
716 0 : log_debug ("pgpkeyattr: %s\n", pgpkeyattr);
717 : }
718 :
719 0 : if (! err && real_ldapp)
720 0 : *real_ldapp = real_ldap;
721 :
722 0 : if (err)
723 0 : xfree (basedn);
724 : else
725 : {
726 0 : if (pgpkeyattrp)
727 : {
728 0 : if (basedn)
729 0 : *pgpkeyattrp = xstrdup (pgpkeyattr);
730 : else
731 0 : *pgpkeyattrp = NULL;
732 : }
733 :
734 0 : if (basednp)
735 0 : *basednp = basedn;
736 : else
737 0 : xfree (basedn);
738 : }
739 :
740 0 : if (err)
741 : {
742 0 : if (ldap_conn)
743 0 : ldap_unbind (ldap_conn);
744 : }
745 : else
746 0 : *ldap_connp = ldap_conn;
747 :
748 0 : return err;
749 : }
750 :
751 : /* Extract keys from an LDAP reply and write them out to the output
752 : stream OUTPUT in a format GnuPG can import (either the OpenPGP
753 : binary format or armored format). */
754 : static void
755 0 : extract_keys (estream_t output,
756 : LDAP *ldap_conn, const char *certid, LDAPMessage *message)
757 : {
758 : char **vals;
759 :
760 0 : es_fprintf (output, "INFO %s BEGIN\n", certid);
761 0 : es_fprintf (output, "pub:%s:", certid);
762 :
763 : /* Note: ldap_get_values returns a NULL terminates array of
764 : strings. */
765 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeytype");
766 0 : if (vals && vals[0])
767 : {
768 0 : if (strcmp (vals[0], "RSA") == 0)
769 0 : es_fprintf (output, "1");
770 0 : else if (strcmp (vals[0],"DSS/DH") == 0)
771 0 : es_fprintf (output, "17");
772 0 : ldap_value_free (vals);
773 : }
774 :
775 0 : es_fprintf (output, ":");
776 :
777 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeysize");
778 0 : if (vals && vals[0])
779 : {
780 0 : int v = atoi (vals[0]);
781 0 : if (v > 0)
782 0 : es_fprintf (output, "%d", v);
783 0 : ldap_value_free (vals);
784 : }
785 :
786 0 : es_fprintf (output, ":");
787 :
788 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeycreatetime");
789 0 : if (vals && vals[0])
790 : {
791 0 : if (strlen (vals[0]) == 15)
792 0 : es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
793 0 : ldap_value_free (vals);
794 : }
795 :
796 0 : es_fprintf (output, ":");
797 :
798 0 : vals = ldap_get_values (ldap_conn, message, "pgpkeyexpiretime");
799 0 : if (vals && vals[0])
800 : {
801 0 : if (strlen (vals[0]) == 15)
802 0 : es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
803 0 : ldap_value_free (vals);
804 : }
805 :
806 0 : es_fprintf (output, ":");
807 :
808 0 : vals = ldap_get_values (ldap_conn, message, "pgprevoked");
809 0 : if (vals && vals[0])
810 : {
811 0 : if (atoi (vals[0]) == 1)
812 0 : es_fprintf (output, "r");
813 0 : ldap_value_free (vals);
814 : }
815 :
816 0 : es_fprintf (output, "\n");
817 :
818 0 : vals = ldap_get_values (ldap_conn, message, "pgpuserid");
819 0 : if (vals && vals[0])
820 : {
821 : int i;
822 0 : for (i = 0; vals[i]; i++)
823 0 : es_fprintf (output, "uid:%s\n", vals[i]);
824 0 : ldap_value_free (vals);
825 : }
826 :
827 0 : es_fprintf (output, "INFO %s END\n", certid);
828 0 : }
829 :
830 : /* Get the key described key the KEYSPEC string from the keyserver
831 : identified by URI. On success R_FP has an open stream to read the
832 : data. */
833 : gpg_error_t
834 0 : ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
835 : estream_t *r_fp)
836 : {
837 0 : gpg_error_t err = 0;
838 : int ldap_err;
839 :
840 0 : char *filter = NULL;
841 :
842 0 : LDAP *ldap_conn = NULL;
843 :
844 0 : char *basedn = NULL;
845 0 : char *pgpkeyattr = NULL;
846 :
847 0 : estream_t fp = NULL;
848 :
849 0 : LDAPMessage *message = NULL;
850 :
851 : (void) ctrl;
852 :
853 0 : if (opt.use_tor)
854 : {
855 : /* For now we do not support LDAP over Tor. */
856 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
857 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
858 : }
859 :
860 : /* Before connecting to the server, make sure we have a sane
861 : keyspec. If not, there is no need to establish a network
862 : connection. */
863 0 : err = keyspec_to_ldap_filter (keyspec, &filter, 1);
864 0 : if (err)
865 0 : return (err);
866 :
867 : /* Make sure we are talking to an OpenPGP LDAP server. */
868 0 : ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL);
869 0 : if (ldap_err || !basedn)
870 : {
871 0 : if (ldap_err)
872 0 : err = ldap_err_to_gpg_err (ldap_err);
873 : else
874 0 : err = GPG_ERR_GENERAL;
875 0 : goto out;
876 : }
877 :
878 : {
879 : /* The ordering is significant. Specifically, "pgpcertid" needs
880 : to be the second item in the list, since everything after it
881 : may be discarded we aren't in verbose mode. */
882 0 : char *attrs[] =
883 : {
884 : pgpkeyattr,
885 : "pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
886 : "pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
887 : NULL
888 : };
889 : /* 1 if we want just attribute types; 0 if we want both attribute
890 : types and values. */
891 0 : int attrsonly = 0;
892 :
893 : int count;
894 :
895 0 : ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
896 : filter, attrs, attrsonly, &message);
897 0 : if (ldap_err)
898 : {
899 0 : err = ldap_err_to_gpg_err (ldap_err);
900 :
901 0 : log_error ("gpgkeys: LDAP search error: %s\n",
902 : ldap_err2string (ldap_err));
903 0 : goto out;
904 : }
905 :
906 0 : count = ldap_count_entries (ldap_conn, message);
907 0 : if (count < 1)
908 : {
909 0 : log_error ("gpgkeys: key %s not found on keyserver\n", keyspec);
910 :
911 0 : if (count == -1)
912 0 : err = ldap_to_gpg_err (ldap_conn);
913 : else
914 0 : err = gpg_error (GPG_ERR_NO_DATA);
915 :
916 0 : goto out;
917 : }
918 :
919 : {
920 : /* There may be more than one unique result for a given keyID,
921 : so we should fetch them all (test this by fetching short key
922 : id 0xDEADBEEF). */
923 :
924 : /* The set of entries that we've seen. */
925 0 : strlist_t seen = NULL;
926 : LDAPMessage *each;
927 :
928 0 : for (each = ldap_first_entry (ldap_conn, message);
929 : each;
930 0 : each = ldap_next_entry (ldap_conn, each))
931 : {
932 : char **vals;
933 : char **certid;
934 :
935 : /* Use the long keyid to remove duplicates. The LDAP
936 : server returns the same keyid more than once if there
937 : are multiple user IDs on the key. Note that this does
938 : NOT mean that a keyid that exists multiple times on the
939 : keyserver will not be fetched. It means that each KEY,
940 : no matter how many user IDs share its keyid, will be
941 : fetched only once. If a keyid that belongs to more
942 : than one key is fetched, the server quite properly
943 : responds with all matching keys. -ds */
944 :
945 0 : certid = ldap_get_values (ldap_conn, each, "pgpcertid");
946 0 : if (certid && certid[0])
947 : {
948 0 : if (! strlist_find (seen, certid[0]))
949 : {
950 : /* It's not a duplicate, add it */
951 :
952 0 : add_to_strlist (&seen, certid[0]);
953 :
954 0 : if (! fp)
955 0 : fp = es_fopenmem(0, "rw");
956 :
957 0 : extract_keys (fp, ldap_conn, certid[0], each);
958 :
959 0 : vals = ldap_get_values (ldap_conn, each, pgpkeyattr);
960 0 : if (! vals)
961 : {
962 0 : err = ldap_to_gpg_err (ldap_conn);
963 0 : log_error("gpgkeys: unable to retrieve key %s "
964 : "from keyserver\n", certid[0]);
965 0 : goto out;
966 : }
967 : else
968 : {
969 : /* We should strip the new lines. */
970 0 : es_fprintf (fp, "KEY 0x%s BEGIN\n", certid[0]);
971 0 : es_fputs (vals[0], fp);
972 0 : es_fprintf (fp, "\nKEY 0x%s END\n", certid[0]);
973 :
974 0 : ldap_value_free (vals);
975 : }
976 : }
977 : }
978 :
979 0 : ldap_value_free (certid);
980 : }
981 :
982 0 : free_strlist (seen);
983 :
984 0 : if (! fp)
985 0 : err = gpg_error (GPG_ERR_NO_DATA);
986 : }
987 : }
988 :
989 : out:
990 0 : if (message)
991 0 : ldap_msgfree (message);
992 :
993 0 : if (err)
994 : {
995 0 : if (fp)
996 0 : es_fclose (fp);
997 : }
998 : else
999 : {
1000 0 : if (fp)
1001 0 : es_fseek (fp, 0, SEEK_SET);
1002 :
1003 0 : *r_fp = fp;
1004 : }
1005 :
1006 0 : xfree (pgpkeyattr);
1007 0 : xfree (basedn);
1008 :
1009 0 : if (ldap_conn)
1010 0 : ldap_unbind (ldap_conn);
1011 :
1012 0 : xfree (filter);
1013 :
1014 0 : return err;
1015 : }
1016 :
1017 : /* Search the keyserver identified by URI for keys matching PATTERN.
1018 : On success R_FP has an open stream to read the data. */
1019 : gpg_error_t
1020 0 : ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
1021 : estream_t *r_fp)
1022 : {
1023 : gpg_error_t err;
1024 : int ldap_err;
1025 :
1026 0 : char *filter = NULL;
1027 :
1028 0 : LDAP *ldap_conn = NULL;
1029 :
1030 0 : char *basedn = NULL;
1031 :
1032 0 : estream_t fp = NULL;
1033 :
1034 : (void) ctrl;
1035 :
1036 0 : if (opt.use_tor)
1037 : {
1038 : /* For now we do not support LDAP over Tor. */
1039 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
1040 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
1041 : }
1042 :
1043 : /* Before connecting to the server, make sure we have a sane
1044 : keyspec. If not, there is no need to establish a network
1045 : connection. */
1046 0 : err = keyspec_to_ldap_filter (pattern, &filter, 0);
1047 0 : if (err)
1048 : {
1049 0 : log_error ("Bad search pattern: '%s'\n", pattern);
1050 0 : return (err);
1051 : }
1052 :
1053 : /* Make sure we are talking to an OpenPGP LDAP server. */
1054 0 : ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL);
1055 0 : if (ldap_err || !basedn)
1056 : {
1057 0 : if (ldap_err)
1058 0 : err = ldap_err_to_gpg_err (ldap_err);
1059 : else
1060 0 : err = GPG_ERR_GENERAL;
1061 0 : goto out;
1062 : }
1063 :
1064 : /* Even if we have no results, we want to return a stream. */
1065 0 : fp = es_fopenmem(0, "rw");
1066 0 : if (!fp)
1067 : {
1068 0 : err = gpg_error_from_syserror ();
1069 0 : goto out;
1070 : }
1071 :
1072 : {
1073 : char **vals;
1074 : LDAPMessage *res, *each;
1075 0 : int count = 0;
1076 0 : strlist_t dupelist = NULL;
1077 :
1078 : /* The maximum size of the search, including the optional stuff
1079 : and the trailing \0 */
1080 0 : char *attrs[] =
1081 : {
1082 : "pgpcertid", "pgpuserid", "pgprevoked", "pgpdisabled",
1083 : "pgpkeycreatetime", "pgpkeyexpiretime", "modifytimestamp",
1084 : "pgpkeysize", "pgpkeytype", NULL
1085 : };
1086 :
1087 0 : log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter);
1088 :
1089 0 : ldap_err = ldap_search_s (ldap_conn, basedn,
1090 : LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res);
1091 :
1092 0 : xfree (filter);
1093 0 : filter = NULL;
1094 :
1095 0 : if (ldap_err != LDAP_SUCCESS && ldap_err != LDAP_SIZELIMIT_EXCEEDED)
1096 : {
1097 0 : err = ldap_err_to_gpg_err (ldap_err);
1098 :
1099 0 : log_error ("SEARCH %s FAILED %d\n", pattern, err);
1100 0 : log_error ("gpgkeys: LDAP search error: %s\n",
1101 : ldap_err2string (err));
1102 0 : goto out;
1103 : }
1104 :
1105 : /* The LDAP server doesn't return a real count of unique keys, so we
1106 : can't use ldap_count_entries here. */
1107 0 : for (each = ldap_first_entry (ldap_conn, res);
1108 : each;
1109 0 : each = ldap_next_entry (ldap_conn, each))
1110 : {
1111 0 : char **certid = ldap_get_values (ldap_conn, each, "pgpcertid");
1112 0 : if (certid && certid[0] && ! strlist_find (dupelist, certid[0]))
1113 : {
1114 0 : add_to_strlist (&dupelist, certid[0]);
1115 0 : count++;
1116 : }
1117 : }
1118 :
1119 0 : if (ldap_err == LDAP_SIZELIMIT_EXCEEDED)
1120 : {
1121 0 : if (count == 1)
1122 0 : log_error ("gpgkeys: search results exceeded server limit."
1123 : " First 1 result shown.\n");
1124 : else
1125 0 : log_error ("gpgkeys: search results exceeded server limit."
1126 : " First %d results shown.\n", count);
1127 : }
1128 :
1129 0 : free_strlist (dupelist);
1130 0 : dupelist = NULL;
1131 :
1132 0 : if (count < 1)
1133 0 : es_fputs ("info:1:0\n", fp);
1134 : else
1135 : {
1136 0 : es_fprintf (fp, "info:1:%d\n", count);
1137 :
1138 0 : for (each = ldap_first_entry (ldap_conn, res);
1139 : each;
1140 0 : each = ldap_next_entry (ldap_conn, each))
1141 : {
1142 : char **certid;
1143 : LDAPMessage *uids;
1144 :
1145 0 : certid = ldap_get_values (ldap_conn, each, "pgpcertid");
1146 0 : if (! certid || ! certid[0])
1147 0 : continue;
1148 :
1149 : /* Have we seen this certid before? */
1150 0 : if (! strlist_find (dupelist, certid[0]))
1151 : {
1152 0 : add_to_strlist (&dupelist, certid[0]);
1153 :
1154 0 : es_fprintf (fp, "pub:%s:",certid[0]);
1155 :
1156 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
1157 0 : if (vals)
1158 : {
1159 : /* The LDAP server doesn't exactly handle this
1160 : well. */
1161 0 : if (strcasecmp (vals[0], "RSA") == 0)
1162 0 : es_fputs ("1", fp);
1163 0 : else if (strcasecmp (vals[0], "DSS/DH") == 0)
1164 0 : es_fputs ("17", fp);
1165 0 : ldap_value_free (vals);
1166 : }
1167 :
1168 0 : es_fputc (':', fp);
1169 :
1170 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
1171 0 : if (vals)
1172 : {
1173 : /* Not sure why, but some keys are listed with a
1174 : key size of 0. Treat that like an unknown. */
1175 0 : if (atoi (vals[0]) > 0)
1176 0 : es_fprintf (fp, "%d", atoi (vals[0]));
1177 0 : ldap_value_free (vals);
1178 : }
1179 :
1180 0 : es_fputc (':', fp);
1181 :
1182 : /* YYYYMMDDHHmmssZ */
1183 :
1184 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
1185 0 : if(vals && strlen (vals[0]) == 15)
1186 : {
1187 0 : es_fprintf (fp, "%u",
1188 0 : (unsigned int) ldap2epochtime(vals[0]));
1189 0 : ldap_value_free (vals);
1190 : }
1191 :
1192 0 : es_fputc (':', fp);
1193 :
1194 0 : vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
1195 0 : if (vals && strlen (vals[0]) == 15)
1196 : {
1197 0 : es_fprintf (fp, "%u",
1198 0 : (unsigned int) ldap2epochtime (vals[0]));
1199 0 : ldap_value_free (vals);
1200 : }
1201 :
1202 0 : es_fputc (':', fp);
1203 :
1204 0 : vals = ldap_get_values (ldap_conn, each, "pgprevoked");
1205 0 : if (vals)
1206 : {
1207 0 : if (atoi (vals[0]) == 1)
1208 0 : es_fprintf (fp, "r");
1209 0 : ldap_value_free (vals);
1210 : }
1211 :
1212 0 : vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
1213 0 : if (vals)
1214 : {
1215 0 : if (atoi (vals[0]) ==1)
1216 0 : es_fprintf (fp, "d");
1217 0 : ldap_value_free (vals);
1218 : }
1219 :
1220 : #if 0
1221 : /* This is not yet specified in the keyserver
1222 : protocol, but may be someday. */
1223 : es_fputc (':', fp);
1224 :
1225 : vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
1226 : if(vals && strlen (vals[0]) == 15)
1227 : {
1228 : es_fprintf (fp, "%u",
1229 : (unsigned int) ldap2epochtime (vals[0]));
1230 : ldap_value_free (vals);
1231 : }
1232 : #endif
1233 :
1234 0 : es_fprintf (fp, "\n");
1235 :
1236 : /* Now print all the uids that have this certid */
1237 0 : for (uids = ldap_first_entry (ldap_conn, res);
1238 : uids;
1239 0 : uids = ldap_next_entry (ldap_conn, uids))
1240 : {
1241 0 : vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
1242 0 : if (! vals)
1243 0 : continue;
1244 :
1245 0 : if (strcasecmp (certid[0], vals[0]) == 0)
1246 : {
1247 : char **uidvals;
1248 :
1249 0 : es_fprintf (fp, "uid:");
1250 :
1251 0 : uidvals = ldap_get_values (ldap_conn,
1252 : uids, "pgpuserid");
1253 0 : if (uidvals)
1254 : {
1255 : /* Need to escape any colons */
1256 0 : char *quoted = percent_escape (uidvals[0], NULL);
1257 0 : es_fputs (quoted, fp);
1258 0 : xfree (quoted);
1259 0 : ldap_value_free (uidvals);
1260 : }
1261 :
1262 0 : es_fprintf (fp, "\n");
1263 : }
1264 :
1265 0 : ldap_value_free(vals);
1266 : }
1267 : }
1268 :
1269 0 : ldap_value_free (certid);
1270 : }
1271 : }
1272 :
1273 0 : ldap_msgfree (res);
1274 0 : free_strlist (dupelist);
1275 : }
1276 :
1277 0 : log_debug ("SEARCH %s END\n", pattern);
1278 :
1279 : out:
1280 0 : if (err)
1281 : {
1282 0 : if (fp)
1283 0 : es_fclose (fp);
1284 : }
1285 : else
1286 : {
1287 : /* Return the read stream. */
1288 0 : if (fp)
1289 0 : es_fseek (fp, 0, SEEK_SET);
1290 :
1291 0 : *r_fp = fp;
1292 : }
1293 :
1294 0 : xfree (basedn);
1295 :
1296 0 : if (ldap_conn)
1297 0 : ldap_unbind (ldap_conn);
1298 :
1299 0 : xfree (filter);
1300 :
1301 0 : return err;
1302 : }
1303 :
1304 :
1305 :
1306 : /* A modlist describes a set of changes to an LDAP entry. (An entry
1307 : consists of 1 or more attributes. Attributes are <name, value>
1308 : pairs. Note: an attribute may be multi-valued in which case
1309 : multiple values are associated with a single name.)
1310 :
1311 : A modlist is a NULL terminated array of struct LDAPMod's.
1312 :
1313 : Thus, if we have:
1314 :
1315 : LDAPMod **modlist;
1316 :
1317 : Then:
1318 :
1319 : modlist[i]
1320 :
1321 : Is the ith modification.
1322 :
1323 : Each LDAPMod describes a change to a single attribute. Further,
1324 : there is one modification for each attribute that we want to
1325 : change. The attribute's new value is stored in LDAPMod.mod_values.
1326 : If the attribute is multi-valued, we still only use a single
1327 : LDAPMod structure: mod_values is a NULL-terminated array of
1328 : strings. To delete an attribute from an entry, we set mod_values
1329 : to NULL.
1330 :
1331 : Thus, if:
1332 :
1333 : modlist[i]->mod_values == NULL
1334 :
1335 : then we remove the attribute.
1336 :
1337 : (Using LDAP_MOD_DELETE doesn't work here as we don't know if the
1338 : attribute in question exists or not.)
1339 :
1340 : Note: this function does NOT copy or free ATTR. It does copy
1341 : VALUE. */
1342 : static void
1343 0 : modlist_add (LDAPMod ***modlistp, char *attr, const char *value)
1344 : {
1345 0 : LDAPMod **modlist = *modlistp;
1346 :
1347 : LDAPMod **m;
1348 0 : int nummods = 0;
1349 :
1350 : /* Search modlist for the attribute we're playing with. If modlist
1351 : is NULL, then the list is empty. Recall: modlist is a NULL
1352 : terminated array. */
1353 0 : for (m = modlist; m && *m; m++, nummods ++)
1354 : {
1355 : /* The attribute is already on the list. */
1356 : char **ptr;
1357 0 : int numvalues = 0;
1358 :
1359 0 : if (strcasecmp ((*m)->mod_type, attr) != 0)
1360 0 : continue;
1361 :
1362 : /* We have this attribute already, so when the REPLACE happens,
1363 : the server attributes will be replaced anyway. */
1364 0 : if (! value)
1365 0 : return;
1366 :
1367 : /* Attributes can be multi-valued. See if the value is already
1368 : present. mod_values is a NULL terminated array of pointers.
1369 : Note: mod_values can be NULL. */
1370 0 : for (ptr = (*m)->mod_values; ptr && *ptr; ptr++)
1371 : {
1372 0 : if (strcmp (*ptr, value) == 0)
1373 : /* Duplicate value, we're done. */
1374 0 : return;
1375 0 : numvalues ++;
1376 : }
1377 :
1378 : /* Append the value. */
1379 0 : ptr = xrealloc ((*m)->mod_values, sizeof (char *) * (numvalues + 2));
1380 :
1381 0 : (*m)->mod_values = ptr;
1382 0 : ptr[numvalues] = xstrdup (value);
1383 :
1384 0 : ptr[numvalues + 1] = NULL;
1385 :
1386 0 : return;
1387 : }
1388 :
1389 : /* We didn't find the attr, so make one and add it to the end */
1390 :
1391 : /* Like attribute values, the list of attributes is NULL terminated
1392 : array of pointers. */
1393 0 : modlist = xrealloc (modlist, sizeof (LDAPMod *) * (nummods + 2));
1394 :
1395 0 : *modlistp = modlist;
1396 0 : modlist[nummods] = xmalloc (sizeof (LDAPMod));
1397 :
1398 0 : modlist[nummods]->mod_op = LDAP_MOD_REPLACE;
1399 0 : modlist[nummods]->mod_type = attr;
1400 0 : if (value)
1401 : {
1402 0 : modlist[nummods]->mod_values = xmalloc (sizeof(char *) * 2);
1403 :
1404 0 : modlist[nummods]->mod_values[0] = xstrdup (value);
1405 0 : modlist[nummods]->mod_values[1] = NULL;
1406 : }
1407 : else
1408 0 : modlist[nummods]->mod_values = NULL;
1409 :
1410 0 : modlist[nummods + 1] = NULL;
1411 :
1412 0 : return;
1413 : }
1414 :
1415 : /* Look up the value of an attribute in the specified modlist. If the
1416 : attribute is not on the mod list, returns NULL. The result is a
1417 : NULL-terminated array of strings. Don't change it. */
1418 : static char **
1419 0 : modlist_lookup (LDAPMod **modlist, const char *attr)
1420 : {
1421 : LDAPMod **m;
1422 0 : for (m = modlist; m && *m; m++)
1423 : {
1424 0 : if (strcasecmp ((*m)->mod_type, attr) != 0)
1425 0 : continue;
1426 :
1427 0 : return (*m)->mod_values;
1428 : }
1429 :
1430 0 : return NULL;
1431 : }
1432 :
1433 : /* Dump a modlist to a file. This is useful for debugging. */
1434 : static estream_t modlist_dump (LDAPMod **modlist, estream_t output)
1435 : GPGRT_ATTR_USED;
1436 :
1437 : static estream_t
1438 0 : modlist_dump (LDAPMod **modlist, estream_t output)
1439 : {
1440 : LDAPMod **m;
1441 :
1442 0 : int opened = 0;
1443 :
1444 0 : if (! output)
1445 : {
1446 0 : output = es_fopenmem (0, "rw");
1447 0 : if (!output)
1448 0 : return NULL;
1449 0 : opened = 1;
1450 : }
1451 :
1452 0 : for (m = modlist; m && *m; m++)
1453 : {
1454 0 : es_fprintf (output, " %s:", (*m)->mod_type);
1455 :
1456 0 : if (! (*m)->mod_values)
1457 0 : es_fprintf(output, " delete.\n");
1458 : else
1459 : {
1460 : char **ptr;
1461 : int i;
1462 :
1463 0 : int multi = 0;
1464 0 : if ((*m)->mod_values[0] && (*m)->mod_values[1])
1465 : /* Have at least 2. */
1466 0 : multi = 1;
1467 :
1468 0 : if (multi)
1469 0 : es_fprintf (output, "\n");
1470 :
1471 0 : for ((ptr = (*m)->mod_values), (i = 1); ptr && *ptr; ptr++, i ++)
1472 : {
1473 : /* Assuming terminals are about 80 characters wide,
1474 : display at most most about 10 lines of debugging
1475 : output. If we do trim the buffer, append '...' to
1476 : the end. */
1477 0 : const int max_len = 10 * 70;
1478 0 : size_t value_len = strlen (*ptr);
1479 0 : int elide = value_len > max_len;
1480 :
1481 0 : if (multi)
1482 0 : es_fprintf (output, " %d. ", i);
1483 0 : es_fprintf (output, "`%.*s", max_len, *ptr);
1484 0 : if (elide)
1485 0 : es_fprintf (output, "...' (%zd bytes elided)",
1486 : value_len - max_len);
1487 : else
1488 0 : es_fprintf (output, "'");
1489 0 : es_fprintf (output, "\n");
1490 : }
1491 : }
1492 : }
1493 :
1494 0 : if (opened)
1495 0 : es_fseek (output, 0, SEEK_SET);
1496 :
1497 0 : return output;
1498 : }
1499 :
1500 : /* Free all of the memory allocated by the mod list. This assumes
1501 : that the attribute names don't have to be freed, but the attributes
1502 : values do. (Which is what modlist_add does.) */
1503 : static void
1504 0 : modlist_free (LDAPMod **modlist)
1505 : {
1506 : LDAPMod **ml;
1507 :
1508 0 : if (! modlist)
1509 0 : return;
1510 :
1511 : /* Unwind and free the whole modlist structure */
1512 :
1513 : /* The modlist is a NULL terminated array of pointers. */
1514 0 : for (ml = modlist; *ml; ml++)
1515 : {
1516 0 : LDAPMod *mod = *ml;
1517 : char **ptr;
1518 :
1519 : /* The list of values is a NULL termianted array of pointers.
1520 : If the list is NULL, there are no values. */
1521 :
1522 0 : if (mod->mod_values)
1523 : {
1524 0 : for (ptr = mod->mod_values; *ptr; ptr++)
1525 0 : xfree (*ptr);
1526 :
1527 0 : xfree (mod->mod_values);
1528 : }
1529 :
1530 0 : xfree (mod);
1531 : }
1532 0 : xfree (modlist);
1533 : }
1534 :
1535 : /* Append two onto the end of one. Two is not freed, but its pointers
1536 : are now part of one. Make sure you don't free them both!
1537 :
1538 : As long as you don't add anything to ONE, TWO is still valid.
1539 : After that all bets are off. */
1540 : static void
1541 0 : modlists_join (LDAPMod ***one, LDAPMod **two)
1542 : {
1543 0 : int i, one_count = 0, two_count = 0;
1544 : LDAPMod **grow;
1545 :
1546 0 : if (!*two)
1547 : /* two is empty. Nothing to do. */
1548 0 : return;
1549 :
1550 0 : if (!*one)
1551 : /* one is empty. Just set it equal to *two. */
1552 : {
1553 0 : *one = two;
1554 0 : return;
1555 : }
1556 :
1557 0 : for (grow = *one; *grow; grow++)
1558 0 : one_count ++;
1559 :
1560 0 : for (grow = two; *grow; grow++)
1561 0 : two_count ++;
1562 :
1563 0 : grow = xrealloc (*one, sizeof(LDAPMod *) * (one_count + two_count + 1));
1564 :
1565 0 : for (i = 0; i < two_count; i++)
1566 0 : grow[one_count + i] = two[i];
1567 :
1568 0 : grow[one_count + i] = NULL;
1569 :
1570 0 : *one = grow;
1571 : }
1572 :
1573 : /* Given a string, unescape C escapes. In particular, \xXX. This
1574 : modifies the string in place. */
1575 : static void
1576 0 : uncescape (char *str)
1577 : {
1578 0 : size_t r = 0;
1579 0 : size_t w = 0;
1580 :
1581 0 : char *first = strchr (str, '\\');
1582 0 : if (! first)
1583 : /* No backslashes => no escaping. We're done. */
1584 0 : return;
1585 :
1586 : /* Start at the first '\\'. */
1587 0 : r = w = (uintptr_t) first - (uintptr_t) str;
1588 :
1589 0 : while (str[r])
1590 : {
1591 : /* XXX: What to do about bad escapes?
1592 : XXX: hextobyte already checks the string thus the hexdigitp
1593 : could be removed. */
1594 0 : if (str[r] == '\\' && str[r + 1] == 'x'
1595 0 : && str[r+2] && str[r+3]
1596 0 : && hexdigitp (str + r + 2)
1597 0 : && hexdigitp (str + r + 3))
1598 0 : {
1599 0 : int x = hextobyte (&str[r + 2]);
1600 0 : assert (0 <= x && x <= 0xff);
1601 :
1602 0 : str[w] = x;
1603 :
1604 : /* We consumed 4 characters and wrote 1. */
1605 0 : r += 4;
1606 0 : w ++;
1607 : }
1608 : else
1609 0 : str[w ++] = str[r ++];
1610 : }
1611 :
1612 0 : str[w] = '\0';
1613 : }
1614 :
1615 : /* Given one line from an info block (`gpg --list-{keys,sigs}
1616 : --with-colons KEYID'), pull it apart and fill in the modlist with
1617 : the relevant (for the LDAP schema) attributes. */
1618 : static void
1619 0 : extract_attributes (LDAPMod ***modlist, char *line)
1620 : {
1621 : int field_count;
1622 : char **fields;
1623 :
1624 : char *keyid;
1625 :
1626 : int is_pub, is_sub, is_uid, is_sig;
1627 :
1628 : /* Remove trailing whitespace */
1629 0 : trim_trailing_spaces (line);
1630 :
1631 0 : fields = strsplit (line, ':', '\0', &field_count);
1632 0 : if (field_count == 1)
1633 : /* We only have a single field. There is definitely nothing to
1634 : do. */
1635 0 : goto out;
1636 :
1637 0 : if (field_count < 7)
1638 0 : goto out;
1639 :
1640 0 : is_pub = strcasecmp ("pub", fields[0]) == 0;
1641 0 : is_sub = strcasecmp ("sub", fields[0]) == 0;
1642 0 : is_uid = strcasecmp ("uid", fields[0]) == 0;
1643 0 : is_sig = strcasecmp ("sig", fields[0]) == 0;
1644 :
1645 0 : if (!is_pub && !is_sub && !is_uid && !is_sig)
1646 : /* Not a relevant line. */
1647 0 : goto out;
1648 :
1649 0 : keyid = fields[4];
1650 :
1651 0 : if (is_uid && strlen (keyid) == 0)
1652 : /* The uid record type can have an empty keyid. */
1653 : ;
1654 0 : else if (strlen (keyid) == 16
1655 0 : && strspn (keyid, "0123456789aAbBcCdDeEfF") == 16)
1656 : /* Otherwise, we expect exactly 16 hex characters. */
1657 : ;
1658 : else
1659 : {
1660 0 : log_error ("malformed record!\n");
1661 0 : goto out;
1662 : }
1663 :
1664 0 : if (is_pub)
1665 : {
1666 0 : int disabled = 0;
1667 0 : int revoked = 0;
1668 : char *flags;
1669 0 : for (flags = fields[1]; *flags; flags ++)
1670 0 : switch (*flags)
1671 : {
1672 : case 'r':
1673 : case 'R':
1674 0 : revoked = 1;
1675 0 : break;
1676 :
1677 : case 'd':
1678 : case 'D':
1679 0 : disabled = 1;
1680 0 : break;
1681 : }
1682 :
1683 : /* Note: we always create the pgpDisabled and pgpRevoked
1684 : attributes, regardless of whether the key is disabled/revoked
1685 : or not. This is because a very common search is like
1686 : "(&(pgpUserID=*isabella*)(pgpDisabled=0))" */
1687 :
1688 0 : if (is_pub)
1689 : {
1690 0 : modlist_add (modlist,"pgpDisabled", disabled ? "1" : "0");
1691 0 : modlist_add (modlist,"pgpRevoked", revoked ? "1" : "0");
1692 : }
1693 : }
1694 :
1695 0 : if (is_pub || is_sub)
1696 : {
1697 0 : char *size = fields[2];
1698 0 : int val = atoi (size);
1699 0 : size = NULL;
1700 :
1701 0 : if (val > 0)
1702 : {
1703 : /* We zero pad this on the left to make PGP happy. */
1704 : char padded[6];
1705 0 : if (val < 99999 && val > 0)
1706 : {
1707 0 : snprintf (padded, sizeof padded, "%05u", val);
1708 0 : size = padded;
1709 : }
1710 : }
1711 :
1712 0 : if (size)
1713 : {
1714 0 : if (is_pub || is_sub)
1715 0 : modlist_add (modlist, "pgpKeySize", size);
1716 : }
1717 : }
1718 :
1719 0 : if (is_pub)
1720 : {
1721 0 : char *algo = fields[3];
1722 0 : int val = atoi (algo);
1723 0 : switch (val)
1724 : {
1725 : case 1:
1726 0 : algo = "RSA";
1727 0 : break;
1728 :
1729 : case 17:
1730 0 : algo = "DSS/DH";
1731 0 : break;
1732 :
1733 : default:
1734 0 : algo = NULL;
1735 0 : break;
1736 : }
1737 :
1738 0 : if (algo)
1739 : {
1740 0 : if (is_pub)
1741 0 : modlist_add (modlist, "pgpKeyType", algo);
1742 : }
1743 : }
1744 :
1745 0 : if (is_pub || is_sub || is_sig)
1746 : {
1747 0 : if (is_pub)
1748 : {
1749 0 : modlist_add (modlist, "pgpCertID", keyid);
1750 0 : modlist_add (modlist, "pgpKeyID", &keyid[8]);
1751 : }
1752 :
1753 0 : if (is_sub)
1754 0 : modlist_add (modlist, "pgpSubKeyID", keyid);
1755 :
1756 0 : if (is_sig)
1757 0 : modlist_add (modlist, "pgpSignerID", keyid);
1758 : }
1759 :
1760 0 : if (is_pub)
1761 : {
1762 0 : char *create_time = fields[5];
1763 :
1764 0 : if (strlen (create_time) == 0)
1765 0 : create_time = NULL;
1766 : else
1767 : {
1768 0 : char *create_time_orig = create_time;
1769 : struct tm tm;
1770 : time_t t;
1771 : char *end;
1772 :
1773 0 : memset (&tm, 0, sizeof (tm));
1774 :
1775 : /* parse_timestamp handles both seconds fromt he epoch and
1776 : ISO 8601 format. We also need to handle YYYY-MM-DD
1777 : format (as generated by gpg1 --with-colons --list-key).
1778 : Check that first and then if it fails, then try
1779 : parse_timestamp. */
1780 :
1781 0 : if (!isodate_human_to_tm (create_time, &tm))
1782 0 : create_time = tm2ldaptime (&tm);
1783 0 : else if ((t = parse_timestamp (create_time, &end)) != (time_t) -1
1784 0 : && *end == '\0')
1785 : {
1786 :
1787 0 : if (!gnupg_gmtime (&t, &tm))
1788 0 : create_time = NULL;
1789 : else
1790 0 : create_time = tm2ldaptime (&tm);
1791 : }
1792 : else
1793 0 : create_time = NULL;
1794 :
1795 0 : if (! create_time)
1796 : /* Failed to parse string. */
1797 0 : log_error ("Failed to parse creation time ('%s')",
1798 : create_time_orig);
1799 : }
1800 :
1801 0 : if (create_time)
1802 : {
1803 0 : modlist_add (modlist, "pgpKeyCreateTime", create_time);
1804 0 : xfree (create_time);
1805 : }
1806 : }
1807 :
1808 0 : if (is_pub)
1809 : {
1810 0 : char *expire_time = fields[6];
1811 :
1812 0 : if (strlen (expire_time) == 0)
1813 0 : expire_time = NULL;
1814 : else
1815 : {
1816 0 : char *expire_time_orig = expire_time;
1817 : struct tm tm;
1818 : time_t t;
1819 : char *end;
1820 :
1821 0 : memset (&tm, 0, sizeof (tm));
1822 :
1823 : /* parse_timestamp handles both seconds fromt he epoch and
1824 : ISO 8601 format. We also need to handle YYYY-MM-DD
1825 : format (as generated by gpg1 --with-colons --list-key).
1826 : Check that first and then if it fails, then try
1827 : parse_timestamp. */
1828 :
1829 0 : if (!isodate_human_to_tm (expire_time, &tm))
1830 0 : expire_time = tm2ldaptime (&tm);
1831 0 : else if ((t = parse_timestamp (expire_time, &end)) != (time_t) -1
1832 0 : && *end == '\0')
1833 : {
1834 0 : if (!gnupg_gmtime (&t, &tm))
1835 0 : expire_time = NULL;
1836 : else
1837 0 : expire_time = tm2ldaptime (&tm);
1838 : }
1839 : else
1840 0 : expire_time = NULL;
1841 :
1842 0 : if (! expire_time)
1843 : /* Failed to parse string. */
1844 0 : log_error ("Failed to parse creation time ('%s')",
1845 : expire_time_orig);
1846 : }
1847 :
1848 0 : if (expire_time)
1849 : {
1850 0 : modlist_add (modlist, "pgpKeyExpireTime", expire_time);
1851 0 : xfree (expire_time);
1852 : }
1853 : }
1854 :
1855 0 : if ((is_uid || is_pub) && field_count >= 10)
1856 : {
1857 0 : char *uid = fields[9];
1858 :
1859 0 : if (is_pub && strlen (uid) == 0)
1860 : /* When using gpg --list-keys, the uid is included. When
1861 : passed via gpg, it is not. It is important to process it
1862 : when it is present, because gpg 1 won't print a UID record
1863 : if there is only one key. */
1864 : ;
1865 : else
1866 : {
1867 0 : uncescape (uid);
1868 0 : modlist_add (modlist, "pgpUserID", uid);
1869 : }
1870 : }
1871 :
1872 : out:
1873 0 : free (fields);
1874 0 : }
1875 :
1876 : /* Send the key in {KEY,KEYLEN} with the metadata {INFO,INFOLEN} to
1877 : the keyserver identified by URI. See server.c:cmd_ks_put for the
1878 : format of the data and metadata. */
1879 : gpg_error_t
1880 0 : ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
1881 : void *data, size_t datalen,
1882 : void *info, size_t infolen)
1883 : {
1884 0 : gpg_error_t err = 0;
1885 : int ldap_err;
1886 :
1887 0 : LDAP *ldap_conn = NULL;
1888 0 : char *basedn = NULL;
1889 0 : char *pgpkeyattr = NULL;
1890 : int real_ldap;
1891 :
1892 0 : LDAPMod **modlist = NULL;
1893 0 : LDAPMod **addlist = NULL;
1894 :
1895 0 : char *data_armored = NULL;
1896 :
1897 : /* The last byte of the info block. */
1898 0 : const char *infoend = (const char *) info + infolen - 1;
1899 :
1900 : /* Enable this code to dump the modlist to /tmp/modlist.txt. */
1901 : #if 0
1902 : # warning Disable debug code before checking in.
1903 : const int dump_modlist = 1;
1904 : #else
1905 0 : const int dump_modlist = 0;
1906 : #endif
1907 0 : estream_t dump = NULL;
1908 :
1909 : /* Elide a warning. */
1910 : (void) ctrl;
1911 :
1912 0 : if (opt.use_tor)
1913 : {
1914 : /* For now we do not support LDAP over Tor. */
1915 0 : log_error (_("LDAP access not possible due to Tor mode\n"));
1916 0 : return gpg_error (GPG_ERR_NOT_SUPPORTED);
1917 : }
1918 :
1919 0 : ldap_err = my_ldap_connect (uri,
1920 : &ldap_conn, &basedn, &pgpkeyattr, &real_ldap);
1921 0 : if (ldap_err || !basedn)
1922 : {
1923 0 : if (ldap_err)
1924 0 : err = ldap_err_to_gpg_err (ldap_err);
1925 : else
1926 0 : err = GPG_ERR_GENERAL;
1927 0 : goto out;
1928 : }
1929 :
1930 0 : if (! real_ldap)
1931 : /* We appear to have an OpenPGP Keyserver, which can unpack the key
1932 : on its own (not just a dumb LDAP server). */
1933 : {
1934 : LDAPMod mod, *attrs[2];
1935 0 : char *key[] = { data, NULL };
1936 : char *dn;
1937 :
1938 0 : memset (&mod, 0, sizeof (mod));
1939 0 : mod.mod_op = LDAP_MOD_ADD;
1940 0 : mod.mod_type = pgpkeyattr;
1941 0 : mod.mod_values = key;
1942 0 : attrs[0] = &mod;
1943 0 : attrs[1] = NULL;
1944 :
1945 0 : dn = xasprintf ("pgpCertid=virtual,%s", basedn);
1946 0 : ldap_err = ldap_add_s (ldap_conn, dn, attrs);
1947 0 : xfree (dn);
1948 :
1949 0 : if (ldap_err != LDAP_SUCCESS)
1950 : {
1951 0 : err = ldap_err_to_gpg_err (err);
1952 0 : goto out;
1953 : }
1954 :
1955 0 : goto out;
1956 : }
1957 :
1958 0 : modlist = xmalloc (sizeof (LDAPMod *));
1959 0 : *modlist = NULL;
1960 :
1961 0 : if (dump_modlist)
1962 : {
1963 0 : dump = es_fopen("/tmp/modlist.txt", "w");
1964 0 : if (! dump)
1965 0 : log_error ("Failed to open /tmp/modlist.txt: %s\n",
1966 0 : strerror (errno));
1967 :
1968 0 : if (dump)
1969 : {
1970 0 : es_fprintf(dump, "data (%zd bytes)\n", datalen);
1971 0 : es_fprintf(dump, "info (%zd bytes): '\n", infolen);
1972 0 : es_fwrite(info, infolen, 1, dump);
1973 0 : es_fprintf(dump, "'\n");
1974 : }
1975 : }
1976 :
1977 : /* Start by nulling out all attributes. We try and do a modify
1978 : operation first, so this ensures that we don't leave old
1979 : attributes lying around. */
1980 0 : modlist_add (&modlist, "pgpDisabled", NULL);
1981 0 : modlist_add (&modlist, "pgpKeyID", NULL);
1982 0 : modlist_add (&modlist, "pgpKeyType", NULL);
1983 0 : modlist_add (&modlist, "pgpUserID", NULL);
1984 0 : modlist_add (&modlist, "pgpKeyCreateTime", NULL);
1985 0 : modlist_add (&modlist, "pgpSignerID", NULL);
1986 0 : modlist_add (&modlist, "pgpRevoked", NULL);
1987 0 : modlist_add (&modlist, "pgpSubKeyID", NULL);
1988 0 : modlist_add (&modlist, "pgpKeySize", NULL);
1989 0 : modlist_add (&modlist, "pgpKeyExpireTime", NULL);
1990 0 : modlist_add (&modlist, "pgpCertID", NULL);
1991 :
1992 : /* Assemble the INFO stuff into LDAP attributes */
1993 :
1994 0 : while (infolen > 0)
1995 : {
1996 0 : char *temp = NULL;
1997 :
1998 0 : char *newline = memchr (info, '\n', infolen);
1999 0 : if (! newline)
2000 : /* The last line is not \n terminated! Make a copy so we can
2001 : add a NUL terminator. */
2002 : {
2003 0 : temp = xmalloc (infolen + 1);
2004 0 : memcpy (temp, info, infolen);
2005 0 : info = temp;
2006 0 : newline = (char *) info + infolen;
2007 : }
2008 :
2009 0 : *newline = '\0';
2010 :
2011 0 : extract_attributes (&modlist, info);
2012 :
2013 0 : infolen = infolen - ((uintptr_t) newline - (uintptr_t) info + 1);
2014 0 : info = newline + 1;
2015 :
2016 : /* Sanity check. */
2017 0 : if (! temp)
2018 0 : assert ((char *) info + infolen - 1 == infoend);
2019 : else
2020 : {
2021 0 : assert (infolen == -1);
2022 0 : xfree (temp);
2023 : }
2024 : }
2025 :
2026 0 : modlist_add (&addlist, "objectClass", "pgpKeyInfo");
2027 :
2028 0 : err = armor_data (&data_armored, data, datalen);
2029 0 : if (err)
2030 0 : goto out;
2031 :
2032 0 : modlist_add (&addlist, pgpkeyattr, data_armored);
2033 :
2034 : /* Now append addlist onto modlist. */
2035 0 : modlists_join (&modlist, addlist);
2036 :
2037 0 : if (dump)
2038 : {
2039 0 : estream_t input = modlist_dump (modlist, NULL);
2040 0 : if (input)
2041 : {
2042 0 : copy_stream (input, dump);
2043 0 : es_fclose (input);
2044 : }
2045 : }
2046 :
2047 : /* Going on the assumption that modify operations are more frequent
2048 : than adds, we try a modify first. If it's not there, we just
2049 : turn around and send an add command for the same key. Otherwise,
2050 : the modify brings the server copy into compliance with our copy.
2051 : Note that unlike the LDAP keyserver (and really, any other
2052 : keyserver) this does NOT merge signatures, but replaces the whole
2053 : key. This should make some people very happy. */
2054 : {
2055 : char **certid;
2056 : char *dn;
2057 :
2058 0 : certid = modlist_lookup (modlist, "pgpCertID");
2059 0 : if (/* We should have a value. */
2060 : ! certid
2061 : /* Exactly one. */
2062 0 : || !(certid[0] && !certid[1]))
2063 : {
2064 0 : log_error ("Bad certid.\n");
2065 0 : err = GPG_ERR_GENERAL;
2066 0 : goto out;
2067 : }
2068 :
2069 0 : dn = xasprintf ("pgpCertID=%s,%s", certid[0], basedn);
2070 :
2071 0 : err = ldap_modify_s (ldap_conn, dn, modlist);
2072 0 : if (err == LDAP_NO_SUCH_OBJECT)
2073 0 : err = ldap_add_s (ldap_conn, dn, addlist);
2074 :
2075 0 : xfree (dn);
2076 :
2077 0 : if (err != LDAP_SUCCESS)
2078 : {
2079 0 : log_error ("gpgkeys: error adding key to keyserver: %s\n",
2080 : ldap_err2string (err));
2081 0 : err = ldap_err_to_gpg_err (err);
2082 : }
2083 : }
2084 :
2085 : out:
2086 0 : if (dump)
2087 0 : es_fclose (dump);
2088 :
2089 0 : if (ldap_conn)
2090 0 : ldap_unbind (ldap_conn);
2091 :
2092 0 : xfree (basedn);
2093 0 : xfree (pgpkeyattr);
2094 :
2095 0 : modlist_free (modlist);
2096 0 : xfree (addlist);
2097 :
2098 0 : xfree (data_armored);
2099 :
2100 0 : return err;
2101 : }
|