Line data Source code
1 : /* call-dirmngr.c - GPG operations to the Dirmngr.
2 : * Copyright (C) 2011 Free Software Foundation, Inc.
3 : * Copyright (C) 2015 g10 Code GmbH
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #include <unistd.h>
27 : #include <time.h>
28 : #ifdef HAVE_LOCALE_H
29 : # include <locale.h>
30 : #endif
31 :
32 : #include "gpg.h"
33 : #include <assuan.h>
34 : #include "util.h"
35 : #include "membuf.h"
36 : #include "options.h"
37 : #include "i18n.h"
38 : #include "asshelp.h"
39 : #include "keyserver.h"
40 : #include "status.h"
41 : #include "call-dirmngr.h"
42 :
43 :
44 : /* Parameter structure used to gather status info. */
45 : struct ks_status_parm_s
46 : {
47 : const char *keyword; /* Look for this keyword or NULL for "SOURCE". */
48 : char *source;
49 : };
50 :
51 :
52 : /* Parameter structure used with the KS_SEARCH command. */
53 : struct ks_search_parm_s
54 : {
55 : gpg_error_t lasterr; /* Last error code. */
56 : membuf_t saveddata; /* Buffer to build complete lines. */
57 : char *helpbuf; /* NULL or malloced buffer. */
58 : size_t helpbufsize; /* Allocated size of HELPBUF. */
59 : gpg_error_t (*data_cb)(void*, int, char*); /* Callback. */
60 : void *data_cb_value; /* First argument for DATA_CB. */
61 : struct ks_status_parm_s *stparm; /* Link to the status parameter. */
62 : };
63 :
64 :
65 : /* Parameter structure used with the KS_GET command. */
66 : struct ks_get_parm_s
67 : {
68 : estream_t memfp;
69 : };
70 :
71 :
72 : /* Parameter structure used with the KS_PUT command. */
73 : struct ks_put_parm_s
74 : {
75 : assuan_context_t ctx;
76 : kbnode_t keyblock; /* The optional keyblock. */
77 : const void *data; /* The key in OpenPGP binary format. */
78 : size_t datalen; /* The length of DATA. */
79 : };
80 :
81 :
82 : /* Parameter structure used with the DNS_CERT command. */
83 : struct dns_cert_parm_s
84 : {
85 : estream_t memfp;
86 : unsigned char *fpr;
87 : size_t fprlen;
88 : char *url;
89 : };
90 :
91 :
92 : /* Data used to associate an session with dirmngr contexts. We can't
93 : use a simple one to one mapping because we sometimes need two
94 : connections to the dirmngr; for example while doing a listing and
95 : being in a data callback we may want to retrieve a key. The local
96 : dirmngr data takes care of this. At the end of the session the
97 : function dirmngr_deinit_session_data is called by gpg.c to cleanup
98 : these resources. Note that gpg.h defines a typedef dirmngr_local_t
99 : for this structure. */
100 : struct dirmngr_local_s
101 : {
102 : /* Link to other contexts which are used simultaneously. */
103 : struct dirmngr_local_s *next;
104 :
105 : /* The active Assuan context. */
106 : assuan_context_t ctx;
107 :
108 : /* Flag set when the keyserver names have been send. */
109 : int set_keyservers_done;
110 :
111 : /* Flag set to true while an operation is running on CTX. */
112 : int is_active;
113 : };
114 :
115 :
116 :
117 : /* Deinitialize all session data of dirmngr pertaining to CTRL. */
118 : void
119 1177 : gpg_dirmngr_deinit_session_data (ctrl_t ctrl)
120 : {
121 : dirmngr_local_t dml;
122 :
123 2354 : while ((dml = ctrl->dirmngr_local))
124 : {
125 0 : ctrl->dirmngr_local = dml->next;
126 0 : if (dml->is_active)
127 0 : log_error ("oops: trying to cleanup an active dirmngr context\n");
128 : else
129 0 : assuan_release (dml->ctx);
130 0 : xfree (dml);
131 : }
132 1177 : }
133 :
134 :
135 : /* Print a warning if the server's version number is less than our
136 : version number. Returns an error code on a connection problem. */
137 : static gpg_error_t
138 0 : warn_version_mismatch (assuan_context_t ctx, const char *servername)
139 : {
140 : gpg_error_t err;
141 : char *serverversion;
142 0 : const char *myversion = strusage (13);
143 :
144 0 : err = get_assuan_server_version (ctx, 0, &serverversion);
145 0 : if (err)
146 0 : log_error (_("error getting version from '%s': %s\n"),
147 : servername, gpg_strerror (err));
148 0 : else if (compare_version_strings (serverversion, myversion) < 0)
149 : {
150 : char *warn;
151 :
152 0 : warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
153 : servername, serverversion, myversion);
154 0 : if (!warn)
155 0 : err = gpg_error_from_syserror ();
156 : else
157 : {
158 0 : log_info (_("WARNING: %s\n"), warn);
159 0 : write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
160 : " ", warn, NULL);
161 0 : xfree (warn);
162 : }
163 : }
164 0 : xfree (serverversion);
165 0 : return err;
166 : }
167 :
168 :
169 : /* Try to connect to the Dirmngr via a socket or spawn it if possible.
170 : Handle the server's initial greeting and set global options. */
171 : static gpg_error_t
172 0 : create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
173 : {
174 : gpg_error_t err;
175 : assuan_context_t ctx;
176 :
177 0 : *r_ctx = NULL;
178 0 : err = start_new_dirmngr (&ctx,
179 : GPG_ERR_SOURCE_DEFAULT,
180 : opt.dirmngr_program,
181 0 : opt.autostart, opt.verbose, DBG_IPC,
182 : NULL /*gpg_status2*/, ctrl);
183 0 : if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
184 0 : {
185 : static int shown;
186 :
187 0 : if (!shown)
188 : {
189 0 : shown = 1;
190 0 : log_info (_("no dirmngr running in this session\n"));
191 : }
192 : }
193 0 : else if (!err && !(err = warn_version_mismatch (ctx, DIRMNGR_NAME)))
194 : {
195 : char *line;
196 :
197 : /* Tell the dirmngr that we want to collect audit event. */
198 : /* err = assuan_transact (agent_ctx, "OPTION audit-events=1", */
199 : /* NULL, NULL, NULL, NULL, NULL, NULL); */
200 0 : if (opt.keyserver_options.http_proxy)
201 : {
202 0 : line = xtryasprintf ("OPTION http-proxy=%s",
203 : opt.keyserver_options.http_proxy);
204 0 : if (!line)
205 0 : err = gpg_error_from_syserror ();
206 : else
207 : {
208 0 : err = assuan_transact (ctx, line, NULL, NULL, NULL,
209 : NULL, NULL, NULL);
210 0 : xfree (line);
211 : }
212 : }
213 :
214 0 : if (err)
215 : ;
216 0 : else if ((opt.keyserver_options.options & KEYSERVER_HONOR_KEYSERVER_URL))
217 : {
218 : /* Tell the dirmngr that this possibly privacy invading
219 : option is in use. If Dirmngr is running in Tor mode, it
220 : will return an error. */
221 0 : err = assuan_transact (ctx, "OPTION honor-keyserver-url-used",
222 : NULL, NULL, NULL, NULL, NULL, NULL);
223 0 : if (gpg_err_code (err) == GPG_ERR_FORBIDDEN)
224 0 : log_error (_("keyserver option \"honor-keyserver-url\""
225 : " may not be used in Tor mode\n"));
226 0 : else if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
227 0 : err = 0; /* Old dirmngr versions do not support this option. */
228 : }
229 : }
230 :
231 0 : if (err)
232 0 : assuan_release (ctx);
233 : else
234 : {
235 : /* audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err); */
236 0 : *r_ctx = ctx;
237 : }
238 :
239 0 : return err;
240 : }
241 :
242 :
243 : /* Get a context for accessing dirmngr. If no context is available a
244 : new one is created and - if required - dirmngr started. On success
245 : an assuan context is stored at R_CTX. This context may only be
246 : released by means of close_context. Note that NULL is stored at
247 : R_CTX on error. */
248 : static gpg_error_t
249 0 : open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
250 : {
251 : gpg_error_t err;
252 : dirmngr_local_t dml;
253 :
254 0 : *r_ctx = NULL;
255 : for (;;)
256 : {
257 0 : for (dml = ctrl->dirmngr_local; dml && dml->is_active; dml = dml->next)
258 : ;
259 0 : if (dml)
260 : {
261 : /* Found an inactive local session - return that. */
262 0 : log_assert (!dml->is_active);
263 :
264 : /* But first do the per session init if not yet done. */
265 0 : if (!dml->set_keyservers_done)
266 : {
267 : keyserver_spec_t ksi;
268 :
269 : /* Set all configured keyservers. We clear existing
270 : keyservers so that any keyserver configured in GPG
271 : overrides keyservers possibly still configured in Dirmngr
272 : for the session (Note that the keyserver list of a
273 : session in Dirmngr survives a RESET. */
274 0 : for (ksi = opt.keyserver; ksi; ksi = ksi->next)
275 : {
276 : char *line;
277 :
278 0 : line = xtryasprintf
279 : ("KEYSERVER%s %s",
280 0 : ksi == opt.keyserver? " --clear":"", ksi->uri);
281 0 : if (!line)
282 0 : err = gpg_error_from_syserror ();
283 : else
284 : {
285 0 : err = assuan_transact (dml->ctx, line, NULL, NULL, NULL,
286 : NULL, NULL, NULL);
287 0 : xfree (line);
288 : }
289 :
290 0 : if (err)
291 0 : return err;
292 : }
293 :
294 0 : dml->set_keyservers_done = 1;
295 : }
296 :
297 0 : dml->is_active = 1;
298 :
299 0 : *r_ctx = dml->ctx;
300 0 : return 0;
301 : }
302 :
303 0 : dml = xtrycalloc (1, sizeof *dml);
304 0 : if (!dml)
305 0 : return gpg_error_from_syserror ();
306 0 : err = create_context (ctrl, &dml->ctx);
307 0 : if (err)
308 : {
309 0 : xfree (dml);
310 0 : return err;
311 : }
312 :
313 : /* To be on the nPth thread safe site we need to add it to a
314 : list; this is far easier than to have a lock for this
315 : function. It should not happen anyway but the code is free
316 : because we need it for the is_active check above. */
317 0 : dml->next = ctrl->dirmngr_local;
318 0 : ctrl->dirmngr_local = dml;
319 0 : }
320 : }
321 :
322 :
323 : /* Close the assuan context CTX or return it to a pool of unused
324 : contexts. If CTX is NULL, the function does nothing. */
325 : static void
326 0 : close_context (ctrl_t ctrl, assuan_context_t ctx)
327 : {
328 : dirmngr_local_t dml;
329 :
330 0 : if (!ctx)
331 0 : return;
332 :
333 0 : for (dml = ctrl->dirmngr_local; dml; dml = dml->next)
334 : {
335 0 : if (dml->ctx == ctx)
336 : {
337 0 : if (!dml->is_active)
338 0 : log_fatal ("closing inactive dirmngr context %p\n", ctx);
339 0 : dml->is_active = 0;
340 0 : return;
341 : }
342 : }
343 0 : log_fatal ("closing unknown dirmngr ctx %p\n", ctx);
344 : }
345 :
346 :
347 : /* Clear the set_keyservers_done flag on context CTX. */
348 : static void
349 0 : clear_context_flags (ctrl_t ctrl, assuan_context_t ctx)
350 : {
351 : dirmngr_local_t dml;
352 :
353 0 : if (!ctx)
354 0 : return;
355 :
356 0 : for (dml = ctrl->dirmngr_local; dml; dml = dml->next)
357 : {
358 0 : if (dml->ctx == ctx)
359 : {
360 0 : if (!dml->is_active)
361 0 : log_fatal ("clear_context_flags on inactive dirmngr ctx %p\n", ctx);
362 0 : dml->set_keyservers_done = 0;
363 0 : return;
364 : }
365 : }
366 0 : log_fatal ("clear_context_flags on unknown dirmngr ctx %p\n", ctx);
367 : }
368 :
369 :
370 :
371 : /* Status callback for ks_list, ks_get and ks_search. */
372 : static gpg_error_t
373 0 : ks_status_cb (void *opaque, const char *line)
374 : {
375 0 : struct ks_status_parm_s *parm = opaque;
376 0 : gpg_error_t err = 0;
377 : const char *s;
378 :
379 0 : if ((s = has_leading_keyword (line, parm->keyword? parm->keyword : "SOURCE")))
380 : {
381 0 : if (!parm->source)
382 : {
383 0 : parm->source = xtrystrdup (s);
384 0 : if (!parm->source)
385 0 : err = gpg_error_from_syserror ();
386 : }
387 : }
388 :
389 0 : return err;
390 : }
391 :
392 :
393 :
394 : /* Run the "KEYSERVER" command to return the name of the used
395 : keyserver at R_KEYSERVER. */
396 : gpg_error_t
397 0 : gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver)
398 : {
399 : gpg_error_t err;
400 : assuan_context_t ctx;
401 : struct ks_status_parm_s stparm;
402 :
403 0 : memset (&stparm, 0, sizeof stparm);
404 0 : stparm.keyword = "KEYSERVER";
405 0 : if (r_keyserver)
406 0 : *r_keyserver = NULL;
407 :
408 0 : err = open_context (ctrl, &ctx);
409 0 : if (err)
410 0 : return err;
411 :
412 0 : err = assuan_transact (ctx, "KEYSERVER", NULL, NULL,
413 : NULL, NULL, ks_status_cb, &stparm);
414 0 : if (err)
415 0 : goto leave;
416 0 : if (!stparm.source)
417 : {
418 0 : err = gpg_error (GPG_ERR_NO_KEYSERVER);
419 0 : goto leave;
420 : }
421 :
422 0 : if (r_keyserver)
423 0 : *r_keyserver = stparm.source;
424 : else
425 0 : xfree (stparm.source);
426 0 : stparm.source = NULL;
427 :
428 : leave:
429 0 : xfree (stparm.source);
430 0 : close_context (ctrl, ctx);
431 0 : return err;
432 : }
433 :
434 :
435 :
436 : /* Data callback for the KS_SEARCH command. */
437 : static gpg_error_t
438 0 : ks_search_data_cb (void *opaque, const void *data, size_t datalen)
439 : {
440 0 : gpg_error_t err = 0;
441 0 : struct ks_search_parm_s *parm = opaque;
442 : const char *line, *s;
443 : size_t rawlen, linelen;
444 : char fixedbuf[256];
445 :
446 0 : if (parm->lasterr)
447 0 : return 0;
448 :
449 0 : if (parm->stparm->source)
450 : {
451 0 : err = parm->data_cb (parm->data_cb_value, 1, parm->stparm->source);
452 0 : if (err)
453 : {
454 0 : parm->lasterr = err;
455 0 : return err;
456 : }
457 : /* Clear it so that we won't get back here unless the server
458 : accidentally sends a second source status line. Note that
459 : will not see all accidentally sent source lines because it
460 : depends on whether data lines have been send in between. */
461 0 : xfree (parm->stparm->source);
462 0 : parm->stparm->source = NULL;
463 : }
464 :
465 0 : if (!data)
466 0 : return 0; /* Ignore END commands. */
467 :
468 0 : put_membuf (&parm->saveddata, data, datalen);
469 :
470 : again:
471 0 : line = peek_membuf (&parm->saveddata, &rawlen);
472 0 : if (!line)
473 : {
474 0 : parm->lasterr = gpg_error_from_syserror ();
475 0 : return parm->lasterr; /* Tell the server about our problem. */
476 : }
477 0 : if ((s = memchr (line, '\n', rawlen)))
478 : {
479 0 : linelen = s - line; /* That is the length excluding the LF. */
480 0 : if (linelen + 1 < sizeof fixedbuf)
481 : {
482 : /* We can use the static buffer. */
483 0 : memcpy (fixedbuf, line, linelen);
484 0 : fixedbuf[linelen] = 0;
485 0 : if (linelen && fixedbuf[linelen-1] == '\r')
486 0 : fixedbuf[linelen-1] = 0;
487 0 : err = parm->data_cb (parm->data_cb_value, 0, fixedbuf);
488 : }
489 : else
490 : {
491 0 : if (linelen + 1 >= parm->helpbufsize)
492 : {
493 0 : xfree (parm->helpbuf);
494 0 : parm->helpbufsize = linelen + 1 + 1024;
495 0 : parm->helpbuf = xtrymalloc (parm->helpbufsize);
496 0 : if (!parm->helpbuf)
497 : {
498 0 : parm->lasterr = gpg_error_from_syserror ();
499 0 : return parm->lasterr;
500 : }
501 : }
502 0 : memcpy (parm->helpbuf, line, linelen);
503 0 : parm->helpbuf[linelen] = 0;
504 0 : if (linelen && parm->helpbuf[linelen-1] == '\r')
505 0 : parm->helpbuf[linelen-1] = 0;
506 0 : err = parm->data_cb (parm->data_cb_value, 0, parm->helpbuf);
507 : }
508 0 : if (err)
509 0 : parm->lasterr = err;
510 : else
511 : {
512 0 : clear_membuf (&parm->saveddata, linelen+1);
513 0 : goto again; /* There might be another complete line. */
514 : }
515 : }
516 :
517 0 : return err;
518 : }
519 :
520 :
521 : /* Run the KS_SEARCH command using the search string SEARCHSTR. All
522 : data lines are passed to the CB function. That function is called
523 : with CB_VALUE as its first argument, a 0 as second argument, and
524 : the decoded data line as third argument. The callback function may
525 : modify the data line and it is guaranteed that this data line is a
526 : complete line with a terminating 0 character but without the
527 : linefeed. NULL is passed to the callback to indicate EOF. */
528 : gpg_error_t
529 0 : gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
530 : gpg_error_t (*cb)(void*, int, char *), void *cb_value)
531 : {
532 : gpg_error_t err;
533 : assuan_context_t ctx;
534 : struct ks_status_parm_s stparm;
535 : struct ks_search_parm_s parm;
536 : char line[ASSUAN_LINELENGTH];
537 :
538 0 : err = open_context (ctrl, &ctx);
539 0 : if (err)
540 0 : return err;
541 :
542 : {
543 0 : char *escsearchstr = percent_plus_escape (searchstr);
544 0 : if (!escsearchstr)
545 : {
546 0 : err = gpg_error_from_syserror ();
547 0 : close_context (ctrl, ctx);
548 0 : return err;
549 : }
550 0 : snprintf (line, sizeof line, "KS_SEARCH -- %s", escsearchstr);
551 0 : xfree (escsearchstr);
552 : }
553 :
554 0 : memset (&stparm, 0, sizeof stparm);
555 0 : memset (&parm, 0, sizeof parm);
556 0 : init_membuf (&parm.saveddata, 1024);
557 0 : parm.data_cb = cb;
558 0 : parm.data_cb_value = cb_value;
559 0 : parm.stparm = &stparm;
560 :
561 0 : err = assuan_transact (ctx, line, ks_search_data_cb, &parm,
562 : NULL, NULL, ks_status_cb, &stparm);
563 0 : if (!err)
564 0 : err = cb (cb_value, 0, NULL); /* Send EOF. */
565 :
566 0 : xfree (get_membuf (&parm.saveddata, NULL));
567 0 : xfree (parm.helpbuf);
568 0 : xfree (stparm.source);
569 :
570 0 : close_context (ctrl, ctx);
571 0 : return err;
572 : }
573 :
574 :
575 :
576 : /* Data callback for the KS_GET and KS_FETCH commands. */
577 : static gpg_error_t
578 0 : ks_get_data_cb (void *opaque, const void *data, size_t datalen)
579 : {
580 0 : gpg_error_t err = 0;
581 0 : struct ks_get_parm_s *parm = opaque;
582 : size_t nwritten;
583 :
584 0 : if (!data)
585 0 : return 0; /* Ignore END commands. */
586 :
587 0 : if (es_write (parm->memfp, data, datalen, &nwritten))
588 0 : err = gpg_error_from_syserror ();
589 :
590 0 : return err;
591 : }
592 :
593 :
594 : /* Run the KS_GET command using the patterns in the array PATTERN. On
595 : success an estream object is returned to retrieve the keys. On
596 : error an error code is returned and NULL stored at R_FP.
597 :
598 : The pattern may only use search specification which a keyserver can
599 : use to retrieve keys. Because we know the format of the pattern we
600 : don't need to escape the patterns before sending them to the
601 : server.
602 :
603 : If QUICK is set the dirmngr is advised to use a shorter timeout.
604 :
605 : If R_SOURCE is not NULL the source of the data is stored as a
606 : malloced string there. If a source is not known NULL is stored.
607 :
608 : If there are too many patterns the function returns an error. That
609 : could be fixed by issuing several search commands or by
610 : implementing a different interface. However with long keyids we
611 : are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once. */
612 : gpg_error_t
613 0 : gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
614 : keyserver_spec_t override_keyserver, int quick,
615 : estream_t *r_fp, char **r_source)
616 : {
617 : gpg_error_t err;
618 : assuan_context_t ctx;
619 : struct ks_status_parm_s stparm;
620 : struct ks_get_parm_s parm;
621 0 : char *line = NULL;
622 : size_t linelen;
623 : membuf_t mb;
624 : int idx;
625 :
626 0 : memset (&stparm, 0, sizeof stparm);
627 0 : memset (&parm, 0, sizeof parm);
628 :
629 0 : *r_fp = NULL;
630 0 : if (r_source)
631 0 : *r_source = NULL;
632 :
633 0 : err = open_context (ctrl, &ctx);
634 0 : if (err)
635 0 : return err;
636 :
637 : /* If we have an override keyserver we first indicate that the next
638 : user of the context needs to again setup the global keyservers and
639 : them we send the override keyserver. */
640 0 : if (override_keyserver)
641 : {
642 0 : clear_context_flags (ctrl, ctx);
643 0 : line = xtryasprintf ("KEYSERVER --clear %s", override_keyserver->uri);
644 0 : if (!line)
645 : {
646 0 : err = gpg_error_from_syserror ();
647 0 : goto leave;
648 : }
649 0 : err = assuan_transact (ctx, line, NULL, NULL, NULL,
650 : NULL, NULL, NULL);
651 0 : if (err)
652 0 : goto leave;
653 :
654 0 : xfree (line);
655 0 : line = NULL;
656 : }
657 :
658 : /* Lump all patterns into one string. */
659 0 : init_membuf (&mb, 1024);
660 0 : put_membuf_str (&mb, quick? "KS_GET --quick --" : "KS_GET --");
661 0 : for (idx=0; pattern[idx]; idx++)
662 : {
663 0 : put_membuf (&mb, " ", 1); /* Append Delimiter. */
664 0 : put_membuf_str (&mb, pattern[idx]);
665 : }
666 0 : put_membuf (&mb, "", 1); /* Append Nul. */
667 0 : line = get_membuf (&mb, &linelen);
668 0 : if (!line)
669 : {
670 0 : err = gpg_error_from_syserror ();
671 0 : goto leave;
672 : }
673 0 : if (linelen + 2 >= ASSUAN_LINELENGTH)
674 : {
675 0 : err = gpg_error (GPG_ERR_TOO_MANY);
676 0 : goto leave;
677 : }
678 :
679 0 : parm.memfp = es_fopenmem (0, "rwb");
680 0 : if (!parm.memfp)
681 : {
682 0 : err = gpg_error_from_syserror ();
683 0 : goto leave;
684 : }
685 0 : err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
686 : NULL, NULL, ks_status_cb, &stparm);
687 0 : if (err)
688 0 : goto leave;
689 :
690 0 : es_rewind (parm.memfp);
691 0 : *r_fp = parm.memfp;
692 0 : parm.memfp = NULL;
693 :
694 0 : if (r_source)
695 : {
696 0 : *r_source = stparm.source;
697 0 : stparm.source = NULL;
698 : }
699 :
700 : leave:
701 0 : es_fclose (parm.memfp);
702 0 : xfree (stparm.source);
703 0 : xfree (line);
704 0 : close_context (ctrl, ctx);
705 0 : return err;
706 : }
707 :
708 :
709 : /* Run the KS_FETCH and pass URL as argument. On success an estream
710 : object is returned to retrieve the keys. On error an error code is
711 : returned and NULL stored at R_FP.
712 :
713 : The url is expected to point to a small set of keys; in many cases
714 : only to one key. However, schemes like finger may return several
715 : keys. Note that the configured keyservers are ignored by the
716 : KS_FETCH command. */
717 : gpg_error_t
718 0 : gpg_dirmngr_ks_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
719 : {
720 : gpg_error_t err;
721 : assuan_context_t ctx;
722 : struct ks_get_parm_s parm;
723 0 : char *line = NULL;
724 :
725 0 : memset (&parm, 0, sizeof parm);
726 :
727 0 : *r_fp = NULL;
728 :
729 0 : err = open_context (ctrl, &ctx);
730 0 : if (err)
731 0 : return err;
732 :
733 0 : line = strconcat ("KS_FETCH -- ", url, NULL);
734 0 : if (!line)
735 : {
736 0 : err = gpg_error_from_syserror ();
737 0 : goto leave;
738 : }
739 0 : if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
740 : {
741 0 : err = gpg_error (GPG_ERR_TOO_LARGE);
742 0 : goto leave;
743 : }
744 :
745 0 : parm.memfp = es_fopenmem (0, "rwb");
746 0 : if (!parm.memfp)
747 : {
748 0 : err = gpg_error_from_syserror ();
749 0 : goto leave;
750 : }
751 0 : err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
752 : NULL, NULL, NULL, NULL);
753 0 : if (err)
754 0 : goto leave;
755 :
756 0 : es_rewind (parm.memfp);
757 0 : *r_fp = parm.memfp;
758 0 : parm.memfp = NULL;
759 :
760 : leave:
761 0 : es_fclose (parm.memfp);
762 0 : xfree (line);
763 0 : close_context (ctrl, ctx);
764 0 : return err;
765 : }
766 :
767 :
768 :
769 : static void
770 0 : record_output (estream_t output,
771 : pkttype_t type,
772 : const char *validity,
773 : /* The public key length or -1. */
774 : int pub_key_length,
775 : /* The public key algo or -1. */
776 : int pub_key_algo,
777 : /* 2 ulongs or NULL. */
778 : const u32 *keyid,
779 : /* The creation / expiration date or 0. */
780 : u32 creation_date,
781 : u32 expiration_date,
782 : const char *userid)
783 : {
784 0 : const char *type_str = NULL;
785 0 : char *pub_key_length_str = NULL;
786 0 : char *pub_key_algo_str = NULL;
787 0 : char *keyid_str = NULL;
788 0 : char *creation_date_str = NULL;
789 0 : char *expiration_date_str = NULL;
790 0 : char *userid_escaped = NULL;
791 :
792 0 : switch (type)
793 : {
794 : case PKT_PUBLIC_KEY:
795 0 : type_str = "pub";
796 0 : break;
797 : case PKT_PUBLIC_SUBKEY:
798 0 : type_str = "sub";
799 0 : break;
800 : case PKT_USER_ID:
801 0 : type_str = "uid";
802 0 : break;
803 : case PKT_SIGNATURE:
804 0 : type_str = "sig";
805 0 : break;
806 : default:
807 0 : log_assert (! "Unhandled type.");
808 : }
809 :
810 0 : if (pub_key_length > 0)
811 0 : pub_key_length_str = xasprintf ("%d", pub_key_length);
812 :
813 0 : if (pub_key_algo != -1)
814 0 : pub_key_algo_str = xasprintf ("%d", pub_key_algo);
815 :
816 0 : if (keyid)
817 0 : keyid_str = xasprintf ("%08lX%08lX", (ulong) keyid[0], (ulong) keyid[1]);
818 :
819 0 : if (creation_date)
820 0 : creation_date_str = xstrdup (colon_strtime (creation_date));
821 :
822 0 : if (expiration_date)
823 0 : expiration_date_str = xstrdup (colon_strtime (expiration_date));
824 :
825 : /* Quote ':', '%', and any 8-bit characters. */
826 0 : if (userid)
827 : {
828 : int r;
829 0 : int w = 0;
830 :
831 0 : int len = strlen (userid);
832 : /* A 100k character limit on the uid should be way more than
833 : enough. */
834 0 : if (len > 100 * 1024)
835 0 : len = 100 * 1024;
836 :
837 : /* The minimum amount of space that we need. */
838 0 : userid_escaped = xmalloc (len * 3 + 1);
839 :
840 0 : for (r = 0; r < len; r++)
841 : {
842 0 : if (userid[r] == ':' || userid[r]== '%' || (userid[r] & 0x80))
843 : {
844 0 : sprintf (&userid_escaped[w], "%%%02X", (byte) userid[r]);
845 0 : w += 3;
846 : }
847 : else
848 0 : userid_escaped[w ++] = userid[r];
849 : }
850 0 : userid_escaped[w] = '\0';
851 : }
852 :
853 0 : es_fprintf (output, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
854 : type_str,
855 0 : validity ?: "",
856 0 : pub_key_length_str ?: "",
857 0 : pub_key_algo_str ?: "",
858 0 : keyid_str ?: "",
859 0 : creation_date_str ?: "",
860 0 : expiration_date_str ?: "",
861 : "" /* Certificate S/N */,
862 : "" /* Ownertrust. */,
863 0 : userid_escaped ?: "",
864 : "" /* Signature class. */,
865 : "" /* Key capabilities. */,
866 : "" /* Issuer certificate fingerprint. */,
867 : "" /* Flag field. */,
868 : "" /* S/N of a token. */,
869 : "" /* Hash algo. */,
870 : "" /* Curve name. */);
871 :
872 0 : xfree (userid_escaped);
873 0 : xfree (expiration_date_str);
874 0 : xfree (creation_date_str);
875 0 : xfree (keyid_str);
876 0 : xfree (pub_key_algo_str);
877 0 : xfree (pub_key_length_str);
878 0 : }
879 :
880 : /* Handle the KS_PUT inquiries. */
881 : static gpg_error_t
882 0 : ks_put_inq_cb (void *opaque, const char *line)
883 : {
884 0 : struct ks_put_parm_s *parm = opaque;
885 0 : gpg_error_t err = 0;
886 :
887 0 : if (has_leading_keyword (line, "KEYBLOCK"))
888 : {
889 0 : if (parm->data)
890 0 : err = assuan_send_data (parm->ctx, parm->data, parm->datalen);
891 : }
892 0 : else if (has_leading_keyword (line, "KEYBLOCK_INFO"))
893 : {
894 : kbnode_t node;
895 : estream_t fp;
896 :
897 : /* Parse the keyblock and send info lines back to the server. */
898 0 : fp = es_fopenmem (0, "rw,samethread");
899 0 : if (!fp)
900 0 : err = gpg_error_from_syserror ();
901 :
902 : /* Note: the output format for the INFO block follows the colon
903 : format as described in doc/DETAILS. We don't actually reuse
904 : the functionality from g10/keylist.c to produce the output,
905 : because we don't need all of it and some of it is quite
906 : expensive to generate.
907 :
908 : The fields are (the starred fields are the ones we need):
909 :
910 : * Field 1 - Type of record
911 : * Field 2 - Validity
912 : * Field 3 - Key length
913 : * Field 4 - Public key algorithm
914 : * Field 5 - KeyID
915 : * Field 6 - Creation date
916 : * Field 7 - Expiration date
917 : Field 8 - Certificate S/N, UID hash, trust signature info
918 : Field 9 - Ownertrust
919 : * Field 10 - User-ID
920 : Field 11 - Signature class
921 : Field 12 - Key capabilities
922 : Field 13 - Issuer certificate fingerprint or other info
923 : Field 14 - Flag field
924 : Field 15 - S/N of a token
925 : Field 16 - Hash algorithm
926 : Field 17 - Curve name
927 : */
928 0 : for (node = parm->keyblock; !err && node; node=node->next)
929 : {
930 0 : switch (node->pkt->pkttype)
931 : {
932 : case PKT_PUBLIC_KEY:
933 : case PKT_PUBLIC_SUBKEY:
934 : {
935 0 : PKT_public_key *pk = node->pkt->pkt.public_key;
936 :
937 : char validity[3];
938 : int i;
939 :
940 0 : i = 0;
941 0 : if (pk->flags.revoked)
942 0 : validity[i ++] = 'r';
943 0 : if (pk->has_expired)
944 0 : validity[i ++] = 'e';
945 0 : validity[i] = '\0';
946 :
947 0 : keyid_from_pk (pk, NULL);
948 :
949 0 : record_output (fp, node->pkt->pkttype, validity,
950 0 : nbits_from_pk (pk), pk->pubkey_algo,
951 0 : pk->keyid, pk->timestamp, pk->expiredate,
952 : NULL);
953 : }
954 0 : break;
955 :
956 : case PKT_USER_ID:
957 : {
958 0 : PKT_user_id *uid = node->pkt->pkt.user_id;
959 :
960 0 : if (!uid->attrib_data)
961 : {
962 : char validity[3];
963 : int i;
964 :
965 0 : i = 0;
966 0 : if (uid->is_revoked)
967 0 : validity[i ++] = 'r';
968 0 : if (uid->is_expired)
969 0 : validity[i ++] = 'e';
970 0 : validity[i] = '\0';
971 :
972 0 : record_output (fp, node->pkt->pkttype, validity,
973 : -1, -1, NULL,
974 : uid->created, uid->expiredate,
975 0 : uid->name);
976 : }
977 : }
978 0 : break;
979 :
980 : /* This bit is really for the benefit of people who
981 : store their keys in LDAP servers. It makes it easy
982 : to do queries for things like "all keys signed by
983 : Isabella". */
984 : case PKT_SIGNATURE:
985 : {
986 0 : PKT_signature *sig = node->pkt->pkt.signature;
987 :
988 0 : if (IS_UID_SIG (sig))
989 0 : record_output (fp, node->pkt->pkttype, NULL,
990 0 : -1, -1, sig->keyid,
991 : sig->timestamp, sig->expiredate, NULL);
992 : }
993 0 : break;
994 :
995 : default:
996 0 : continue;
997 : }
998 : /* Given that the last operation was an es_fprintf we should
999 : get the correct ERRNO if ferror indicates an error. */
1000 0 : if (es_ferror (fp))
1001 0 : err = gpg_error_from_syserror ();
1002 : }
1003 :
1004 : /* Without an error and if we have an keyblock at all, send the
1005 : data back. */
1006 0 : if (!err && parm->keyblock)
1007 : {
1008 : int rc;
1009 : char buffer[512];
1010 : size_t nread;
1011 :
1012 0 : es_rewind (fp);
1013 0 : while (!(rc=es_read (fp, buffer, sizeof buffer, &nread)) && nread)
1014 : {
1015 0 : err = assuan_send_data (parm->ctx, buffer, nread);
1016 0 : if (err)
1017 0 : break;
1018 : }
1019 0 : if (!err && rc)
1020 0 : err = gpg_error_from_syserror ();
1021 : }
1022 0 : es_fclose (fp);
1023 : }
1024 : else
1025 0 : return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
1026 :
1027 0 : return err;
1028 : }
1029 :
1030 :
1031 : /* Send a key to the configured server. {DATA,DATLEN} contains the
1032 : key in OpenPGP binary transport format. If KEYBLOCK is not NULL it
1033 : has the internal representaion of that key; this is for example
1034 : used to convey meta data to LDAP keyservers. */
1035 : gpg_error_t
1036 0 : gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
1037 : {
1038 : gpg_error_t err;
1039 : assuan_context_t ctx;
1040 : struct ks_put_parm_s parm;
1041 :
1042 0 : memset (&parm, 0, sizeof parm);
1043 :
1044 : /* We are going to parse the keyblock, thus we better make sure the
1045 : all information is readily available. */
1046 0 : if (keyblock)
1047 0 : merge_keys_and_selfsig (keyblock);
1048 :
1049 0 : err = open_context (ctrl, &ctx);
1050 0 : if (err)
1051 0 : return err;
1052 :
1053 0 : parm.ctx = ctx;
1054 0 : parm.keyblock = keyblock;
1055 0 : parm.data = data;
1056 0 : parm.datalen = datalen;
1057 :
1058 0 : err = assuan_transact (ctx, "KS_PUT", NULL, NULL,
1059 : ks_put_inq_cb, &parm, NULL, NULL);
1060 :
1061 0 : close_context (ctrl, ctx);
1062 0 : return err;
1063 : }
1064 :
1065 :
1066 :
1067 : /* Data callback for the DNS_CERT and WKD_GET commands. */
1068 : static gpg_error_t
1069 0 : dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
1070 : {
1071 0 : struct dns_cert_parm_s *parm = opaque;
1072 0 : gpg_error_t err = 0;
1073 : size_t nwritten;
1074 :
1075 0 : if (!data)
1076 0 : return 0; /* Ignore END commands. */
1077 0 : if (!parm->memfp)
1078 0 : return 0; /* Data is not required. */
1079 :
1080 0 : if (es_write (parm->memfp, data, datalen, &nwritten))
1081 0 : err = gpg_error_from_syserror ();
1082 :
1083 0 : return err;
1084 : }
1085 :
1086 :
1087 : /* Status callback for the DNS_CERT command. */
1088 : static gpg_error_t
1089 0 : dns_cert_status_cb (void *opaque, const char *line)
1090 : {
1091 0 : struct dns_cert_parm_s *parm = opaque;
1092 0 : gpg_error_t err = 0;
1093 : const char *s;
1094 : size_t nbytes;
1095 :
1096 0 : if ((s = has_leading_keyword (line, "FPR")))
1097 : {
1098 : char *buf;
1099 :
1100 0 : if (!(buf = xtrystrdup (s)))
1101 0 : err = gpg_error_from_syserror ();
1102 0 : else if (parm->fpr)
1103 0 : err = gpg_error (GPG_ERR_DUP_KEY);
1104 0 : else if (!hex2str (buf, buf, strlen (buf)+1, &nbytes))
1105 0 : err = gpg_error_from_syserror ();
1106 0 : else if (nbytes < 20)
1107 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
1108 : else
1109 : {
1110 0 : parm->fpr = xtrymalloc (nbytes);
1111 0 : if (!parm->fpr)
1112 0 : err = gpg_error_from_syserror ();
1113 : else
1114 0 : memcpy (parm->fpr, buf, (parm->fprlen = nbytes));
1115 : }
1116 0 : xfree (buf);
1117 : }
1118 0 : else if ((s = has_leading_keyword (line, "URL")) && *s)
1119 : {
1120 0 : if (parm->url)
1121 0 : err = gpg_error (GPG_ERR_DUP_KEY);
1122 0 : else if (!(parm->url = xtrystrdup (s)))
1123 0 : err = gpg_error_from_syserror ();
1124 : }
1125 :
1126 0 : return err;
1127 : }
1128 :
1129 : /* Ask the dirmngr for a DNS CERT record. Depending on the found
1130 : subtypes different return values are set:
1131 :
1132 : - For a PGP subtype a new estream with that key will be returned at
1133 : R_KEY and the other return parameters are set to NULL/0.
1134 :
1135 : - For an IPGP subtype the fingerprint is stored as a malloced block
1136 : at (R_FPR,R_FPRLEN). If an URL is available it is stored as a
1137 : malloced string at R_URL; NULL is stored if there is no URL.
1138 :
1139 : If CERTTYPE is DNS_CERTTYPE_ANY this function returns the first
1140 : CERT record found with a supported type; it is expected that only
1141 : one CERT record is used. If CERTTYPE is one of the supported
1142 : certtypes, only records with this certtype are considered and the
1143 : first one found is returned. All R_* args are optional.
1144 :
1145 : If CERTTYPE is NULL the DANE method is used to fetch the key.
1146 : */
1147 : gpg_error_t
1148 0 : gpg_dirmngr_dns_cert (ctrl_t ctrl, const char *name, const char *certtype,
1149 : estream_t *r_key,
1150 : unsigned char **r_fpr, size_t *r_fprlen,
1151 : char **r_url)
1152 : {
1153 : gpg_error_t err;
1154 : assuan_context_t ctx;
1155 : struct dns_cert_parm_s parm;
1156 0 : char *line = NULL;
1157 :
1158 0 : memset (&parm, 0, sizeof parm);
1159 0 : if (r_key)
1160 0 : *r_key = NULL;
1161 0 : if (r_fpr)
1162 0 : *r_fpr = NULL;
1163 0 : if (r_fprlen)
1164 0 : *r_fprlen = 0;
1165 0 : if (r_url)
1166 0 : *r_url = NULL;
1167 :
1168 0 : err = open_context (ctrl, &ctx);
1169 0 : if (err)
1170 0 : return err;
1171 :
1172 0 : line = es_bsprintf ("DNS_CERT %s %s", certtype? certtype : "--dane", name);
1173 0 : if (!line)
1174 : {
1175 0 : err = gpg_error_from_syserror ();
1176 0 : goto leave;
1177 : }
1178 0 : if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
1179 : {
1180 0 : err = gpg_error (GPG_ERR_TOO_LARGE);
1181 0 : goto leave;
1182 : }
1183 :
1184 0 : parm.memfp = es_fopenmem (0, "rwb");
1185 0 : if (!parm.memfp)
1186 : {
1187 0 : err = gpg_error_from_syserror ();
1188 0 : goto leave;
1189 : }
1190 0 : err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
1191 : NULL, NULL, dns_cert_status_cb, &parm);
1192 0 : if (err)
1193 0 : goto leave;
1194 :
1195 0 : if (r_key)
1196 : {
1197 0 : es_rewind (parm.memfp);
1198 0 : *r_key = parm.memfp;
1199 0 : parm.memfp = NULL;
1200 : }
1201 :
1202 0 : if (r_fpr && parm.fpr)
1203 : {
1204 0 : *r_fpr = parm.fpr;
1205 0 : parm.fpr = NULL;
1206 : }
1207 0 : if (r_fprlen)
1208 0 : *r_fprlen = parm.fprlen;
1209 :
1210 0 : if (r_url && parm.url)
1211 : {
1212 0 : *r_url = parm.url;
1213 0 : parm.url = NULL;
1214 : }
1215 :
1216 : leave:
1217 0 : xfree (parm.fpr);
1218 0 : xfree (parm.url);
1219 0 : es_fclose (parm.memfp);
1220 0 : xfree (line);
1221 0 : close_context (ctrl, ctx);
1222 0 : return err;
1223 : }
1224 :
1225 :
1226 : /* Ask the dirmngr for PKA info. On success the retrieved fingerprint
1227 : is returned in a malloced buffer at R_FPR and its length is stored
1228 : at R_FPRLEN. If an URL is available it is stored as a malloced
1229 : string at R_URL. On error all return values are set to NULL/0. */
1230 : gpg_error_t
1231 0 : gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
1232 : unsigned char **r_fpr, size_t *r_fprlen,
1233 : char **r_url)
1234 : {
1235 : gpg_error_t err;
1236 : assuan_context_t ctx;
1237 : struct dns_cert_parm_s parm;
1238 0 : char *line = NULL;
1239 :
1240 0 : memset (&parm, 0, sizeof parm);
1241 0 : if (r_fpr)
1242 0 : *r_fpr = NULL;
1243 0 : if (r_fprlen)
1244 0 : *r_fprlen = 0;
1245 0 : if (r_url)
1246 0 : *r_url = NULL;
1247 :
1248 0 : err = open_context (ctrl, &ctx);
1249 0 : if (err)
1250 0 : return err;
1251 :
1252 0 : line = es_bsprintf ("DNS_CERT --pka -- %s", userid);
1253 0 : if (!line)
1254 : {
1255 0 : err = gpg_error_from_syserror ();
1256 0 : goto leave;
1257 : }
1258 0 : if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
1259 : {
1260 0 : err = gpg_error (GPG_ERR_TOO_LARGE);
1261 0 : goto leave;
1262 : }
1263 :
1264 0 : err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
1265 : NULL, NULL, dns_cert_status_cb, &parm);
1266 0 : if (err)
1267 0 : goto leave;
1268 :
1269 0 : if (r_fpr && parm.fpr)
1270 : {
1271 0 : *r_fpr = parm.fpr;
1272 0 : parm.fpr = NULL;
1273 : }
1274 0 : if (r_fprlen)
1275 0 : *r_fprlen = parm.fprlen;
1276 :
1277 0 : if (r_url && parm.url)
1278 : {
1279 0 : *r_url = parm.url;
1280 0 : parm.url = NULL;
1281 : }
1282 :
1283 : leave:
1284 0 : xfree (parm.fpr);
1285 0 : xfree (parm.url);
1286 0 : xfree (line);
1287 0 : close_context (ctrl, ctx);
1288 0 : return err;
1289 : }
1290 :
1291 :
1292 :
1293 : /* Ask the dirmngr to retrieve a key via the Web Key Directory
1294 : * protocol. If QUICK is set the dirmngr is advised to use a shorter
1295 : * timeout. On success a new estream with the key is stored at R_KEY.
1296 : */
1297 : gpg_error_t
1298 0 : gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
1299 : {
1300 : gpg_error_t err;
1301 : assuan_context_t ctx;
1302 : struct dns_cert_parm_s parm;
1303 0 : char *line = NULL;
1304 :
1305 0 : memset (&parm, 0, sizeof parm);
1306 :
1307 0 : err = open_context (ctrl, &ctx);
1308 0 : if (err)
1309 0 : return err;
1310 :
1311 0 : line = es_bsprintf ("WKD_GET%s -- %s", quick?" --quick":"", name);
1312 0 : if (!line)
1313 : {
1314 0 : err = gpg_error_from_syserror ();
1315 0 : goto leave;
1316 : }
1317 0 : if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
1318 : {
1319 0 : err = gpg_error (GPG_ERR_TOO_LARGE);
1320 0 : goto leave;
1321 : }
1322 :
1323 0 : parm.memfp = es_fopenmem (0, "rwb");
1324 0 : if (!parm.memfp)
1325 : {
1326 0 : err = gpg_error_from_syserror ();
1327 0 : goto leave;
1328 : }
1329 0 : err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
1330 : NULL, NULL, NULL, &parm);
1331 0 : if (err)
1332 0 : goto leave;
1333 :
1334 0 : if (r_key)
1335 : {
1336 0 : es_rewind (parm.memfp);
1337 0 : *r_key = parm.memfp;
1338 0 : parm.memfp = NULL;
1339 : }
1340 :
1341 : leave:
1342 0 : xfree (parm.fpr);
1343 0 : xfree (parm.url);
1344 0 : es_fclose (parm.memfp);
1345 0 : xfree (line);
1346 0 : close_context (ctrl, ctx);
1347 0 : return err;
1348 : }
|