Add libpwmd.conf option "include".
[libpwmd.git] / src / libpwmd.c
blobf3a21d1078b9bad4c366bf00833020e171256fac
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of libpwmd.
8 Libpwmd 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 2 of the License, or
11 (at your option) any later version.
13 Libpwmd 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 Libpwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #include <signal.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <sys/wait.h>
39 #include <fcntl.h>
40 #include <pwd.h>
41 #include <time.h>
42 #include <limits.h>
43 #include <sys/select.h>
44 #include <termios.h>
45 #include <libpwmd.h>
47 #ifdef HAVE_STRINGS_H
48 #include <strings.h>
49 #endif
51 #ifndef LINE_MAX
52 #define LINE_MAX 2048
53 #endif
55 #include "mem.h"
56 #include "misc.h"
57 #include "types.h"
59 #ifdef WITH_PINENTRY
60 #include "pinentry.h"
61 #endif
63 #ifdef WITH_QUALITY
64 #include "zxcvbn.h"
65 #endif
67 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
68 #include <sys/types.h>
69 #include <sys/socket.h>
70 #include <netdb.h>
71 #include <netinet/in.h>
72 #endif
74 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
75 ? gpg_error(rc) : rc
77 typedef struct
79 size_t len;
80 void *buf;
81 } membuf_t;
83 static gpg_error_t status_cb (void *data, const char *line);
85 ssize_t
86 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
88 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
89 pwm_t *pwm = assuan_get_pointer (ctx);
91 #ifdef WITH_SSH
92 if (pwm && pwm->tcp && pwm->tcp->ssh)
93 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
94 #endif
95 #ifdef WITH_GNUTLS
96 if (pwm && pwm->tcp && pwm->tcp->tls)
97 return tls_read_hook (pwm, fd, data, len);
98 #endif
99 #else
100 (void)ctx;
101 #endif
103 return read ((int) fd, data, len);
106 ssize_t
107 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
108 size_t len)
110 ssize_t wrote;
111 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
112 pwm_t *pwm = assuan_get_pointer (ctx);
114 #ifdef WITH_SSH
115 if (pwm && pwm->tcp && pwm->tcp->ssh)
116 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
117 #endif
118 #ifdef WITH_GNUTLS
119 if (pwm && pwm->tcp && pwm->tcp->tls)
120 return tls_write_hook (pwm, fd, data, len);
121 #endif
122 #else
123 (void)ctx;
124 #endif
126 /* libassuan cannot handle EAGAIN when doing writes. */
129 wrote = write ((int) fd, data, len);
130 if (wrote == -1 && errno == EAGAIN)
131 usleep (50000);
133 while (wrote == -1 && errno == EAGAIN);
135 return wrote;
138 pid_t
139 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
140 int options)
142 (void)ctx;
143 (void)action;
144 return waitpid (pid, status, options);
147 gpg_error_t
148 pwmd_init ()
150 static int initialized;
152 #ifdef WITH_GNUTLS
153 // May be called more than once.
154 gnutls_global_init ();
155 #endif
157 if (initialized)
158 return 0;
160 #ifdef ENABLE_NLS
161 bindtextdomain ("libpwmd", LOCALEDIR);
162 #endif
163 #ifdef WITH_SSH
164 libssh2_init (0);
165 #endif
166 gpgrt_init ();
167 //gpgrt_set_alloc_func (_xrealloc_gpgrt);
169 #ifdef WITH_QUALITY
170 ZxcvbnInit (NULL);
171 #endif
173 initialized = 1;
174 return 0;
177 void
178 pwmd_deinit ()
180 #ifdef WITH_GNUTLS
181 gnutls_global_deinit ();
182 #endif
183 #ifdef WITH_QUALITY
184 ZxcvbnUnInit();
185 #endif
188 gpg_error_t
189 _connect_finalize (pwm_t * pwm)
191 gpg_error_t rc = 0;
192 char *result = NULL;
193 int active[2];
194 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
196 if (n <= 0)
197 return GPG_ERR_EBADFD;
199 pwm->fd = active[0];
200 #ifdef WITH_PINENTRY
201 pwm->pinentry_pid = -1;
202 #endif
204 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
205 if (!rc)
207 pwm->version = strtoul (result, NULL, 16);
208 pwmd_free (result);
211 if (!rc && pwm->name)
212 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
213 pwm->name);
215 return rc;
218 static gpg_error_t
219 connect_uds (pwm_t * pwm, const char *path)
221 char *socketpath = NULL;
222 struct passwd pw;
223 char *pwbuf;
224 gpg_error_t rc;
226 if (!pwm)
227 return GPG_ERR_INV_ARG;
229 pwbuf = _getpwuid (&pw);
230 if (!pwbuf)
231 return gpg_error_from_syserror ();
233 if (!path || !*path)
234 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
235 else
236 socketpath = _expand_homedir ((char *) path, &pw);
238 pwmd_free (pwbuf);
239 if (!socketpath)
240 return GPG_ERR_ENOMEM;
242 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
243 pwmd_free (socketpath);
244 return rc ? rc : _connect_finalize (pwm);
247 static gpg_error_t
248 init_handle (pwm_t * pwm)
250 gpg_error_t rc;
251 static struct assuan_malloc_hooks mhooks = {
252 pwmd_malloc, pwmd_realloc, pwmd_free
254 static struct assuan_system_hooks shooks = {
255 ASSUAN_SYSTEM_HOOKS_VERSION,
256 __assuan_usleep,
257 __assuan_pipe,
258 __assuan_close,
259 hook_read,
260 hook_write,
261 //FIXME
262 NULL, //recvmsg
263 NULL, //sendmsg both are used for FD passing
264 __assuan_spawn,
265 hook_waitpid,
266 __assuan_socketpair,
267 __assuan_socket,
268 __assuan_connect
271 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
272 NULL);
273 if (rc)
274 return rc;
276 assuan_set_pointer (pwm->ctx, pwm);
277 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
278 return 0;
281 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
282 void
283 free_tcp (pwm_t *pwm)
285 struct tcp_s *tcp = pwm->tcp;
287 if (!tcp)
288 return;
290 #ifdef WITH_SSH
291 _free_ssh_conn (tcp->ssh);
292 #endif
293 #ifdef WITH_GNUTLS
294 tls_free (pwm);
295 #endif
297 pwmd_free (tcp->host);
298 if (tcp->addrs)
300 freeaddrinfo (tcp->addrs);
301 tcp->addrs = NULL;
304 pthread_cond_destroy (&tcp->dns_cond);
305 pthread_mutex_destroy (&tcp->dns_mutex);
306 pwmd_free (tcp);
307 pwm->tcp = NULL;
309 #endif
311 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
312 static void *
313 resolve_host_thread (void *arg)
315 pwm_t *pwm = arg;
316 struct addrinfo hints = { 0 };
317 char portstr[6];
319 switch (pwm->prot)
321 case PWMD_IP_ANY:
322 hints.ai_family = AF_UNSPEC;
323 break;
324 case PWMD_IPV4:
325 hints.ai_family = AF_INET;
326 break;
327 case PWMD_IPV6:
328 hints.ai_family = AF_INET6;
329 break;
332 hints.ai_socktype = SOCK_STREAM;
333 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
334 int *n = pwmd_malloc (sizeof (int));
335 pthread_cleanup_push (pwmd_free, n);
336 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
337 pthread_cleanup_pop (0);
338 pthread_cond_broadcast (&pwm->tcp->dns_cond);
339 pthread_exit (n);
340 return NULL;
343 gpg_error_t
344 tcp_connect_common (pwm_t * pwm)
346 #define TS_TIMEOUT 50000000L
347 int n;
348 gpg_error_t rc = 0;
349 pthread_t tid;
350 time_t now;
352 time (&now);
353 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
354 if (n)
355 return gpg_error_from_errno (n);
357 pthread_mutex_lock (&pwm->tcp->dns_mutex);
359 for (;;)
361 struct timespec ts;
362 int *result = NULL;
364 clock_gettime (CLOCK_REALTIME, &ts);
365 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
366 ts.tv_sec++;
367 ts.tv_nsec = 0;
369 else
370 ts.tv_nsec += TS_TIMEOUT;
372 if (pwm->cancel)
374 #ifdef HAVE_PTHREAD_CANCEL
375 pthread_cancel (tid);
376 pthread_join (tid, NULL);
377 #else
378 pthread_join (tid, (void **)&result);
379 pwmd_free (result);
380 #endif
381 return GPG_ERR_CANCELED;
384 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
385 &ts);
386 if (n == ETIMEDOUT)
388 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
390 #ifdef HAVE_PTHREAD_CANCEL
391 pthread_cancel (tid);
392 pthread_join (tid, NULL);
393 #else
394 pthread_join (tid, (void **)&result);
395 pwmd_free (result);
396 #endif
397 return GPG_ERR_ETIMEDOUT;
400 continue;
402 else if (n)
404 #ifdef HAVE_PTHREAD_CANCEL
405 pthread_cancel (tid);
406 pthread_join (tid, NULL);
407 #else
408 pthread_join (tid, (void **)&result);
409 pwmd_free (result);
410 #endif
411 return gpg_error_from_errno (n);
414 pthread_join (tid, (void **)&result);
415 n = *result;
416 pwmd_free (result);
417 break;
420 if (n)
421 return GPG_ERR_UNKNOWN_HOST; //FIXME
423 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
424 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
426 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
427 if (pwm->fd == -1)
429 rc = gpg_error_from_syserror ();
430 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
431 break;
432 continue;
435 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
437 rc = gpg_error_from_syserror ();
438 break;
441 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
442 pwm->tcp->addr->ai_family == AF_INET6
443 ? sizeof (struct sockaddr_in6)
444 : sizeof (struct sockaddr)) == -1)
446 struct timeval tv;
447 fd_set wfds;
448 unsigned elapsed = 0;
450 rc = gpg_error_from_syserror ();
451 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
453 close (pwm->fd);
454 pwm->fd = -1;
455 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
456 return rc;
457 continue;
460 again:
461 tv.tv_sec = 1;
462 tv.tv_usec = 0;
463 FD_ZERO (&wfds);
464 FD_SET (pwm->fd, &wfds);
465 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
466 rc = 0;
467 if (!n || pwm->cancel)
469 if (pwm->cancel)
470 rc = gpg_error (GPG_ERR_CANCELED);
471 else if (++elapsed >= pwm->socket_timeout)
472 rc = gpg_error (GPG_ERR_ETIMEDOUT);
473 else
474 goto again;
476 else if (n != -1)
478 socklen_t len = sizeof(int);
480 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
481 if (n)
482 rc = gpg_error_from_errno (n);
484 else if (n == -1)
485 rc = gpg_error_from_syserror ();
487 if (rc)
489 close (pwm->fd);
490 pwm->fd = -1;
491 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
492 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
493 || pwm->cancel)
494 return rc;
496 else
497 break;
499 else
500 break;
503 if (!rc)
504 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
505 rc = gpg_error_from_syserror ();
507 return rc;
509 #endif
511 static void
512 command_start (pwm_t *pwm)
514 pwm->cancel = 0;
517 gpg_error_t
518 pwmd_connect (pwm_t * pwm, const char *url, ...)
520 const char *p = url;
521 gpg_error_t rc;
523 if (!pwm)
524 return FINISH (GPG_ERR_INV_ARG);
525 else if (!pwm->ctx)
527 rc = init_handle (pwm);
528 if (rc)
529 return rc;
532 command_start (pwm);
534 if (!(pwm->opts & OPT_SIGPIPE))
535 signal (SIGPIPE, SIG_IGN);
537 #ifdef WITH_GNUTLS
538 pwm->tls_error = 0;
539 #endif
540 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
542 if (p && (*p == '/' || *p == '~'))
543 rc = connect_uds (pwm, p);
544 else if (!p || !strncmp (p, "file://", 7))
546 if (p)
547 p += 7;
548 #ifdef DEFAULT_PWMD_SOCKET
549 else
550 p = DEFAULT_PWMD_SOCKET;
551 #endif
552 rc = connect_uds (pwm, p);
554 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
555 !strncmp (p, "ssh4://", 7))
557 #ifndef WITH_SSH
558 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
559 #else
560 char *host = NULL;
561 int port;
562 char *username = NULL;
564 if (!strncmp (p, "ssh6://", 7))
566 pwm->prot = PWMD_IPV6;
567 p += 7;
569 else if (!strncmp (p, "ssh4://", 7))
571 pwm->prot = PWMD_IPV4;
572 p += 7;
574 else
576 pwm->prot = PWMD_IP_ANY;
577 p += 6;
580 rc = _parse_ssh_url (p, &host, &port, &username);
581 if (!rc)
583 va_list ap;
584 char *identity = NULL;
585 char *knownhosts = NULL;
587 va_start (ap, url);
588 identity = va_arg (ap, char *);
590 if (!identity && !pwm->use_agent)
591 rc = GPG_ERR_INV_ARG;
592 else
593 knownhosts = va_arg (ap, char *);
595 va_end (ap);
597 if (!rc)
598 rc = _do_ssh_connect (pwm, host, port, identity, username,
599 knownhosts);
600 if (!rc)
602 rc = _connect_finalize (pwm);
603 if (rc)
604 free_tcp (pwm);
608 pwmd_free (host);
609 pwmd_free (username);
610 pwm->local_pinentry = 1;
611 pwmd_free (pwm->ssh_passphrase);
612 pwm->ssh_passphrase = NULL;
613 #endif
615 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
616 !strncmp (p, "tls4://", 7))
618 #ifndef WITH_GNUTLS
619 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
620 #else
621 char *host = NULL;
622 int port;
624 if (!strncmp (p, "tls6://", 7))
626 pwm->prot = PWMD_IPV6;
627 p += 7;
629 else if (!strncmp (p, "tls4://", 7))
631 pwm->prot = PWMD_IPV4;
632 p += 7;
634 else
636 pwm->prot = PWMD_IP_ANY;
637 p += 6;
640 rc = tls_parse_url (p, &host, &port);
641 if (!rc)
643 va_list ap;
644 char *clientcert = NULL;
645 char *clientkey = NULL;
646 char *cacert = NULL;
647 char *server_fp = NULL;
649 va_start (ap, url);
650 clientcert = va_arg (ap, char *);
652 if (!clientcert)
653 rc = GPG_ERR_INV_ARG;
654 else
656 clientkey = va_arg (ap, char *);
657 if (!clientkey)
658 rc = GPG_ERR_INV_ARG;
659 else
661 cacert = va_arg (ap, char *);
662 if (!cacert)
663 rc = GPG_ERR_INV_ARG;
664 else
665 server_fp = va_arg (ap, char *);
669 va_end (ap);
671 if (!rc)
672 rc = tls_connect (pwm, host, port, clientcert, clientkey, cacert,
673 pwm->tls_priority, server_fp, pwm->tls_verify);
674 if (!rc)
676 rc = _connect_finalize (pwm);
677 if (rc)
678 free_tcp (pwm);
682 pwmd_free (host);
683 pwm->local_pinentry = 1;
684 #endif
687 if (!rc)
688 pwm->connected = 1;
690 return FINISH (rc);
693 static void
694 disconnect (pwm_t * pwm)
696 if (!pwm)
697 return;
699 if (pwm->ctx)
700 assuan_release (pwm->ctx);
702 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
703 free_tcp (pwm);
704 #endif
705 pwm->ctx = NULL;
706 pwm->fd = -1;
707 pwm->connected = 0;
710 void
711 pwmd_close (pwm_t * pwm)
713 if (!pwm)
714 return;
716 disconnect (pwm);
717 pwmd_free (pwm->pinentry_error);
718 pwmd_free (pwm->pinentry_desc);
719 pwmd_free (pwm->pinentry_prompt);
720 pwmd_free (pwm->pinentry_tty);
721 pwmd_free (pwm->pinentry_display);
722 pwmd_free (pwm->pinentry_term);
723 pwmd_free (pwm->pinentry_lcctype);
724 pwmd_free (pwm->pinentry_lcmessages);
725 pwmd_free (pwm->filename);
726 pwmd_free (pwm->name);
727 pwmd_free (pwm->passphrase_info);
728 pwmd_free (pwm->passphrase_hint);
729 pwmd_free (pwm->ssh_passphrase);
730 pwmd_free (pwm->tls_priority);
732 #ifdef WITH_PINENTRY
733 if (pwm->pctx)
734 _pinentry_disconnect (pwm);
735 #endif
737 pwmd_free (pwm);
740 static gpg_error_t
741 inquire_realloc_cb (void *data, const void *buffer, size_t len)
743 membuf_t *mem = (membuf_t *) data;
744 void *p;
746 if (!buffer)
747 return 0;
749 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
750 return gpg_error (GPG_ERR_ENOMEM);
752 mem->buf = p;
753 memcpy ((char *) mem->buf + mem->len, buffer, len);
754 mem->len += len;
755 return 0;
758 static gpg_error_t
759 get_password (pwm_t * pwm, char **result, size_t * len,
760 pwmd_pinentry_t w, int echo)
762 char buf[ASSUAN_LINELENGTH+1] = { 0 }, *p;
763 struct termios told, tnew;
764 char *key = NULL;
766 if (result)
767 *result = NULL;
769 if (len)
770 *len = 0;
772 if (!isatty (STDIN_FILENO))
774 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
775 return GPG_ERR_ENOTTY;
778 if (!echo)
780 if (tcgetattr (STDIN_FILENO, &told) == -1)
781 return gpg_error_from_syserror ();
783 memcpy (&tnew, &told, sizeof (struct termios));
784 tnew.c_lflag &= ~(ECHO);
785 tnew.c_lflag |= ICANON | ECHONL;
787 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
789 int n = errno;
791 tcsetattr (STDIN_FILENO, TCSANOW, &told);
792 return gpg_error_from_errno (n);
796 if (pwm->passphrase_hint)
797 fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint);
799 switch (w)
801 case PWMD_PINENTRY_OPEN:
802 fprintf (stderr, N_("Passphrase for %s: "), pwm->filename);
803 break;
804 case PWMD_PINENTRY_OPEN_FAILED:
805 fprintf (stderr, N_("Invalid passphrase. Passphrase for %s: "),
806 pwm->filename);
807 break;
808 case PWMD_PINENTRY_SAVE:
809 fprintf (stderr, N_("New passphrase for %s: "), pwm->filename);
810 break;
811 case PWMD_PINENTRY_SAVE_CONFIRM:
812 fprintf (stderr, N_("Repeat passphrase: "));
813 break;
814 case PWMD_PINENTRY_CONFIRM:
815 if (pwm->pinentry_desc)
816 fprintf (stderr, "%s", pwm->pinentry_desc);
818 if (pwm->pinentry_prompt)
819 fprintf (stderr, "%s", pwm->pinentry_prompt);
820 else
821 fprintf(stderr, N_("Confirm [y/N]:"));
822 default:
823 break;
826 p = fgets (buf, sizeof (buf), stdin);
828 if (!echo)
829 tcsetattr (STDIN_FILENO, TCSANOW, &told);
831 if (!p || feof (stdin))
833 clearerr (stdin);
834 return GPG_ERR_CANCELED;
837 /* Strip the newline character. */
838 p[strlen (p) - 1] = 0;
840 if (buf[0])
842 if (w == PWMD_PINENTRY_CONFIRM)
844 if (*p != 'y' && *p != 'Y')
845 return GPG_ERR_CANCELED;
846 return 0;
849 key = pwmd_strdup_printf ("%s", p);
850 wipememory (buf, 0, sizeof (buf));
851 if (!key)
852 return GPG_ERR_ENOMEM;
854 if (result)
855 *result = key;
857 if (len)
858 *len = strlen (key);
860 else
862 if (w == PWMD_PINENTRY_CONFIRM)
863 return GPG_ERR_CANCELED;
865 /* To satisfy inquire_cb(). */
866 if (result)
867 *result = pwmd_strdup ("");
869 if (len)
870 *len = 1;
873 return 0;
876 gpg_error_t
877 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
879 gpg_error_t rc;
880 int new_password = 0;
881 char *password = NULL, *newpass = NULL;
882 int error = 0;
884 command_start (pwm);
886 if (data)
887 *data = NULL;
889 if (size)
890 *size = 0;
892 if (!strcmp (keyword, "NEW_PASSPHRASE"))
893 new_password = 1;
895 if (!new_password && pwm->pinentry_try)
896 error = 1;
898 again:
899 if (pwm->disable_pinentry)
901 rc = get_password (pwm, &password, size,
902 new_password ? PWMD_PINENTRY_SAVE :
903 error ? PWMD_PINENTRY_OPEN_FAILED :
904 PWMD_PINENTRY_OPEN, 0);
905 if (!rc && new_password)
906 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
909 else
911 pwmd_pinentry_t which;
913 if (error)
914 which = new_password
915 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
916 else
917 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
919 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
920 if (!rc && new_password)
921 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
922 PWMD_PINENTRY_SAVE_CONFIRM);
925 if (!rc && new_password)
927 if ((!password && newpass) || (!newpass && password)
928 || (newpass && password && strcmp (newpass, password)))
930 if (pwm->disable_pinentry)
931 fprintf (stderr, N_("Passphrases do not match.\n"));
933 pwmd_free (password);
934 pwmd_free (newpass);
935 password = newpass = NULL;
936 error = 1;
937 goto again;
941 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
942 pwmd_free (newpass);
943 if (!rc && data)
944 *data = password;
945 else
946 pwmd_free (password);
948 return rc;
951 static gpg_error_t
952 inquire_cb (void *data, const char *keyword)
954 pwm_t *pwm = (pwm_t *) data;
955 gpg_error_t rc = 0;
956 int free_result = 0;
957 char *result = NULL;
958 int is_password = 0;
959 int new_password = 0;
961 if (!strcmp (keyword, "PASSPHRASE") || !strcmp (keyword, "SIGN_PASSPHRASE"))
962 is_password = 1;
963 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
964 new_password = 1;
966 /* Shouldn't get this far without a callback. */
967 if (!pwm->override_inquire && !pwm->inquire_func
968 && !is_password && !new_password)
969 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
971 for (;;)
973 size_t len = 0;
974 gpg_error_t arc;
976 result = NULL;
978 if (!pwm->override_inquire && (is_password || new_password))
980 free_result = 1;
981 rc = pwmd_password (data, keyword, &result, &len);
982 if (!rc)
983 rc = GPG_ERR_EOF;
985 else
986 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
987 &len);
989 /* gpg will truncate a passphrase at the first nil byte which may be bad
990 * for generated key files. */
991 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
992 && (is_password || new_password))
994 if (len && result && *result)
996 for (size_t n = 0; n < len; n++)
998 if (result[n] == 0 && n+1 != len)
999 rc = GPG_ERR_INV_PASSPHRASE;
1004 cancel:
1005 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
1007 #ifndef LIBASSUAN_2_1_0
1008 gpg_error_t trc = rc;
1010 /* Cancel this inquire. */
1011 rc = assuan_send_data (pwm->ctx, NULL, 1);
1012 if (!rc)
1014 char *line;
1015 size_t len;
1017 /* There is a bug (or feature?) in assuan_send_data() that
1018 * when cancelling an inquire the next read from the server is
1019 * not done until the next command making the next command
1020 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1022 rc = assuan_read_line (pwm->ctx, &line, &len);
1024 /* Restore the original error. This differs from the error
1025 * returned from the pwmd command (GPG_ERR_CANCELED). This
1026 * error is returned to the calling function.
1028 if (!rc)
1029 rc = trc;
1031 #endif
1032 break;
1035 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1037 if (len <= 0 && !result)
1039 rc = 0;
1040 break;
1042 else if ((len <= 0 && result) || (len && !result))
1044 rc = gpg_error (GPG_ERR_INV_ARG);
1045 break;
1048 if (pwm->inquire_maxlen
1049 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1051 rc = gpg_error (GPG_ERR_TOO_LARGE);
1052 if (!free_result)
1053 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1054 &result, &len);
1055 goto cancel;
1058 arc = assuan_send_data (pwm->ctx, result, len);
1059 if (gpg_err_code (rc) == GPG_ERR_EOF)
1061 rc = arc;
1062 break;
1065 rc = arc;
1067 else if (rc)
1068 break;
1070 if (!rc)
1072 pwm->inquire_sent += len;
1074 if (pwm->status_func)
1076 char buf[ASSUAN_LINELENGTH];
1078 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1079 pwm->inquire_total);
1080 rc = pwm->status_func (pwm->status_data, buf);
1081 if (rc)
1082 continue;
1087 if (free_result)
1088 pwmd_free (result);
1090 pwm->inquire_maxlen = pwm->inquire_sent = 0;
1091 return rc;
1094 static gpg_error_t
1095 parse_assuan_line (pwm_t * pwm)
1097 gpg_error_t rc;
1098 char *line;
1099 size_t len;
1101 rc = assuan_read_line (pwm->ctx, &line, &len);
1102 if (!rc)
1104 if (line[0] == 'O' && line[1] == 'K' &&
1105 (line[2] == 0 || line[2] == ' '))
1108 else if (line[0] == '#')
1111 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1113 rc = status_cb (pwm, line[1] == 0 ? line + 1 : line + 2);
1115 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1116 (line[3] == 0 || line[3] == ' '))
1118 line += 4;
1119 rc = strtol (line, NULL, 10);
1123 return rc;
1126 static void
1127 reset_handle (pwm_t *pwm)
1129 pwm->fd = -1;
1130 pwm->cancel = 0;
1131 pwm->pinentry_disabled = 0;
1132 #ifdef WITH_PINENTRY
1133 if (pwm->pctx)
1134 _pinentry_disconnect (pwm);
1135 #endif
1136 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1137 #ifdef WITH_GNUTLS
1138 pwm->tls_error = 0;
1139 #endif
1141 if (pwm->tcp)
1142 pwm->tcp->rc = 0;
1143 #endif
1146 gpg_error_t
1147 pwmd_disconnect (pwm_t * pwm)
1149 if (!pwm)
1150 return FINISH (GPG_ERR_INV_ARG);
1152 command_start (pwm);
1154 if (pwm->fd == -1)
1155 return FINISH (GPG_ERR_INV_STATE);
1157 disconnect (pwm);
1158 reset_handle (pwm);
1159 return 0;
1162 /* Note that this should only be called when not in a command. */
1163 gpg_error_t
1164 pwmd_process (pwm_t * pwm)
1166 gpg_error_t rc = 0;
1167 fd_set fds;
1168 struct timeval tv = { 0, 0 };
1169 int n;
1171 if (!pwm || pwm->fd == -1)
1172 return FINISH (GPG_ERR_INV_ARG);
1173 else if (!pwm->ctx)
1174 return FINISH (GPG_ERR_INV_STATE);
1176 FD_ZERO (&fds);
1177 FD_SET (pwm->fd, &fds);
1178 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1180 if (n == -1)
1181 return FINISH (gpg_error_from_syserror ());
1183 if (n > 0)
1185 if (FD_ISSET (pwm->fd, &fds))
1186 rc = parse_assuan_line (pwm);
1189 while (!rc && assuan_pending_line (pwm->ctx))
1190 rc = parse_assuan_line (pwm);
1192 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1193 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1195 close (pwm->fd);
1196 pwm->fd = -1;
1198 #endif
1200 return FINISH (rc);
1203 static gpg_error_t
1204 status_cb (void *data, const char *line)
1206 pwm_t *pwm = data;
1208 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1209 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1210 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1212 pwmd_free (pwm->passphrase_hint);
1213 pwm->passphrase_hint = pwmd_strdup (line+16);
1215 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1217 pwmd_free (pwm->passphrase_info);
1218 pwm->passphrase_info = pwmd_strdup (line+16);
1220 #ifdef WITH_GNUTLS
1221 else if (!strcmp (line, "REHANDSHAKE"))
1223 char buf[32];
1224 ssize_t ret;
1226 ret = tls_read_hook (pwm, pwm->fd, buf, sizeof (buf));
1227 if (ret < 0)
1229 pwm->tls_error = ret;
1230 return GPG_ERR_GENERAL;
1233 #endif
1235 if (pwm->status_func)
1236 return pwm->status_func (pwm->status_data, line);
1238 return 0;
1241 gpg_error_t
1242 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1243 char **result, size_t * len, const char *cmd)
1245 membuf_t data;
1246 gpg_error_t rc;
1248 if (!cmd || !*cmd)
1249 return FINISH (GPG_ERR_INV_ARG);
1251 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1252 return FINISH (GPG_ERR_LINE_TOO_LONG);
1254 data.len = 0;
1255 data.buf = NULL;
1256 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1257 #ifdef WITH_QUALITY
1258 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1259 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1260 #else
1261 inquire_cb, pwm,
1262 #endif
1263 status_cb, pwm);
1265 if (rc)
1267 if (data.buf)
1269 pwmd_free (data.buf);
1270 data.buf = NULL;
1273 else
1275 if (data.buf)
1277 inquire_realloc_cb (&data, "", 1);
1279 if (result)
1280 *result = (char *) data.buf;
1281 else
1282 pwmd_free (data.buf);
1284 if (len)
1285 *len = data.len;
1289 pwm->inquire_maxlen = 0;
1290 return rc;
1293 gpg_error_t
1294 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1295 pwmd_inquire_cb_t func, void *user, const char *cmd,
1296 va_list ap)
1298 char *buf;
1299 size_t len;
1300 va_list ap2;
1302 if (!pwm)
1303 return GPG_ERR_INV_ARG;
1305 command_start (pwm);
1307 if (result)
1308 *result = NULL;
1310 if (rlen)
1311 *rlen = 0;
1313 if (!pwm || !cmd)
1314 return FINISH (GPG_ERR_INV_ARG);
1315 if (!pwm->ctx)
1316 return FINISH (GPG_ERR_INV_STATE);
1319 * C99 allows the dst pointer to be null which will calculate the length
1320 * of the would-be result and return it.
1322 va_copy (ap2, ap);
1323 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1324 buf = (char *) pwmd_malloc (len);
1325 if (!buf)
1327 va_end (ap2);
1328 return FINISH (GPG_ERR_ENOMEM);
1331 len = vsnprintf (buf, len, cmd, ap2);
1332 va_end (ap2);
1334 if (buf[strlen (buf) - 1] == '\n')
1335 buf[strlen (buf) - 1] = 0;
1336 if (buf[strlen (buf) - 1] == '\r')
1337 buf[strlen (buf) - 1] = 0;
1339 pwm->inquire_func = func;
1340 pwm->inquire_data = user;
1341 pwm->inquire_sent = 0;
1342 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1343 pwmd_free (buf);
1344 return rc;
1347 gpg_error_t
1348 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1349 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1351 va_list ap;
1353 if (result)
1354 *result = NULL;
1356 if (len)
1357 *len = 0;
1359 if (!pwm || !cmd)
1360 return FINISH (GPG_ERR_INV_ARG);
1361 if (!pwm->ctx)
1362 return FINISH (GPG_ERR_INV_STATE);
1364 va_start (ap, cmd);
1365 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1366 va_end (ap);
1367 return rc;
1370 static gpg_error_t
1371 send_pinentry_timeout (pwm_t *pwm)
1373 gpg_error_t rc = 0;
1375 if ((pwm->pinentry_timeout >= 0
1376 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1377 || (pwm->pinentry_timeout == -1
1378 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1380 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1381 "OPTION pinentry-timeout=%i",
1382 pwm->pinentry_timeout);
1383 if (!rc)
1384 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1387 return rc;
1390 static gpg_error_t
1391 send_pinentry_options (pwm_t * pwm)
1393 gpg_error_t rc;
1395 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1396 "OPTION disable-pinentry=0");
1397 if (!rc && pwm->pinentry_tty)
1398 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1399 pwm->pinentry_tty);
1401 if (!rc && pwm->pinentry_term)
1402 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1403 pwm->pinentry_term);
1405 if (!rc && pwm->pinentry_display)
1406 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1407 pwm->pinentry_display);
1409 if (!rc && pwm->pinentry_desc)
1410 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1411 pwm->pinentry_desc);
1413 if (!rc && pwm->pinentry_lcctype)
1414 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1415 pwm->pinentry_lcctype);
1417 if (!rc && pwm->pinentry_lcmessages)
1418 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1419 pwm->pinentry_lcmessages);
1421 if (!rc)
1422 rc = send_pinentry_timeout (pwm);
1424 return rc;
1427 gpg_error_t
1428 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1430 if (!pwm || !result)
1431 return FINISH (GPG_ERR_INV_ARG);
1433 *result = PWMD_SOCKET_LOCAL;
1435 if (pwm->fd == -1)
1436 return FINISH (GPG_ERR_INV_STATE);
1438 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1439 #ifdef WITH_SSH
1440 if (pwm->tcp && pwm->tcp->ssh)
1441 *result = PWMD_SOCKET_SSH;
1442 #endif
1443 #ifdef WITH_GNUTLS
1444 if (pwm->tcp && pwm->tcp->tls)
1445 *result = PWMD_SOCKET_TLS;
1446 #endif
1447 #endif
1448 return 0;
1451 static gpg_error_t
1452 disable_pinentry (pwm_t *pwm, int *disable)
1454 gpg_error_t rc;
1455 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1456 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1457 #else
1458 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1459 #endif
1461 if (disable)
1462 *disable = no_pinentry;
1464 if (pwm->pinentry_disabled && no_pinentry)
1465 return 0;
1466 else if (!pwm->pinentry_disabled && !no_pinentry)
1467 return 0;
1469 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1470 no_pinentry);
1471 if (!rc)
1472 pwm->pinentry_disabled = no_pinentry;
1474 return rc;
1477 gpg_error_t
1478 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1479 void *data)
1481 gpg_error_t rc = 0;
1482 int no_pinentry = 0;
1484 if (!pwm || !filename || !*filename)
1485 return FINISH (GPG_ERR_INV_ARG);
1487 if (!pwm->ctx)
1488 return FINISH (GPG_ERR_INV_STATE);
1490 command_start (pwm);
1491 rc = disable_pinentry (pwm, &no_pinentry);
1492 if (!rc && !no_pinentry)
1493 rc = send_pinentry_options (pwm);
1495 if (!rc)
1497 pwm->pinentry_try = 0;
1498 pwmd_free (pwm->filename);
1499 pwm->filename = pwmd_strdup (filename);
1503 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1504 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1505 filename);
1507 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1508 && pwm->pinentry_disabled
1509 && ++pwm->pinentry_try < pwm->pinentry_tries);
1511 pwm->pinentry_try = 0;
1513 if (rc)
1515 pwmd_free (pwm->filename);
1516 pwm->filename = NULL;
1520 pwmd_free (pwm->passphrase_hint);
1521 pwmd_free (pwm->passphrase_info);
1522 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1523 return FINISH (rc);
1526 static gpg_error_t
1527 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1528 void *data, int save)
1530 gpg_error_t rc = 0;
1531 int no_pinentry = 0;
1533 if (!pwm)
1534 return FINISH (GPG_ERR_INV_ARG);
1535 if (!pwm->ctx)
1536 return FINISH (GPG_ERR_INV_STATE);
1538 command_start (pwm);
1539 rc = disable_pinentry (pwm, &no_pinentry);
1540 if (!rc && !no_pinentry)
1541 rc = send_pinentry_options (pwm);
1543 if (!rc)
1544 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1545 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1547 pwmd_free (pwm->passphrase_hint);
1548 pwmd_free (pwm->passphrase_info);
1549 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1550 return FINISH (rc);
1553 gpg_error_t
1554 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1556 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1559 gpg_error_t
1560 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1562 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1565 static gpg_error_t
1566 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1568 int n, *intp;
1569 size_t *sizetp;
1570 char *arg1, **charpp;
1571 gpg_error_t rc = 0;
1573 if (!pwm)
1574 return GPG_ERR_INV_ARG;
1576 command_start (pwm);
1577 switch (opt)
1579 case PWMD_OPTION_SERVER_VERSION:
1580 if (!get)
1581 return GPG_ERR_NOT_SUPPORTED;
1583 if (!pwm->ctx)
1584 rc = GPG_ERR_INV_STATE;
1585 else
1587 unsigned *u = va_arg (ap, unsigned *);
1588 *u = pwm->version;
1591 break;
1592 case PWMD_OPTION_SIGPIPE:
1593 if (get)
1595 intp = va_arg (ap, int *);
1596 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1597 break;
1600 n = va_arg (ap, int);
1601 if (n < 0 || n > 1)
1603 rc = GPG_ERR_INV_VALUE;
1604 break;
1607 if (n)
1608 pwm->opts |= OPT_SIGPIPE;
1609 else
1610 pwm->opts &= ~OPT_SIGPIPE;
1612 break;
1613 case PWMD_OPTION_LOCK_ON_OPEN:
1614 if (get)
1616 intp = va_arg (ap, int *);
1617 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1618 break;
1621 n = va_arg (ap, int);
1622 if (n < 0 || n > 1)
1624 rc = GPG_ERR_INV_VALUE;
1625 break;
1628 if (n)
1629 pwm->opts |= OPT_LOCK_ON_OPEN;
1630 else
1631 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1633 break;
1634 case PWMD_OPTION_INQUIRE_TOTAL:
1635 if (get)
1637 sizetp = va_arg (ap, size_t *);
1638 *sizetp = pwm->inquire_total;
1639 break;
1642 pwm->inquire_total = va_arg (ap, size_t);
1643 break;
1644 case PWMD_OPTION_STATUS_CB:
1645 if (get)
1647 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1649 *cb = pwm->status_func;
1650 break;
1653 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1654 break;
1655 case PWMD_OPTION_STATUS_DATA:
1656 if (get)
1658 void **data = va_arg (ap, void **);
1660 *data = pwm->status_data;
1661 break;
1664 pwm->status_data = va_arg (ap, void *);
1665 break;
1666 case PWMD_OPTION_NO_PINENTRY:
1667 if (get)
1669 intp = va_arg (ap, int *);
1670 *intp = pwm->disable_pinentry;
1671 break;
1674 n = va_arg (ap, int);
1675 if (n < 0 || n > 1)
1676 rc = GPG_ERR_INV_VALUE;
1677 else
1678 pwm->disable_pinentry = n;
1679 break;
1680 case PWMD_OPTION_LOCAL_PINENTRY:
1681 if (get)
1683 intp = va_arg (ap, int *);
1684 *intp = pwm->local_pinentry;
1685 break;
1688 n = va_arg (ap, int);
1689 if (n < 0 || n > 1)
1690 rc = GPG_ERR_INV_VALUE;
1691 else
1692 pwm->local_pinentry = n;
1694 break;
1695 case PWMD_OPTION_PINENTRY_TIMEOUT:
1696 if (get)
1698 intp = va_arg (ap, int *);
1699 *intp = pwm->pinentry_timeout;
1700 break;
1703 n = va_arg (ap, int);
1704 if (n < 0)
1705 rc = GPG_ERR_INV_VALUE;
1706 else
1707 pwm->pinentry_timeout = n;
1708 break;
1709 case PWMD_OPTION_PINENTRY_TRIES:
1710 if (get)
1712 intp = va_arg (ap, int *);
1713 *intp = pwm->pinentry_tries;
1714 break;
1717 n = va_arg (ap, int);
1718 if (n < 0)
1719 rc = GPG_ERR_INV_VALUE;
1720 else
1721 pwm->pinentry_tries = n;
1722 break;
1723 case PWMD_OPTION_PINENTRY_PATH:
1724 if (get)
1726 charpp = va_arg (ap, char **);
1727 *charpp = pwm->pinentry_path;
1728 break;
1731 arg1 = va_arg (ap, char *);
1732 pwmd_free (pwm->pinentry_path);
1733 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1734 break;
1735 case PWMD_OPTION_PINENTRY_TTY:
1736 if (get)
1738 charpp = va_arg (ap, char **);
1739 *charpp = pwm->pinentry_tty;
1740 break;
1743 arg1 = va_arg (ap, char *);
1744 pwmd_free (pwm->pinentry_tty);
1745 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1746 break;
1747 case PWMD_OPTION_PINENTRY_DISPLAY:
1748 if (get)
1750 charpp = va_arg (ap, char **);
1751 *charpp = pwm->pinentry_display;
1752 break;
1755 arg1 = va_arg (ap, char *);
1756 pwmd_free (pwm->pinentry_display);
1757 pwm->pinentry_display = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL;
1758 if (!pwm->pinentry_display)
1759 unsetenv ("DISPLAY");
1760 break;
1761 case PWMD_OPTION_PINENTRY_TERM:
1762 if (get)
1764 charpp = va_arg (ap, char **);
1765 *charpp = pwm->pinentry_term;
1766 break;
1769 arg1 = va_arg (ap, char *);
1770 pwmd_free (pwm->pinentry_term);
1771 pwm->pinentry_term = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL;
1772 if (pwm->pinentry_term)
1773 unsetenv ("TERM");
1774 break;
1775 case PWMD_OPTION_PINENTRY_ERROR:
1776 if (get)
1778 charpp = va_arg (ap, char **);
1779 *charpp = pwm->pinentry_error;
1780 break;
1783 arg1 = va_arg (ap, char *);
1784 pwmd_free (pwm->pinentry_error);
1785 if (pwm->disable_pinentry)
1786 pwm->pinentry_error = arg1 ? pwmd_strdup (arg1) : NULL;
1787 else
1788 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1789 break;
1790 case PWMD_OPTION_PINENTRY_PROMPT:
1791 if (get)
1793 charpp = va_arg (ap, char **);
1794 *charpp = pwm->pinentry_prompt;
1795 break;
1798 arg1 = va_arg (ap, char *);
1799 pwmd_free (pwm->pinentry_prompt);
1800 if (pwm->disable_pinentry)
1801 pwm->pinentry_prompt = arg1 ? pwmd_strdup (arg1) : NULL;
1802 else
1803 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1804 break;
1805 case PWMD_OPTION_PINENTRY_DESC:
1806 if (get)
1808 charpp = va_arg (ap, char **);
1809 *charpp = pwm->pinentry_desc;
1810 break;
1813 arg1 = va_arg (ap, char *);
1814 pwmd_free (pwm->pinentry_desc);
1815 if (pwm->disable_pinentry)
1816 pwm->pinentry_desc = arg1 ? pwmd_strdup (arg1) : NULL;
1817 else
1818 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1819 break;
1820 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1821 if (get)
1823 charpp = va_arg (ap, char **);
1824 *charpp = pwm->pinentry_lcctype;
1825 break;
1828 arg1 = va_arg (ap, char *);
1829 pwmd_free (pwm->pinentry_lcctype);
1830 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1831 break;
1832 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1833 if (get)
1835 charpp = va_arg (ap, char **);
1836 *charpp = pwm->pinentry_lcmessages;
1837 break;
1840 arg1 = va_arg (ap, char *);
1841 pwmd_free (pwm->pinentry_lcmessages);
1842 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1843 break;
1844 case PWMD_OPTION_KNOWNHOST_CB:
1845 if (get)
1847 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1849 *cb = pwm->kh_cb;
1850 break;
1853 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1854 break;
1855 case PWMD_OPTION_KNOWNHOST_DATA:
1856 if (get)
1858 void **data = va_arg (ap, void **);
1860 *data = pwm->kh_data;
1861 break;
1864 pwm->kh_data = va_arg (ap, void *);
1865 break;
1866 case PWMD_OPTION_SSH_AGENT:
1867 if (get)
1869 intp = va_arg (ap, int *);
1870 *intp = pwm->use_agent;
1871 break;
1874 n = va_arg (ap, int);
1875 if (n < 0 || n > 1)
1876 rc = GPG_ERR_INV_VALUE;
1877 else
1878 pwm->use_agent = n;
1879 break;
1880 case PWMD_OPTION_SSH_PASSPHRASE:
1881 if (get)
1882 return GPG_ERR_NOT_SUPPORTED;
1884 pwmd_free (pwm->ssh_passphrase);
1885 pwm->ssh_passphrase = NULL;
1886 arg1 = va_arg (ap, char *);
1887 if (arg1)
1889 pwm->ssh_passphrase = pwmd_strdup (arg1);
1890 if (!pwm->ssh_passphrase)
1891 return GPG_ERR_ENOMEM;
1893 break;
1894 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE:
1895 if (get)
1897 intp = va_arg (ap, int *);
1898 *intp = pwm->needs_passphrase;
1899 break;
1902 n = va_arg (ap, int);
1903 if (n < 0 || n > 1)
1904 rc = GPG_ERR_INV_VALUE;
1905 else
1906 pwm->needs_passphrase = n;
1907 break;
1908 case PWMD_OPTION_TLS_VERIFY:
1909 if (get)
1911 intp = va_arg (ap, int *);
1912 *intp = pwm->tls_verify;
1913 break;
1916 n = va_arg (ap, int);
1917 if (n < 0 || n > 1)
1918 rc = GPG_ERR_INV_VALUE;
1919 else
1920 pwm->tls_verify = n;
1921 break;
1922 case PWMD_OPTION_TLS_PRIORITY:
1923 if (get)
1925 charpp = va_arg (ap, char **);
1926 *charpp = pwm->tls_priority;
1927 break;
1930 pwmd_free (pwm->tls_priority);
1931 pwm->tls_priority = NULL;
1932 arg1 = va_arg (ap, char *);
1933 if (arg1)
1935 pwm->tls_priority = pwmd_strdup (arg1);
1936 if (!pwm->tls_priority)
1937 rc = GPG_ERR_ENOMEM;
1939 break;
1940 case PWMD_OPTION_SOCKET_TIMEOUT:
1941 if (get)
1943 intp = va_arg (ap, int *);
1944 *intp = pwm->socket_timeout;
1945 break;
1948 n = va_arg (ap, int);
1949 if (n < 0)
1951 rc = GPG_ERR_INV_VALUE;
1952 break;
1954 else
1955 pwm->socket_timeout = n;
1957 #ifdef WITH_SSH
1958 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1960 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1961 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1962 pwm->socket_timeout * 1000);
1964 #endif
1965 #ifdef WITH_GNUTLS
1966 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1967 pwm->tcp->tls->timeout = pwm->socket_timeout;
1968 #endif
1969 break;
1970 case PWMD_OPTION_OVERRIDE_INQUIRE:
1971 if (get)
1973 intp = va_arg (ap, int *);
1974 *intp = pwm->override_inquire;
1975 break;
1978 n = va_arg (ap, int);
1979 if (n < 0 || n > 1)
1980 rc = GPG_ERR_INV_VALUE;
1981 else
1982 pwm->override_inquire = n;
1983 break;
1984 default:
1985 rc = GPG_ERR_UNKNOWN_OPTION;
1986 break;
1989 return FINISH (rc);
1992 gpg_error_t
1993 pwmd_setopt (pwm_t * pwm, int opt, ...)
1995 va_list ap;
1996 gpg_error_t rc = 0;
1998 va_start (ap, opt);
1999 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
2000 va_end (ap);
2001 return FINISH (rc);
2004 gpg_error_t
2005 pwmd_getopt (pwm_t *pwm, int opt, ...)
2007 va_list ap;
2008 gpg_error_t rc = 0;
2010 va_start (ap, opt);
2011 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
2012 va_end (ap);
2013 return FINISH (rc);
2016 gpg_error_t
2017 set_rcdefaults (pwm_t *pwm, char *filename)
2019 char *f;
2020 FILE *fp;
2021 char *line, *p;
2022 unsigned line_n = 0;
2023 gpg_error_t rc = 0;
2025 if (!filename && isatty (STDIN_FILENO))
2027 char buf[256];
2028 int err = ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
2030 if (!err)
2032 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, buf);
2033 if (rc)
2034 return rc;
2036 if (getenv ("TERM"))
2038 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, getenv ("TERM"));
2039 if (rc)
2040 return rc;
2045 if (!filename && getenv ("DISPLAY"))
2047 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, getenv ("DISPLAY"));
2048 if (rc)
2049 return rc;
2052 f = _expand_homedir (filename ? filename : (char *)"~/.config/libpwmd.conf",
2053 NULL);
2054 if (f)
2056 line = pwmd_malloc (LINE_MAX);
2057 if (line)
2059 fp = fopen (f, "r");
2060 if (!fp)
2062 pwmd_free (line);
2063 pwmd_free (f);
2064 return 0;
2067 else
2068 rc = GPG_ERR_ENOMEM;
2070 else
2071 rc = GPG_ERR_ENOMEM;
2073 if (rc)
2075 pwmd_free (f);
2076 pwmd_free (line);
2077 return rc;
2080 while ((p = fgets (line, LINE_MAX, fp)))
2082 char name[32] = {0}, val[512] = {0};
2083 char *np;
2084 char *t;
2085 size_t len = 0;
2087 line_n++;
2089 while (isspace (*p))
2090 p++;
2092 if (!*p || *p == '#')
2093 continue;
2095 if (p[strlen (p)-1] == '\n')
2096 p[strlen (p)-1] = 0;
2098 t = strchr (p, '=');
2099 if (!t)
2101 fprintf(stderr, N_("%s(%u): malformed line\n"), f, line_n);
2102 continue;
2105 for (np = name; p != t; p++)
2107 if (++len == sizeof (name))
2108 break;
2110 if (isspace (*p))
2111 break;
2113 *np++ = *p;
2116 while (isspace (*t))
2117 t++;
2118 t++; // '='
2119 while (isspace (*t))
2120 t++;
2122 strncpy (val, t, sizeof (val)-1);
2124 if (!strcasecmp (name, "pinentry-path"))
2125 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_PATH, val);
2126 else if (!strcasecmp (name, "pinentry-tries"))
2127 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TRIES, atoi (val));
2128 else if (!strcasecmp (name, "pinentry-timeout"))
2129 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TIMEOUT, atoi (val));
2130 else if (!strcasecmp (name, "no-pinentry"))
2131 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, !!(atoi (val)));
2132 else if (!strcasecmp (name, "local-pinentry"))
2133 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCAL_PINENTRY, !!(atoi (val)));
2134 else if (!strcasecmp (name, "pinentry-display"))
2135 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, val);
2136 else if (!strcasecmp (name, "pinentry-ttyname"))
2137 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, val);
2138 else if (!strcasecmp (name, "pinentry-ttytype"))
2139 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, val);
2140 else if (!strcasecmp (name, "pinentry-lc-messages"))
2141 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES, val);
2142 else if (!strcasecmp (name, "pinentry-lc-ctype"))
2143 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, val);
2144 else if (!strcasecmp (name, "no-ssh-agent"))
2145 rc = pwmd_setopt (pwm, PWMD_OPTION_SSH_AGENT, !(atoi (val)));
2146 else if (!strcasecmp (name, "no-tls-verify"))
2147 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_VERIFY, !(atoi (val)));
2148 else if (!strcasecmp (name, "tls-priority"))
2149 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_PRIORITY, val);
2150 else if (!strcasecmp (name, "socket-timeout"))
2151 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, atoi (val));
2152 else if (!strcasecmp (name, "no-lock"))
2153 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, !(atoi (val)));
2154 else if (!strcasecmp (name, "include"))
2155 rc = set_rcdefaults (pwm, val);
2156 else
2157 fprintf(stderr, N_("%s(%u): invalid option '%s', ignored.\n"), f,
2158 line_n, name);
2160 if (rc)
2161 break;
2164 fclose (fp);
2165 pwmd_free (line);
2166 pwmd_free (f);
2167 return rc;
2170 gpg_error_t
2171 pwmd_new (const char *name, pwm_t ** pwm)
2173 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
2174 gpg_error_t rc;
2176 if (!h)
2177 return FINISH (GPG_ERR_ENOMEM);
2179 if (name)
2181 h->name = pwmd_strdup (name);
2182 if (!h->name)
2184 pwmd_free (h);
2185 return FINISH (GPG_ERR_ENOMEM);
2189 reset_handle (h);
2190 h->pinentry_timeout = -1;
2191 h->current_pinentry_timeout = -1;
2192 h->pinentry_tries = 3;
2193 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2194 h->prot = PWMD_IP_ANY;
2195 h->socket_timeout = 120;
2196 h->tls_verify = 1;
2197 #endif
2198 h->opts |= OPT_LOCK_ON_OPEN;
2200 rc = set_rcdefaults (h, NULL);
2201 if (rc)
2202 goto fail;
2204 *pwm = h;
2205 return 0;
2207 fail:
2208 pwmd_close (h);
2209 return FINISH (rc);
2212 void
2213 pwmd_free (void *ptr)
2215 _xfree (ptr);
2218 void *
2219 pwmd_malloc (size_t size)
2221 return _xmalloc (size);
2224 void *
2225 pwmd_calloc (size_t nmemb, size_t size)
2227 return _xcalloc (nmemb, size);
2230 void *
2231 pwmd_realloc (void *ptr, size_t size)
2233 return _xrealloc (ptr, size);
2236 char *
2237 pwmd_strdup (const char *str)
2239 char *t;
2240 size_t len;
2241 register size_t c;
2243 len = strlen (str);
2244 t = _xmalloc ((len + 1) * sizeof (char));
2245 if (!t)
2246 return NULL;
2248 for (c = 0; c < len; c++)
2249 t[c] = str[c];
2251 t[c] = 0;
2252 return t;
2255 char *
2256 pwmd_strdup_printf (const char *fmt, ...)
2258 va_list ap, ap2;
2259 int len;
2260 char *buf;
2262 if (!fmt)
2263 return NULL;
2265 va_start (ap, fmt);
2266 va_copy (ap2, ap);
2267 len = vsnprintf (NULL, 0, fmt, ap);
2268 va_end (ap);
2269 buf = pwmd_malloc (++len);
2270 if (buf)
2271 vsnprintf (buf, len, fmt, ap2);
2273 va_end (ap2);
2274 return buf;
2277 gpg_error_t
2278 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2279 size_t * len, pwmd_pinentry_t which)
2281 #ifndef WITH_PINENTRY
2282 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2283 #else
2284 gpg_error_t rc;
2286 command_start (pwm);
2287 if (which == PWMD_PINENTRY_CONFIRM && pwm->disable_pinentry)
2289 rc = get_password (pwm, NULL, NULL, which, 1);
2290 return FINISH (rc);
2293 rc = _pwmd_getpin (pwm, filename, result, len, which);
2294 return FINISH (rc);
2295 #endif
2298 const char *
2299 pwmd_version ()
2301 return LIBPWMD_VERSION_STR;
2304 unsigned int
2305 pwmd_features ()
2307 unsigned int n = 0;
2309 #ifdef WITH_PINENTRY
2310 n |= PWMD_FEATURE_PINENTRY;
2311 #endif
2312 #ifdef WITH_SSH
2313 n |= PWMD_FEATURE_SSH;
2314 #endif
2315 #ifdef WITH_QUALITY
2316 n |= PWMD_FEATURE_QUALITY;
2317 #endif
2318 #ifdef WITH_GNUTLS
2319 n |= PWMD_FEATURE_GNUTLS;
2320 #endif
2321 return n;
2324 gpg_error_t
2325 pwmd_fd (pwm_t * pwm, int *fd)
2327 if (!pwm || !fd)
2328 return FINISH (GPG_ERR_INV_ARG);
2330 if (pwm->fd == -1)
2331 return FINISH (GPG_ERR_INV_STATE);
2333 *fd = pwm->fd;
2334 return 0;
2337 void
2338 pwmd_set_pointer (pwm_t *pwm, void *data)
2340 pwm->user_data = data;
2343 void *
2344 pwmd_get_pointer (pwm_t *pwm)
2346 return pwm->user_data;
2350 pwmd_gnutls_error (pwm_t *pwm, const char **str)
2352 #ifndef WITH_GNUTLS
2353 (void)pwm;
2354 (void)str;
2355 return 0;
2356 #else
2357 if (str && pwm && pwm->tls_error)
2358 *str = gnutls_strerror (pwm->tls_error);
2360 return pwm ? pwm->tls_error : 0;
2361 #endif
2364 gpg_error_t
2365 pwmd_cancel (pwm_t *pwm)
2367 if (!pwm)
2368 return FINISH (GPG_ERR_INV_ARG);
2370 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2371 if (pwm->fd == -1 && !pwm->tcp)
2372 #else
2373 if (pwm->fd == -1)
2374 #endif
2375 return FINISH (GPG_ERR_INV_STATE);
2377 /* Can only cancel the connection for the time being. */
2378 if (pwm->connected)
2379 return FINISH (GPG_ERR_INV_STATE);
2381 pwm->cancel = 1;
2382 return 0;
2385 gpg_error_t
2386 pwmd_test_quality (const char *str, double *result)
2388 #ifndef WITH_QUALITY
2389 (void)str;
2390 (void)result;
2391 return GPG_ERR_NOT_IMPLEMENTED;
2392 #else
2393 if (!result)
2394 return GPG_ERR_INV_ARG;
2396 *result = ZxcvbnMatch (str, NULL, NULL);
2397 return 0;
2398 #endif