Line data Source code
1 : /* server.c - LDAP and Keyserver access server
2 : * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3 : * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011, 2015 g10 Code GmbH
4 : * Copyright (C) 2014 Werner Koch
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 <stdlib.h>
25 : #include <stddef.h>
26 : #include <string.h>
27 : #include <assert.h>
28 : #include <sys/types.h>
29 : #include <sys/stat.h>
30 : #include <unistd.h>
31 : #include <errno.h>
32 :
33 : #include "dirmngr.h"
34 : #include <assuan.h>
35 :
36 : #include "crlcache.h"
37 : #include "crlfetch.h"
38 : #if USE_LDAP
39 : # include "ldapserver.h"
40 : #endif
41 : #include "ocsp.h"
42 : #include "certcache.h"
43 : #include "validate.h"
44 : #include "misc.h"
45 : #if USE_LDAP
46 : # include "ldap-wrapper.h"
47 : #endif
48 : #include "ks-action.h"
49 : #include "ks-engine.h" /* (ks_hkp_print_hosttable) */
50 : #if USE_LDAP
51 : # include "ldap-parse-uri.h"
52 : #endif
53 : #include "dns-stuff.h"
54 : #include "mbox-util.h"
55 : #include "zb32.h"
56 :
57 : /* To avoid DoS attacks we limit the size of a certificate to
58 : something reasonable. The DoS was actually only an issue back when
59 : Dirmngr was a system service and not a user service. */
60 : #define MAX_CERT_LENGTH (16*1024)
61 :
62 : /* The same goes for OpenPGP keyblocks, but here we need to allow for
63 : much longer blocks; a 200k keyblock is not too unusual for keys
64 : with a lot of signatures (e.g. 0x5b0358a2). 9C31503C6D866396 even
65 : has 770 KiB as of 2015-08-23. To avoid adding a runtime option we
66 : now use 20MiB which should really be enough. Well, a key with
67 : several pictures could be larger (the parser as a 18MiB limit for
68 : attribute packets) but it won't be nice to the keyservers to send
69 : them such large blobs. */
70 : #define MAX_KEYBLOCK_LENGTH (20*1024*1024)
71 :
72 :
73 : #define PARM_ERROR(t) assuan_set_error (ctx, \
74 : gpg_error (GPG_ERR_ASS_PARAMETER), (t))
75 : #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
76 :
77 :
78 :
79 : /* Control structure per connection. */
80 : struct server_local_s
81 : {
82 : /* Data used to associate an Assuan context with local server data */
83 : assuan_context_t assuan_ctx;
84 :
85 : /* Per-session LDAP servers. */
86 : ldap_server_t ldapservers;
87 :
88 : /* Per-session list of keyservers. */
89 : uri_item_t keyservers;
90 :
91 : /* If this flag is set to true this dirmngr process will be
92 : terminated after the end of this session. */
93 : int stopme;
94 : };
95 :
96 :
97 : /* Cookie definition for assuan data line output. */
98 : static ssize_t data_line_cookie_write (void *cookie,
99 : const void *buffer, size_t size);
100 : static int data_line_cookie_close (void *cookie);
101 : static es_cookie_io_functions_t data_line_cookie_functions =
102 : {
103 : NULL,
104 : data_line_cookie_write,
105 : NULL,
106 : data_line_cookie_close
107 : };
108 :
109 :
110 :
111 :
112 :
113 : /* Accessor for the local ldapservers variable. */
114 : ldap_server_t
115 0 : get_ldapservers_from_ctrl (ctrl_t ctrl)
116 : {
117 0 : if (ctrl && ctrl->server_local)
118 0 : return ctrl->server_local->ldapservers;
119 : else
120 0 : return NULL;
121 : }
122 :
123 :
124 : /* Release all configured keyserver info from CTRL. */
125 : void
126 0 : release_ctrl_keyservers (ctrl_t ctrl)
127 : {
128 0 : if (! ctrl->server_local)
129 0 : return;
130 :
131 0 : while (ctrl->server_local->keyservers)
132 : {
133 0 : uri_item_t tmp = ctrl->server_local->keyservers->next;
134 0 : http_release_parsed_uri (ctrl->server_local->keyservers->parsed_uri);
135 0 : xfree (ctrl->server_local->keyservers);
136 0 : ctrl->server_local->keyservers = tmp;
137 : }
138 : }
139 :
140 :
141 :
142 : /* Helper to print a message while leaving a command. */
143 : static gpg_error_t
144 0 : leave_cmd (assuan_context_t ctx, gpg_error_t err)
145 : {
146 0 : if (err)
147 : {
148 0 : const char *name = assuan_get_command_name (ctx);
149 0 : if (!name)
150 0 : name = "?";
151 0 : if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
152 0 : log_error ("command '%s' failed: %s\n", name,
153 : gpg_strerror (err));
154 : else
155 0 : log_error ("command '%s' failed: %s <%s>\n", name,
156 : gpg_strerror (err), gpg_strsource (err));
157 : }
158 0 : return err;
159 : }
160 :
161 :
162 : /* This is a wrapper around assuan_send_data which makes debugging the
163 : output in verbose mode easier. */
164 : static gpg_error_t
165 0 : data_line_write (assuan_context_t ctx, const void *buffer_arg, size_t size)
166 : {
167 0 : const char *buffer = buffer_arg;
168 : gpg_error_t err;
169 :
170 0 : if (opt.verbose && buffer && size)
171 0 : {
172 : /* Ease reading of output by sending a physical line at each LF. */
173 : const char *p;
174 : size_t n, nbytes;
175 :
176 0 : nbytes = size;
177 : do
178 : {
179 0 : p = memchr (buffer, '\n', nbytes);
180 0 : n = p ? (p - buffer) + 1 : nbytes;
181 0 : err = assuan_send_data (ctx, buffer, n);
182 0 : if (err)
183 : {
184 0 : gpg_err_set_errno (EIO);
185 0 : return err;
186 : }
187 0 : buffer += n;
188 0 : nbytes -= n;
189 0 : if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
190 : {
191 0 : gpg_err_set_errno (EIO);
192 0 : return err;
193 : }
194 : }
195 0 : while (nbytes);
196 : }
197 : else
198 : {
199 0 : err = assuan_send_data (ctx, buffer, size);
200 0 : if (err)
201 : {
202 0 : gpg_err_set_errno (EIO); /* For use by data_line_cookie_write. */
203 0 : return err;
204 : }
205 : }
206 :
207 0 : return 0;
208 : }
209 :
210 :
211 : /* A write handler used by es_fopencookie to write assuan data
212 : lines. */
213 : static ssize_t
214 0 : data_line_cookie_write (void *cookie, const void *buffer, size_t size)
215 : {
216 0 : assuan_context_t ctx = cookie;
217 :
218 0 : if (data_line_write (ctx, buffer, size))
219 0 : return -1;
220 0 : return (ssize_t)size;
221 : }
222 :
223 :
224 : static int
225 0 : data_line_cookie_close (void *cookie)
226 : {
227 0 : assuan_context_t ctx = cookie;
228 :
229 0 : if (assuan_send_data (ctx, NULL, 0))
230 : {
231 0 : gpg_err_set_errno (EIO);
232 0 : return -1;
233 : }
234 :
235 0 : return 0;
236 : }
237 :
238 :
239 : /* Copy the % and + escaped string S into the buffer D and replace the
240 : escape sequences. Note, that it is sufficient to allocate the
241 : target string D as long as the source string S, i.e.: strlen(s)+1.
242 : Note further that if S contains an escaped binary Nul the resulting
243 : string D will contain the 0 as well as all other characters but it
244 : will be impossible to know whether this is the original EOS or a
245 : copied Nul. */
246 : static void
247 0 : strcpy_escaped_plus (char *d, const unsigned char *s)
248 : {
249 0 : while (*s)
250 : {
251 0 : if (*s == '%' && s[1] && s[2])
252 : {
253 0 : s++;
254 0 : *d++ = xtoi_2 ( s);
255 0 : s += 2;
256 : }
257 0 : else if (*s == '+')
258 0 : *d++ = ' ', s++;
259 : else
260 0 : *d++ = *s++;
261 : }
262 0 : *d = 0;
263 0 : }
264 :
265 :
266 : /* Check whether the option NAME appears in LINE */
267 : static int
268 0 : has_option (const char *line, const char *name)
269 : {
270 : const char *s;
271 0 : int n = strlen (name);
272 :
273 0 : s = strstr (line, name);
274 0 : return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
275 : }
276 :
277 : /* Same as has_option but only considers options at the begin of the
278 : line. This is useful for commands which allow arbitrary strings on
279 : the line. */
280 : static int
281 0 : has_leading_option (const char *line, const char *name)
282 : {
283 : const char *s;
284 : int n;
285 :
286 0 : if (name[0] != '-' || name[1] != '-' || !name[2] || spacep (name+2))
287 0 : return 0;
288 0 : n = strlen (name);
289 0 : while ( *line == '-' && line[1] == '-' )
290 : {
291 0 : s = line;
292 0 : while (*line && !spacep (line))
293 0 : line++;
294 0 : if (n == (line - s) && !strncmp (s, name, n))
295 0 : return 1;
296 0 : while (spacep (line))
297 0 : line++;
298 : }
299 0 : return 0;
300 : }
301 :
302 :
303 : /* Same as has_option but does only test for the name of the option
304 : and ignores an argument, i.e. with NAME being "--hash" it would
305 : return a pointer for "--hash" as well as for "--hash=foo". If
306 : thhere is no such option NULL is returned. The pointer returned
307 : points right behind the option name, this may be an equal sign, Nul
308 : or a space. */
309 : /* static const char * */
310 : /* has_option_name (const char *line, const char *name) */
311 : /* { */
312 : /* const char *s; */
313 : /* int n = strlen (name); */
314 :
315 : /* s = strstr (line, name); */
316 : /* return (s && (s == line || spacep (s-1)) */
317 : /* && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */
318 : /* } */
319 :
320 :
321 : /* Skip over options. It is assumed that leading spaces have been
322 : removed (this is the case for lines passed to a handler from
323 : assuan). Blanks after the options are also removed. */
324 : static char *
325 0 : skip_options (char *line)
326 : {
327 0 : while ( *line == '-' && line[1] == '-' )
328 : {
329 0 : while (*line && !spacep (line))
330 0 : line++;
331 0 : while (spacep (line))
332 0 : line++;
333 : }
334 0 : return line;
335 : }
336 :
337 :
338 : /* Return an error if the assuan context does not belong to the owner
339 : of the process or to root. On error FAILTEXT is set as Assuan
340 : error string. */
341 : static gpg_error_t
342 0 : check_owner_permission (assuan_context_t ctx, const char *failtext)
343 : {
344 : #ifdef HAVE_W32_SYSTEM
345 : /* Under Windows the dirmngr is always run under the control of the
346 : user. */
347 : (void)ctx;
348 : (void)failtext;
349 : #else
350 : gpg_err_code_t ec;
351 : assuan_peercred_t cred;
352 :
353 0 : ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
354 0 : if (!ec && cred->uid && cred->uid != getuid ())
355 0 : ec = GPG_ERR_EPERM;
356 0 : if (ec)
357 0 : return set_error (ec, failtext);
358 : #endif
359 0 : return 0;
360 : }
361 :
362 :
363 :
364 : /* Common code for get_cert_local and get_issuer_cert_local. */
365 : static ksba_cert_t
366 0 : do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
367 : {
368 : unsigned char *value;
369 : size_t valuelen;
370 : int rc;
371 : char *buf;
372 : ksba_cert_t cert;
373 :
374 0 : if (name)
375 : {
376 0 : buf = xmalloc ( strlen (command) + 1 + strlen(name) + 1);
377 0 : strcpy (stpcpy (stpcpy (buf, command), " "), name);
378 : }
379 : else
380 0 : buf = xstrdup (command);
381 :
382 0 : rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
383 : &value, &valuelen, MAX_CERT_LENGTH);
384 0 : xfree (buf);
385 0 : if (rc)
386 : {
387 0 : log_error (_("assuan_inquire(%s) failed: %s\n"),
388 : command, gpg_strerror (rc));
389 0 : return NULL;
390 : }
391 :
392 0 : if (!valuelen)
393 : {
394 0 : xfree (value);
395 0 : return NULL;
396 : }
397 :
398 0 : rc = ksba_cert_new (&cert);
399 0 : if (!rc)
400 : {
401 0 : rc = ksba_cert_init_from_mem (cert, value, valuelen);
402 0 : if (rc)
403 : {
404 0 : ksba_cert_release (cert);
405 0 : cert = NULL;
406 : }
407 : }
408 0 : xfree (value);
409 0 : return cert;
410 : }
411 :
412 :
413 :
414 : /* Ask back to return a certificate for name, given as a regular
415 : gpgsm certificate indentificates (e.g. fingerprint or one of the
416 : other methods). Alternatively, NULL may be used for NAME to
417 : return the current target certificate. Either return the certificate
418 : in a KSBA object or NULL if it is not available.
419 : */
420 : ksba_cert_t
421 0 : get_cert_local (ctrl_t ctrl, const char *name)
422 : {
423 0 : if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
424 : {
425 0 : if (opt.debug)
426 0 : log_debug ("get_cert_local called w/o context\n");
427 0 : return NULL;
428 : }
429 0 : return do_get_cert_local (ctrl, name, "SENDCERT");
430 :
431 : }
432 :
433 : /* Ask back to return the issuing certificate for name, given as a
434 : regular gpgsm certificate indentificates (e.g. fingerprint or one
435 : of the other methods). Alternatively, NULL may be used for NAME to
436 : return thecurrent target certificate. Either return the certificate
437 : in a KSBA object or NULL if it is not available.
438 :
439 : */
440 : ksba_cert_t
441 0 : get_issuing_cert_local (ctrl_t ctrl, const char *name)
442 : {
443 0 : if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
444 : {
445 0 : if (opt.debug)
446 0 : log_debug ("get_issuing_cert_local called w/o context\n");
447 0 : return NULL;
448 : }
449 0 : return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
450 : }
451 :
452 : /* Ask back to return a certificate with subject NAME and a
453 : subjectKeyIdentifier of KEYID. */
454 : ksba_cert_t
455 0 : get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
456 : {
457 : unsigned char *value;
458 : size_t valuelen;
459 : int rc;
460 : char *buf;
461 : ksba_cert_t cert;
462 : char *hexkeyid;
463 :
464 0 : if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
465 : {
466 0 : if (opt.debug)
467 0 : log_debug ("get_cert_local_ski called w/o context\n");
468 0 : return NULL;
469 : }
470 0 : if (!name || !keyid)
471 : {
472 0 : log_debug ("get_cert_local_ski called with insufficient arguments\n");
473 0 : return NULL;
474 : }
475 :
476 0 : hexkeyid = serial_hex (keyid);
477 0 : if (!hexkeyid)
478 : {
479 0 : log_debug ("serial_hex() failed\n");
480 0 : return NULL;
481 : }
482 :
483 0 : buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
484 0 : if (!buf)
485 : {
486 :
487 0 : log_error ("can't allocate enough memory: %s\n", strerror (errno));
488 0 : xfree (hexkeyid);
489 0 : return NULL;
490 : }
491 0 : strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
492 0 : xfree (hexkeyid);
493 :
494 0 : rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
495 : &value, &valuelen, MAX_CERT_LENGTH);
496 0 : xfree (buf);
497 0 : if (rc)
498 : {
499 0 : log_error (_("assuan_inquire(%s) failed: %s\n"), "SENDCERT_SKI",
500 : gpg_strerror (rc));
501 0 : return NULL;
502 : }
503 :
504 0 : if (!valuelen)
505 : {
506 0 : xfree (value);
507 0 : return NULL;
508 : }
509 :
510 0 : rc = ksba_cert_new (&cert);
511 0 : if (!rc)
512 : {
513 0 : rc = ksba_cert_init_from_mem (cert, value, valuelen);
514 0 : if (rc)
515 : {
516 0 : ksba_cert_release (cert);
517 0 : cert = NULL;
518 : }
519 : }
520 0 : xfree (value);
521 0 : return cert;
522 : }
523 :
524 :
525 : /* Ask the client via an inquiry to check the istrusted status of the
526 : certificate specified by the hexified fingerprint HEXFPR. Returns
527 : 0 if the certificate is trusted by the client or an error code. */
528 : gpg_error_t
529 0 : get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr)
530 : {
531 : unsigned char *value;
532 : size_t valuelen;
533 : int rc;
534 : char request[100];
535 :
536 0 : if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx
537 0 : || !hexfpr)
538 0 : return gpg_error (GPG_ERR_INV_ARG);
539 :
540 0 : snprintf (request, sizeof request, "ISTRUSTED %s", hexfpr);
541 0 : rc = assuan_inquire (ctrl->server_local->assuan_ctx, request,
542 : &value, &valuelen, 100);
543 0 : if (rc)
544 : {
545 0 : log_error (_("assuan_inquire(%s) failed: %s\n"),
546 : request, gpg_strerror (rc));
547 0 : return rc;
548 : }
549 : /* The expected data is: "1" or "1 cruft" (not a C-string). */
550 0 : if (valuelen && *value == '1' && (valuelen == 1 || spacep (value+1)))
551 0 : rc = 0;
552 : else
553 0 : rc = gpg_error (GPG_ERR_NOT_TRUSTED);
554 0 : xfree (value);
555 0 : return rc;
556 : }
557 :
558 :
559 :
560 :
561 : /* Ask the client to return the certificate associated with the
562 : current command. This is sometimes needed because the client usually
563 : sends us just the cert ID, assuming that the request can be
564 : satisfied from the cache, where the cert ID is used as key. */
565 : static int
566 0 : inquire_cert_and_load_crl (assuan_context_t ctx)
567 : {
568 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
569 : gpg_error_t err;
570 0 : unsigned char *value = NULL;
571 : size_t valuelen;
572 0 : ksba_cert_t cert = NULL;
573 :
574 0 : err = assuan_inquire( ctx, "SENDCERT", &value, &valuelen, 0);
575 0 : if (err)
576 0 : return err;
577 :
578 : /* { */
579 : /* FILE *fp = fopen ("foo.der", "r"); */
580 : /* value = xmalloc (2000); */
581 : /* valuelen = fread (value, 1, 2000, fp); */
582 : /* fclose (fp); */
583 : /* } */
584 :
585 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
586 0 : return gpg_error (GPG_ERR_MISSING_CERT);
587 :
588 0 : err = ksba_cert_new (&cert);
589 0 : if (err)
590 0 : goto leave;
591 0 : err = ksba_cert_init_from_mem (cert, value, valuelen);
592 0 : if(err)
593 0 : goto leave;
594 0 : xfree (value); value = NULL;
595 :
596 0 : err = crl_cache_reload_crl (ctrl, cert);
597 :
598 : leave:
599 0 : ksba_cert_release (cert);
600 0 : xfree (value);
601 0 : return err;
602 : }
603 :
604 :
605 : /* Handle OPTION commands. */
606 : static gpg_error_t
607 0 : option_handler (assuan_context_t ctx, const char *key, const char *value)
608 : {
609 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
610 0 : gpg_error_t err = 0;
611 :
612 0 : if (!strcmp (key, "force-crl-refresh"))
613 : {
614 0 : int i = *value? atoi (value) : 0;
615 0 : ctrl->force_crl_refresh = i;
616 : }
617 0 : else if (!strcmp (key, "audit-events"))
618 : {
619 0 : int i = *value? atoi (value) : 0;
620 0 : ctrl->audit_events = i;
621 : }
622 0 : else if (!strcmp (key, "http-proxy"))
623 : {
624 0 : xfree (ctrl->http_proxy);
625 0 : if (!*value || !strcmp (value, "none"))
626 0 : ctrl->http_proxy = NULL;
627 0 : else if (!(ctrl->http_proxy = xtrystrdup (value)))
628 0 : err = gpg_error_from_syserror ();
629 : }
630 0 : else if (!strcmp (key, "honor-keyserver-url-used"))
631 : {
632 : /* Return an error if we are running in Tor mode. */
633 0 : if (opt.use_tor)
634 0 : err = gpg_error (GPG_ERR_FORBIDDEN);
635 : }
636 : else
637 0 : err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
638 :
639 0 : return err;
640 : }
641 :
642 :
643 :
644 : static const char hlp_dns_cert[] =
645 : "DNS_CERT <subtype> <name>\n"
646 : "DNS_CERT --pka <user_id>\n"
647 : "DNS_CERT --dane <user_id>\n"
648 : "\n"
649 : "Return the CERT record for <name>. <subtype> is one of\n"
650 : " * Return the first record of any supported subtype\n"
651 : " PGP Return the first record of subtype PGP (3)\n"
652 : " IPGP Return the first record of subtype IPGP (6)\n"
653 : "If the content of a certifciate is available (PGP) it is returned\n"
654 : "by data lines. Fingerprints and URLs are returned via status lines.\n"
655 : "In --pka mode the fingerprint and if available an URL is returned.\n"
656 : "In --dane mode the key is returned from RR type 61";
657 : static gpg_error_t
658 0 : cmd_dns_cert (assuan_context_t ctx, char *line)
659 : {
660 : /* ctrl_t ctrl = assuan_get_pointer (ctx); */
661 0 : gpg_error_t err = 0;
662 : int pka_mode, dane_mode;
663 0 : char *mbox = NULL;
664 0 : char *namebuf = NULL;
665 0 : char *encodedhash = NULL;
666 : const char *name;
667 : int certtype;
668 : char *p;
669 0 : void *key = NULL;
670 : size_t keylen;
671 0 : unsigned char *fpr = NULL;
672 : size_t fprlen;
673 0 : char *url = NULL;
674 :
675 0 : pka_mode = has_option (line, "--pka");
676 0 : dane_mode = has_option (line, "--dane");
677 0 : line = skip_options (line);
678 :
679 0 : if (pka_mode && dane_mode)
680 : {
681 0 : err = PARM_ERROR ("either --pka or --dane may be given");
682 0 : goto leave;
683 : }
684 :
685 0 : if (pka_mode || dane_mode)
686 : ; /* No need to parse here - we do this later. */
687 : else
688 : {
689 0 : p = strchr (line, ' ');
690 0 : if (!p)
691 : {
692 0 : err = PARM_ERROR ("missing arguments");
693 0 : goto leave;
694 : }
695 0 : *p++ = 0;
696 0 : if (!strcmp (line, "*"))
697 0 : certtype = DNS_CERTTYPE_ANY;
698 0 : else if (!strcmp (line, "IPGP"))
699 0 : certtype = DNS_CERTTYPE_IPGP;
700 0 : else if (!strcmp (line, "PGP"))
701 0 : certtype = DNS_CERTTYPE_PGP;
702 : else
703 : {
704 0 : err = PARM_ERROR ("unknown subtype");
705 0 : goto leave;
706 : }
707 0 : while (spacep (p))
708 0 : p++;
709 0 : line = p;
710 0 : if (!*line)
711 : {
712 0 : err = PARM_ERROR ("name missing");
713 0 : goto leave;
714 : }
715 : }
716 :
717 0 : if (opt.use_tor && enable_dns_tormode ())
718 : {
719 : /* Tor mode is requested but the DNS code can't enable it. */
720 0 : err = gpg_error (GPG_ERR_FORBIDDEN);
721 0 : goto leave;
722 : }
723 :
724 0 : if (pka_mode || dane_mode)
725 0 : {
726 : char *domain; /* Points to mbox. */
727 : char hashbuf[32]; /* For SHA-1 and SHA-256. */
728 :
729 : /* We lowercase ascii characters but the DANE I-D does not allow
730 : this. FIXME: Check after the release of the RFC whether to
731 : change this. */
732 0 : mbox = mailbox_from_userid (line);
733 0 : if (!mbox || !(domain = strchr (mbox, '@')))
734 : {
735 0 : err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
736 0 : goto leave;
737 : }
738 0 : *domain++ = 0;
739 :
740 0 : if (pka_mode)
741 : {
742 0 : gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
743 0 : encodedhash = zb32_encode (hashbuf, 8*20);
744 0 : if (!encodedhash)
745 : {
746 0 : err = gpg_error_from_syserror ();
747 0 : goto leave;
748 : }
749 0 : namebuf = strconcat (encodedhash, "._pka.", domain, NULL);
750 0 : if (!namebuf)
751 : {
752 0 : err = gpg_error_from_syserror ();
753 0 : goto leave;
754 : }
755 0 : name = namebuf;
756 0 : certtype = DNS_CERTTYPE_IPGP;
757 : }
758 : else
759 : {
760 : /* Note: The hash is truncated to 28 bytes and we lowercase
761 : the result only for aesthetic reasons. */
762 0 : gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf, mbox, strlen (mbox));
763 0 : encodedhash = bin2hex (hashbuf, 28, NULL);
764 0 : if (!encodedhash)
765 : {
766 0 : err = gpg_error_from_syserror ();
767 0 : goto leave;
768 : }
769 0 : ascii_strlwr (encodedhash);
770 0 : namebuf = strconcat (encodedhash, "._openpgpkey.", domain, NULL);
771 0 : if (!namebuf)
772 : {
773 0 : err = gpg_error_from_syserror ();
774 0 : goto leave;
775 : }
776 0 : name = namebuf;
777 0 : certtype = DNS_CERTTYPE_RR61;
778 : }
779 : }
780 : else
781 0 : name = line;
782 :
783 0 : err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
784 0 : if (err)
785 0 : goto leave;
786 :
787 0 : if (key)
788 : {
789 0 : err = data_line_write (ctx, key, keylen);
790 0 : if (err)
791 0 : goto leave;
792 : }
793 :
794 0 : if (fpr)
795 : {
796 : char *tmpstr;
797 :
798 0 : tmpstr = bin2hex (fpr, fprlen, NULL);
799 0 : if (!tmpstr)
800 0 : err = gpg_error_from_syserror ();
801 : else
802 : {
803 0 : err = assuan_write_status (ctx, "FPR", tmpstr);
804 0 : xfree (tmpstr);
805 : }
806 0 : if (err)
807 0 : goto leave;
808 : }
809 :
810 0 : if (url)
811 : {
812 0 : err = assuan_write_status (ctx, "URL", url);
813 0 : if (err)
814 0 : goto leave;
815 : }
816 :
817 :
818 : leave:
819 0 : xfree (key);
820 0 : xfree (fpr);
821 0 : xfree (url);
822 0 : xfree (mbox);
823 0 : xfree (namebuf);
824 0 : xfree (encodedhash);
825 0 : return leave_cmd (ctx, err);
826 : }
827 :
828 :
829 :
830 : static const char hlp_ldapserver[] =
831 : "LDAPSERVER <data>\n"
832 : "\n"
833 : "Add a new LDAP server to the list of configured LDAP servers.\n"
834 : "DATA is in the same format as expected in the configure file.";
835 : static gpg_error_t
836 0 : cmd_ldapserver (assuan_context_t ctx, char *line)
837 : {
838 : #if USE_LDAP
839 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
840 : ldap_server_t server;
841 : ldap_server_t *last_next_p;
842 :
843 0 : while (spacep (line))
844 0 : line++;
845 0 : if (*line == '\0')
846 0 : return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
847 :
848 0 : server = ldapserver_parse_one (line, "", 0);
849 0 : if (! server)
850 0 : return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
851 :
852 0 : last_next_p = &ctrl->server_local->ldapservers;
853 0 : while (*last_next_p)
854 0 : last_next_p = &(*last_next_p)->next;
855 0 : *last_next_p = server;
856 0 : return leave_cmd (ctx, 0);
857 : #else
858 : (void)line;
859 : return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
860 : #endif
861 : }
862 :
863 :
864 : static const char hlp_isvalid[] =
865 : "ISVALID [--only-ocsp] [--force-default-responder]"
866 : " <certificate_id>|<certificate_fpr>\n"
867 : "\n"
868 : "This command checks whether the certificate identified by the\n"
869 : "certificate_id is valid. This is done by consulting CRLs or\n"
870 : "whatever has been configured. Note, that the returned error codes\n"
871 : "are from gpg-error.h. The command may callback using the inquire\n"
872 : "function. See the manual for details.\n"
873 : "\n"
874 : "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
875 : "delimited by a single dot. The first part is the SHA-1 hash of the\n"
876 : "issuer name and the second part the serial number.\n"
877 : "\n"
878 : "Alternatively the certificate's fingerprint may be given in which\n"
879 : "case an OCSP request is done before consulting the CRL.\n"
880 : "\n"
881 : "If the option --only-ocsp is given, no fallback to a CRL check will\n"
882 : "be used.\n"
883 : "\n"
884 : "If the option --force-default-responder is given, only the default\n"
885 : "OCSP responder will be used and any other methods of obtaining an\n"
886 : "OCSP responder URL won't be used.";
887 : static gpg_error_t
888 0 : cmd_isvalid (assuan_context_t ctx, char *line)
889 : {
890 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
891 : char *issuerhash, *serialno;
892 : gpg_error_t err;
893 0 : int did_inquire = 0;
894 0 : int ocsp_mode = 0;
895 : int only_ocsp;
896 : int force_default_responder;
897 :
898 0 : only_ocsp = has_option (line, "--only-ocsp");
899 0 : force_default_responder = has_option (line, "--force-default-responder");
900 0 : line = skip_options (line);
901 :
902 0 : issuerhash = xstrdup (line); /* We need to work on a copy of the
903 : line because that same Assuan
904 : context may be used for an inquiry.
905 : That is because Assuan reuses its
906 : line buffer.
907 : */
908 :
909 0 : serialno = strchr (issuerhash, '.');
910 0 : if (serialno)
911 0 : *serialno++ = 0;
912 : else
913 : {
914 0 : char *endp = strchr (issuerhash, ' ');
915 0 : if (endp)
916 0 : *endp = 0;
917 0 : if (strlen (issuerhash) != 40)
918 : {
919 0 : xfree (issuerhash);
920 0 : return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
921 : }
922 0 : ocsp_mode = 1;
923 : }
924 :
925 :
926 : again:
927 0 : if (ocsp_mode)
928 : {
929 : /* Note, that we ignore the given issuer hash and instead rely
930 : on the current certificate semantics used with this
931 : command. */
932 0 : if (!opt.allow_ocsp)
933 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
934 : else
935 0 : err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
936 : /* Fixme: If we got no ocsp response and --only-ocsp is not used
937 : we should fall back to CRL mode. Thus we need to clear
938 : OCSP_MODE, get the issuerhash and the serialno from the
939 : current certificate and jump to again. */
940 : }
941 0 : else if (only_ocsp)
942 0 : err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
943 : else
944 : {
945 0 : switch (crl_cache_isvalid (ctrl,
946 : issuerhash, serialno,
947 : ctrl->force_crl_refresh))
948 : {
949 : case CRL_CACHE_VALID:
950 0 : err = 0;
951 0 : break;
952 : case CRL_CACHE_INVALID:
953 0 : err = gpg_error (GPG_ERR_CERT_REVOKED);
954 0 : break;
955 : case CRL_CACHE_DONTKNOW:
956 0 : if (did_inquire)
957 0 : err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
958 0 : else if (!(err = inquire_cert_and_load_crl (ctx)))
959 : {
960 0 : did_inquire = 1;
961 0 : goto again;
962 : }
963 0 : break;
964 : case CRL_CACHE_CANTUSE:
965 0 : err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
966 0 : break;
967 : default:
968 0 : log_fatal ("crl_cache_isvalid returned invalid code\n");
969 : }
970 : }
971 :
972 0 : xfree (issuerhash);
973 0 : return leave_cmd (ctx, err);
974 : }
975 :
976 :
977 : /* If the line contains a SHA-1 fingerprint as the first argument,
978 : return the FPR vuffer on success. The function checks that the
979 : fingerprint consists of valid characters and prints and error
980 : message if it does not and returns NULL. Fingerprints are
981 : considered optional and thus no explicit error is returned. NULL is
982 : also returned if there is no fingerprint at all available.
983 : FPR must be a caller provided buffer of at least 20 bytes.
984 :
985 : Note that colons within the fingerprint are allowed to separate 2
986 : hex digits; this allows for easier cutting and pasting using the
987 : usual fingerprint rendering.
988 : */
989 : static unsigned char *
990 0 : get_fingerprint_from_line (const char *line, unsigned char *fpr)
991 : {
992 : const char *s;
993 : int i;
994 :
995 0 : for (s=line, i=0; *s && *s != ' '; s++ )
996 : {
997 0 : if ( hexdigitp (s) && hexdigitp (s+1) )
998 : {
999 0 : if ( i >= 20 )
1000 0 : return NULL; /* Fingerprint too long. */
1001 0 : fpr[i++] = xtoi_2 (s);
1002 0 : s++;
1003 : }
1004 0 : else if ( *s != ':' )
1005 0 : return NULL; /* Invalid. */
1006 : }
1007 0 : if ( i != 20 )
1008 0 : return NULL; /* Fingerprint to short. */
1009 0 : return fpr;
1010 : }
1011 :
1012 :
1013 :
1014 : static const char hlp_checkcrl[] =
1015 : "CHECKCRL [<fingerprint>]\n"
1016 : "\n"
1017 : "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1018 : "entire X.509 certificate blob) is valid or not by consulting the\n"
1019 : "CRL responsible for this certificate. If the fingerprint has not\n"
1020 : "been given or the certificate is not known, the function \n"
1021 : "inquires the certificate using an\n"
1022 : "\n"
1023 : " INQUIRE TARGETCERT\n"
1024 : "\n"
1025 : "and the caller is expected to return the certificate for the\n"
1026 : "request (which should match FINGERPRINT) as a binary blob.\n"
1027 : "Processing then takes place without further interaction; in\n"
1028 : "particular dirmngr tries to locate other required certificate by\n"
1029 : "its own mechanism which includes a local certificate store as well\n"
1030 : "as a list of trusted root certificates.\n"
1031 : "\n"
1032 : "The return value is the usual gpg-error code or 0 for ducesss;\n"
1033 : "i.e. the certificate validity has been confirmed by a valid CRL.";
1034 : static gpg_error_t
1035 0 : cmd_checkcrl (assuan_context_t ctx, char *line)
1036 : {
1037 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1038 : gpg_error_t err;
1039 : unsigned char fprbuffer[20], *fpr;
1040 : ksba_cert_t cert;
1041 :
1042 0 : fpr = get_fingerprint_from_line (line, fprbuffer);
1043 0 : cert = fpr? get_cert_byfpr (fpr) : NULL;
1044 :
1045 0 : if (!cert)
1046 : {
1047 : /* We do not have this certificate yet or the fingerprint has
1048 : not been given. Inquire it from the client. */
1049 0 : unsigned char *value = NULL;
1050 : size_t valuelen;
1051 :
1052 0 : err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1053 : &value, &valuelen, MAX_CERT_LENGTH);
1054 0 : if (err)
1055 : {
1056 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1057 0 : goto leave;
1058 : }
1059 :
1060 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
1061 0 : err = gpg_error (GPG_ERR_MISSING_CERT);
1062 : else
1063 : {
1064 0 : err = ksba_cert_new (&cert);
1065 0 : if (!err)
1066 0 : err = ksba_cert_init_from_mem (cert, value, valuelen);
1067 : }
1068 0 : xfree (value);
1069 0 : if(err)
1070 0 : goto leave;
1071 : }
1072 :
1073 0 : assert (cert);
1074 :
1075 0 : err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
1076 0 : if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
1077 : {
1078 0 : err = crl_cache_reload_crl (ctrl, cert);
1079 0 : if (!err)
1080 0 : err = crl_cache_cert_isvalid (ctrl, cert, 0);
1081 : }
1082 :
1083 : leave:
1084 0 : ksba_cert_release (cert);
1085 0 : return leave_cmd (ctx, err);
1086 : }
1087 :
1088 :
1089 : static const char hlp_checkocsp[] =
1090 : "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
1091 : "\n"
1092 : "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1093 : "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
1094 : "responder responsible for this certificate. The optional\n"
1095 : "fingerprint may be used for a quick check in case an OCSP check has\n"
1096 : "been done for this certificate recently (we always cache OCSP\n"
1097 : "responses for a couple of minutes). If the fingerprint has not been\n"
1098 : "given or there is no cached result, the function inquires the\n"
1099 : "certificate using an\n"
1100 : "\n"
1101 : " INQUIRE TARGETCERT\n"
1102 : "\n"
1103 : "and the caller is expected to return the certificate for the\n"
1104 : "request (which should match FINGERPRINT) as a binary blob.\n"
1105 : "Processing then takes place without further interaction; in\n"
1106 : "particular dirmngr tries to locate other required certificates by\n"
1107 : "its own mechanism which includes a local certificate store as well\n"
1108 : "as a list of trusted root certifciates.\n"
1109 : "\n"
1110 : "If the option --force-default-responder is given, only the default\n"
1111 : "OCSP responder will be used and any other methods of obtaining an\n"
1112 : "OCSP responder URL won't be used.\n"
1113 : "\n"
1114 : "The return value is the usual gpg-error code or 0 for ducesss;\n"
1115 : "i.e. the certificate validity has been confirmed by a valid CRL.";
1116 : static gpg_error_t
1117 0 : cmd_checkocsp (assuan_context_t ctx, char *line)
1118 : {
1119 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1120 : gpg_error_t err;
1121 : unsigned char fprbuffer[20], *fpr;
1122 : ksba_cert_t cert;
1123 : int force_default_responder;
1124 :
1125 0 : force_default_responder = has_option (line, "--force-default-responder");
1126 0 : line = skip_options (line);
1127 :
1128 0 : fpr = get_fingerprint_from_line (line, fprbuffer);
1129 0 : cert = fpr? get_cert_byfpr (fpr) : NULL;
1130 :
1131 0 : if (!cert)
1132 : {
1133 : /* We do not have this certificate yet or the fingerprint has
1134 : not been given. Inquire it from the client. */
1135 0 : unsigned char *value = NULL;
1136 : size_t valuelen;
1137 :
1138 0 : err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1139 : &value, &valuelen, MAX_CERT_LENGTH);
1140 0 : if (err)
1141 : {
1142 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1143 0 : goto leave;
1144 : }
1145 :
1146 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
1147 0 : err = gpg_error (GPG_ERR_MISSING_CERT);
1148 : else
1149 : {
1150 0 : err = ksba_cert_new (&cert);
1151 0 : if (!err)
1152 0 : err = ksba_cert_init_from_mem (cert, value, valuelen);
1153 : }
1154 0 : xfree (value);
1155 0 : if(err)
1156 0 : goto leave;
1157 : }
1158 :
1159 0 : assert (cert);
1160 :
1161 0 : if (!opt.allow_ocsp)
1162 0 : err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1163 : else
1164 0 : err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
1165 :
1166 : leave:
1167 0 : ksba_cert_release (cert);
1168 0 : return leave_cmd (ctx, err);
1169 : }
1170 :
1171 :
1172 :
1173 : static int
1174 0 : lookup_cert_by_url (assuan_context_t ctx, const char *url)
1175 : {
1176 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1177 0 : gpg_error_t err = 0;
1178 0 : unsigned char *value = NULL;
1179 : size_t valuelen;
1180 :
1181 : /* Fetch single certificate given it's URL. */
1182 0 : err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
1183 0 : if (err)
1184 : {
1185 0 : log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
1186 0 : goto leave;
1187 : }
1188 :
1189 : /* Send the data, flush the buffer and then send an END. */
1190 0 : err = assuan_send_data (ctx, value, valuelen);
1191 0 : if (!err)
1192 0 : err = assuan_send_data (ctx, NULL, 0);
1193 0 : if (!err)
1194 0 : err = assuan_write_line (ctx, "END");
1195 0 : if (err)
1196 : {
1197 0 : log_error (_("error sending data: %s\n"), gpg_strerror (err));
1198 0 : goto leave;
1199 : }
1200 :
1201 : leave:
1202 :
1203 0 : return err;
1204 : }
1205 :
1206 :
1207 : /* Send the certificate, flush the buffer and then send an END. */
1208 : static gpg_error_t
1209 0 : return_one_cert (void *opaque, ksba_cert_t cert)
1210 : {
1211 0 : assuan_context_t ctx = opaque;
1212 : gpg_error_t err;
1213 : const unsigned char *der;
1214 : size_t derlen;
1215 :
1216 0 : der = ksba_cert_get_image (cert, &derlen);
1217 0 : if (!der)
1218 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1219 : else
1220 : {
1221 0 : err = assuan_send_data (ctx, der, derlen);
1222 0 : if (!err)
1223 0 : err = assuan_send_data (ctx, NULL, 0);
1224 0 : if (!err)
1225 0 : err = assuan_write_line (ctx, "END");
1226 : }
1227 0 : if (err)
1228 0 : log_error (_("error sending data: %s\n"), gpg_strerror (err));
1229 0 : return err;
1230 : }
1231 :
1232 :
1233 : /* Lookup certificates from the internal cache or using the ldap
1234 : servers. */
1235 : static int
1236 0 : lookup_cert_by_pattern (assuan_context_t ctx, char *line,
1237 : int single, int cache_only)
1238 : {
1239 0 : gpg_error_t err = 0;
1240 : char *p;
1241 0 : strlist_t sl, list = NULL;
1242 0 : int truncated = 0, truncation_forced = 0;
1243 0 : int count = 0;
1244 0 : int local_count = 0;
1245 : #if USE_LDAP
1246 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1247 0 : unsigned char *value = NULL;
1248 : size_t valuelen;
1249 : struct ldapserver_iter ldapserver_iter;
1250 : cert_fetch_context_t fetch_context;
1251 : #endif /*USE_LDAP*/
1252 0 : int any_no_data = 0;
1253 :
1254 : /* Break the line down into an STRLIST */
1255 0 : for (p=line; *p; line = p)
1256 : {
1257 0 : while (*p && *p != ' ')
1258 0 : p++;
1259 0 : if (*p)
1260 0 : *p++ = 0;
1261 :
1262 0 : if (*line)
1263 : {
1264 0 : sl = xtrymalloc (sizeof *sl + strlen (line));
1265 0 : if (!sl)
1266 : {
1267 0 : err = gpg_error_from_errno (errno);
1268 0 : goto leave;
1269 : }
1270 0 : memset (sl, 0, sizeof *sl);
1271 0 : strcpy_escaped_plus (sl->d, line);
1272 0 : sl->next = list;
1273 0 : list = sl;
1274 : }
1275 : }
1276 :
1277 : /* First look through the internal cache. The certifcates retruned
1278 : here are not counted towards the truncation limit. */
1279 0 : if (single && !cache_only)
1280 : ; /* Do not read from the local cache in this case. */
1281 : else
1282 : {
1283 0 : for (sl=list; sl; sl = sl->next)
1284 : {
1285 0 : err = get_certs_bypattern (sl->d, return_one_cert, ctx);
1286 0 : if (!err)
1287 0 : local_count++;
1288 0 : if (!err && single)
1289 0 : goto ready;
1290 :
1291 0 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1292 : {
1293 0 : err = 0;
1294 0 : if (cache_only)
1295 0 : any_no_data = 1;
1296 : }
1297 0 : else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
1298 : {
1299 : /* No real fault because the internal pattern lookup
1300 : can't yet cope with all types of pattern. */
1301 0 : err = 0;
1302 : }
1303 0 : if (err)
1304 0 : goto ready;
1305 : }
1306 : }
1307 :
1308 : /* Loop over all configured servers unless we want only the
1309 : certificates from the cache. */
1310 : #if USE_LDAP
1311 0 : for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
1312 0 : !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
1313 0 : && ldapserver_iter.server->host && !truncation_forced;
1314 0 : ldapserver_iter_next (&ldapserver_iter))
1315 : {
1316 0 : ldap_server_t ldapserver = ldapserver_iter.server;
1317 :
1318 0 : if (DBG_LOOKUP)
1319 0 : log_debug ("cmd_lookup: trying %s:%d base=%s\n",
1320 : ldapserver->host, ldapserver->port,
1321 0 : ldapserver->base?ldapserver->base : "[default]");
1322 :
1323 : /* Fetch certificates matching pattern */
1324 0 : err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
1325 0 : if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
1326 : {
1327 0 : if (DBG_LOOKUP)
1328 0 : log_debug ("cmd_lookup: no data\n");
1329 0 : err = 0;
1330 0 : any_no_data = 1;
1331 0 : continue;
1332 : }
1333 0 : if (err)
1334 : {
1335 0 : log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1336 0 : goto leave;
1337 : }
1338 :
1339 : /* Fetch the certificates for this query. */
1340 0 : while (!truncation_forced)
1341 : {
1342 0 : xfree (value); value = NULL;
1343 0 : err = fetch_next_cert (fetch_context, &value, &valuelen);
1344 0 : if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1345 : {
1346 0 : err = 0;
1347 0 : any_no_data = 1;
1348 0 : break; /* Ready. */
1349 : }
1350 0 : if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1351 : {
1352 0 : truncated = 1;
1353 0 : err = 0;
1354 0 : break; /* Ready. */
1355 : }
1356 0 : if (gpg_err_code (err) == GPG_ERR_EOF)
1357 : {
1358 0 : err = 0;
1359 0 : break; /* Ready. */
1360 : }
1361 0 : if (!err && !value)
1362 : {
1363 0 : err = gpg_error (GPG_ERR_BUG);
1364 0 : goto leave;
1365 : }
1366 0 : if (err)
1367 : {
1368 0 : log_error (_("fetch_next_cert failed: %s\n"),
1369 : gpg_strerror (err));
1370 0 : end_cert_fetch (fetch_context);
1371 0 : goto leave;
1372 : }
1373 :
1374 0 : if (DBG_LOOKUP)
1375 0 : log_debug ("cmd_lookup: returning one cert%s\n",
1376 : truncated? " (truncated)":"");
1377 :
1378 : /* Send the data, flush the buffer and then send an END line
1379 : as a certificate delimiter. */
1380 0 : err = assuan_send_data (ctx, value, valuelen);
1381 0 : if (!err)
1382 0 : err = assuan_send_data (ctx, NULL, 0);
1383 0 : if (!err)
1384 0 : err = assuan_write_line (ctx, "END");
1385 0 : if (err)
1386 : {
1387 0 : log_error (_("error sending data: %s\n"), gpg_strerror (err));
1388 0 : end_cert_fetch (fetch_context);
1389 0 : goto leave;
1390 : }
1391 :
1392 0 : if (++count >= opt.max_replies )
1393 : {
1394 0 : truncation_forced = 1;
1395 0 : log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1396 : }
1397 0 : if (single)
1398 0 : break;
1399 : }
1400 :
1401 0 : end_cert_fetch (fetch_context);
1402 : }
1403 : #endif /*USE_LDAP*/
1404 :
1405 : ready:
1406 0 : if (truncated || truncation_forced)
1407 : {
1408 : char str[50];
1409 :
1410 0 : sprintf (str, "%d", count);
1411 0 : assuan_write_status (ctx, "TRUNCATED", str);
1412 : }
1413 :
1414 0 : if (!err && !count && !local_count && any_no_data)
1415 0 : err = gpg_error (GPG_ERR_NO_DATA);
1416 :
1417 : leave:
1418 0 : free_strlist (list);
1419 0 : return err;
1420 : }
1421 :
1422 :
1423 : static const char hlp_lookup[] =
1424 : "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1425 : "\n"
1426 : "Lookup certificates matching PATTERN. With --url the pattern is\n"
1427 : "expected to be one URL.\n"
1428 : "\n"
1429 : "If --url is not given: To allow for multiple patterns (which are ORed)\n"
1430 : "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1431 : "obviously this requires that the usual escape quoting rules are applied.\n"
1432 : "\n"
1433 : "If --url is given no special escaping is required because URLs are\n"
1434 : "already escaped this way.\n"
1435 : "\n"
1436 : "If --single is given the first and only the first match will be\n"
1437 : "returned. If --cache-only is _not_ given, no local query will be\n"
1438 : "done.\n"
1439 : "\n"
1440 : "If --cache-only is given no external lookup is done so that only\n"
1441 : "certificates from the cache may get returned.";
1442 : static gpg_error_t
1443 0 : cmd_lookup (assuan_context_t ctx, char *line)
1444 : {
1445 : gpg_error_t err;
1446 : int lookup_url, single, cache_only;
1447 :
1448 0 : lookup_url = has_leading_option (line, "--url");
1449 0 : single = has_leading_option (line, "--single");
1450 0 : cache_only = has_leading_option (line, "--cache-only");
1451 0 : line = skip_options (line);
1452 :
1453 0 : if (lookup_url && cache_only)
1454 0 : err = gpg_error (GPG_ERR_NOT_FOUND);
1455 0 : else if (lookup_url && single)
1456 0 : err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1457 0 : else if (lookup_url)
1458 0 : err = lookup_cert_by_url (ctx, line);
1459 : else
1460 0 : err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1461 :
1462 0 : return leave_cmd (ctx, err);
1463 : }
1464 :
1465 :
1466 : static const char hlp_loadcrl[] =
1467 : "LOADCRL [--url] <filename|url>\n"
1468 : "\n"
1469 : "Load the CRL in the file with name FILENAME into our cache. Note\n"
1470 : "that FILENAME should be given with an absolute path because\n"
1471 : "Dirmngrs cwd is not known. With --url the CRL is directly loaded\n"
1472 : "from the given URL.\n"
1473 : "\n"
1474 : "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1475 : "--call-dirmngr loadcrl <filename>\". A direct invocation of Dirmngr\n"
1476 : "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1477 : "the CA's certificate.";
1478 : static gpg_error_t
1479 0 : cmd_loadcrl (assuan_context_t ctx, char *line)
1480 : {
1481 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1482 0 : gpg_error_t err = 0;
1483 0 : int use_url = has_leading_option (line, "--url");
1484 :
1485 0 : line = skip_options (line);
1486 :
1487 0 : if (use_url)
1488 : {
1489 : ksba_reader_t reader;
1490 :
1491 0 : err = crl_fetch (ctrl, line, &reader);
1492 0 : if (err)
1493 0 : log_error (_("fetching CRL from '%s' failed: %s\n"),
1494 : line, gpg_strerror (err));
1495 : else
1496 : {
1497 0 : err = crl_cache_insert (ctrl, line, reader);
1498 0 : if (err)
1499 0 : log_error (_("processing CRL from '%s' failed: %s\n"),
1500 : line, gpg_strerror (err));
1501 0 : crl_close_reader (reader);
1502 : }
1503 : }
1504 : else
1505 : {
1506 : char *buf;
1507 :
1508 0 : buf = xtrymalloc (strlen (line)+1);
1509 0 : if (!buf)
1510 0 : err = gpg_error_from_syserror ();
1511 : else
1512 : {
1513 0 : strcpy_escaped_plus (buf, line);
1514 0 : err = crl_cache_load (ctrl, buf);
1515 0 : xfree (buf);
1516 : }
1517 : }
1518 :
1519 0 : return leave_cmd (ctx, err);
1520 : }
1521 :
1522 :
1523 : static const char hlp_listcrls[] =
1524 : "LISTCRLS\n"
1525 : "\n"
1526 : "List the content of all CRLs in a readable format. This command is\n"
1527 : "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1528 : "listcrls\". It may also be used directly using \"dirmngr\n"
1529 : "--list-crls\".";
1530 : static gpg_error_t
1531 0 : cmd_listcrls (assuan_context_t ctx, char *line)
1532 : {
1533 : gpg_error_t err;
1534 : estream_t fp;
1535 :
1536 : (void)line;
1537 :
1538 0 : fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1539 0 : if (!fp)
1540 0 : err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1541 : else
1542 : {
1543 0 : err = crl_cache_list (fp);
1544 0 : es_fclose (fp);
1545 : }
1546 0 : return leave_cmd (ctx, err);
1547 : }
1548 :
1549 :
1550 : static const char hlp_cachecert[] =
1551 : "CACHECERT\n"
1552 : "\n"
1553 : "Put a certificate into the internal cache. This command might be\n"
1554 : "useful if a client knows in advance certificates required for a\n"
1555 : "test and wants to make sure they get added to the internal cache.\n"
1556 : "It is also helpful for debugging. To get the actual certificate,\n"
1557 : "this command immediately inquires it using\n"
1558 : "\n"
1559 : " INQUIRE TARGETCERT\n"
1560 : "\n"
1561 : "and the caller is expected to return the certificate for the\n"
1562 : "request as a binary blob.";
1563 : static gpg_error_t
1564 0 : cmd_cachecert (assuan_context_t ctx, char *line)
1565 : {
1566 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1567 : gpg_error_t err;
1568 0 : ksba_cert_t cert = NULL;
1569 0 : unsigned char *value = NULL;
1570 : size_t valuelen;
1571 :
1572 : (void)line;
1573 :
1574 0 : err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1575 : &value, &valuelen, MAX_CERT_LENGTH);
1576 0 : if (err)
1577 : {
1578 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1579 0 : goto leave;
1580 : }
1581 :
1582 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
1583 0 : err = gpg_error (GPG_ERR_MISSING_CERT);
1584 : else
1585 : {
1586 0 : err = ksba_cert_new (&cert);
1587 0 : if (!err)
1588 0 : err = ksba_cert_init_from_mem (cert, value, valuelen);
1589 : }
1590 0 : xfree (value);
1591 0 : if(err)
1592 0 : goto leave;
1593 :
1594 0 : err = cache_cert (cert);
1595 :
1596 : leave:
1597 0 : ksba_cert_release (cert);
1598 0 : return leave_cmd (ctx, err);
1599 : }
1600 :
1601 :
1602 : static const char hlp_validate[] =
1603 : "VALIDATE\n"
1604 : "\n"
1605 : "Validate a certificate using the certificate validation function\n"
1606 : "used internally by dirmngr. This command is only useful for\n"
1607 : "debugging. To get the actual certificate, this command immediately\n"
1608 : "inquires it using\n"
1609 : "\n"
1610 : " INQUIRE TARGETCERT\n"
1611 : "\n"
1612 : "and the caller is expected to return the certificate for the\n"
1613 : "request as a binary blob.";
1614 : static gpg_error_t
1615 0 : cmd_validate (assuan_context_t ctx, char *line)
1616 : {
1617 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1618 : gpg_error_t err;
1619 0 : ksba_cert_t cert = NULL;
1620 0 : unsigned char *value = NULL;
1621 : size_t valuelen;
1622 :
1623 : (void)line;
1624 :
1625 0 : err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1626 : &value, &valuelen, MAX_CERT_LENGTH);
1627 0 : if (err)
1628 : {
1629 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1630 0 : goto leave;
1631 : }
1632 :
1633 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
1634 0 : err = gpg_error (GPG_ERR_MISSING_CERT);
1635 : else
1636 : {
1637 0 : err = ksba_cert_new (&cert);
1638 0 : if (!err)
1639 0 : err = ksba_cert_init_from_mem (cert, value, valuelen);
1640 : }
1641 0 : xfree (value);
1642 0 : if(err)
1643 0 : goto leave;
1644 :
1645 : /* If we have this certificate already in our cache, use the cached
1646 : version for validation because this will take care of any cached
1647 : results. */
1648 : {
1649 : unsigned char fpr[20];
1650 : ksba_cert_t tmpcert;
1651 :
1652 0 : cert_compute_fpr (cert, fpr);
1653 0 : tmpcert = get_cert_byfpr (fpr);
1654 0 : if (tmpcert)
1655 : {
1656 0 : ksba_cert_release (cert);
1657 0 : cert = tmpcert;
1658 : }
1659 : }
1660 :
1661 0 : err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
1662 :
1663 : leave:
1664 0 : ksba_cert_release (cert);
1665 0 : return leave_cmd (ctx, err);
1666 : }
1667 :
1668 :
1669 :
1670 : /* Parse an keyserver URI and store it in a new uri item which is
1671 : returned at R_ITEM. On error return an error code. */
1672 : static gpg_error_t
1673 0 : make_keyserver_item (const char *uri, uri_item_t *r_item)
1674 : {
1675 : gpg_error_t err;
1676 : uri_item_t item;
1677 :
1678 0 : *r_item = NULL;
1679 0 : item = xtrymalloc (sizeof *item + strlen (uri));
1680 0 : if (!item)
1681 0 : return gpg_error_from_syserror ();
1682 :
1683 0 : item->next = NULL;
1684 0 : item->parsed_uri = NULL;
1685 0 : strcpy (item->uri, uri);
1686 :
1687 : #if USE_LDAP
1688 0 : if (ldap_uri_p (item->uri))
1689 0 : err = ldap_parse_uri (&item->parsed_uri, uri);
1690 : else
1691 : #endif
1692 : {
1693 0 : err = http_parse_uri (&item->parsed_uri, uri, 1);
1694 : }
1695 :
1696 0 : if (err)
1697 0 : xfree (item);
1698 : else
1699 0 : *r_item = item;
1700 0 : return err;
1701 : }
1702 :
1703 :
1704 : /* If no keyserver is stored in CTRL but a global keyserver has been
1705 : set, put that global keyserver into CTRL. We need use this
1706 : function to help migrate from the old gpg based keyserver
1707 : configuration to the new dirmngr based configuration. */
1708 : static gpg_error_t
1709 0 : ensure_keyserver (ctrl_t ctrl)
1710 : {
1711 : gpg_error_t err;
1712 : uri_item_t item;
1713 :
1714 0 : if (ctrl->server_local->keyservers)
1715 0 : return 0; /* Already set for this session. */
1716 0 : if (!opt.keyserver)
1717 0 : return 0; /* No global option set. */
1718 :
1719 0 : err = make_keyserver_item (opt.keyserver, &item);
1720 0 : if (!err)
1721 0 : ctrl->server_local->keyservers = item;
1722 :
1723 0 : return err;
1724 : }
1725 :
1726 :
1727 : static const char hlp_keyserver[] =
1728 : "KEYSERVER [<options>] [<uri>|<host>]\n"
1729 : "Options are:\n"
1730 : " --help\n"
1731 : " --clear Remove all configured keyservers\n"
1732 : " --resolve Resolve HKP host names and rotate\n"
1733 : " --hosttable Print table of known hosts and pools\n"
1734 : " --dead Mark <host> as dead\n"
1735 : " --alive Mark <host> as alive\n"
1736 : "\n"
1737 : "If called without arguments list all configured keyserver URLs.\n"
1738 : "If called with an URI add this as keyserver. Note that keyservers\n"
1739 : "are configured on a per-session base. A default keyserver may already be\n"
1740 : "present, thus the \"--clear\" option must be used to get full control.\n"
1741 : "If \"--clear\" and an URI are used together the clear command is\n"
1742 : "obviously executed first. A RESET command does not change the list\n"
1743 : "of configured keyservers.";
1744 : static gpg_error_t
1745 0 : cmd_keyserver (assuan_context_t ctx, char *line)
1746 : {
1747 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1748 0 : gpg_error_t err = 0;
1749 : int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
1750 : int dead_flag, alive_flag;
1751 0 : uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
1752 : is always initialized. */
1753 :
1754 0 : clear_flag = has_option (line, "--clear");
1755 0 : help_flag = has_option (line, "--help");
1756 0 : resolve_flag = has_option (line, "--resolve");
1757 0 : host_flag = has_option (line, "--hosttable");
1758 0 : dead_flag = has_option (line, "--dead");
1759 0 : alive_flag = has_option (line, "--alive");
1760 0 : line = skip_options (line);
1761 0 : add_flag = !!*line;
1762 :
1763 0 : if (help_flag)
1764 : {
1765 0 : err = ks_action_help (ctrl, line);
1766 0 : goto leave;
1767 : }
1768 :
1769 0 : if (resolve_flag)
1770 : {
1771 0 : err = ensure_keyserver (ctrl);
1772 0 : if (!err)
1773 0 : err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
1774 0 : if (err)
1775 0 : goto leave;
1776 : }
1777 :
1778 0 : if (alive_flag && dead_flag)
1779 : {
1780 0 : err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
1781 0 : goto leave;
1782 : }
1783 0 : if (dead_flag)
1784 : {
1785 0 : err = check_owner_permission (ctx, "no permission to use --dead");
1786 0 : if (err)
1787 0 : goto leave;
1788 : }
1789 0 : if (alive_flag || dead_flag)
1790 : {
1791 0 : if (!*line)
1792 : {
1793 0 : err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
1794 0 : goto leave;
1795 : }
1796 :
1797 0 : err = ks_hkp_mark_host (ctrl, line, alive_flag);
1798 0 : if (err)
1799 0 : goto leave;
1800 : }
1801 :
1802 0 : if (host_flag)
1803 : {
1804 0 : err = ks_hkp_print_hosttable (ctrl);
1805 0 : if (err)
1806 0 : goto leave;
1807 : }
1808 0 : if (resolve_flag || host_flag || alive_flag || dead_flag)
1809 : goto leave;
1810 :
1811 0 : if (add_flag)
1812 : {
1813 0 : err = make_keyserver_item (line, &item);
1814 0 : if (err)
1815 0 : goto leave;
1816 : }
1817 0 : if (clear_flag)
1818 0 : release_ctrl_keyservers (ctrl);
1819 0 : if (add_flag)
1820 : {
1821 0 : item->next = ctrl->server_local->keyservers;
1822 0 : ctrl->server_local->keyservers = item;
1823 : }
1824 :
1825 0 : if (!add_flag && !clear_flag && !help_flag)
1826 : {
1827 : /* List configured keyservers. However, we first add a global
1828 : keyserver. */
1829 : uri_item_t u;
1830 :
1831 0 : err = ensure_keyserver (ctrl);
1832 0 : if (err)
1833 : {
1834 0 : assuan_set_error (ctx, err,
1835 : "Bad keyserver configuration in dirmngr.conf");
1836 0 : goto leave;
1837 : }
1838 :
1839 0 : for (u=ctrl->server_local->keyservers; u; u = u->next)
1840 0 : dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
1841 : }
1842 0 : err = 0;
1843 :
1844 : leave:
1845 0 : return leave_cmd (ctx, err);
1846 : }
1847 :
1848 :
1849 :
1850 : static const char hlp_ks_search[] =
1851 : "KS_SEARCH {<pattern>}\n"
1852 : "\n"
1853 : "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
1854 : "for keys matching PATTERN";
1855 : static gpg_error_t
1856 0 : cmd_ks_search (assuan_context_t ctx, char *line)
1857 : {
1858 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1859 : gpg_error_t err;
1860 : strlist_t list, sl;
1861 : char *p;
1862 : estream_t outfp;
1863 :
1864 : /* No options for now. */
1865 0 : line = skip_options (line);
1866 :
1867 : /* Break the line down into an strlist. Each pattern is
1868 : percent-plus escaped. */
1869 0 : list = NULL;
1870 0 : for (p=line; *p; line = p)
1871 : {
1872 0 : while (*p && *p != ' ')
1873 0 : p++;
1874 0 : if (*p)
1875 0 : *p++ = 0;
1876 0 : if (*line)
1877 : {
1878 0 : sl = xtrymalloc (sizeof *sl + strlen (line));
1879 0 : if (!sl)
1880 : {
1881 0 : err = gpg_error_from_syserror ();
1882 0 : goto leave;
1883 : }
1884 0 : sl->flags = 0;
1885 0 : strcpy_escaped_plus (sl->d, line);
1886 0 : sl->next = list;
1887 0 : list = sl;
1888 : }
1889 : }
1890 :
1891 0 : err = ensure_keyserver (ctrl);
1892 0 : if (err)
1893 0 : goto leave;
1894 :
1895 : /* Setup an output stream and perform the search. */
1896 0 : outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1897 0 : if (!outfp)
1898 0 : err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1899 : else
1900 : {
1901 0 : err = ks_action_search (ctrl, ctrl->server_local->keyservers,
1902 : list, outfp);
1903 0 : es_fclose (outfp);
1904 : }
1905 :
1906 : leave:
1907 0 : free_strlist (list);
1908 0 : return leave_cmd (ctx, err);
1909 : }
1910 :
1911 :
1912 :
1913 : static const char hlp_ks_get[] =
1914 : "KS_GET {<pattern>}\n"
1915 : "\n"
1916 : "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
1917 : "(see command KEYSERVER). Each pattern should be a keyid, a fingerprint,\n"
1918 : "or an exact name indicated by the '=' prefix.";
1919 : static gpg_error_t
1920 0 : cmd_ks_get (assuan_context_t ctx, char *line)
1921 : {
1922 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1923 : gpg_error_t err;
1924 : strlist_t list, sl;
1925 : char *p;
1926 : estream_t outfp;
1927 :
1928 : /* No options for now. */
1929 0 : line = skip_options (line);
1930 :
1931 : /* Break the line into a strlist. Each pattern is by
1932 : definition percent-plus escaped. However we only support keyids
1933 : and fingerprints and thus the client has no need to apply the
1934 : escaping. */
1935 0 : list = NULL;
1936 0 : for (p=line; *p; line = p)
1937 : {
1938 0 : while (*p && *p != ' ')
1939 0 : p++;
1940 0 : if (*p)
1941 0 : *p++ = 0;
1942 0 : if (*line)
1943 : {
1944 0 : sl = xtrymalloc (sizeof *sl + strlen (line));
1945 0 : if (!sl)
1946 : {
1947 0 : err = gpg_error_from_syserror ();
1948 0 : goto leave;
1949 : }
1950 0 : sl->flags = 0;
1951 0 : strcpy_escaped_plus (sl->d, line);
1952 0 : sl->next = list;
1953 0 : list = sl;
1954 : }
1955 : }
1956 :
1957 0 : err = ensure_keyserver (ctrl);
1958 0 : if (err)
1959 0 : goto leave;
1960 :
1961 : /* Setup an output stream and perform the get. */
1962 0 : outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1963 0 : if (!outfp)
1964 0 : err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1965 : else
1966 : {
1967 0 : err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
1968 0 : es_fclose (outfp);
1969 : }
1970 :
1971 : leave:
1972 0 : free_strlist (list);
1973 0 : return leave_cmd (ctx, err);
1974 : }
1975 :
1976 :
1977 : static const char hlp_ks_fetch[] =
1978 : "KS_FETCH <URL>\n"
1979 : "\n"
1980 : "Get the key(s) from URL.";
1981 : static gpg_error_t
1982 0 : cmd_ks_fetch (assuan_context_t ctx, char *line)
1983 : {
1984 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
1985 : gpg_error_t err;
1986 : estream_t outfp;
1987 :
1988 : /* No options for now. */
1989 0 : line = skip_options (line);
1990 :
1991 0 : err = ensure_keyserver (ctrl);
1992 0 : if (err)
1993 0 : goto leave;
1994 :
1995 : /* Setup an output stream and perform the get. */
1996 0 : outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1997 0 : if (!outfp)
1998 0 : err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1999 : else
2000 : {
2001 0 : err = ks_action_fetch (ctrl, line, outfp);
2002 0 : es_fclose (outfp);
2003 : }
2004 :
2005 : leave:
2006 0 : return leave_cmd (ctx, err);
2007 : }
2008 :
2009 :
2010 :
2011 : static const char hlp_ks_put[] =
2012 : "KS_PUT\n"
2013 : "\n"
2014 : "Send a key to the configured OpenPGP keyservers. The actual key material\n"
2015 : "is then requested by Dirmngr using\n"
2016 : "\n"
2017 : " INQUIRE KEYBLOCK\n"
2018 : "\n"
2019 : "The client shall respond with a binary version of the keyblock (e.g.,\n"
2020 : "the output of `gpg --export KEYID'). For LDAP\n"
2021 : "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
2022 : "using:\n"
2023 : "\n"
2024 : " INQUIRE KEYBLOCK_INFO\n"
2025 : "\n"
2026 : "The client shall respond with a colon delimited info lines (the output\n"
2027 : "of 'for x in keys sigs; do gpg --list-$x --with-colons KEYID; done').\n";
2028 : static gpg_error_t
2029 0 : cmd_ks_put (assuan_context_t ctx, char *line)
2030 : {
2031 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
2032 : gpg_error_t err;
2033 0 : unsigned char *value = NULL;
2034 : size_t valuelen;
2035 0 : unsigned char *info = NULL;
2036 : size_t infolen;
2037 :
2038 : /* No options for now. */
2039 0 : line = skip_options (line);
2040 :
2041 0 : err = ensure_keyserver (ctrl);
2042 0 : if (err)
2043 0 : goto leave;
2044 :
2045 : /* Ask for the key material. */
2046 0 : err = assuan_inquire (ctx, "KEYBLOCK",
2047 : &value, &valuelen, MAX_KEYBLOCK_LENGTH);
2048 0 : if (err)
2049 : {
2050 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2051 0 : goto leave;
2052 : }
2053 :
2054 0 : if (!valuelen) /* No data returned; return a comprehensible error. */
2055 : {
2056 0 : err = gpg_error (GPG_ERR_MISSING_CERT);
2057 0 : goto leave;
2058 : }
2059 :
2060 : /* Ask for the key meta data. Not actually needed for HKP servers
2061 : but we do it anyway to test the client implementaion. */
2062 0 : err = assuan_inquire (ctx, "KEYBLOCK_INFO",
2063 : &info, &infolen, MAX_KEYBLOCK_LENGTH);
2064 0 : if (err)
2065 : {
2066 0 : log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2067 0 : goto leave;
2068 : }
2069 :
2070 : /* Send the key. */
2071 0 : err = ks_action_put (ctrl, ctrl->server_local->keyservers,
2072 : value, valuelen, info, infolen);
2073 :
2074 : leave:
2075 0 : xfree (info);
2076 0 : xfree (value);
2077 0 : return leave_cmd (ctx, err);
2078 : }
2079 :
2080 :
2081 :
2082 :
2083 : static const char hlp_getinfo[] =
2084 : "GETINFO <what>\n"
2085 : "\n"
2086 : "Multi purpose command to return certain information. \n"
2087 : "Supported values of WHAT are:\n"
2088 : "\n"
2089 : "version - Return the version of the program.\n"
2090 : "pid - Return the process id of the server.\n"
2091 : "tor - Return OK if running in Tor mode\n"
2092 : "socket_name - Return the name of the socket.\n";
2093 : static gpg_error_t
2094 0 : cmd_getinfo (assuan_context_t ctx, char *line)
2095 : {
2096 : gpg_error_t err;
2097 :
2098 0 : if (!strcmp (line, "version"))
2099 : {
2100 0 : const char *s = VERSION;
2101 0 : err = assuan_send_data (ctx, s, strlen (s));
2102 : }
2103 0 : else if (!strcmp (line, "pid"))
2104 : {
2105 : char numbuf[50];
2106 :
2107 0 : snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
2108 0 : err = assuan_send_data (ctx, numbuf, strlen (numbuf));
2109 : }
2110 0 : else if (!strcmp (line, "socket_name"))
2111 : {
2112 0 : const char *s = dirmngr_user_socket_name ();
2113 :
2114 0 : if (!s)
2115 0 : s = dirmngr_sys_socket_name ();
2116 :
2117 0 : if (s)
2118 0 : err = assuan_send_data (ctx, s, strlen (s));
2119 : else
2120 0 : err = gpg_error (GPG_ERR_NO_DATA);
2121 : }
2122 0 : else if (!strcmp (line, "tor"))
2123 : {
2124 0 : err = opt.use_tor? 0:set_error (GPG_ERR_GENERAL, "Tor mode not enabled");
2125 : }
2126 : else
2127 0 : err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
2128 :
2129 0 : return leave_cmd (ctx, err);
2130 : }
2131 :
2132 :
2133 :
2134 : static const char hlp_killdirmngr[] =
2135 : "KILLDIRMNGR\n"
2136 : "\n"
2137 : "This command allows a user - given sufficient permissions -\n"
2138 : "to kill this dirmngr process.\n";
2139 : static gpg_error_t
2140 0 : cmd_killdirmngr (assuan_context_t ctx, char *line)
2141 : {
2142 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
2143 : gpg_error_t err;
2144 :
2145 : (void)line;
2146 :
2147 0 : if (opt.system_daemon)
2148 : {
2149 0 : if (opt.system_service)
2150 0 : err = set_error (GPG_ERR_NOT_SUPPORTED,
2151 : "can't do that whilst running as system service");
2152 : else
2153 0 : err = check_owner_permission (ctx,
2154 : "no permission to kill this process");
2155 : }
2156 : else
2157 0 : err = 0;
2158 :
2159 0 : if (!err)
2160 : {
2161 0 : ctrl->server_local->stopme = 1;
2162 0 : assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
2163 0 : err = gpg_error (GPG_ERR_EOF);
2164 : }
2165 0 : return err;
2166 : }
2167 :
2168 :
2169 : static const char hlp_reloaddirmngr[] =
2170 : "RELOADDIRMNGR\n"
2171 : "\n"
2172 : "This command is an alternative to SIGHUP\n"
2173 : "to reload the configuration.";
2174 : static gpg_error_t
2175 0 : cmd_reloaddirmngr (assuan_context_t ctx, char *line)
2176 : {
2177 : (void)ctx;
2178 : (void)line;
2179 :
2180 0 : if (opt.system_daemon)
2181 : {
2182 : #ifndef HAVE_W32_SYSTEM
2183 : {
2184 : gpg_error_t err;
2185 :
2186 0 : err = check_owner_permission (ctx,
2187 : "no permission to reload this process");
2188 0 : if (err)
2189 0 : return err;
2190 : }
2191 : #endif
2192 : }
2193 :
2194 0 : dirmngr_sighup_action ();
2195 0 : return 0;
2196 : }
2197 :
2198 :
2199 :
2200 :
2201 : /* Tell the assuan library about our commands. */
2202 : static int
2203 0 : register_commands (assuan_context_t ctx)
2204 : {
2205 : static struct {
2206 : const char *name;
2207 : assuan_handler_t handler;
2208 : const char * const help;
2209 : } table[] = {
2210 : { "DNS_CERT", cmd_dns_cert, hlp_dns_cert },
2211 : { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
2212 : { "ISVALID", cmd_isvalid, hlp_isvalid },
2213 : { "CHECKCRL", cmd_checkcrl, hlp_checkcrl },
2214 : { "CHECKOCSP", cmd_checkocsp, hlp_checkocsp },
2215 : { "LOOKUP", cmd_lookup, hlp_lookup },
2216 : { "LOADCRL", cmd_loadcrl, hlp_loadcrl },
2217 : { "LISTCRLS", cmd_listcrls, hlp_listcrls },
2218 : { "CACHECERT", cmd_cachecert, hlp_cachecert },
2219 : { "VALIDATE", cmd_validate, hlp_validate },
2220 : { "KEYSERVER", cmd_keyserver, hlp_keyserver },
2221 : { "KS_SEARCH", cmd_ks_search, hlp_ks_search },
2222 : { "KS_GET", cmd_ks_get, hlp_ks_get },
2223 : { "KS_FETCH", cmd_ks_fetch, hlp_ks_fetch },
2224 : { "KS_PUT", cmd_ks_put, hlp_ks_put },
2225 : { "GETINFO", cmd_getinfo, hlp_getinfo },
2226 : { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
2227 : { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
2228 : { NULL, NULL }
2229 : };
2230 : int i, j, rc;
2231 :
2232 0 : for (i=j=0; table[i].name; i++)
2233 : {
2234 0 : rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2235 : table[i].help);
2236 0 : if (rc)
2237 0 : return rc;
2238 : }
2239 0 : return 0;
2240 : }
2241 :
2242 :
2243 : /* Note that we do not reset the list of configured keyservers. */
2244 : static gpg_error_t
2245 0 : reset_notify (assuan_context_t ctx, char *line)
2246 : {
2247 0 : ctrl_t ctrl = assuan_get_pointer (ctx);
2248 : (void)line;
2249 :
2250 : #if USE_LDAP
2251 0 : ldapserver_list_free (ctrl->server_local->ldapservers);
2252 : #endif /*USE_LDAP*/
2253 0 : ctrl->server_local->ldapservers = NULL;
2254 0 : return 0;
2255 : }
2256 :
2257 :
2258 : /* Startup the server and run the main command loop. With FD = -1,
2259 : use stdin/stdout. */
2260 : void
2261 0 : start_command_handler (assuan_fd_t fd)
2262 : {
2263 : static const char hello[] = "Dirmngr " VERSION " at your service";
2264 : static char *hello_line;
2265 : int rc;
2266 : assuan_context_t ctx;
2267 : ctrl_t ctrl;
2268 :
2269 0 : ctrl = xtrycalloc (1, sizeof *ctrl);
2270 0 : if (ctrl)
2271 0 : ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
2272 0 : if (!ctrl || !ctrl->server_local)
2273 : {
2274 0 : log_error (_("can't allocate control structure: %s\n"),
2275 0 : strerror (errno));
2276 0 : xfree (ctrl);
2277 0 : return;
2278 : }
2279 :
2280 0 : dirmngr_init_default_ctrl (ctrl);
2281 :
2282 0 : rc = assuan_new (&ctx);
2283 0 : if (rc)
2284 : {
2285 0 : log_error (_("failed to allocate assuan context: %s\n"),
2286 : gpg_strerror (rc));
2287 0 : dirmngr_exit (2);
2288 : }
2289 :
2290 0 : if (fd == ASSUAN_INVALID_FD)
2291 : {
2292 : assuan_fd_t filedes[2];
2293 :
2294 0 : filedes[0] = assuan_fdopen (0);
2295 0 : filedes[1] = assuan_fdopen (1);
2296 0 : rc = assuan_init_pipe_server (ctx, filedes);
2297 : }
2298 : else
2299 : {
2300 0 : rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
2301 : }
2302 :
2303 0 : if (rc)
2304 : {
2305 0 : assuan_release (ctx);
2306 0 : log_error (_("failed to initialize the server: %s\n"),
2307 : gpg_strerror(rc));
2308 0 : dirmngr_exit (2);
2309 : }
2310 :
2311 0 : rc = register_commands (ctx);
2312 0 : if (rc)
2313 : {
2314 0 : log_error (_("failed to the register commands with Assuan: %s\n"),
2315 : gpg_strerror(rc));
2316 0 : dirmngr_exit (2);
2317 : }
2318 :
2319 :
2320 0 : if (!hello_line)
2321 : {
2322 : size_t n;
2323 : const char *cfgname;
2324 :
2325 0 : cfgname = opt.config_filename? opt.config_filename : "[none]";
2326 :
2327 0 : n = (30 + strlen (opt.homedir) + strlen (cfgname)
2328 : + strlen (hello) + 1);
2329 0 : hello_line = xmalloc (n+1);
2330 0 : snprintf (hello_line, n,
2331 : "Home: %s\n"
2332 : "Config: %s\n"
2333 : "%s",
2334 : opt.homedir,
2335 : cfgname,
2336 : hello);
2337 0 : hello_line[n] = 0;
2338 : }
2339 :
2340 0 : ctrl->server_local->assuan_ctx = ctx;
2341 0 : assuan_set_pointer (ctx, ctrl);
2342 :
2343 0 : assuan_set_hello_line (ctx, hello_line);
2344 0 : assuan_register_option_handler (ctx, option_handler);
2345 0 : assuan_register_reset_notify (ctx, reset_notify);
2346 :
2347 : for (;;)
2348 : {
2349 0 : rc = assuan_accept (ctx);
2350 0 : if (rc == -1)
2351 0 : break;
2352 0 : if (rc)
2353 : {
2354 0 : log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
2355 0 : break;
2356 : }
2357 :
2358 : #ifndef HAVE_W32_SYSTEM
2359 0 : if (opt.verbose)
2360 : {
2361 : assuan_peercred_t peercred;
2362 :
2363 0 : if (!assuan_get_peercred (ctx, &peercred))
2364 0 : log_info ("connection from process %ld (%ld:%ld)\n",
2365 0 : (long)peercred->pid, (long)peercred->uid,
2366 0 : (long)peercred->gid);
2367 : }
2368 : #endif
2369 :
2370 0 : rc = assuan_process (ctx);
2371 0 : if (rc)
2372 : {
2373 0 : log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
2374 0 : continue;
2375 : }
2376 0 : }
2377 :
2378 : #if USE_LDAP
2379 0 : ldap_wrapper_connection_cleanup (ctrl);
2380 :
2381 0 : ldapserver_list_free (ctrl->server_local->ldapservers);
2382 : #endif /*USE_LDAP*/
2383 0 : ctrl->server_local->ldapservers = NULL;
2384 :
2385 0 : ctrl->server_local->assuan_ctx = NULL;
2386 0 : assuan_release (ctx);
2387 :
2388 0 : if (ctrl->server_local->stopme)
2389 0 : dirmngr_exit (0);
2390 :
2391 0 : if (ctrl->refcount)
2392 0 : log_error ("oops: connection control structure still referenced (%d)\n",
2393 : ctrl->refcount);
2394 : else
2395 : {
2396 0 : release_ctrl_ocsp_certs (ctrl);
2397 0 : xfree (ctrl->server_local);
2398 0 : dirmngr_deinit_default_ctrl (ctrl);
2399 0 : xfree (ctrl);
2400 : }
2401 : }
2402 :
2403 :
2404 : /* Send a status line back to the client. KEYWORD is the status
2405 : keyword, the optional string arguments are blank separated added to
2406 : the line, the last argument must be a NULL. */
2407 : gpg_error_t
2408 0 : dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
2409 : {
2410 0 : gpg_error_t err = 0;
2411 : va_list arg_ptr;
2412 : const char *text;
2413 :
2414 0 : va_start (arg_ptr, keyword);
2415 :
2416 0 : if (ctrl->server_local)
2417 : {
2418 0 : assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2419 : char buf[950], *p;
2420 : size_t n;
2421 :
2422 0 : p = buf;
2423 0 : n = 0;
2424 0 : while ( (text = va_arg (arg_ptr, const char *)) )
2425 : {
2426 0 : if (n)
2427 : {
2428 0 : *p++ = ' ';
2429 0 : n++;
2430 : }
2431 0 : for ( ; *text && n < DIM (buf)-2; n++)
2432 0 : *p++ = *text++;
2433 : }
2434 0 : *p = 0;
2435 0 : err = assuan_write_status (ctx, keyword, buf);
2436 : }
2437 :
2438 0 : va_end (arg_ptr);
2439 0 : return err;
2440 : }
2441 :
2442 :
2443 : /* Print a help status line. TEXTLEN gives the length of the text
2444 : from TEXT to be printed. The function splits text at LFs. */
2445 : gpg_error_t
2446 0 : dirmngr_status_help (ctrl_t ctrl, const char *text)
2447 : {
2448 0 : gpg_error_t err = 0;
2449 :
2450 0 : if (ctrl->server_local)
2451 : {
2452 0 : assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2453 : char buf[950], *p;
2454 : size_t n;
2455 :
2456 : do
2457 : {
2458 0 : p = buf;
2459 0 : n = 0;
2460 0 : for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
2461 0 : *p++ = *text++;
2462 0 : if (*text == '\n')
2463 0 : text++;
2464 0 : *p = 0;
2465 0 : err = assuan_write_status (ctx, "#", buf);
2466 : }
2467 0 : while (!err && *text);
2468 : }
2469 :
2470 0 : return err;
2471 : }
2472 :
2473 : /* Send a tick progress indicator back. Fixme: This is only done for
2474 : the currently active channel. */
2475 : gpg_error_t
2476 0 : dirmngr_tick (ctrl_t ctrl)
2477 : {
2478 : static time_t next_tick = 0;
2479 0 : gpg_error_t err = 0;
2480 0 : time_t now = time (NULL);
2481 :
2482 0 : if (!next_tick)
2483 : {
2484 0 : next_tick = now + 1;
2485 : }
2486 0 : else if ( now > next_tick )
2487 : {
2488 0 : if (ctrl)
2489 : {
2490 0 : err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
2491 0 : if (err)
2492 : {
2493 : /* Take this as in indication for a cancel request. */
2494 0 : err = gpg_error (GPG_ERR_CANCELED);
2495 : }
2496 0 : now = time (NULL);
2497 : }
2498 :
2499 0 : next_tick = now + 1;
2500 : }
2501 0 : return err;
2502 : }
|