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 g10 Code GmbH
4 * Copyright (C) 2014 Werner Koch
6 * This file is part of GnuPG.
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.
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.
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/>.
28 #include <sys/types.h>
33 #define JNLIB_NEED_LOG_LOGV
40 # include "ldapserver.h"
43 #include "certcache.h"
47 # include "ldap-wrapper.h"
49 #include "ks-action.h"
50 #include "ks-engine.h" /* (ks_hkp_print_hosttable) */
52 /* To avoid DoS attacks we limit the size of a certificate to
53 something reasonable. */
54 #define MAX_CERT_LENGTH (8*1024)
56 /* The same goes for OpenPGP keyblocks, but here we need to allow for
57 much longer blocks; a 200k keyblock is not too unusual for keys
58 with a lot of signatures (e.g. 0x5b0358a2). */
59 #define MAX_KEYBLOCK_LENGTH (512*1024)
62 #define PARM_ERROR(t) assuan_set_error (ctx, \
63 gpg_error (GPG_ERR_ASS_PARAMETER), (t))
64 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
68 /* Control structure per connection. */
71 /* Data used to associate an Assuan context with local server data */
72 assuan_context_t assuan_ctx;
74 /* Per-session LDAP servers. */
75 ldap_server_t ldapservers;
77 /* If this flag is set to true this dirmngr process will be
78 terminated after the end of this session. */
83 /* Cookie definition for assuan data line output. */
84 static ssize_t data_line_cookie_write (void *cookie,
85 const void *buffer, size_t size);
86 static int data_line_cookie_close (void *cookie);
87 static es_cookie_io_functions_t data_line_cookie_functions =
90 data_line_cookie_write,
92 data_line_cookie_close
99 /* Accessor for the local ldapservers variable. */
101 get_ldapservers_from_ctrl (ctrl_t ctrl)
103 if (ctrl && ctrl->server_local)
104 return ctrl->server_local->ldapservers;
110 /* Release all configured keyserver info from CTRL. */
112 release_ctrl_keyservers (ctrl_t ctrl)
114 while (ctrl->keyservers)
116 uri_item_t tmp = ctrl->keyservers->next;
117 http_release_parsed_uri (ctrl->keyservers->parsed_uri);
118 xfree (ctrl->keyservers);
119 ctrl->keyservers = tmp;
125 /* Helper to print a message while leaving a command. */
127 leave_cmd (assuan_context_t ctx, gpg_error_t err)
132 const char *name = assuan_get_command_name (ctx);
135 if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
136 log_error ("command '%s' failed: %s\n", name,
139 log_error ("command '%s' failed: %s <%s>\n", name,
140 gpg_strerror (err), gpg_strsource (err));
145 /* A write handler used by es_fopencookie to write assuan data
148 data_line_cookie_write (void *cookie, const void *buffer_arg, size_t size)
150 assuan_context_t ctx = cookie;
151 const char *buffer = buffer_arg;
153 if (opt.verbose && buffer && size)
155 /* Ease reading of output by sending a physical line at each LF. */
162 p = memchr (buffer, '\n', nbytes);
163 n = p ? (p - buffer) + 1 : nbytes;
164 if (assuan_send_data (ctx, buffer, n))
166 gpg_err_set_errno (EIO);
171 if (nbytes && assuan_send_data (ctx, NULL, 0)) /* Flush line. */
173 gpg_err_set_errno (EIO);
181 if (assuan_send_data (ctx, buffer, size))
183 gpg_err_set_errno (EIO);
192 data_line_cookie_close (void *cookie)
194 assuan_context_t ctx = cookie;
196 if (assuan_send_data (ctx, NULL, 0))
198 gpg_err_set_errno (EIO);
206 /* Copy the % and + escaped string S into the buffer D and replace the
207 escape sequences. Note, that it is sufficient to allocate the
208 target string D as long as the source string S, i.e.: strlen(s)+1.
209 Note further that if S contains an escaped binary Nul the resulting
210 string D will contain the 0 as well as all other characters but it
211 will be impossible to know whether this is the original EOS or a
214 strcpy_escaped_plus (char *d, const unsigned char *s)
218 if (*s == '%' && s[1] && s[2])
233 /* Check whether the option NAME appears in LINE */
235 has_option (const char *line, const char *name)
238 int n = strlen (name);
240 s = strstr (line, name);
241 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
244 /* Same as has_option but only considers options at the begin of the
245 line. This is useful for commands which allow arbitrary strings on
248 has_leading_option (const char *line, const char *name)
253 if (name[0] != '-' || name[1] != '-' || !name[2] || spacep (name+2))
256 while ( *line == '-' && line[1] == '-' )
259 while (*line && !spacep (line))
261 if (n == (line - s) && !strncmp (s, name, n))
263 while (spacep (line))
270 /* Same as has_option but does only test for the name of the option
271 and ignores an argument, i.e. with NAME being "--hash" it would
272 return a pointer for "--hash" as well as for "--hash=foo". If
273 thhere is no such option NULL is returned. The pointer returned
274 points right behind the option name, this may be an equal sign, Nul
276 /* static const char * */
277 /* has_option_name (const char *line, const char *name) */
280 /* int n = strlen (name); */
282 /* s = strstr (line, name); */
283 /* return (s && (s == line || spacep (s-1)) */
284 /* && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */
288 /* Skip over options. It is assumed that leading spaces have been
289 removed (this is the case for lines passed to a handler from
290 assuan). Blanks after the options are also removed. */
292 skip_options (char *line)
294 while ( *line == '-' && line[1] == '-' )
296 while (*line && !spacep (line))
298 while (spacep (line))
305 /* Return an error if the assuan context does not belong to the owner
306 of the process or to root. On error FAILTEXT is set as Assuan
309 check_owner_permission (assuan_context_t ctx, const char *failtext)
311 #ifdef HAVE_W32_SYSTEM
312 /* Under Windows the dirmngr is always run under the control of the
318 assuan_peercred_t cred;
320 ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
321 if (!ec && cred->uid && cred->uid != getuid ())
324 return set_error (ec, failtext);
331 /* Common code for get_cert_local and get_issuer_cert_local. */
333 do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
335 unsigned char *value;
343 buf = xmalloc ( strlen (command) + 1 + strlen(name) + 1);
344 strcpy (stpcpy (stpcpy (buf, command), " "), name);
347 buf = xstrdup (command);
349 rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
350 &value, &valuelen, MAX_CERT_LENGTH);
354 log_error (_("assuan_inquire(%s) failed: %s\n"),
355 command, gpg_strerror (rc));
365 rc = ksba_cert_new (&cert);
368 rc = ksba_cert_init_from_mem (cert, value, valuelen);
371 ksba_cert_release (cert);
381 /* Ask back to return a certificate for name, given as a regular
382 gpgsm certificate indentificates (e.g. fingerprint or one of the
383 other methods). Alternatively, NULL may be used for NAME to
384 return the current target certificate. Either return the certificate
385 in a KSBA object or NULL if it is not available.
388 get_cert_local (ctrl_t ctrl, const char *name)
390 if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
393 log_debug ("get_cert_local called w/o context\n");
396 return do_get_cert_local (ctrl, name, "SENDCERT");
400 /* Ask back to return the issuing certificate for name, given as a
401 regular gpgsm certificate indentificates (e.g. fingerprint or one
402 of the other methods). Alternatively, NULL may be used for NAME to
403 return thecurrent target certificate. Either return the certificate
404 in a KSBA object or NULL if it is not available.
408 get_issuing_cert_local (ctrl_t ctrl, const char *name)
410 if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
413 log_debug ("get_issuing_cert_local called w/o context\n");
416 return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
419 /* Ask back to return a certificate with subject NAME and a
420 subjectKeyIdentifier of KEYID. */
422 get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
424 unsigned char *value;
431 if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
434 log_debug ("get_cert_local_ski called w/o context\n");
439 log_debug ("get_cert_local_ski called with insufficient arguments\n");
443 hexkeyid = serial_hex (keyid);
446 log_debug ("serial_hex() failed\n");
450 buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
454 log_error ("can't allocate enough memory: %s\n", strerror (errno));
458 strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
461 rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
462 &value, &valuelen, MAX_CERT_LENGTH);
466 log_error (_("assuan_inquire(%s) failed: %s\n"), "SENDCERT_SKI",
477 rc = ksba_cert_new (&cert);
480 rc = ksba_cert_init_from_mem (cert, value, valuelen);
483 ksba_cert_release (cert);
492 /* Ask the client via an inquiry to check the istrusted status of the
493 certificate specified by the hexified fingerprint HEXFPR. Returns
494 0 if the certificate is trusted by the client or an error code. */
496 get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr)
498 unsigned char *value;
503 if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx
505 return gpg_error (GPG_ERR_INV_ARG);
507 snprintf (request, sizeof request, "ISTRUSTED %s", hexfpr);
508 rc = assuan_inquire (ctrl->server_local->assuan_ctx, request,
509 &value, &valuelen, 100);
512 log_error (_("assuan_inquire(%s) failed: %s\n"),
513 request, gpg_strerror (rc));
516 /* The expected data is: "1" or "1 cruft" (not a C-string). */
517 if (valuelen && *value == '1' && (valuelen == 1 || spacep (value+1)))
520 rc = gpg_error (GPG_ERR_NOT_TRUSTED);
528 /* Ask the client to return the certificate associated with the
529 current command. This is sometimes needed because the client usually
530 sends us just the cert ID, assuming that the request can be
531 satisfied from the cache, where the cert ID is used as key. */
533 inquire_cert_and_load_crl (assuan_context_t ctx)
535 ctrl_t ctrl = assuan_get_pointer (ctx);
537 unsigned char *value = NULL;
539 ksba_cert_t cert = NULL;
541 err = assuan_inquire( ctx, "SENDCERT", &value, &valuelen, 0);
546 /* FILE *fp = fopen ("foo.der", "r"); */
547 /* value = xmalloc (2000); */
548 /* valuelen = fread (value, 1, 2000, fp); */
552 if (!valuelen) /* No data returned; return a comprehensible error. */
553 return gpg_error (GPG_ERR_MISSING_CERT);
555 err = ksba_cert_new (&cert);
558 err = ksba_cert_init_from_mem (cert, value, valuelen);
561 xfree (value); value = NULL;
563 err = crl_cache_reload_crl (ctrl, cert);
566 ksba_cert_release (cert);
572 /* Handle OPTION commands. */
574 option_handler (assuan_context_t ctx, const char *key, const char *value)
576 ctrl_t ctrl = assuan_get_pointer (ctx);
578 if (!strcmp (key, "force-crl-refresh"))
580 int i = *value? atoi (value) : 0;
581 ctrl->force_crl_refresh = i;
583 else if (!strcmp (key, "audit-events"))
585 int i = *value? atoi (value) : 0;
586 ctrl->audit_events = i;
589 return gpg_error (GPG_ERR_UNKNOWN_OPTION);
594 static const char hlp_ldapserver[] =
595 "LDAPSERVER <data>\n"
597 "Add a new LDAP server to the list of configured LDAP servers.\n"
598 "DATA is in the same format as expected in the configure file.";
600 cmd_ldapserver (assuan_context_t ctx, char *line)
603 ctrl_t ctrl = assuan_get_pointer (ctx);
604 ldap_server_t server;
605 ldap_server_t *last_next_p;
607 while (spacep (line))
610 return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
612 server = ldapserver_parse_one (line, "", 0);
614 return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
616 last_next_p = &ctrl->server_local->ldapservers;
618 last_next_p = &(*last_next_p)->next;
619 *last_next_p = server;
620 return leave_cmd (ctx, 0);
623 return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
628 static const char hlp_isvalid[] =
629 "ISVALID [--only-ocsp] [--force-default-responder]"
630 " <certificate_id>|<certificate_fpr>\n"
632 "This command checks whether the certificate identified by the\n"
633 "certificate_id is valid. This is done by consulting CRLs or\n"
634 "whatever has been configured. Note, that the returned error codes\n"
635 "are from gpg-error.h. The command may callback using the inquire\n"
636 "function. See the manual for details.\n"
638 "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
639 "delimited by a single dot. The first part is the SHA-1 hash of the\n"
640 "issuer name and the second part the serial number.\n"
642 "Alternatively the certificate's fingerprint may be given in which\n"
643 "case an OCSP request is done before consulting the CRL.\n"
645 "If the option --only-ocsp is given, no fallback to a CRL check will\n"
648 "If the option --force-default-responder is given, only the default\n"
649 "OCSP responder will be used and any other methods of obtaining an\n"
650 "OCSP responder URL won't be used.";
652 cmd_isvalid (assuan_context_t ctx, char *line)
654 ctrl_t ctrl = assuan_get_pointer (ctx);
655 char *issuerhash, *serialno;
660 int force_default_responder;
662 only_ocsp = has_option (line, "--only-ocsp");
663 force_default_responder = has_option (line, "--force-default-responder");
664 line = skip_options (line);
666 issuerhash = xstrdup (line); /* We need to work on a copy of the
667 line because that same Assuan
668 context may be used for an inquiry.
669 That is because Assuan reuses its
673 serialno = strchr (issuerhash, '.');
678 char *endp = strchr (issuerhash, ' ');
681 if (strlen (issuerhash) != 40)
684 return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
693 /* Note, that we ignore the given issuer hash and instead rely
694 on the current certificate semantics used with this
697 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
699 err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
700 /* Fixme: If we got no ocsp response and --only-ocsp is not used
701 we should fall back to CRL mode. Thus we need to clear
702 OCSP_MODE, get the issuerhash and the serialno from the
703 current certificate and jump to again. */
706 err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
709 switch (crl_cache_isvalid (ctrl,
710 issuerhash, serialno,
711 ctrl->force_crl_refresh))
713 case CRL_CACHE_VALID:
716 case CRL_CACHE_INVALID:
717 err = gpg_error (GPG_ERR_CERT_REVOKED);
719 case CRL_CACHE_DONTKNOW:
721 err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
722 else if (!(err = inquire_cert_and_load_crl (ctx)))
728 case CRL_CACHE_CANTUSE:
729 err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
732 log_fatal ("crl_cache_isvalid returned invalid code\n");
737 return leave_cmd (ctx, err);
741 /* If the line contains a SHA-1 fingerprint as the first argument,
742 return the FPR vuffer on success. The function checks that the
743 fingerprint consists of valid characters and prints and error
744 message if it does not and returns NULL. Fingerprints are
745 considered optional and thus no explicit error is returned. NULL is
746 also returned if there is no fingerprint at all available.
747 FPR must be a caller provided buffer of at least 20 bytes.
749 Note that colons within the fingerprint are allowed to separate 2
750 hex digits; this allows for easier cutting and pasting using the
751 usual fingerprint rendering.
753 static unsigned char *
754 get_fingerprint_from_line (const char *line, unsigned char *fpr)
759 for (s=line, i=0; *s && *s != ' '; s++ )
761 if ( hexdigitp (s) && hexdigitp (s+1) )
764 return NULL; /* Fingerprint too long. */
765 fpr[i++] = xtoi_2 (s);
768 else if ( *s != ':' )
769 return NULL; /* Invalid. */
772 return NULL; /* Fingerprint to short. */
778 static const char hlp_checkcrl[] =
779 "CHECKCRL [<fingerprint>]\n"
781 "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
782 "entire X.509 certificate blob) is valid or not by consulting the\n"
783 "CRL responsible for this certificate. If the fingerprint has not\n"
784 "been given or the certificate is not known, the function \n"
785 "inquires the certificate using an\n"
787 " INQUIRE TARGETCERT\n"
789 "and the caller is expected to return the certificate for the\n"
790 "request (which should match FINGERPRINT) as a binary blob.\n"
791 "Processing then takes place without further interaction; in\n"
792 "particular dirmngr tries to locate other required certificate by\n"
793 "its own mechanism which includes a local certificate store as well\n"
794 "as a list of trusted root certificates.\n"
796 "The return value is the usual gpg-error code or 0 for ducesss;\n"
797 "i.e. the certificate validity has been confirmed by a valid CRL.";
799 cmd_checkcrl (assuan_context_t ctx, char *line)
801 ctrl_t ctrl = assuan_get_pointer (ctx);
803 unsigned char fprbuffer[20], *fpr;
806 fpr = get_fingerprint_from_line (line, fprbuffer);
807 cert = fpr? get_cert_byfpr (fpr) : NULL;
811 /* We do not have this certificate yet or the fingerprint has
812 not been given. Inquire it from the client. */
813 unsigned char *value = NULL;
816 err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
817 &value, &valuelen, MAX_CERT_LENGTH);
820 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
824 if (!valuelen) /* No data returned; return a comprehensible error. */
825 err = gpg_error (GPG_ERR_MISSING_CERT);
828 err = ksba_cert_new (&cert);
830 err = ksba_cert_init_from_mem (cert, value, valuelen);
839 err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
840 if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
842 err = crl_cache_reload_crl (ctrl, cert);
844 err = crl_cache_cert_isvalid (ctrl, cert, 0);
848 ksba_cert_release (cert);
849 return leave_cmd (ctx, err);
853 static const char hlp_checkocsp[] =
854 "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
856 "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
857 "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
858 "responder responsible for this certificate. The optional\n"
859 "fingerprint may be used for a quick check in case an OCSP check has\n"
860 "been done for this certificate recently (we always cache OCSP\n"
861 "responses for a couple of minutes). If the fingerprint has not been\n"
862 "given or there is no cached result, the function inquires the\n"
863 "certificate using an\n"
865 " INQUIRE TARGETCERT\n"
867 "and the caller is expected to return the certificate for the\n"
868 "request (which should match FINGERPRINT) as a binary blob.\n"
869 "Processing then takes place without further interaction; in\n"
870 "particular dirmngr tries to locate other required certificates by\n"
871 "its own mechanism which includes a local certificate store as well\n"
872 "as a list of trusted root certifciates.\n"
874 "If the option --force-default-responder is given, only the default\n"
875 "OCSP responder will be used and any other methods of obtaining an\n"
876 "OCSP responder URL won't be used.\n"
878 "The return value is the usual gpg-error code or 0 for ducesss;\n"
879 "i.e. the certificate validity has been confirmed by a valid CRL.";
881 cmd_checkocsp (assuan_context_t ctx, char *line)
883 ctrl_t ctrl = assuan_get_pointer (ctx);
885 unsigned char fprbuffer[20], *fpr;
887 int force_default_responder;
889 force_default_responder = has_option (line, "--force-default-responder");
890 line = skip_options (line);
892 fpr = get_fingerprint_from_line (line, fprbuffer);
893 cert = fpr? get_cert_byfpr (fpr) : NULL;
897 /* We do not have this certificate yet or the fingerprint has
898 not been given. Inquire it from the client. */
899 unsigned char *value = NULL;
902 err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
903 &value, &valuelen, MAX_CERT_LENGTH);
906 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
910 if (!valuelen) /* No data returned; return a comprehensible error. */
911 err = gpg_error (GPG_ERR_MISSING_CERT);
914 err = ksba_cert_new (&cert);
916 err = ksba_cert_init_from_mem (cert, value, valuelen);
926 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
928 err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
931 ksba_cert_release (cert);
932 return leave_cmd (ctx, err);
938 lookup_cert_by_url (assuan_context_t ctx, const char *url)
940 ctrl_t ctrl = assuan_get_pointer (ctx);
942 unsigned char *value = NULL;
945 /* Fetch single certificate given it's URL. */
946 err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
949 log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
953 /* Send the data, flush the buffer and then send an END. */
954 err = assuan_send_data (ctx, value, valuelen);
956 err = assuan_send_data (ctx, NULL, 0);
958 err = assuan_write_line (ctx, "END");
961 log_error (_("error sending data: %s\n"), gpg_strerror (err));
971 /* Send the certificate, flush the buffer and then send an END. */
973 return_one_cert (void *opaque, ksba_cert_t cert)
975 assuan_context_t ctx = opaque;
977 const unsigned char *der;
980 der = ksba_cert_get_image (cert, &derlen);
982 err = gpg_error (GPG_ERR_INV_CERT_OBJ);
985 err = assuan_send_data (ctx, der, derlen);
987 err = assuan_send_data (ctx, NULL, 0);
989 err = assuan_write_line (ctx, "END");
992 log_error (_("error sending data: %s\n"), gpg_strerror (err));
997 /* Lookup certificates from the internal cache or using the ldap
1000 lookup_cert_by_pattern (assuan_context_t ctx, char *line,
1001 int single, int cache_only)
1003 gpg_error_t err = 0;
1005 strlist_t sl, list = NULL;
1006 int truncated = 0, truncation_forced = 0;
1008 int local_count = 0;
1010 ctrl_t ctrl = assuan_get_pointer (ctx);
1011 unsigned char *value = NULL;
1013 struct ldapserver_iter ldapserver_iter;
1014 cert_fetch_context_t fetch_context;
1016 int any_no_data = 0;
1018 /* Break the line down into an STRLIST */
1019 for (p=line; *p; line = p)
1021 while (*p && *p != ' ')
1028 sl = xtrymalloc (sizeof *sl + strlen (line));
1031 err = gpg_error_from_errno (errno);
1034 memset (sl, 0, sizeof *sl);
1035 strcpy_escaped_plus (sl->d, line);
1041 /* First look through the internal cache. The certifcates retruned
1042 here are not counted towards the truncation limit. */
1043 if (single && !cache_only)
1044 ; /* Do not read from the local cache in this case. */
1047 for (sl=list; sl; sl = sl->next)
1049 err = get_certs_bypattern (sl->d, return_one_cert, ctx);
1055 if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1061 else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
1063 /* No real fault because the internal pattern lookup
1064 can't yet cope with all types of pattern. */
1072 /* Loop over all configured servers unless we want only the
1073 certificates from the cache. */
1075 for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
1076 !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
1077 && ldapserver_iter.server->host && !truncation_forced;
1078 ldapserver_iter_next (&ldapserver_iter))
1080 ldap_server_t ldapserver = ldapserver_iter.server;
1083 log_debug ("cmd_lookup: trying %s:%d base=%s\n",
1084 ldapserver->host, ldapserver->port,
1085 ldapserver->base?ldapserver->base : "[default]");
1087 /* Fetch certificates matching pattern */
1088 err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
1089 if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
1092 log_debug ("cmd_lookup: no data\n");
1099 log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1103 /* Fetch the certificates for this query. */
1104 while (!truncation_forced)
1106 xfree (value); value = NULL;
1107 err = fetch_next_cert (fetch_context, &value, &valuelen);
1108 if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1114 if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1120 if (gpg_err_code (err) == GPG_ERR_EOF)
1127 err = gpg_error (GPG_ERR_BUG);
1132 log_error (_("fetch_next_cert failed: %s\n"),
1133 gpg_strerror (err));
1134 end_cert_fetch (fetch_context);
1139 log_debug ("cmd_lookup: returning one cert%s\n",
1140 truncated? " (truncated)":"");
1142 /* Send the data, flush the buffer and then send an END line
1143 as a certificate delimiter. */
1144 err = assuan_send_data (ctx, value, valuelen);
1146 err = assuan_send_data (ctx, NULL, 0);
1148 err = assuan_write_line (ctx, "END");
1151 log_error (_("error sending data: %s\n"), gpg_strerror (err));
1152 end_cert_fetch (fetch_context);
1156 if (++count >= opt.max_replies )
1158 truncation_forced = 1;
1159 log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1165 end_cert_fetch (fetch_context);
1170 if (truncated || truncation_forced)
1174 sprintf (str, "%d", count);
1175 assuan_write_status (ctx, "TRUNCATED", str);
1178 if (!err && !count && !local_count && any_no_data)
1179 err = gpg_error (GPG_ERR_NO_DATA);
1182 free_strlist (list);
1187 static const char hlp_lookup[] =
1188 "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1190 "Lookup certificates matching PATTERN. With --url the pattern is\n"
1191 "expected to be one URL.\n"
1193 "If --url is not given: To allow for multiple patterns (which are ORed)\n"
1194 "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1195 "obviously this requires that the usual escape quoting rules are applied.\n"
1197 "If --url is given no special escaping is required because URLs are\n"
1198 "already escaped this way.\n"
1200 "If --single is given the first and only the first match will be\n"
1201 "returned. If --cache-only is _not_ given, no local query will be\n"
1204 "If --cache-only is given no external lookup is done so that only\n"
1205 "certificates from the cache may get returned.";
1207 cmd_lookup (assuan_context_t ctx, char *line)
1210 int lookup_url, single, cache_only;
1212 lookup_url = has_leading_option (line, "--url");
1213 single = has_leading_option (line, "--single");
1214 cache_only = has_leading_option (line, "--cache-only");
1215 line = skip_options (line);
1217 if (lookup_url && cache_only)
1218 err = gpg_error (GPG_ERR_NOT_FOUND);
1219 else if (lookup_url && single)
1220 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1221 else if (lookup_url)
1222 err = lookup_cert_by_url (ctx, line);
1224 err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1226 return leave_cmd (ctx, err);
1230 static const char hlp_loadcrl[] =
1231 "LOADCRL [--url] <filename|url>\n"
1233 "Load the CRL in the file with name FILENAME into our cache. Note\n"
1234 "that FILENAME should be given with an absolute path because\n"
1235 "Dirmngrs cwd is not known. With --url the CRL is directly loaded\n"
1236 "from the given URL.\n"
1238 "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1239 "--call-dirmngr loadcrl <filename>\". A direct invocation of Dirmngr\n"
1240 "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1241 "the CA's certificate.";
1243 cmd_loadcrl (assuan_context_t ctx, char *line)
1245 ctrl_t ctrl = assuan_get_pointer (ctx);
1246 gpg_error_t err = 0;
1247 int use_url = has_leading_option (line, "--url");
1249 line = skip_options (line);
1253 ksba_reader_t reader;
1255 err = crl_fetch (ctrl, line, &reader);
1257 log_error (_("fetching CRL from '%s' failed: %s\n"),
1258 line, gpg_strerror (err));
1261 err = crl_cache_insert (ctrl, line, reader);
1263 log_error (_("processing CRL from '%s' failed: %s\n"),
1264 line, gpg_strerror (err));
1265 crl_close_reader (reader);
1272 buf = xtrymalloc (strlen (line)+1);
1274 err = gpg_error_from_syserror ();
1277 strcpy_escaped_plus (buf, line);
1278 err = crl_cache_load (ctrl, buf);
1283 return leave_cmd (ctx, err);
1287 static const char hlp_listcrls[] =
1290 "List the content of all CRLs in a readable format. This command is\n"
1291 "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1292 "listcrls\". It may also be used directly using \"dirmngr\n"
1295 cmd_listcrls (assuan_context_t ctx, char *line)
1302 fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1304 err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1307 err = crl_cache_list (fp);
1310 return leave_cmd (ctx, err);
1314 static const char hlp_cachecert[] =
1317 "Put a certificate into the internal cache. This command might be\n"
1318 "useful if a client knows in advance certificates required for a\n"
1319 "test and wants to make sure they get added to the internal cache.\n"
1320 "It is also helpful for debugging. To get the actual certificate,\n"
1321 "this command immediately inquires it using\n"
1323 " INQUIRE TARGETCERT\n"
1325 "and the caller is expected to return the certificate for the\n"
1326 "request as a binary blob.";
1328 cmd_cachecert (assuan_context_t ctx, char *line)
1330 ctrl_t ctrl = assuan_get_pointer (ctx);
1332 ksba_cert_t cert = NULL;
1333 unsigned char *value = NULL;
1338 err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1339 &value, &valuelen, MAX_CERT_LENGTH);
1342 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1346 if (!valuelen) /* No data returned; return a comprehensible error. */
1347 err = gpg_error (GPG_ERR_MISSING_CERT);
1350 err = ksba_cert_new (&cert);
1352 err = ksba_cert_init_from_mem (cert, value, valuelen);
1358 err = cache_cert (cert);
1361 ksba_cert_release (cert);
1362 return leave_cmd (ctx, err);
1366 static const char hlp_validate[] =
1369 "Validate a certificate using the certificate validation function\n"
1370 "used internally by dirmngr. This command is only useful for\n"
1371 "debugging. To get the actual certificate, this command immediately\n"
1372 "inquires it using\n"
1374 " INQUIRE TARGETCERT\n"
1376 "and the caller is expected to return the certificate for the\n"
1377 "request as a binary blob.";
1379 cmd_validate (assuan_context_t ctx, char *line)
1381 ctrl_t ctrl = assuan_get_pointer (ctx);
1383 ksba_cert_t cert = NULL;
1384 unsigned char *value = NULL;
1389 err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1390 &value, &valuelen, MAX_CERT_LENGTH);
1393 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1397 if (!valuelen) /* No data returned; return a comprehensible error. */
1398 err = gpg_error (GPG_ERR_MISSING_CERT);
1401 err = ksba_cert_new (&cert);
1403 err = ksba_cert_init_from_mem (cert, value, valuelen);
1409 /* If we have this certificate already in our cache, use the cached
1410 version for validation because this will take care of any cached
1413 unsigned char fpr[20];
1414 ksba_cert_t tmpcert;
1416 cert_compute_fpr (cert, fpr);
1417 tmpcert = get_cert_byfpr (fpr);
1420 ksba_cert_release (cert);
1425 err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
1428 ksba_cert_release (cert);
1429 return leave_cmd (ctx, err);
1433 static const char hlp_keyserver[] =
1434 "KEYSERVER [<options>] [<uri>|<host>]\n"
1437 " --clear Remove all configured keyservers\n"
1438 " --resolve Resolve HKP host names and rotate\n"
1439 " --hosttable Print table of known hosts and pools\n"
1440 " --dead Mark <host> as dead\n"
1441 " --alive Mark <host> as alive\n"
1443 "If called without arguments list all configured keyserver URLs.\n"
1444 "If called with an URI add this as keyserver. Note that keyservers\n"
1445 "are configured on a per-session base. A default keyserver may already be\n"
1446 "present, thus the \"--clear\" option must be used to get full control.\n"
1447 "If \"--clear\" and an URI are used together the clear command is\n"
1448 "obviously executed first. A RESET command does not change the list\n"
1449 "of configured keyservers.";
1451 cmd_keyserver (assuan_context_t ctx, char *line)
1453 ctrl_t ctrl = assuan_get_pointer (ctx);
1454 gpg_error_t err = 0;
1455 int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
1456 int dead_flag, alive_flag;
1457 uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
1458 is always initialized. */
1460 clear_flag = has_option (line, "--clear");
1461 help_flag = has_option (line, "--help");
1462 resolve_flag = has_option (line, "--resolve");
1463 host_flag = has_option (line, "--hosttable");
1464 dead_flag = has_option (line, "--dead");
1465 alive_flag = has_option (line, "--alive");
1466 line = skip_options (line);
1471 err = ks_action_help (ctrl, line);
1477 err = ks_action_resolve (ctrl);
1482 if (alive_flag && dead_flag)
1484 err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
1489 err = check_owner_permission (ctx, "no permission to use --dead");
1493 if (alive_flag || dead_flag)
1497 err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
1501 err = ks_hkp_mark_host (ctrl, line, alive_flag);
1508 err = ks_hkp_print_hosttable (ctrl);
1512 if (resolve_flag || host_flag || alive_flag || dead_flag)
1517 item = xtrymalloc (sizeof *item + strlen (line));
1520 err = gpg_error_from_syserror ();
1524 item->parsed_uri = NULL;
1525 strcpy (item->uri, line);
1527 err = http_parse_uri (&item->parsed_uri, line, 1);
1535 release_ctrl_keyservers (ctrl);
1538 item->next = ctrl->keyservers;
1539 ctrl->keyservers = item;
1542 if (!add_flag && !clear_flag && !help_flag) /* List configured keyservers. */
1546 for (u=ctrl->keyservers; u; u = u->next)
1547 dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
1552 return leave_cmd (ctx, err);
1557 static const char hlp_ks_search[] =
1558 "KS_SEARCH {<pattern>}\n"
1560 "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
1561 "for keys matching PATTERN";
1563 cmd_ks_search (assuan_context_t ctx, char *line)
1565 ctrl_t ctrl = assuan_get_pointer (ctx);
1571 /* No options for now. */
1572 line = skip_options (line);
1574 /* Break the line down into an strlist. Each pattern is
1575 percent-plus escaped. */
1577 for (p=line; *p; line = p)
1579 while (*p && *p != ' ')
1585 sl = xtrymalloc (sizeof *sl + strlen (line));
1588 err = gpg_error_from_syserror ();
1592 strcpy_escaped_plus (sl->d, line);
1598 /* Setup an output stream and perform the search. */
1599 outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1601 err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1604 err = ks_action_search (ctrl, list, outfp);
1609 free_strlist (list);
1610 return leave_cmd (ctx, err);
1615 static const char hlp_ks_get[] =
1616 "KS_GET {<pattern>}\n"
1618 "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
1619 "(see command KEYSERVER). Each pattern should be a keyid, a fingerprint,\n"
1620 "or an exact name indicastes by the '=' prefix.";
1622 cmd_ks_get (assuan_context_t ctx, char *line)
1624 ctrl_t ctrl = assuan_get_pointer (ctx);
1630 /* No options for now. */
1631 line = skip_options (line);
1633 /* Break the line down into an strlist. Each pattern is by
1634 definition percent-plus escaped. However we only support keyids
1635 and fingerprints and thus the client has no need to apply the
1638 for (p=line; *p; line = p)
1640 while (*p && *p != ' ')
1646 sl = xtrymalloc (sizeof *sl + strlen (line));
1649 err = gpg_error_from_syserror ();
1653 strcpy_escaped_plus (sl->d, line);
1659 /* Setup an output stream and perform the get. */
1660 outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1662 err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1665 err = ks_action_get (ctrl, list, outfp);
1670 free_strlist (list);
1671 return leave_cmd (ctx, err);
1675 static const char hlp_ks_fetch[] =
1678 "Get the key(s) from URL.";
1680 cmd_ks_fetch (assuan_context_t ctx, char *line)
1682 ctrl_t ctrl = assuan_get_pointer (ctx);
1686 /* No options for now. */
1687 line = skip_options (line);
1689 /* Setup an output stream and perform the get. */
1690 outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1692 err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1695 err = ks_action_fetch (ctrl, line, outfp);
1699 return leave_cmd (ctx, err);
1704 static const char hlp_ks_put[] =
1707 "Send a key to the configured OpenPGP keyservers. The actual key material\n"
1708 "is then requested by Dirmngr using\n"
1710 " INQUIRE KEYBLOCK\n"
1712 "The client shall respond with a binary version of the keyblock. For LDAP\n"
1713 "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
1716 " INQUIRE KEYBLOCK_INFO\n"
1718 "The client shall respond with a colon delimited info lines";
1720 cmd_ks_put (assuan_context_t ctx, char *line)
1722 ctrl_t ctrl = assuan_get_pointer (ctx);
1724 unsigned char *value = NULL;
1726 unsigned char *info = NULL;
1729 /* No options for now. */
1730 line = skip_options (line);
1732 /* Ask for the key material. */
1733 err = assuan_inquire (ctx, "KEYBLOCK",
1734 &value, &valuelen, MAX_KEYBLOCK_LENGTH);
1737 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1741 if (!valuelen) /* No data returned; return a comprehensible error. */
1743 err = gpg_error (GPG_ERR_MISSING_CERT);
1747 /* Ask for the key meta data. Not actually needed for HKP servers
1748 but we do it anyway test the client implementaion. */
1749 err = assuan_inquire (ctx, "KEYBLOCK_INFO",
1750 &info, &infolen, MAX_KEYBLOCK_LENGTH);
1753 log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1758 err = ks_action_put (ctrl, value, valuelen);
1763 return leave_cmd (ctx, err);
1769 static const char hlp_getinfo[] =
1772 "Multi purpose command to return certain information. \n"
1773 "Supported values of WHAT are:\n"
1775 "version - Return the version of the program.\n"
1776 "pid - Return the process id of the server.\n"
1778 "socket_name - Return the name of the socket.\n";
1780 cmd_getinfo (assuan_context_t ctx, char *line)
1784 if (!strcmp (line, "version"))
1786 const char *s = VERSION;
1787 err = assuan_send_data (ctx, s, strlen (s));
1789 else if (!strcmp (line, "pid"))
1793 snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1794 err = assuan_send_data (ctx, numbuf, strlen (numbuf));
1796 else if (!strcmp (line, "socket_name"))
1798 const char *s = dirmngr_user_socket_name ();
1801 s = dirmngr_sys_socket_name ();
1804 err = assuan_send_data (ctx, s, strlen (s));
1806 err = gpg_error (GPG_ERR_NO_DATA);
1809 err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1811 return leave_cmd (ctx, err);
1816 static const char hlp_killdirmngr[] =
1819 "This command allows a user - given sufficient permissions -\n"
1820 "to kill this dirmngr process.\n";
1822 cmd_killdirmngr (assuan_context_t ctx, char *line)
1824 ctrl_t ctrl = assuan_get_pointer (ctx);
1829 if (opt.system_daemon)
1831 if (opt.system_service)
1832 err = set_error (GPG_ERR_NOT_SUPPORTED,
1833 "can't do that whilst running as system service");
1835 err = check_owner_permission (ctx,
1836 "no permission to kill this process");
1843 ctrl->server_local->stopme = 1;
1844 err = gpg_error (GPG_ERR_EOF);
1850 static const char hlp_reloaddirmngr[] =
1853 "This command is an alternative to SIGHUP\n"
1854 "to reload the configuration.";
1856 cmd_reloaddirmngr (assuan_context_t ctx, char *line)
1861 if (opt.system_daemon)
1863 #ifndef HAVE_W32_SYSTEM
1866 assuan_peercred_t cred;
1868 ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
1869 if (!ec && cred->uid)
1870 ec = GPG_ERR_EPERM; /* Only root may terminate. */
1872 return set_error (ec, "no permission to reload this process");
1877 dirmngr_sighup_action ();
1884 /* Tell the assuan library about our commands. */
1886 register_commands (assuan_context_t ctx)
1890 assuan_handler_t handler;
1891 const char * const help;
1893 { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
1894 { "ISVALID", cmd_isvalid, hlp_isvalid },
1895 { "CHECKCRL", cmd_checkcrl, hlp_checkcrl },
1896 { "CHECKOCSP", cmd_checkocsp, hlp_checkocsp },
1897 { "LOOKUP", cmd_lookup, hlp_lookup },
1898 { "LOADCRL", cmd_loadcrl, hlp_loadcrl },
1899 { "LISTCRLS", cmd_listcrls, hlp_listcrls },
1900 { "CACHECERT", cmd_cachecert, hlp_cachecert },
1901 { "VALIDATE", cmd_validate, hlp_validate },
1902 { "KEYSERVER", cmd_keyserver, hlp_keyserver },
1903 { "KS_SEARCH", cmd_ks_search, hlp_ks_search },
1904 { "KS_GET", cmd_ks_get, hlp_ks_get },
1905 { "KS_FETCH", cmd_ks_fetch, hlp_ks_fetch },
1906 { "KS_PUT", cmd_ks_put, hlp_ks_put },
1907 { "GETINFO", cmd_getinfo, hlp_getinfo },
1908 { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
1909 { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
1914 for (i=j=0; table[i].name; i++)
1916 rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1925 /* Note that we do not reset the list of configured keyservers. */
1927 reset_notify (assuan_context_t ctx, char *line)
1929 ctrl_t ctrl = assuan_get_pointer (ctx);
1933 ldapserver_list_free (ctrl->server_local->ldapservers);
1935 ctrl->server_local->ldapservers = NULL;
1940 /* Startup the server and run the main command loop. With FD = -1
1941 used stdin/stdout. */
1943 start_command_handler (assuan_fd_t fd)
1945 static const char hello[] = "Dirmngr " VERSION " at your service";
1946 static char *hello_line;
1948 assuan_context_t ctx;
1951 ctrl = xtrycalloc (1, sizeof *ctrl);
1953 ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
1954 if (!ctrl || !ctrl->server_local)
1956 log_error (_("can't allocate control structure: %s\n"),
1962 dirmngr_init_default_ctrl (ctrl);
1964 rc = assuan_new (&ctx);
1967 log_error (_("failed to allocate assuan context: %s\n"),
1972 if (fd == ASSUAN_INVALID_FD)
1974 assuan_fd_t filedes[2];
1976 filedes[0] = assuan_fdopen (0);
1977 filedes[1] = assuan_fdopen (1);
1978 rc = assuan_init_pipe_server (ctx, filedes);
1982 rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
1987 assuan_release (ctx);
1988 log_error (_("failed to initialize the server: %s\n"),
1993 rc = register_commands (ctx);
1996 log_error (_("failed to the register commands with Assuan: %s\n"),
2005 const char *cfgname;
2007 cfgname = opt.config_filename? opt.config_filename : "[none]";
2009 n = (30 + strlen (opt.homedir) + strlen (cfgname)
2010 + strlen (hello) + 1);
2011 hello_line = xmalloc (n+1);
2012 snprintf (hello_line, n,
2022 ctrl->server_local->assuan_ctx = ctx;
2023 assuan_set_pointer (ctx, ctrl);
2025 assuan_set_hello_line (ctx, hello_line);
2026 assuan_register_option_handler (ctx, option_handler);
2027 assuan_register_reset_notify (ctx, reset_notify);
2031 rc = assuan_accept (ctx);
2036 log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
2040 #ifndef HAVE_W32_SYSTEM
2043 assuan_peercred_t peercred;
2045 if (!assuan_get_peercred (ctx, &peercred))
2046 log_info ("connection from process %ld (%ld:%ld)\n",
2047 (long)peercred->pid, (long)peercred->uid,
2048 (long)peercred->gid);
2052 rc = assuan_process (ctx);
2055 log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
2061 ldap_wrapper_connection_cleanup (ctrl);
2063 ldapserver_list_free (ctrl->server_local->ldapservers);
2065 ctrl->server_local->ldapservers = NULL;
2067 ctrl->server_local->assuan_ctx = NULL;
2068 assuan_release (ctx);
2070 if (ctrl->server_local->stopme)
2074 log_error ("oops: connection control structure still referenced (%d)\n",
2078 release_ctrl_ocsp_certs (ctrl);
2079 xfree (ctrl->server_local);
2085 /* Send a status line back to the client. KEYWORD is the status
2086 keyword, the optional string arguments are blank separated added to
2087 the line, the last argument must be a NULL. */
2089 dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
2091 gpg_error_t err = 0;
2095 va_start (arg_ptr, keyword);
2097 if (ctrl->server_local)
2099 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2105 while ( (text = va_arg (arg_ptr, const char *)) )
2112 for ( ; *text && n < DIM (buf)-2; n++)
2116 err = assuan_write_status (ctx, keyword, buf);
2124 /* Print a help status line. TEXTLEN gives the length of the text
2125 from TEXT to be printed. The function splits text at LFs. */
2127 dirmngr_status_help (ctrl_t ctrl, const char *text)
2129 gpg_error_t err = 0;
2131 if (ctrl->server_local)
2133 assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2141 for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
2146 err = assuan_write_status (ctx, "#", buf);
2148 while (!err && *text);
2154 /* Send a tick progress indicator back. Fixme: This is only done for
2155 the currently active channel. */
2157 dirmngr_tick (ctrl_t ctrl)
2159 static time_t next_tick = 0;
2160 gpg_error_t err = 0;
2161 time_t now = time (NULL);
2165 next_tick = now + 1;
2167 else if ( now > next_tick )
2171 err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
2174 /* Take this as in indication for a cancel request. */
2175 err = gpg_error (GPG_ERR_CANCELED);
2180 next_tick = now + 1;