pwmc: Reset filename upon .open failure.
[libpwmd.git] / src / libpwmd.c
blob0fbb6a88afbedd44e10253972af47d3e58bb4ac0
1 /*
2 Copyright (C) 2006-2016 Ben Kibbey <bjk@luxsci.net>
4 This file is part of libpwmd.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
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 enum
76 PWMD_WHICH_SAVE,
77 PWMD_WHICH_PASSWD,
78 PWMD_WHICH_GENKEY
81 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
82 ? gpg_error(rc) : rc
84 typedef struct
86 size_t len;
87 void *buf;
88 } membuf_t;
90 static gpg_error_t status_cb (void *data, const char *line);
92 ssize_t
93 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
95 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
96 pwm_t *pwm = assuan_get_pointer (ctx);
98 #ifdef WITH_SSH
99 if (pwm && pwm->tcp && pwm->tcp->ssh)
100 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
101 #endif
102 #ifdef WITH_GNUTLS
103 if (pwm && pwm->tcp && pwm->tcp->tls)
104 return tls_read_hook (pwm, fd, data, len);
105 #endif
106 #else
107 (void)ctx;
108 #endif
110 return read ((int) fd, data, len);
113 ssize_t
114 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
115 size_t len)
117 ssize_t wrote;
118 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
119 pwm_t *pwm = assuan_get_pointer (ctx);
121 #ifdef WITH_SSH
122 if (pwm && pwm->tcp && pwm->tcp->ssh)
123 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
124 #endif
125 #ifdef WITH_GNUTLS
126 if (pwm && pwm->tcp && pwm->tcp->tls)
127 return tls_write_hook (pwm, fd, data, len);
128 #endif
129 #else
130 (void)ctx;
131 #endif
133 /* libassuan cannot handle EAGAIN when doing writes. */
136 wrote = write ((int) fd, data, len);
137 if (wrote == -1 && errno == EAGAIN)
138 usleep (50000);
140 while (wrote == -1 && errno == EAGAIN);
142 return wrote;
145 pid_t
146 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
147 int options)
149 (void)ctx;
150 (void)action;
151 return waitpid (pid, status, options);
154 gpg_error_t
155 pwmd_init ()
157 static int initialized;
159 #ifdef WITH_GNUTLS
160 // May be called more than once.
161 gnutls_global_init ();
162 #endif
164 if (initialized)
165 return 0;
167 #ifdef ENABLE_NLS
168 bindtextdomain ("libpwmd", LOCALEDIR);
169 #endif
170 #ifdef WITH_SSH
171 libssh2_init (0);
172 #endif
173 gpgrt_init ();
174 //gpgrt_set_alloc_func (_xrealloc_gpgrt);
176 #ifdef WITH_QUALITY
177 ZxcvbnInit (NULL);
178 #endif
180 initialized = 1;
181 return 0;
184 void
185 pwmd_deinit ()
187 #ifdef WITH_GNUTLS
188 gnutls_global_deinit ();
189 #endif
190 #ifdef WITH_QUALITY
191 ZxcvbnUnInit();
192 #endif
195 gpg_error_t
196 _connect_finalize (pwm_t * pwm)
198 gpg_error_t rc = 0;
199 char *result = NULL;
200 int active[2];
201 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
203 if (n <= 0)
204 return GPG_ERR_EBADFD;
206 pwm->fd = active[0];
207 #ifdef WITH_PINENTRY
208 pwm->pinentry_pid = -1;
209 #endif
211 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
212 if (!rc)
214 pwm->version = strtoul (result, NULL, 16);
215 pwmd_free (result);
218 if (!rc && pwm->name)
219 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
220 pwm->name);
222 return rc;
225 static gpg_error_t
226 connect_uds (pwm_t * pwm, const char *path)
228 char *socketpath = NULL;
229 struct passwd pw;
230 char *pwbuf;
231 gpg_error_t rc;
233 if (!pwm)
234 return GPG_ERR_INV_ARG;
236 pwbuf = _getpwuid (&pw);
237 if (!pwbuf)
238 return gpg_error_from_syserror ();
240 if (!path || !*path)
241 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
242 else
243 socketpath = _expand_homedir ((char *) path, &pw);
245 pwmd_free (pwbuf);
246 if (!socketpath)
247 return GPG_ERR_ENOMEM;
249 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
250 pwmd_free (socketpath);
251 return rc ? rc : _connect_finalize (pwm);
254 static gpg_error_t
255 init_handle (pwm_t * pwm)
257 gpg_error_t rc;
258 static struct assuan_malloc_hooks mhooks = {
259 pwmd_malloc, pwmd_realloc, pwmd_free
261 static struct assuan_system_hooks shooks = {
262 ASSUAN_SYSTEM_HOOKS_VERSION,
263 __assuan_usleep,
264 __assuan_pipe,
265 __assuan_close,
266 hook_read,
267 hook_write,
268 //FIXME
269 NULL, //recvmsg
270 NULL, //sendmsg both are used for FD passing
271 __assuan_spawn,
272 hook_waitpid,
273 __assuan_socketpair,
274 __assuan_socket,
275 __assuan_connect
278 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
279 NULL);
280 if (rc)
281 return rc;
283 assuan_set_pointer (pwm->ctx, pwm);
284 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
285 return 0;
288 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
289 void
290 free_tcp (pwm_t *pwm)
292 struct tcp_s *tcp = pwm->tcp;
294 if (!tcp)
295 return;
297 #ifdef WITH_SSH
298 _free_ssh_conn (tcp->ssh);
299 #endif
300 #ifdef WITH_GNUTLS
301 tls_free (pwm);
302 #endif
304 pwmd_free (tcp->host);
305 if (tcp->addrs)
307 freeaddrinfo (tcp->addrs);
308 tcp->addrs = NULL;
311 pthread_cond_destroy (&tcp->dns_cond);
312 pthread_mutex_destroy (&tcp->dns_mutex);
313 pwmd_free (tcp);
314 pwm->tcp = NULL;
316 #endif
318 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
319 static void *
320 resolve_host_thread (void *arg)
322 pwm_t *pwm = arg;
323 struct addrinfo hints = { 0 };
324 char portstr[6];
326 switch (pwm->prot)
328 case PWMD_IP_ANY:
329 hints.ai_family = AF_UNSPEC;
330 break;
331 case PWMD_IPV4:
332 hints.ai_family = AF_INET;
333 break;
334 case PWMD_IPV6:
335 hints.ai_family = AF_INET6;
336 break;
339 hints.ai_socktype = SOCK_STREAM;
340 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
341 int *n = pwmd_malloc (sizeof (int));
342 pthread_cleanup_push (pwmd_free, n);
343 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
344 pthread_cleanup_pop (0);
345 pthread_cond_broadcast (&pwm->tcp->dns_cond);
346 pthread_exit (n);
347 return NULL;
350 gpg_error_t
351 tcp_connect_common (pwm_t * pwm)
353 #define TS_TIMEOUT 50000000L
354 int n;
355 gpg_error_t rc = 0;
356 pthread_t tid;
357 time_t now;
359 time (&now);
360 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
361 if (n)
362 return gpg_error_from_errno (n);
364 pthread_mutex_lock (&pwm->tcp->dns_mutex);
366 for (;;)
368 struct timespec ts;
369 int *result = NULL;
371 clock_gettime (CLOCK_REALTIME, &ts);
372 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
373 ts.tv_sec++;
374 ts.tv_nsec = 0;
376 else
377 ts.tv_nsec += TS_TIMEOUT;
379 if (pwm->cancel)
381 #ifdef HAVE_PTHREAD_CANCEL
382 pthread_cancel (tid);
383 pthread_join (tid, NULL);
384 #else
385 pthread_join (tid, (void **)&result);
386 pwmd_free (result);
387 #endif
388 return GPG_ERR_CANCELED;
391 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
392 &ts);
393 if (n == ETIMEDOUT)
395 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
397 #ifdef HAVE_PTHREAD_CANCEL
398 pthread_cancel (tid);
399 pthread_join (tid, NULL);
400 #else
401 pthread_join (tid, (void **)&result);
402 pwmd_free (result);
403 #endif
404 return GPG_ERR_ETIMEDOUT;
407 continue;
409 else if (n)
411 #ifdef HAVE_PTHREAD_CANCEL
412 pthread_cancel (tid);
413 pthread_join (tid, NULL);
414 #else
415 pthread_join (tid, (void **)&result);
416 pwmd_free (result);
417 #endif
418 return gpg_error_from_errno (n);
421 pthread_join (tid, (void **)&result);
422 n = *result;
423 pwmd_free (result);
424 break;
427 if (n)
428 return GPG_ERR_UNKNOWN_HOST; //FIXME
430 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
431 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
433 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
434 if (pwm->fd == -1)
436 rc = gpg_error_from_syserror ();
437 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
438 break;
439 continue;
442 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
444 rc = gpg_error_from_syserror ();
445 break;
448 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
449 pwm->tcp->addr->ai_family == AF_INET6
450 ? sizeof (struct sockaddr_in6)
451 : sizeof (struct sockaddr)) == -1)
453 struct timeval tv;
454 fd_set wfds;
455 unsigned elapsed = 0;
457 rc = gpg_error_from_syserror ();
458 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
460 close (pwm->fd);
461 pwm->fd = -1;
462 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
463 return rc;
464 continue;
467 again:
468 tv.tv_sec = 1;
469 tv.tv_usec = 0;
470 FD_ZERO (&wfds);
471 FD_SET (pwm->fd, &wfds);
472 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
473 rc = 0;
474 if (!n || pwm->cancel)
476 if (pwm->cancel)
477 rc = gpg_error (GPG_ERR_CANCELED);
478 else if (++elapsed >= pwm->socket_timeout)
479 rc = gpg_error (GPG_ERR_ETIMEDOUT);
480 else
481 goto again;
483 else if (n != -1)
485 socklen_t len = sizeof(int);
487 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
488 if (n)
489 rc = gpg_error_from_errno (n);
491 else if (n == -1)
492 rc = gpg_error_from_syserror ();
494 if (rc)
496 close (pwm->fd);
497 pwm->fd = -1;
498 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
499 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
500 || pwm->cancel)
501 return rc;
503 else
504 break;
506 else
507 break;
510 if (!rc)
511 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
512 rc = gpg_error_from_syserror ();
514 return rc;
516 #endif
518 static void
519 command_start (pwm_t *pwm)
521 pwm->cancel = 0;
524 gpg_error_t
525 pwmd_connect (pwm_t * pwm, const char *url, ...)
527 const char *p = url;
528 gpg_error_t rc;
530 if (!pwm)
531 return FINISH (GPG_ERR_INV_ARG);
532 else if (!pwm->ctx)
534 rc = init_handle (pwm);
535 if (rc)
536 return rc;
539 command_start (pwm);
541 if (!(pwm->opts & OPT_SIGPIPE))
542 signal (SIGPIPE, SIG_IGN);
544 #ifdef WITH_GNUTLS
545 pwm->tls_error = 0;
546 #endif
547 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
549 if (p && (*p == '/' || *p == '~'))
550 rc = connect_uds (pwm, p);
551 else if (!p || !strncmp (p, "file://", 7))
553 if (p)
554 p += 7;
555 #ifdef DEFAULT_PWMD_SOCKET
556 else
557 p = DEFAULT_PWMD_SOCKET;
558 #endif
559 rc = connect_uds (pwm, p);
561 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
562 !strncmp (p, "ssh4://", 7))
564 #ifndef WITH_SSH
565 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
566 #else
567 char *host = NULL;
568 int port;
569 char *username = NULL;
571 if (!strncmp (p, "ssh6://", 7))
573 pwm->prot = PWMD_IPV6;
574 p += 7;
576 else if (!strncmp (p, "ssh4://", 7))
578 pwm->prot = PWMD_IPV4;
579 p += 7;
581 else
583 pwm->prot = PWMD_IP_ANY;
584 p += 6;
587 rc = _parse_ssh_url (p, &host, &port, &username);
588 if (!rc)
590 va_list ap;
591 char *identity = NULL;
592 char *knownhosts = NULL;
594 va_start (ap, url);
595 identity = va_arg (ap, char *);
597 if (!identity && !pwm->use_agent)
598 rc = GPG_ERR_INV_ARG;
599 else
600 knownhosts = va_arg (ap, char *);
602 va_end (ap);
604 if (!rc)
605 rc = _do_ssh_connect (pwm, host, port, identity, username,
606 knownhosts);
607 if (!rc)
609 rc = _connect_finalize (pwm);
610 if (rc)
611 free_tcp (pwm);
615 pwmd_free (host);
616 pwmd_free (username);
617 pwm->local_pinentry = 1;
618 pwmd_free (pwm->ssh_passphrase);
619 pwm->ssh_passphrase = NULL;
620 #endif
622 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
623 !strncmp (p, "tls4://", 7))
625 #ifndef WITH_GNUTLS
626 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
627 #else
628 char *host = NULL;
629 int port;
631 if (!strncmp (p, "tls6://", 7))
633 pwm->prot = PWMD_IPV6;
634 p += 7;
636 else if (!strncmp (p, "tls4://", 7))
638 pwm->prot = PWMD_IPV4;
639 p += 7;
641 else
643 pwm->prot = PWMD_IP_ANY;
644 p += 6;
647 rc = tls_parse_url (p, &host, &port);
648 if (!rc)
650 va_list ap;
651 char *clientcert = NULL;
652 char *clientkey = NULL;
653 char *cacert = NULL;
654 char *server_fp = NULL;
656 va_start (ap, url);
657 clientcert = va_arg (ap, char *);
659 if (!clientcert)
660 rc = GPG_ERR_INV_ARG;
661 else
663 clientkey = va_arg (ap, char *);
664 if (!clientkey)
665 rc = GPG_ERR_INV_ARG;
666 else
668 cacert = va_arg (ap, char *);
669 if (!cacert)
670 rc = GPG_ERR_INV_ARG;
671 else
672 server_fp = va_arg (ap, char *);
676 va_end (ap);
678 if (!rc)
679 rc = tls_connect (pwm, host, port, clientcert, clientkey, cacert,
680 pwm->tls_priority, server_fp, pwm->tls_verify);
681 if (!rc)
683 rc = _connect_finalize (pwm);
684 if (rc)
685 free_tcp (pwm);
689 pwmd_free (host);
690 pwm->local_pinentry = 1;
691 #endif
694 if (!rc)
695 pwm->connected = 1;
697 return FINISH (rc);
700 static void
701 disconnect (pwm_t * pwm)
703 if (!pwm)
704 return;
706 if (pwm->ctx)
707 assuan_release (pwm->ctx);
709 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
710 free_tcp (pwm);
711 #endif
712 pwm->ctx = NULL;
713 pwm->fd = -1;
714 pwm->connected = 0;
717 void
718 pwmd_close (pwm_t * pwm)
720 if (!pwm)
721 return;
723 disconnect (pwm);
724 pwmd_free (pwm->pinentry_error);
725 pwmd_free (pwm->pinentry_desc);
726 pwmd_free (pwm->pinentry_prompt);
727 pwmd_free (pwm->pinentry_tty);
728 pwmd_free (pwm->pinentry_display);
729 pwmd_free (pwm->pinentry_term);
730 pwmd_free (pwm->pinentry_lcctype);
731 pwmd_free (pwm->pinentry_lcmessages);
732 pwmd_free (pwm->filename);
733 pwmd_free (pwm->name);
734 pwmd_free (pwm->passphrase_info);
735 pwmd_free (pwm->passphrase_hint);
736 pwmd_free (pwm->ssh_passphrase);
737 pwmd_free (pwm->tls_priority);
739 #ifdef WITH_PINENTRY
740 if (pwm->pctx)
741 _pinentry_disconnect (pwm);
742 #endif
744 pwmd_free (pwm);
747 static gpg_error_t
748 inquire_realloc_cb (void *data, const void *buffer, size_t len)
750 membuf_t *mem = (membuf_t *) data;
751 void *p;
753 if (!buffer)
754 return 0;
756 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
757 return gpg_error (GPG_ERR_ENOMEM);
759 mem->buf = p;
760 memcpy ((char *) mem->buf + mem->len, buffer, len);
761 mem->len += len;
762 return 0;
765 static gpg_error_t
766 get_password (pwm_t * pwm, char **result, size_t * len,
767 pwmd_pinentry_t w, int echo)
769 char buf[ASSUAN_LINELENGTH+1] = { 0 }, *p;
770 struct termios told, tnew;
771 char *key = NULL;
773 if (result)
774 *result = NULL;
776 if (len)
777 *len = 0;
779 if (!isatty (STDIN_FILENO))
781 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
782 return GPG_ERR_ENOTTY;
785 if (!echo)
787 if (tcgetattr (STDIN_FILENO, &told) == -1)
788 return gpg_error_from_syserror ();
790 memcpy (&tnew, &told, sizeof (struct termios));
791 tnew.c_lflag &= ~(ECHO);
792 tnew.c_lflag |= ICANON | ECHONL;
794 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
796 int n = errno;
798 tcsetattr (STDIN_FILENO, TCSANOW, &told);
799 return gpg_error_from_errno (n);
803 if (pwm->passphrase_hint)
804 fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint);
806 switch (w)
808 case PWMD_PINENTRY_OPEN:
809 fprintf (stderr, N_("Passphrase for %s: "), pwm->filename);
810 break;
811 case PWMD_PINENTRY_OPEN_FAILED:
812 fprintf (stderr, N_("Invalid passphrase. Passphrase for %s: "),
813 pwm->filename);
814 break;
815 case PWMD_PINENTRY_SAVE:
816 fprintf (stderr, N_("New passphrase for %s: "), pwm->filename);
817 break;
818 case PWMD_PINENTRY_SAVE_CONFIRM:
819 fprintf (stderr, N_("Repeat passphrase: "));
820 break;
821 case PWMD_PINENTRY_CONFIRM:
822 if (pwm->pinentry_desc)
823 fprintf (stderr, "%s", pwm->pinentry_desc);
825 if (pwm->pinentry_prompt)
826 fprintf (stderr, "%s", pwm->pinentry_prompt);
827 else
828 fprintf(stderr, N_("Confirm [y/N]:"));
829 default:
830 break;
833 p = fgets (buf, sizeof (buf), stdin);
835 if (!echo)
836 tcsetattr (STDIN_FILENO, TCSANOW, &told);
838 if (!p || feof (stdin))
840 clearerr (stdin);
841 return GPG_ERR_CANCELED;
844 /* Strip the newline character. */
845 p[strlen (p) - 1] = 0;
847 if (buf[0])
849 if (w == PWMD_PINENTRY_CONFIRM)
851 if (*p != 'y' && *p != 'Y')
852 return GPG_ERR_CANCELED;
853 return 0;
856 key = pwmd_strdup_printf ("%s", p);
857 wipememory (buf, 0, sizeof (buf));
858 if (!key)
859 return GPG_ERR_ENOMEM;
861 if (result)
862 *result = key;
864 if (len)
865 *len = strlen (key);
867 else
869 if (w == PWMD_PINENTRY_CONFIRM)
870 return GPG_ERR_CANCELED;
872 /* To satisfy inquire_cb(). */
873 if (result)
874 *result = pwmd_strdup ("");
876 if (len)
877 *len = 1;
880 return 0;
883 gpg_error_t
884 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
886 gpg_error_t rc;
887 int new_password = 0;
888 char *password = NULL, *newpass = NULL;
889 int error = 0;
891 command_start (pwm);
893 if (data)
894 *data = NULL;
896 if (size)
897 *size = 0;
899 if (!strcmp (keyword, "NEW_PASSPHRASE"))
900 new_password = 1;
902 if (!new_password && pwm->pinentry_try)
903 error = 1;
905 again:
906 if (pwm->disable_pinentry)
908 rc = get_password (pwm, &password, size,
909 new_password ? PWMD_PINENTRY_SAVE :
910 error ? PWMD_PINENTRY_OPEN_FAILED :
911 PWMD_PINENTRY_OPEN, 0);
912 if (!rc && new_password)
913 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
916 else
918 pwmd_pinentry_t which;
920 if (error)
921 which = new_password
922 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
923 else
924 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
926 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
927 if (!rc && new_password)
928 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
929 PWMD_PINENTRY_SAVE_CONFIRM);
932 if (!rc && new_password)
934 if ((!password && newpass) || (!newpass && password)
935 || (newpass && password && strcmp (newpass, password)))
937 if (pwm->disable_pinentry)
938 fprintf (stderr, N_("Passphrases do not match.\n"));
940 pwmd_free (password);
941 pwmd_free (newpass);
942 password = newpass = NULL;
943 error = 1;
944 goto again;
948 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
949 pwmd_free (newpass);
950 if (!rc && data)
951 *data = password;
952 else
953 pwmd_free (password);
955 return rc;
958 static gpg_error_t
959 inquire_cb (void *data, const char *keyword)
961 pwm_t *pwm = (pwm_t *) data;
962 gpg_error_t rc = 0;
963 int free_result = 0;
964 char *result = NULL;
965 int is_password = 0;
966 int new_password = 0;
968 if (!strcmp (keyword, "PASSPHRASE") || !strcmp (keyword, "SIGN_PASSPHRASE"))
969 is_password = 1;
970 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
971 new_password = 1;
973 /* Shouldn't get this far without a callback. */
974 if (!pwm->override_inquire && !pwm->inquire_func
975 && !is_password && !new_password)
976 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
978 for (;;)
980 size_t len = 0;
981 gpg_error_t arc;
983 result = NULL;
985 if (!pwm->override_inquire && (is_password || new_password))
987 free_result = 1;
988 rc = pwmd_password (data, keyword, &result, &len);
989 if (!rc)
990 rc = GPG_ERR_EOF;
992 else
993 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
994 &len);
996 /* gpg will truncate a passphrase at the first nil byte which may be bad
997 * for generated key files. */
998 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
999 && (is_password || new_password))
1001 if (len && result && *result)
1003 for (size_t n = 0; n < len; n++)
1005 if (result[n] == 0 && n+1 != len)
1006 rc = GPG_ERR_INV_PASSPHRASE;
1011 cancel:
1012 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
1014 #ifndef LIBASSUAN_2_1_0
1015 gpg_error_t trc = rc;
1017 /* Cancel this inquire. */
1018 rc = assuan_send_data (pwm->ctx, NULL, 1);
1019 if (!rc)
1021 char *line;
1022 size_t len;
1024 /* There is a bug (or feature?) in assuan_send_data() that
1025 * when cancelling an inquire the next read from the server is
1026 * not done until the next command making the next command
1027 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1029 rc = assuan_read_line (pwm->ctx, &line, &len);
1031 /* Restore the original error. This differs from the error
1032 * returned from the pwmd command (GPG_ERR_CANCELED). This
1033 * error is returned to the calling function.
1035 if (!rc)
1036 rc = trc;
1038 #endif
1039 break;
1042 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1044 if (len <= 0 && !result)
1046 rc = 0;
1047 break;
1049 else if ((len <= 0 && result) || (len && !result))
1051 rc = gpg_error (GPG_ERR_INV_ARG);
1052 break;
1055 if (pwm->inquire_maxlen
1056 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1058 rc = gpg_error (GPG_ERR_TOO_LARGE);
1059 if (!free_result)
1060 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1061 &result, &len);
1062 goto cancel;
1065 arc = assuan_send_data (pwm->ctx, result, len);
1066 if (gpg_err_code (rc) == GPG_ERR_EOF)
1068 rc = arc;
1069 break;
1072 rc = arc;
1074 else if (rc)
1075 break;
1077 if (!rc)
1079 pwm->inquire_sent += len;
1081 if (pwm->status_func)
1083 char buf[ASSUAN_LINELENGTH];
1085 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1086 pwm->inquire_total);
1087 rc = pwm->status_func (pwm->status_data, buf);
1088 if (rc)
1089 continue;
1094 if (free_result)
1095 pwmd_free (result);
1097 pwm->inquire_maxlen = pwm->inquire_sent = 0;
1098 return rc;
1101 static gpg_error_t
1102 parse_assuan_line (pwm_t * pwm)
1104 gpg_error_t rc;
1105 char *line;
1106 size_t len;
1108 rc = assuan_read_line (pwm->ctx, &line, &len);
1109 if (!rc)
1111 if (line[0] == 'O' && line[1] == 'K' &&
1112 (line[2] == 0 || line[2] == ' '))
1115 else if (line[0] == '#')
1118 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1120 rc = status_cb (pwm, line[1] == 0 ? line + 1 : line + 2);
1122 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1123 (line[3] == 0 || line[3] == ' '))
1125 line += 4;
1126 rc = strtol (line, NULL, 10);
1130 return rc;
1133 static void
1134 reset_handle (pwm_t *pwm)
1136 pwm->fd = -1;
1137 pwm->cancel = 0;
1138 pwm->pinentry_disabled = 0;
1139 #ifdef WITH_PINENTRY
1140 if (pwm->pctx)
1141 _pinentry_disconnect (pwm);
1142 #endif
1143 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1144 #ifdef WITH_GNUTLS
1145 pwm->tls_error = 0;
1146 #endif
1148 if (pwm->tcp)
1149 pwm->tcp->rc = 0;
1150 #endif
1153 gpg_error_t
1154 pwmd_disconnect (pwm_t * pwm)
1156 if (!pwm)
1157 return FINISH (GPG_ERR_INV_ARG);
1159 command_start (pwm);
1161 if (pwm->fd == -1)
1162 return FINISH (GPG_ERR_INV_STATE);
1164 disconnect (pwm);
1165 reset_handle (pwm);
1166 return 0;
1169 /* Note that this should only be called when not in a command. */
1170 gpg_error_t
1171 pwmd_process (pwm_t * pwm)
1173 gpg_error_t rc = 0;
1174 fd_set fds;
1175 struct timeval tv = { 0, 0 };
1176 int n;
1178 if (!pwm || pwm->fd == -1)
1179 return FINISH (GPG_ERR_INV_ARG);
1180 else if (!pwm->ctx)
1181 return FINISH (GPG_ERR_INV_STATE);
1183 FD_ZERO (&fds);
1184 FD_SET (pwm->fd, &fds);
1185 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1187 if (n == -1)
1188 return FINISH (gpg_error_from_syserror ());
1190 if (n > 0)
1192 if (FD_ISSET (pwm->fd, &fds))
1193 rc = parse_assuan_line (pwm);
1196 while (!rc && assuan_pending_line (pwm->ctx))
1197 rc = parse_assuan_line (pwm);
1199 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1200 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1202 close (pwm->fd);
1203 pwm->fd = -1;
1205 #endif
1207 return FINISH (rc);
1210 static gpg_error_t
1211 status_cb (void *data, const char *line)
1213 pwm_t *pwm = data;
1215 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1216 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1217 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1219 pwmd_free (pwm->passphrase_hint);
1220 pwm->passphrase_hint = pwmd_strdup (line+16);
1222 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1224 pwmd_free (pwm->passphrase_info);
1225 pwm->passphrase_info = pwmd_strdup (line+16);
1227 #ifdef WITH_GNUTLS
1228 else if (!strcmp (line, "REHANDSHAKE"))
1230 char buf[32];
1231 ssize_t ret;
1233 ret = tls_read_hook (pwm, pwm->fd, buf, sizeof (buf));
1234 if (ret < 0)
1236 pwm->tls_error = ret;
1237 return GPG_ERR_GENERAL;
1240 #endif
1242 if (pwm->status_func)
1243 return pwm->status_func (pwm->status_data, line);
1245 return 0;
1248 gpg_error_t
1249 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1250 char **result, size_t * len, const char *cmd)
1252 membuf_t data;
1253 gpg_error_t rc;
1255 if (!cmd || !*cmd)
1256 return FINISH (GPG_ERR_INV_ARG);
1258 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1259 return FINISH (GPG_ERR_LINE_TOO_LONG);
1261 data.len = 0;
1262 data.buf = NULL;
1263 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1264 #ifdef WITH_QUALITY
1265 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1266 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1267 #else
1268 inquire_cb, pwm,
1269 #endif
1270 status_cb, pwm);
1272 if (rc)
1274 if (data.buf)
1276 pwmd_free (data.buf);
1277 data.buf = NULL;
1280 else
1282 if (data.buf)
1284 inquire_realloc_cb (&data, "", 1);
1286 if (result)
1287 *result = (char *) data.buf;
1288 else
1289 pwmd_free (data.buf);
1291 if (len)
1292 *len = data.len;
1296 pwm->inquire_maxlen = 0;
1297 return rc;
1300 gpg_error_t
1301 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1302 pwmd_inquire_cb_t func, void *user, const char *cmd,
1303 va_list ap)
1305 char *buf;
1306 size_t len;
1307 va_list ap2;
1309 if (!pwm)
1310 return GPG_ERR_INV_ARG;
1312 command_start (pwm);
1314 if (result)
1315 *result = NULL;
1317 if (rlen)
1318 *rlen = 0;
1320 if (!pwm || !cmd)
1321 return FINISH (GPG_ERR_INV_ARG);
1322 if (!pwm->ctx)
1323 return FINISH (GPG_ERR_INV_STATE);
1326 * C99 allows the dst pointer to be null which will calculate the length
1327 * of the would-be result and return it.
1329 va_copy (ap2, ap);
1330 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1331 buf = (char *) pwmd_malloc (len);
1332 if (!buf)
1334 va_end (ap2);
1335 return FINISH (GPG_ERR_ENOMEM);
1338 len = vsnprintf (buf, len, cmd, ap2);
1339 va_end (ap2);
1341 if (buf[strlen (buf) - 1] == '\n')
1342 buf[strlen (buf) - 1] = 0;
1343 if (buf[strlen (buf) - 1] == '\r')
1344 buf[strlen (buf) - 1] = 0;
1346 pwm->inquire_func = func;
1347 pwm->inquire_data = user;
1348 pwm->inquire_sent = 0;
1349 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1350 pwmd_free (buf);
1351 return rc;
1354 gpg_error_t
1355 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1356 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1358 va_list ap;
1360 if (result)
1361 *result = NULL;
1363 if (len)
1364 *len = 0;
1366 if (!pwm || !cmd)
1367 return FINISH (GPG_ERR_INV_ARG);
1368 if (!pwm->ctx)
1369 return FINISH (GPG_ERR_INV_STATE);
1371 va_start (ap, cmd);
1372 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1373 va_end (ap);
1374 return rc;
1377 static gpg_error_t
1378 send_pinentry_timeout (pwm_t *pwm)
1380 gpg_error_t rc = 0;
1382 if ((pwm->pinentry_timeout >= 0
1383 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1384 || (pwm->pinentry_timeout == -1
1385 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1387 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1388 "OPTION pinentry-timeout=%i",
1389 pwm->pinentry_timeout);
1390 if (!rc)
1391 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1394 return rc;
1397 static gpg_error_t
1398 send_pinentry_options (pwm_t * pwm)
1400 gpg_error_t rc;
1402 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1403 "OPTION disable-pinentry=0");
1404 if (!rc && pwm->pinentry_tty)
1405 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1406 pwm->pinentry_tty);
1408 if (!rc && pwm->pinentry_term)
1409 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1410 pwm->pinentry_term);
1412 if (!rc && pwm->pinentry_display)
1413 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1414 pwm->pinentry_display);
1416 if (!rc && pwm->pinentry_desc)
1417 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1418 pwm->pinentry_desc);
1420 if (!rc && pwm->pinentry_lcctype)
1421 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1422 pwm->pinentry_lcctype);
1424 if (!rc && pwm->pinentry_lcmessages)
1425 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1426 pwm->pinentry_lcmessages);
1428 if (!rc)
1429 rc = send_pinentry_timeout (pwm);
1431 return rc;
1434 gpg_error_t
1435 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1437 if (!pwm || !result)
1438 return FINISH (GPG_ERR_INV_ARG);
1440 *result = PWMD_SOCKET_LOCAL;
1442 if (pwm->fd == -1)
1443 return FINISH (GPG_ERR_INV_STATE);
1445 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1446 #ifdef WITH_SSH
1447 if (pwm->tcp && pwm->tcp->ssh)
1448 *result = PWMD_SOCKET_SSH;
1449 #endif
1450 #ifdef WITH_GNUTLS
1451 if (pwm->tcp && pwm->tcp->tls)
1452 *result = PWMD_SOCKET_TLS;
1453 #endif
1454 #endif
1455 return 0;
1458 static gpg_error_t
1459 disable_pinentry (pwm_t *pwm, int *disable)
1461 gpg_error_t rc;
1462 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1463 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1464 #else
1465 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1466 #endif
1468 if (disable)
1469 *disable = no_pinentry;
1471 if (pwm->pinentry_disabled && no_pinentry)
1472 return 0;
1473 else if (!pwm->pinentry_disabled && !no_pinentry)
1474 return 0;
1476 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1477 no_pinentry);
1478 if (!rc)
1479 pwm->pinentry_disabled = no_pinentry;
1481 return rc;
1484 gpg_error_t
1485 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1486 void *data)
1488 gpg_error_t rc = 0;
1489 int no_pinentry = 0;
1491 if (!pwm || !filename || !*filename)
1492 return FINISH (GPG_ERR_INV_ARG);
1494 if (!pwm->ctx)
1495 return FINISH (GPG_ERR_INV_STATE);
1497 command_start (pwm);
1498 rc = disable_pinentry (pwm, &no_pinentry);
1499 if (!rc && !no_pinentry)
1500 rc = send_pinentry_options (pwm);
1502 if (!rc)
1504 pwm->pinentry_try = 0;
1505 pwmd_free (pwm->filename);
1506 pwm->filename = pwmd_strdup (filename);
1510 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1511 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1512 filename);
1514 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1515 && pwm->pinentry_disabled
1516 && ++pwm->pinentry_try < pwm->pinentry_tries);
1518 pwm->pinentry_try = 0;
1520 if (rc)
1522 pwmd_free (pwm->filename);
1523 pwm->filename = NULL;
1527 pwmd_free (pwm->passphrase_hint);
1528 pwmd_free (pwm->passphrase_info);
1529 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1530 return FINISH (rc);
1533 static gpg_error_t
1534 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1535 void *data, int which)
1537 gpg_error_t rc = 0;
1538 int no_pinentry = 0;
1540 if (!pwm)
1541 return FINISH (GPG_ERR_INV_ARG);
1542 if (!pwm->ctx)
1543 return FINISH (GPG_ERR_INV_STATE);
1545 command_start (pwm);
1546 rc = disable_pinentry (pwm, &no_pinentry);
1547 if (!rc && !no_pinentry)
1548 rc = send_pinentry_options (pwm);
1550 if (!rc)
1552 if (which == PWMD_WHICH_SAVE)
1553 rc = pwmd_command (pwm, NULL, NULL, cb, data, "SAVE %s", args ? args : "");
1554 else if (which == PWMD_WHICH_PASSWD)
1555 rc = pwmd_command (pwm, NULL, NULL, cb, data, "PASSWD %s", args ? args : "");
1556 else if (which == PWMD_WHICH_GENKEY)
1557 rc = pwmd_command (pwm, NULL, NULL, cb, data, "GENKEY %s", args ? args : "");
1560 pwmd_free (pwm->passphrase_hint);
1561 pwmd_free (pwm->passphrase_info);
1562 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1563 return FINISH (rc);
1566 gpg_error_t
1567 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1569 return do_pwmd_save_passwd (pwm, args, cb, data, PWMD_WHICH_PASSWD);
1572 gpg_error_t
1573 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1575 return do_pwmd_save_passwd (pwm, args, cb, data, PWMD_WHICH_SAVE);
1578 gpg_error_t
1579 pwmd_genkey (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1581 return do_pwmd_save_passwd (pwm, args, cb, data, PWMD_WHICH_GENKEY);
1584 static gpg_error_t
1585 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1587 int n, *intp;
1588 size_t *sizetp;
1589 char *arg1, **charpp;
1590 gpg_error_t rc = 0;
1592 if (!pwm)
1593 return GPG_ERR_INV_ARG;
1595 command_start (pwm);
1596 switch (opt)
1598 case PWMD_OPTION_SERVER_VERSION:
1599 if (!get)
1600 return GPG_ERR_NOT_SUPPORTED;
1602 if (!pwm->ctx)
1603 rc = GPG_ERR_INV_STATE;
1604 else
1606 unsigned *u = va_arg (ap, unsigned *);
1607 *u = pwm->version;
1610 break;
1611 case PWMD_OPTION_SIGPIPE:
1612 if (get)
1614 intp = va_arg (ap, int *);
1615 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1616 break;
1619 n = va_arg (ap, int);
1620 if (n < 0 || n > 1)
1622 rc = GPG_ERR_INV_VALUE;
1623 break;
1626 if (n)
1627 pwm->opts |= OPT_SIGPIPE;
1628 else
1629 pwm->opts &= ~OPT_SIGPIPE;
1631 break;
1632 case PWMD_OPTION_LOCK_ON_OPEN:
1633 if (get)
1635 intp = va_arg (ap, int *);
1636 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1637 break;
1640 n = va_arg (ap, int);
1641 if (n < 0 || n > 1)
1643 rc = GPG_ERR_INV_VALUE;
1644 break;
1647 if (n)
1648 pwm->opts |= OPT_LOCK_ON_OPEN;
1649 else
1650 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1652 break;
1653 case PWMD_OPTION_INQUIRE_TOTAL:
1654 if (get)
1656 sizetp = va_arg (ap, size_t *);
1657 *sizetp = pwm->inquire_total;
1658 break;
1661 pwm->inquire_total = va_arg (ap, size_t);
1662 break;
1663 case PWMD_OPTION_STATUS_CB:
1664 if (get)
1666 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1668 *cb = pwm->status_func;
1669 break;
1672 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1673 break;
1674 case PWMD_OPTION_STATUS_DATA:
1675 if (get)
1677 void **data = va_arg (ap, void **);
1679 *data = pwm->status_data;
1680 break;
1683 pwm->status_data = va_arg (ap, void *);
1684 break;
1685 case PWMD_OPTION_NO_PINENTRY:
1686 if (get)
1688 intp = va_arg (ap, int *);
1689 *intp = pwm->disable_pinentry;
1690 break;
1693 n = va_arg (ap, int);
1694 if (n < 0 || n > 1)
1695 rc = GPG_ERR_INV_VALUE;
1696 else
1697 pwm->disable_pinentry = n;
1698 break;
1699 case PWMD_OPTION_LOCAL_PINENTRY:
1700 if (get)
1702 intp = va_arg (ap, int *);
1703 *intp = pwm->local_pinentry;
1704 break;
1707 n = va_arg (ap, int);
1708 if (n < 0 || n > 1)
1709 rc = GPG_ERR_INV_VALUE;
1710 else
1711 pwm->local_pinentry = n;
1713 break;
1714 case PWMD_OPTION_PINENTRY_TIMEOUT:
1715 if (get)
1717 intp = va_arg (ap, int *);
1718 *intp = pwm->pinentry_timeout;
1719 break;
1722 n = va_arg (ap, int);
1723 if (n < 0)
1724 rc = GPG_ERR_INV_VALUE;
1725 else
1726 pwm->pinentry_timeout = n;
1727 break;
1728 case PWMD_OPTION_PINENTRY_TRIES:
1729 if (get)
1731 intp = va_arg (ap, int *);
1732 *intp = pwm->pinentry_tries;
1733 break;
1736 n = va_arg (ap, int);
1737 if (n < 0)
1738 rc = GPG_ERR_INV_VALUE;
1739 else
1740 pwm->pinentry_tries = n;
1741 break;
1742 case PWMD_OPTION_PINENTRY_PATH:
1743 if (get)
1745 charpp = va_arg (ap, char **);
1746 *charpp = pwm->pinentry_path;
1747 break;
1750 arg1 = va_arg (ap, char *);
1751 pwmd_free (pwm->pinentry_path);
1752 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1753 break;
1754 case PWMD_OPTION_PINENTRY_TTY:
1755 if (get)
1757 charpp = va_arg (ap, char **);
1758 *charpp = pwm->pinentry_tty;
1759 break;
1762 arg1 = va_arg (ap, char *);
1763 pwmd_free (pwm->pinentry_tty);
1764 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1765 break;
1766 case PWMD_OPTION_PINENTRY_DISPLAY:
1767 if (get)
1769 charpp = va_arg (ap, char **);
1770 *charpp = pwm->pinentry_display;
1771 break;
1774 arg1 = va_arg (ap, char *);
1775 pwmd_free (pwm->pinentry_display);
1776 pwm->pinentry_display = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL;
1777 if (!pwm->pinentry_display)
1778 unsetenv ("DISPLAY");
1779 break;
1780 case PWMD_OPTION_PINENTRY_TERM:
1781 if (get)
1783 charpp = va_arg (ap, char **);
1784 *charpp = pwm->pinentry_term;
1785 break;
1788 arg1 = va_arg (ap, char *);
1789 pwmd_free (pwm->pinentry_term);
1790 pwm->pinentry_term = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL;
1791 if (pwm->pinentry_term)
1792 unsetenv ("TERM");
1793 break;
1794 case PWMD_OPTION_PINENTRY_ERROR:
1795 if (get)
1797 charpp = va_arg (ap, char **);
1798 *charpp = pwm->pinentry_error;
1799 break;
1802 arg1 = va_arg (ap, char *);
1803 pwmd_free (pwm->pinentry_error);
1804 if (pwm->disable_pinentry)
1805 pwm->pinentry_error = arg1 ? pwmd_strdup (arg1) : NULL;
1806 else
1807 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1808 break;
1809 case PWMD_OPTION_PINENTRY_PROMPT:
1810 if (get)
1812 charpp = va_arg (ap, char **);
1813 *charpp = pwm->pinentry_prompt;
1814 break;
1817 arg1 = va_arg (ap, char *);
1818 pwmd_free (pwm->pinentry_prompt);
1819 if (pwm->disable_pinentry)
1820 pwm->pinentry_prompt = arg1 ? pwmd_strdup (arg1) : NULL;
1821 else
1822 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1823 break;
1824 case PWMD_OPTION_PINENTRY_DESC:
1825 if (get)
1827 charpp = va_arg (ap, char **);
1828 *charpp = pwm->pinentry_desc;
1829 break;
1832 arg1 = va_arg (ap, char *);
1833 pwmd_free (pwm->pinentry_desc);
1834 if (pwm->disable_pinentry)
1835 pwm->pinentry_desc = arg1 ? pwmd_strdup (arg1) : NULL;
1836 else
1837 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1838 break;
1839 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1840 if (get)
1842 charpp = va_arg (ap, char **);
1843 *charpp = pwm->pinentry_lcctype;
1844 break;
1847 arg1 = va_arg (ap, char *);
1848 pwmd_free (pwm->pinentry_lcctype);
1849 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1850 break;
1851 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1852 if (get)
1854 charpp = va_arg (ap, char **);
1855 *charpp = pwm->pinentry_lcmessages;
1856 break;
1859 arg1 = va_arg (ap, char *);
1860 pwmd_free (pwm->pinentry_lcmessages);
1861 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1862 break;
1863 case PWMD_OPTION_KNOWNHOST_CB:
1864 if (get)
1866 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1868 *cb = pwm->kh_cb;
1869 break;
1872 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1873 break;
1874 case PWMD_OPTION_KNOWNHOST_DATA:
1875 if (get)
1877 void **data = va_arg (ap, void **);
1879 *data = pwm->kh_data;
1880 break;
1883 pwm->kh_data = va_arg (ap, void *);
1884 break;
1885 case PWMD_OPTION_SSH_AGENT:
1886 if (get)
1888 intp = va_arg (ap, int *);
1889 *intp = pwm->use_agent;
1890 break;
1893 n = va_arg (ap, int);
1894 if (n < 0 || n > 1)
1895 rc = GPG_ERR_INV_VALUE;
1896 else
1897 pwm->use_agent = n;
1898 break;
1899 case PWMD_OPTION_SSH_PASSPHRASE:
1900 if (get)
1901 return GPG_ERR_NOT_SUPPORTED;
1903 pwmd_free (pwm->ssh_passphrase);
1904 pwm->ssh_passphrase = NULL;
1905 arg1 = va_arg (ap, char *);
1906 if (arg1)
1908 pwm->ssh_passphrase = pwmd_strdup (arg1);
1909 if (!pwm->ssh_passphrase)
1910 return GPG_ERR_ENOMEM;
1912 break;
1913 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE:
1914 if (get)
1916 intp = va_arg (ap, int *);
1917 *intp = pwm->needs_passphrase;
1918 break;
1921 n = va_arg (ap, int);
1922 if (n < 0 || n > 1)
1923 rc = GPG_ERR_INV_VALUE;
1924 else
1925 pwm->needs_passphrase = n;
1926 break;
1927 case PWMD_OPTION_TLS_VERIFY:
1928 if (get)
1930 intp = va_arg (ap, int *);
1931 *intp = pwm->tls_verify;
1932 break;
1935 n = va_arg (ap, int);
1936 if (n < 0 || n > 1)
1937 rc = GPG_ERR_INV_VALUE;
1938 else
1939 pwm->tls_verify = n;
1940 break;
1941 case PWMD_OPTION_TLS_PRIORITY:
1942 if (get)
1944 charpp = va_arg (ap, char **);
1945 *charpp = pwm->tls_priority;
1946 break;
1949 pwmd_free (pwm->tls_priority);
1950 pwm->tls_priority = NULL;
1951 arg1 = va_arg (ap, char *);
1952 if (arg1)
1954 pwm->tls_priority = pwmd_strdup (arg1);
1955 if (!pwm->tls_priority)
1956 rc = GPG_ERR_ENOMEM;
1958 break;
1959 case PWMD_OPTION_SOCKET_TIMEOUT:
1960 if (get)
1962 intp = va_arg (ap, int *);
1963 *intp = pwm->socket_timeout;
1964 break;
1967 n = va_arg (ap, int);
1968 if (n < 0)
1970 rc = GPG_ERR_INV_VALUE;
1971 break;
1973 else
1974 pwm->socket_timeout = n;
1976 #ifdef WITH_SSH
1977 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1979 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1980 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1981 pwm->socket_timeout * 1000);
1983 #endif
1984 #ifdef WITH_GNUTLS
1985 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1986 pwm->tcp->tls->timeout = pwm->socket_timeout;
1987 #endif
1988 break;
1989 case PWMD_OPTION_OVERRIDE_INQUIRE:
1990 if (get)
1992 intp = va_arg (ap, int *);
1993 *intp = pwm->override_inquire;
1994 break;
1997 n = va_arg (ap, int);
1998 if (n < 0 || n > 1)
1999 rc = GPG_ERR_INV_VALUE;
2000 else
2001 pwm->override_inquire = n;
2002 break;
2003 default:
2004 rc = GPG_ERR_UNKNOWN_OPTION;
2005 break;
2008 return FINISH (rc);
2011 gpg_error_t
2012 pwmd_setopt (pwm_t * pwm, int opt, ...)
2014 va_list ap;
2015 gpg_error_t rc = 0;
2017 va_start (ap, opt);
2018 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
2019 va_end (ap);
2020 return FINISH (rc);
2023 gpg_error_t
2024 pwmd_getopt (pwm_t *pwm, int opt, ...)
2026 va_list ap;
2027 gpg_error_t rc = 0;
2029 va_start (ap, opt);
2030 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
2031 va_end (ap);
2032 return FINISH (rc);
2035 gpg_error_t
2036 set_rcdefaults (pwm_t *pwm, char *filename)
2038 char *f;
2039 FILE *fp;
2040 char *line, *p;
2041 unsigned line_n = 0;
2042 gpg_error_t rc = 0;
2044 if (!filename && isatty (STDIN_FILENO))
2046 char buf[256];
2047 int err = ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
2049 if (!err)
2051 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, buf);
2052 if (rc)
2053 return rc;
2055 if (getenv ("TERM"))
2057 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, getenv ("TERM"));
2058 if (rc)
2059 return rc;
2064 if (!filename && getenv ("DISPLAY"))
2066 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, getenv ("DISPLAY"));
2067 if (rc)
2068 return rc;
2071 f = _expand_homedir (filename ? filename : (char *)"~/.config/libpwmd.conf",
2072 NULL);
2073 if (f)
2075 line = pwmd_malloc (LINE_MAX);
2076 if (line)
2078 fp = fopen (f, "r");
2079 if (!fp)
2081 pwmd_free (line);
2082 pwmd_free (f);
2083 return 0;
2086 else
2087 rc = GPG_ERR_ENOMEM;
2089 else
2090 rc = GPG_ERR_ENOMEM;
2092 if (rc)
2094 pwmd_free (f);
2095 pwmd_free (line);
2096 return rc;
2099 while ((p = fgets (line, LINE_MAX, fp)))
2101 char name[32] = {0}, val[512] = {0};
2102 char *np;
2103 char *t;
2104 size_t len = 0;
2106 line_n++;
2108 while (isspace (*p))
2109 p++;
2111 if (!*p || *p == '#')
2112 continue;
2114 if (p[strlen (p)-1] == '\n')
2115 p[strlen (p)-1] = 0;
2117 t = strchr (p, '=');
2118 if (!t)
2120 fprintf(stderr, N_("%s(%u): malformed line\n"), f, line_n);
2121 continue;
2124 for (np = name; p != t; p++)
2126 if (++len == sizeof (name))
2127 break;
2129 if (isspace (*p))
2130 break;
2132 *np++ = *p;
2135 while (isspace (*t))
2136 t++;
2137 t++; // '='
2138 while (isspace (*t))
2139 t++;
2141 strncpy (val, t, sizeof (val)-1);
2143 if (!strcasecmp (name, "pinentry-path"))
2144 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_PATH, val);
2145 else if (!strcasecmp (name, "pinentry-tries"))
2146 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TRIES, atoi (val));
2147 else if (!strcasecmp (name, "pinentry-timeout"))
2148 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TIMEOUT, atoi (val));
2149 else if (!strcasecmp (name, "no-pinentry"))
2150 rc = pwmd_setopt (pwm, PWMD_OPTION_NO_PINENTRY, !!(atoi (val)));
2151 else if (!strcasecmp (name, "local-pinentry"))
2152 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCAL_PINENTRY, !!(atoi (val)));
2153 else if (!strcasecmp (name, "pinentry-display"))
2154 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_DISPLAY, val);
2155 else if (!strcasecmp (name, "pinentry-ttyname"))
2156 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TTY, val);
2157 else if (!strcasecmp (name, "pinentry-ttytype"))
2158 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_TERM, val);
2159 else if (!strcasecmp (name, "pinentry-lc-messages"))
2160 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_MESSAGES, val);
2161 else if (!strcasecmp (name, "pinentry-lc-ctype"))
2162 rc = pwmd_setopt (pwm, PWMD_OPTION_PINENTRY_LC_CTYPE, val);
2163 else if (!strcasecmp (name, "no-ssh-agent"))
2164 rc = pwmd_setopt (pwm, PWMD_OPTION_SSH_AGENT, !(atoi (val)));
2165 else if (!strcasecmp (name, "no-tls-verify"))
2166 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_VERIFY, !(atoi (val)));
2167 else if (!strcasecmp (name, "tls-priority"))
2168 rc = pwmd_setopt (pwm, PWMD_OPTION_TLS_PRIORITY, val);
2169 else if (!strcasecmp (name, "socket-timeout"))
2170 rc = pwmd_setopt (pwm, PWMD_OPTION_SOCKET_TIMEOUT, atoi (val));
2171 else if (!strcasecmp (name, "no-lock"))
2172 rc = pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, !(atoi (val)));
2173 else if (!strcasecmp (name, "include"))
2174 rc = set_rcdefaults (pwm, val);
2175 else
2176 fprintf(stderr, N_("%s(%u): invalid option '%s', ignored.\n"), f,
2177 line_n, name);
2179 if (rc)
2180 break;
2183 fclose (fp);
2184 pwmd_free (line);
2185 pwmd_free (f);
2186 return rc;
2189 gpg_error_t
2190 pwmd_new (const char *name, pwm_t ** pwm)
2192 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
2193 gpg_error_t rc;
2195 if (!h)
2196 return FINISH (GPG_ERR_ENOMEM);
2198 if (name)
2200 h->name = pwmd_strdup (name);
2201 if (!h->name)
2203 pwmd_free (h);
2204 return FINISH (GPG_ERR_ENOMEM);
2208 reset_handle (h);
2209 h->pinentry_timeout = -1;
2210 h->current_pinentry_timeout = -1;
2211 h->pinentry_tries = 3;
2212 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2213 h->prot = PWMD_IP_ANY;
2214 h->socket_timeout = 120;
2215 h->tls_verify = 1;
2216 #endif
2217 h->opts |= OPT_LOCK_ON_OPEN;
2219 rc = set_rcdefaults (h, NULL);
2220 if (rc)
2221 goto fail;
2223 *pwm = h;
2224 return 0;
2226 fail:
2227 pwmd_close (h);
2228 return FINISH (rc);
2231 void
2232 pwmd_free (void *ptr)
2234 _xfree (ptr);
2237 void *
2238 pwmd_malloc (size_t size)
2240 return _xmalloc (size);
2243 void *
2244 pwmd_calloc (size_t nmemb, size_t size)
2246 return _xcalloc (nmemb, size);
2249 void *
2250 pwmd_realloc (void *ptr, size_t size)
2252 return _xrealloc (ptr, size);
2255 char *
2256 pwmd_strdup (const char *str)
2258 char *t;
2259 size_t len;
2260 register size_t c;
2262 len = strlen (str);
2263 t = _xmalloc ((len + 1) * sizeof (char));
2264 if (!t)
2265 return NULL;
2267 for (c = 0; c < len; c++)
2268 t[c] = str[c];
2270 t[c] = 0;
2271 return t;
2274 char *
2275 pwmd_strdup_printf (const char *fmt, ...)
2277 va_list ap, ap2;
2278 int len;
2279 char *buf;
2281 if (!fmt)
2282 return NULL;
2284 va_start (ap, fmt);
2285 va_copy (ap2, ap);
2286 len = vsnprintf (NULL, 0, fmt, ap);
2287 va_end (ap);
2288 buf = pwmd_malloc (++len);
2289 if (buf)
2290 vsnprintf (buf, len, fmt, ap2);
2292 va_end (ap2);
2293 return buf;
2296 gpg_error_t
2297 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2298 size_t * len, pwmd_pinentry_t which)
2300 #ifndef WITH_PINENTRY
2301 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2302 #else
2303 gpg_error_t rc;
2305 command_start (pwm);
2306 if (which == PWMD_PINENTRY_CONFIRM && pwm->disable_pinentry)
2308 rc = get_password (pwm, NULL, NULL, which, 1);
2309 return FINISH (rc);
2312 rc = _pwmd_getpin (pwm, filename, result, len, which);
2313 return FINISH (rc);
2314 #endif
2317 const char *
2318 pwmd_version ()
2320 return LIBPWMD_VERSION_STR;
2323 unsigned int
2324 pwmd_features ()
2326 unsigned int n = 0;
2328 #ifdef WITH_PINENTRY
2329 n |= PWMD_FEATURE_PINENTRY;
2330 #endif
2331 #ifdef WITH_SSH
2332 n |= PWMD_FEATURE_SSH;
2333 #endif
2334 #ifdef WITH_QUALITY
2335 n |= PWMD_FEATURE_QUALITY;
2336 #endif
2337 #ifdef WITH_GNUTLS
2338 n |= PWMD_FEATURE_GNUTLS;
2339 #endif
2340 return n;
2343 gpg_error_t
2344 pwmd_fd (pwm_t * pwm, int *fd)
2346 if (!pwm || !fd)
2347 return FINISH (GPG_ERR_INV_ARG);
2349 if (pwm->fd == -1)
2350 return FINISH (GPG_ERR_INV_STATE);
2352 *fd = pwm->fd;
2353 return 0;
2356 void
2357 pwmd_set_pointer (pwm_t *pwm, void *data)
2359 pwm->user_data = data;
2362 void *
2363 pwmd_get_pointer (pwm_t *pwm)
2365 return pwm->user_data;
2369 pwmd_gnutls_error (pwm_t *pwm, const char **str)
2371 #ifndef WITH_GNUTLS
2372 (void)pwm;
2373 (void)str;
2374 return 0;
2375 #else
2376 if (str && pwm && pwm->tls_error)
2377 *str = gnutls_strerror (pwm->tls_error);
2379 return pwm ? pwm->tls_error : 0;
2380 #endif
2383 gpg_error_t
2384 pwmd_cancel (pwm_t *pwm)
2386 if (!pwm)
2387 return FINISH (GPG_ERR_INV_ARG);
2389 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2390 if (pwm->fd == -1 && !pwm->tcp)
2391 #else
2392 if (pwm->fd == -1)
2393 #endif
2394 return FINISH (GPG_ERR_INV_STATE);
2396 /* Can only cancel the connection for the time being. */
2397 if (pwm->connected)
2398 return FINISH (GPG_ERR_INV_STATE);
2400 pwm->cancel = 1;
2401 return 0;
2404 gpg_error_t
2405 pwmd_test_quality (const char *str, double *result)
2407 #ifndef WITH_QUALITY
2408 (void)str;
2409 (void)result;
2410 return GPG_ERR_NOT_IMPLEMENTED;
2411 #else
2412 if (!result)
2413 return GPG_ERR_INV_ARG;
2415 *result = ZxcvbnMatch (str, NULL, NULL);
2416 return 0;
2417 #endif