Revert "Remove pinentry.conf support."
[libpwmd.git] / src / libpwmd.c
blobb37de0d1acb3a1bda665dd3466222d8a9ccdcc84
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 ssize_t
84 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
86 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
87 pwm_t *pwm = assuan_get_pointer (ctx);
89 #ifdef WITH_SSH
90 if (pwm && pwm->tcp && pwm->tcp->ssh)
91 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
92 #endif
93 #ifdef WITH_GNUTLS
94 if (pwm && pwm->tcp && pwm->tcp->tls)
95 return read_hook_tls (pwm, fd, data, len);
96 #endif
97 #endif
99 return read ((int) fd, data, len);
102 ssize_t
103 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
104 size_t len)
106 ssize_t wrote;
107 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
108 pwm_t *pwm = assuan_get_pointer (ctx);
110 #ifdef WITH_SSH
111 if (pwm && pwm->tcp && pwm->tcp->ssh)
112 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
113 #endif
114 #ifdef WITH_GNUTLS
115 if (pwm && pwm->tcp && pwm->tcp->tls)
116 return write_hook_tls (pwm, fd, data, len);
117 #endif
118 #endif
120 /* libassuan cannot handle EAGAIN when doing writes. */
123 wrote = write ((int) fd, data, len);
124 if (wrote == -1 && errno == EAGAIN)
125 usleep (50000);
127 while (wrote == -1 && errno == EAGAIN);
129 return wrote;
132 pid_t
133 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
134 int options)
136 return waitpid (pid, status, options);
139 gpg_error_t
140 pwmd_init ()
142 static int initialized;
144 #ifdef WITH_GNUTLS
145 // May be called more than once.
146 gnutls_global_init ();
147 #endif
149 if (initialized)
150 return 0;
152 #ifdef ENABLE_NLS
153 bindtextdomain ("libpwmd", LOCALEDIR);
154 #endif
155 #ifdef WITH_SSH
156 libssh2_init (0);
157 #endif
158 gpgrt_init ();
159 gpgrt_set_alloc_func (_xrealloc_gpgrt);
161 #ifdef WITH_QUALITY
162 ZxcvbnInit (NULL);
163 #endif
165 initialized = 1;
166 return 0;
169 void
170 pwmd_deinit ()
172 #ifdef WITH_GNUTLS
173 gnutls_global_deinit ();
174 #endif
175 #ifdef WITH_QUALITY
176 ZxcvbnUnInit();
177 #endif
180 gpg_error_t
181 _connect_finalize (pwm_t * pwm)
183 gpg_error_t rc = 0;
184 char *result = NULL;
185 int active[2];
186 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
188 if (n <= 0)
189 return GPG_ERR_EBADFD;
191 pwm->fd = active[0];
192 #ifdef WITH_PINENTRY
193 pwm->pinentry_pid = -1;
194 #endif
196 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
197 if (!rc)
199 pwm->version = strtoul (result, NULL, 16);
200 pwmd_free (result);
203 if (!rc && pwm->name)
204 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
205 pwm->name);
207 return rc;
210 static gpg_error_t
211 connect_uds (pwm_t * pwm, const char *path)
213 char *socketpath = NULL;
214 struct passwd pw;
215 char *pwbuf;
216 gpg_error_t rc;
218 if (!pwm)
219 return GPG_ERR_INV_ARG;
221 pwbuf = _getpwuid (&pw);
222 if (!pwbuf)
223 return gpg_error_from_syserror ();
225 if (!path || !*path)
226 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
227 else
228 socketpath = _expand_homedir ((char *) path, &pw);
230 pwmd_free (pwbuf);
231 if (!socketpath)
232 return GPG_ERR_ENOMEM;
234 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
235 pwmd_free (socketpath);
236 return rc ? rc : _connect_finalize (pwm);
239 static gpg_error_t
240 init_handle (pwm_t * pwm)
242 gpg_error_t rc;
243 static struct assuan_malloc_hooks mhooks = {
244 pwmd_malloc, pwmd_realloc, pwmd_free
246 static struct assuan_system_hooks shooks = {
247 ASSUAN_SYSTEM_HOOKS_VERSION,
248 __assuan_usleep,
249 __assuan_pipe,
250 __assuan_close,
251 hook_read,
252 hook_write,
253 //FIXME
254 NULL, //recvmsg
255 NULL, //sendmsg both are used for FD passing
256 __assuan_spawn,
257 hook_waitpid,
258 __assuan_socketpair,
259 __assuan_socket,
260 __assuan_connect
263 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
264 NULL);
265 if (rc)
266 return rc;
268 assuan_set_pointer (pwm->ctx, pwm);
269 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
270 return 0;
273 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
274 void
275 free_tcp (pwm_t *pwm)
277 struct tcp_s *tcp = pwm->tcp;
279 if (!tcp)
280 return;
282 #ifdef WITH_SSH
283 _free_ssh_conn (tcp->ssh);
284 #endif
285 #ifdef WITH_GNUTLS
286 tls_free (pwm);
287 #endif
289 pwmd_free (tcp->host);
290 if (tcp->addrs)
292 freeaddrinfo (tcp->addrs);
293 tcp->addrs = NULL;
296 pthread_cond_destroy (&tcp->dns_cond);
297 pthread_mutex_destroy (&tcp->dns_mutex);
298 pwmd_free (tcp);
299 pwm->tcp = NULL;
301 #endif
303 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
304 static void *
305 resolve_host_thread (void *arg)
307 pwm_t *pwm = arg;
308 struct addrinfo hints = { 0 };
309 char portstr[6];
311 switch (pwm->prot)
313 case PWMD_IP_ANY:
314 hints.ai_family = AF_UNSPEC;
315 break;
316 case PWMD_IPV4:
317 hints.ai_family = AF_INET;
318 break;
319 case PWMD_IPV6:
320 hints.ai_family = AF_INET6;
321 break;
324 hints.ai_socktype = SOCK_STREAM;
325 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
326 int *n = pwmd_malloc (sizeof (int));
327 pthread_cleanup_push (pwmd_free, n);
328 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
329 pthread_cleanup_pop (0);
330 pthread_cond_broadcast (&pwm->tcp->dns_cond);
331 pthread_exit (n);
332 return NULL;
335 gpg_error_t
336 tcp_connect_common (pwm_t * pwm)
338 #define TS_TIMEOUT 50000000L
339 int n;
340 gpg_error_t rc = 0;
341 pthread_t tid;
342 time_t now;
344 time (&now);
345 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
346 if (n)
347 return gpg_error_from_errno (n);
349 pthread_mutex_lock (&pwm->tcp->dns_mutex);
351 for (;;)
353 struct timespec ts;
354 int *result = NULL;
356 clock_gettime (CLOCK_REALTIME, &ts);
357 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
358 ts.tv_sec++;
359 ts.tv_nsec = 0;
361 else
362 ts.tv_nsec += TS_TIMEOUT;
364 if (pwm->cancel)
366 #ifdef HAVE_PTHREAD_CANCEL
367 pthread_cancel (tid);
368 pthread_join (tid, NULL);
369 #else
370 pthread_join (tid, (void **)&result);
371 pwmd_free (result);
372 #endif
373 return GPG_ERR_CANCELED;
376 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
377 &ts);
378 if (n == ETIMEDOUT)
380 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
382 #ifdef HAVE_PTHREAD_CANCEL
383 pthread_cancel (tid);
384 pthread_join (tid, NULL);
385 #else
386 pthread_join (tid, (void **)&result);
387 pwmd_free (result);
388 #endif
389 return GPG_ERR_ETIMEDOUT;
392 continue;
394 else if (n)
396 #ifdef HAVE_PTHREAD_CANCEL
397 pthread_cancel (tid);
398 pthread_join (tid, NULL);
399 #else
400 pthread_join (tid, (void **)&result);
401 pwmd_free (result);
402 #endif
403 return gpg_error_from_errno (n);
406 pthread_join (tid, (void **)&result);
407 n = *result;
408 pwmd_free (result);
409 break;
412 if (n)
413 return GPG_ERR_UNKNOWN_HOST; //FIXME
415 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
416 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
418 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
419 if (pwm->fd == -1)
421 rc = gpg_error_from_syserror ();
422 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
423 break;
424 continue;
427 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
429 rc = gpg_error_from_syserror ();
430 break;
433 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
434 pwm->tcp->addr->ai_family == AF_INET6
435 ? sizeof (struct sockaddr_in6)
436 : sizeof (struct sockaddr)) == -1)
438 int n;
439 struct timeval tv;
440 fd_set wfds;
441 unsigned elapsed = 0;
443 rc = gpg_error_from_syserror ();
444 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
446 close (pwm->fd);
447 pwm->fd = -1;
448 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
449 return rc;
450 continue;
453 again:
454 tv.tv_sec = 1;
455 tv.tv_usec = 0;
456 FD_ZERO (&wfds);
457 FD_SET (pwm->fd, &wfds);
458 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
459 rc = 0;
460 if (!n || pwm->cancel)
462 if (pwm->cancel)
463 rc = gpg_error (GPG_ERR_CANCELED);
464 else if (++elapsed >= pwm->socket_timeout)
465 rc = gpg_error (GPG_ERR_ETIMEDOUT);
466 else
467 goto again;
469 else if (n != -1)
471 socklen_t len = sizeof(int);
473 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
474 if (n)
475 rc = gpg_error_from_errno (n);
477 else if (n == -1)
478 rc = gpg_error_from_syserror ();
480 if (rc)
482 close (pwm->fd);
483 pwm->fd = -1;
484 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
485 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
486 || pwm->cancel)
487 return rc;
489 else
490 break;
492 else
493 break;
496 if (!rc)
497 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
498 rc = gpg_error_from_syserror ();
500 return rc;
502 #endif
504 static void
505 command_start (pwm_t *pwm)
507 pwm->cancel = 0;
510 gpg_error_t
511 pwmd_connect (pwm_t * pwm, const char *url, ...)
513 const char *p = url;
514 gpg_error_t rc;
516 if (!pwm)
517 return FINISH (GPG_ERR_INV_ARG);
518 else if (!pwm->ctx)
520 rc = init_handle (pwm);
521 if (rc)
522 return rc;
525 command_start (pwm);
527 if (!(pwm->opts & OPT_SIGPIPE))
528 signal (SIGPIPE, SIG_IGN);
530 #ifdef WITH_GNUTLS
531 pwm->tls_error = 0;
532 #endif
533 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
535 if (p && (*p == '/' || *p == '~'))
536 rc = connect_uds (pwm, p);
537 else if (!p || !strncmp (p, "file://", 7))
539 if (p)
540 p += 7;
541 #ifdef DEFAULT_PWMD_SOCKET
542 else
543 p = DEFAULT_PWMD_SOCKET;
544 #endif
545 rc = connect_uds (pwm, p);
547 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
548 !strncmp (p, "ssh4://", 7))
550 #ifndef WITH_SSH
551 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
552 #else
553 char *host = NULL;
554 int port;
555 char *username = NULL;
557 if (!strncmp (p, "ssh6://", 7))
559 pwm->prot = PWMD_IPV6;
560 p += 7;
562 else if (!strncmp (p, "ssh4://", 7))
564 pwm->prot = PWMD_IPV4;
565 p += 7;
567 else
569 pwm->prot = PWMD_IP_ANY;
570 p += 6;
573 rc = _parse_ssh_url (p, &host, &port, &username);
574 if (!rc)
576 va_list ap;
577 char *identity = NULL;
578 char *knownhosts = NULL;
580 va_start (ap, url);
581 identity = va_arg (ap, char *);
583 if (!identity && !pwm->use_agent)
584 rc = GPG_ERR_INV_ARG;
585 else
586 knownhosts = va_arg (ap, char *);
588 va_end (ap);
590 if (!rc)
591 rc = _do_ssh_connect (pwm, host, port, identity, username,
592 knownhosts);
593 if (!rc)
595 rc = _connect_finalize (pwm);
596 if (rc)
597 free_tcp (pwm);
601 pwmd_free (host);
602 pwmd_free (username);
603 pwm->local_pinentry = 1;
604 #endif
606 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
607 !strncmp (p, "tls4://", 7))
609 #ifndef WITH_GNUTLS
610 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
611 #else
612 char *host = NULL;
613 int port;
615 if (!strncmp (p, "tls6://", 7))
617 pwm->prot = PWMD_IPV6;
618 p += 7;
620 else if (!strncmp (p, "tls4://", 7))
622 pwm->prot = PWMD_IPV4;
623 p += 7;
625 else
627 pwm->prot = PWMD_IP_ANY;
628 p += 6;
631 rc = _parse_tls_url (p, &host, &port);
632 if (!rc)
634 va_list ap;
635 char *clientcert = NULL;
636 char *clientkey = NULL;
637 char *cacert = NULL;
638 char *prio = NULL;
639 char *server_fp = NULL;
641 va_start (ap, url);
642 clientcert = va_arg (ap, char *);
644 if (!clientcert)
645 rc = GPG_ERR_INV_ARG;
646 else
648 clientkey = va_arg (ap, char *);
649 if (!clientkey)
650 rc = GPG_ERR_INV_ARG;
651 else
653 cacert = va_arg (ap, char *);
654 if (!cacert)
655 rc = GPG_ERR_INV_ARG;
656 else
658 prio = va_arg (ap, char *);
659 server_fp = va_arg (ap, char *);
664 va_end (ap);
666 if (!rc)
667 rc = _do_tls_connect (pwm, host, port, clientcert, clientkey,
668 cacert, prio, server_fp, pwm->tls_verify);
669 if (!rc)
671 rc = _connect_finalize (pwm);
672 if (rc)
673 free_tcp (pwm);
677 pwmd_free (host);
678 pwm->local_pinentry = 1;
679 #endif
682 if (!rc)
683 pwm->connected = 1;
685 return FINISH (rc);
688 static void
689 disconnect (pwm_t * pwm)
691 if (!pwm)
692 return;
694 if (pwm->ctx)
695 assuan_release (pwm->ctx);
697 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
698 free_tcp (pwm);
699 #endif
700 pwm->ctx = NULL;
701 pwm->fd = -1;
702 pwm->connected = 0;
705 void
706 pwmd_close (pwm_t * pwm)
708 if (!pwm)
709 return;
711 disconnect (pwm);
712 pwmd_free (pwm->pinentry_error);
713 pwmd_free (pwm->pinentry_desc);
714 pwmd_free (pwm->pinentry_prompt);
715 pwmd_free (pwm->pinentry_tty);
716 pwmd_free (pwm->pinentry_display);
717 pwmd_free (pwm->pinentry_term);
718 pwmd_free (pwm->pinentry_lcctype);
719 pwmd_free (pwm->pinentry_lcmessages);
720 pwmd_free (pwm->filename);
721 pwmd_free (pwm->name);
722 pwmd_free (pwm->passphrase_info);
723 pwmd_free (pwm->passphrase_hint);
725 #ifdef WITH_PINENTRY
726 if (pwm->pctx)
727 _pinentry_disconnect (pwm);
728 #endif
730 pwmd_free (pwm);
733 static gpg_error_t
734 inquire_realloc_cb (void *data, const void *buffer, size_t len)
736 membuf_t *mem = (membuf_t *) data;
737 void *p;
739 if (!buffer)
740 return 0;
742 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
743 return gpg_error (GPG_ERR_ENOMEM);
745 mem->buf = p;
746 memcpy ((char *) mem->buf + mem->len, buffer, len);
747 mem->len += len;
748 return 0;
751 static gpg_error_t
752 get_password (pwm_t * pwm, char **result, size_t * len,
753 pwmd_pinentry_t w, int echo)
755 char buf[ASSUAN_LINELENGTH+1] = { 0 }, *p;
756 struct termios told, tnew;
757 char *key = NULL;
759 if (result)
760 *result = NULL;
762 if (len)
763 *len = 0;
765 if (!isatty (STDIN_FILENO))
767 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
768 return GPG_ERR_ENOTTY;
771 if (!echo)
773 if (tcgetattr (STDIN_FILENO, &told) == -1)
774 return gpg_error_from_syserror ();
776 memcpy (&tnew, &told, sizeof (struct termios));
777 tnew.c_lflag &= ~(ECHO);
778 tnew.c_lflag |= ICANON | ECHONL;
780 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
782 int n = errno;
784 tcsetattr (STDIN_FILENO, TCSANOW, &told);
785 return gpg_error_from_errno (n);
789 if (pwm->passphrase_hint)
790 fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint);
792 switch (w)
794 case PWMD_PINENTRY_OPEN:
795 fprintf (stderr, N_("Passphrase for %s: "), pwm->filename);
796 break;
797 case PWMD_PINENTRY_OPEN_FAILED:
798 fprintf (stderr, N_("Invalid passphrase. Passphrase for %s: "),
799 pwm->filename);
800 break;
801 case PWMD_PINENTRY_SAVE:
802 fprintf (stderr, N_("New passphrase for %s: "), pwm->filename);
803 break;
804 case PWMD_PINENTRY_SAVE_CONFIRM:
805 fprintf (stderr, N_("Repeat passphrase: "));
806 break;
807 case PWMD_PINENTRY_CONFIRM:
808 if (pwm->pinentry_desc)
809 fprintf (stderr, "%s", pwm->pinentry_desc);
811 if (pwm->pinentry_prompt)
812 fprintf (stderr, "%s", pwm->pinentry_prompt);
813 else
814 fprintf(stderr, N_("Confirm [y/N]:"));
815 default:
816 break;
819 p = fgets (buf, sizeof (buf), stdin);
821 if (!echo)
822 tcsetattr (STDIN_FILENO, TCSANOW, &told);
824 if (!p || feof (stdin))
826 clearerr (stdin);
827 return GPG_ERR_CANCELED;
830 /* Strip the newline character. */
831 p[strlen (p) - 1] = 0;
833 if (buf[0])
835 if (w == PWMD_PINENTRY_CONFIRM)
837 if (*p != 'y' && *p != 'Y')
838 return GPG_ERR_CANCELED;
839 return 0;
842 key = pwmd_strdup_printf ("%s", p);
843 wipememory (buf, 0, sizeof (buf));
844 if (!key)
845 return GPG_ERR_ENOMEM;
847 if (result)
848 *result = key;
850 if (len)
851 *len = strlen (key);
853 else
855 if (w == PWMD_PINENTRY_CONFIRM)
856 return GPG_ERR_CANCELED;
858 /* To satisfy inquire_cb(). */
859 if (result)
860 *result = pwmd_strdup ("");
862 if (len)
863 *len = 1;
866 return 0;
869 gpg_error_t
870 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
872 gpg_error_t rc;
873 int new_password = 0;
874 char *password = NULL, *newpass = NULL;
875 int error = 0;
877 command_start (pwm);
879 if (data)
880 *data = NULL;
882 if (size)
883 *size = 0;
885 if (!strcmp (keyword, "NEW_PASSPHRASE"))
886 new_password = 1;
888 if (!new_password && pwm->pinentry_try)
889 error = 1;
891 again:
892 if (pwm->disable_pinentry)
894 rc = get_password (pwm, &password, size,
895 new_password ? PWMD_PINENTRY_SAVE :
896 error ? PWMD_PINENTRY_OPEN_FAILED :
897 PWMD_PINENTRY_OPEN, 0);
898 if (!rc && new_password)
899 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
902 else
904 pwmd_pinentry_t which;
906 if (error)
907 which = new_password
908 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
909 else
910 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
912 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
913 if (!rc && new_password)
914 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
915 PWMD_PINENTRY_SAVE_CONFIRM);
918 if (!rc && new_password)
920 if ((!password && newpass) || (!newpass && password)
921 || (newpass && password && strcmp (newpass, password)))
923 if (pwm->disable_pinentry)
924 fprintf (stderr, N_("Passphrases do not match.\n"));
926 pwmd_free (password);
927 pwmd_free (newpass);
928 password = newpass = NULL;
929 error = 1;
930 goto again;
934 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
935 pwmd_free (newpass);
936 if (!rc && data)
937 *data = password;
938 else
939 pwmd_free (password);
941 return rc;
944 static gpg_error_t
945 inquire_cb (void *data, const char *keyword)
947 pwm_t *pwm = (pwm_t *) data;
948 gpg_error_t rc = 0;
949 int free_result = 0;
950 char *result = NULL;
951 int is_password = 0;
952 int new_password = 0;
954 if (!strcmp (keyword, "PASSPHRASE") || !strcmp (keyword, "SIGN_PASSPHRASE"))
955 is_password = 1;
956 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
957 new_password = 1;
959 /* Shouldn't get this far without a callback. */
960 if (!pwm->override_inquire && !pwm->inquire_func
961 && !is_password && !new_password)
962 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
964 for (;;)
966 size_t len = 0;
967 gpg_error_t arc;
969 result = NULL;
971 if (!pwm->override_inquire && (is_password || new_password))
973 free_result = 1;
974 rc = pwmd_password (data, keyword, &result, &len);
975 if (!rc)
976 rc = GPG_ERR_EOF;
978 else
979 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
980 &len);
982 /* gpg will truncate a passphrase at the first nil byte which may be bad
983 * for generated key files. */
984 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
985 && (is_password || new_password))
987 if (len && result && *result)
989 for (size_t n = 0; n < len; n++)
991 if (result[n] == 0 && n+1 != len)
992 rc = GPG_ERR_INV_PASSPHRASE;
997 cancel:
998 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
1000 #ifndef LIBASSUAN_2_1_0
1001 gpg_error_t trc = rc;
1003 /* Cancel this inquire. */
1004 rc = assuan_send_data (pwm->ctx, NULL, 1);
1005 if (!rc)
1007 char *line;
1008 size_t len;
1010 /* There is a bug (or feature?) in assuan_send_data() that
1011 * when cancelling an inquire the next read from the server is
1012 * not done until the next command making the next command
1013 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1015 rc = assuan_read_line (pwm->ctx, &line, &len);
1017 /* Restore the original error. This differs from the error
1018 * returned from the pwmd command (GPG_ERR_CANCELED). This
1019 * error is returned to the calling function.
1021 if (!rc)
1022 rc = trc;
1024 #endif
1025 break;
1028 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1030 if (len <= 0 && !result)
1032 rc = 0;
1033 break;
1035 else if ((len <= 0 && result) || (len && !result))
1037 rc = gpg_error (GPG_ERR_INV_ARG);
1038 break;
1041 if (pwm->inquire_maxlen
1042 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1044 rc = gpg_error (GPG_ERR_TOO_LARGE);
1045 if (!free_result)
1046 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1047 &result, &len);
1048 goto cancel;
1051 arc = assuan_send_data (pwm->ctx, result, len);
1052 if (gpg_err_code (rc) == GPG_ERR_EOF)
1054 rc = arc;
1055 break;
1058 rc = arc;
1060 else if (rc)
1061 break;
1063 if (!rc)
1065 pwm->inquire_sent += len;
1067 if (pwm->status_func)
1069 char buf[ASSUAN_LINELENGTH];
1071 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1072 pwm->inquire_total);
1073 rc = pwm->status_func (pwm->status_data, buf);
1074 if (rc)
1075 continue;
1080 if (free_result)
1081 pwmd_free (result);
1083 pwm->inquire_maxlen = pwm->inquire_sent = 0;
1084 return rc;
1087 static gpg_error_t
1088 parse_assuan_line (pwm_t * pwm)
1090 gpg_error_t rc;
1091 char *line;
1092 size_t len;
1094 rc = assuan_read_line (pwm->ctx, &line, &len);
1095 if (!rc)
1097 if (line[0] == 'O' && line[1] == 'K' &&
1098 (line[2] == 0 || line[2] == ' '))
1101 else if (line[0] == '#')
1104 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1106 if (pwm->status_func)
1108 rc = pwm->status_func (pwm->status_data,
1109 line[1] == 0 ? line + 1 : line + 2);
1112 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1113 (line[3] == 0 || line[3] == ' '))
1115 line += 4;
1116 rc = strtol (line, NULL, 10);
1120 return rc;
1123 static void
1124 reset_handle (pwm_t *pwm)
1126 pwm->fd = -1;
1127 pwm->cancel = 0;
1128 pwm->pinentry_disabled = 0;
1129 #ifdef WITH_PINENTRY
1130 if (pwm->pctx)
1131 _pinentry_disconnect (pwm);
1132 #endif
1133 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1134 #ifdef WITH_GNUTLS
1135 pwm->tls_error = 0;
1136 #endif
1138 if (pwm->tcp)
1139 pwm->tcp->rc = 0;
1140 #endif
1143 gpg_error_t
1144 pwmd_disconnect (pwm_t * pwm)
1146 if (!pwm)
1147 return FINISH (GPG_ERR_INV_ARG);
1149 command_start (pwm);
1151 if (pwm->fd == -1)
1152 return FINISH (GPG_ERR_INV_STATE);
1154 disconnect (pwm);
1155 reset_handle (pwm);
1156 return 0;
1159 /* Note that this should only be called when not in a command. */
1160 gpg_error_t
1161 pwmd_process (pwm_t * pwm)
1163 gpg_error_t rc = 0;
1164 fd_set fds;
1165 struct timeval tv = { 0, 0 };
1166 int n;
1168 if (!pwm || pwm->fd == -1)
1169 return FINISH (GPG_ERR_INV_ARG);
1170 else if (!pwm->ctx)
1171 return FINISH (GPG_ERR_INV_STATE);
1173 FD_ZERO (&fds);
1174 FD_SET (pwm->fd, &fds);
1175 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1177 if (n == -1)
1178 return FINISH (gpg_error_from_syserror ());
1180 if (n > 0)
1182 if (FD_ISSET (pwm->fd, &fds))
1183 rc = parse_assuan_line (pwm);
1186 while (!rc && assuan_pending_line (pwm->ctx))
1187 rc = parse_assuan_line (pwm);
1189 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1190 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1192 close (pwm->fd);
1193 pwm->fd = -1;
1195 #endif
1197 return FINISH (rc);
1200 static gpg_error_t
1201 status_cb (void *data, const char *line)
1203 pwm_t *pwm = data;
1205 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1206 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1207 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1209 pwmd_free (pwm->passphrase_hint);
1210 pwm->passphrase_hint = pwmd_strdup (line+16);
1212 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1214 pwmd_free (pwm->passphrase_info);
1215 pwm->passphrase_info = pwmd_strdup (line+16);
1218 if (pwm->status_func)
1219 return pwm->status_func (pwm->status_data, line);
1221 return 0;
1224 gpg_error_t
1225 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1226 char **result, size_t * len, const char *cmd)
1228 membuf_t data;
1229 gpg_error_t rc;
1231 if (!cmd || !*cmd)
1232 return FINISH (GPG_ERR_INV_ARG);
1234 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1235 return FINISH (GPG_ERR_LINE_TOO_LONG);
1237 data.len = 0;
1238 data.buf = NULL;
1239 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1240 #ifdef WITH_QUALITY
1241 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1242 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1243 #else
1244 inquire_cb, pwm,
1245 #endif
1246 status_cb, pwm);
1248 if (rc)
1250 if (data.buf)
1252 pwmd_free (data.buf);
1253 data.buf = NULL;
1256 else
1258 if (data.buf)
1260 inquire_realloc_cb (&data, "", 1);
1262 if (result)
1263 *result = (char *) data.buf;
1264 else
1265 pwmd_free (data.buf);
1267 if (len)
1268 *len = data.len;
1272 pwm->inquire_maxlen = 0;
1273 return rc;
1276 gpg_error_t
1277 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1278 pwmd_inquire_cb_t func, void *user, const char *cmd,
1279 va_list ap)
1281 char *buf;
1282 size_t len;
1283 va_list ap2;
1285 command_start (pwm);
1287 if (result)
1288 *result = NULL;
1290 if (rlen)
1291 *rlen = 0;
1293 if (!pwm || !cmd)
1294 return FINISH (GPG_ERR_INV_ARG);
1295 if (!pwm->ctx)
1296 return FINISH (GPG_ERR_INV_STATE);
1299 * C99 allows the dst pointer to be null which will calculate the length
1300 * of the would-be result and return it.
1302 va_copy (ap2, ap);
1303 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1304 buf = (char *) pwmd_malloc (len);
1305 if (!buf)
1307 va_end (ap2);
1308 return FINISH (GPG_ERR_ENOMEM);
1311 len = vsnprintf (buf, len, cmd, ap2);
1312 va_end (ap2);
1314 if (buf[strlen (buf) - 1] == '\n')
1315 buf[strlen (buf) - 1] = 0;
1316 if (buf[strlen (buf) - 1] == '\r')
1317 buf[strlen (buf) - 1] = 0;
1319 pwm->inquire_func = func;
1320 pwm->inquire_data = user;
1321 pwm->inquire_sent = 0;
1322 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1323 pwmd_free (buf);
1324 return rc;
1327 gpg_error_t
1328 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1329 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1331 va_list ap;
1333 if (result)
1334 *result = NULL;
1336 if (len)
1337 *len = 0;
1339 if (!pwm || !cmd)
1340 return FINISH (GPG_ERR_INV_ARG);
1341 if (!pwm->ctx)
1342 return FINISH (GPG_ERR_INV_STATE);
1344 va_start (ap, cmd);
1345 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1346 va_end (ap);
1347 return rc;
1350 static gpg_error_t
1351 send_pinentry_timeout (pwm_t *pwm)
1353 gpg_error_t rc = 0;
1355 if ((pwm->pinentry_timeout >= 0
1356 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1357 || (pwm->pinentry_timeout == -1
1358 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1360 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1361 "OPTION pinentry-timeout=%i",
1362 pwm->pinentry_timeout);
1363 if (!rc)
1364 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1367 return rc;
1370 static gpg_error_t
1371 send_pinentry_options (pwm_t * pwm)
1373 gpg_error_t rc;
1375 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1376 "OPTION disable-pinentry=0");
1377 if (!rc && pwm->pinentry_tty)
1378 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1379 pwm->pinentry_tty);
1381 if (!rc && pwm->pinentry_term)
1382 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1383 pwm->pinentry_term);
1385 if (!rc && pwm->pinentry_display)
1386 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1387 pwm->pinentry_display);
1389 if (!rc && pwm->pinentry_desc)
1390 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1391 pwm->pinentry_desc);
1393 if (!rc && pwm->pinentry_lcctype)
1394 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1395 pwm->pinentry_lcctype);
1397 if (!rc && pwm->pinentry_lcmessages)
1398 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1399 pwm->pinentry_lcmessages);
1401 if (!rc)
1402 rc = send_pinentry_timeout (pwm);
1404 return rc;
1407 gpg_error_t
1408 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1410 if (!pwm || !result)
1411 return FINISH (GPG_ERR_INV_ARG);
1413 *result = PWMD_SOCKET_LOCAL;
1415 if (pwm->fd == -1)
1416 return FINISH (GPG_ERR_INV_STATE);
1418 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1419 #ifdef WITH_SSH
1420 if (pwm->tcp && pwm->tcp->ssh)
1421 *result = PWMD_SOCKET_SSH;
1422 #endif
1423 #ifdef WITH_GNUTLS
1424 if (pwm->tcp && pwm->tcp->tls)
1425 *result = PWMD_SOCKET_TLS;
1426 #endif
1427 #endif
1428 return 0;
1431 static gpg_error_t
1432 disable_pinentry (pwm_t *pwm, int *disable)
1434 gpg_error_t rc;
1435 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1436 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1437 #else
1438 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1439 #endif
1441 if (disable)
1442 *disable = no_pinentry;
1444 if (pwm->pinentry_disabled && no_pinentry)
1445 return 0;
1446 else if (!pwm->pinentry_disabled && !no_pinentry)
1447 return 0;
1449 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1450 no_pinentry);
1451 if (!rc)
1452 pwm->pinentry_disabled = no_pinentry;
1454 return rc;
1457 gpg_error_t
1458 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1459 void *data)
1461 gpg_error_t rc = 0;
1462 int no_pinentry = 0;
1464 if (!pwm || !filename || !*filename)
1465 return FINISH (GPG_ERR_INV_ARG);
1467 if (!pwm->ctx)
1468 return FINISH (GPG_ERR_INV_STATE);
1470 command_start (pwm);
1471 rc = disable_pinentry (pwm, &no_pinentry);
1472 if (!rc && !no_pinentry)
1473 rc = send_pinentry_options (pwm);
1475 if (!rc)
1477 pwm->pinentry_try = 0;
1478 pwmd_free (pwm->filename);
1479 pwm->filename = pwmd_strdup (filename);
1483 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1484 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1485 filename);
1487 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1488 && pwm->pinentry_disabled
1489 && ++pwm->pinentry_try < pwm->pinentry_tries);
1491 pwm->pinentry_try = 0;
1493 if (rc)
1495 pwmd_free (pwm->filename);
1496 pwm->filename = NULL;
1500 pwmd_free (pwm->passphrase_hint);
1501 pwmd_free (pwm->passphrase_info);
1502 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1503 return FINISH (rc);
1506 static gpg_error_t
1507 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1508 void *data, int save)
1510 gpg_error_t rc = 0;
1511 int no_pinentry = 0;
1513 if (!pwm)
1514 return FINISH (GPG_ERR_INV_ARG);
1515 if (!pwm->ctx)
1516 return FINISH (GPG_ERR_INV_STATE);
1518 command_start (pwm);
1519 rc = disable_pinentry (pwm, &no_pinentry);
1520 if (!rc && !no_pinentry)
1521 rc = send_pinentry_options (pwm);
1523 if (!rc)
1524 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1525 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
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 gpg_error_t
1534 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1536 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1539 gpg_error_t
1540 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1542 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1545 static gpg_error_t
1546 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1548 int n, *intp;
1549 size_t *sizetp;
1550 char *arg1, **charpp;
1551 gpg_error_t rc = 0;
1553 if (!pwm)
1554 return GPG_ERR_INV_ARG;
1556 command_start (pwm);
1557 switch (opt)
1559 case PWMD_OPTION_SERVER_VERSION:
1560 if (!get)
1561 return GPG_ERR_NOT_SUPPORTED;
1563 if (!pwm)
1564 rc = GPG_ERR_INV_ARG;
1565 else if (!pwm->ctx)
1566 rc = GPG_ERR_INV_STATE;
1567 else
1569 unsigned *u = va_arg (ap, unsigned *);
1570 *u = pwm->version;
1573 break;
1574 case PWMD_OPTION_SIGPIPE:
1575 if (get)
1577 intp = va_arg (ap, int *);
1578 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1579 break;
1582 n = va_arg (ap, int);
1583 if (n < 0 || n > 1)
1584 rc = GPG_ERR_INV_VALUE;
1586 if (n)
1587 pwm->opts |= OPT_SIGPIPE;
1588 else
1589 pwm->opts &= ~OPT_SIGPIPE;
1591 break;
1592 case PWMD_OPTION_LOCK_ON_OPEN:
1593 if (get)
1595 intp = va_arg (ap, int *);
1596 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1597 break;
1600 n = va_arg (ap, int);
1602 if (n < 0 || n > 1)
1603 rc = GPG_ERR_INV_VALUE;
1605 if (n)
1606 pwm->opts |= OPT_LOCK_ON_OPEN;
1607 else
1608 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1610 break;
1611 case PWMD_OPTION_INQUIRE_TOTAL:
1612 if (get)
1614 sizetp = va_arg (ap, size_t *);
1615 *sizetp = pwm->inquire_total;
1616 break;
1619 pwm->inquire_total = va_arg (ap, size_t);
1620 break;
1621 case PWMD_OPTION_STATUS_CB:
1622 if (get)
1624 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1626 *cb = pwm->status_func;
1627 break;
1630 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1631 break;
1632 case PWMD_OPTION_STATUS_DATA:
1633 if (get)
1635 void **data = va_arg (ap, void **);
1637 *data = pwm->status_data;
1638 break;
1641 pwm->status_data = va_arg (ap, void *);
1642 break;
1643 case PWMD_OPTION_NO_PINENTRY:
1644 if (get)
1646 intp = va_arg (ap, int *);
1647 *intp = pwm->disable_pinentry;
1648 break;
1651 n = va_arg (ap, int);
1653 if (n < 0 || n > 1)
1654 rc = GPG_ERR_INV_VALUE;
1655 else
1656 pwm->disable_pinentry = n;
1657 break;
1658 case PWMD_OPTION_LOCAL_PINENTRY:
1659 if (get)
1661 intp = va_arg (ap, int *);
1662 *intp = pwm->local_pinentry;
1663 break;
1666 n = va_arg (ap, int);
1668 if (n < 0 || n > 1)
1669 rc = GPG_ERR_INV_VALUE;
1670 else
1671 pwm->local_pinentry = n;
1673 break;
1674 case PWMD_OPTION_PINENTRY_TIMEOUT:
1675 if (get)
1677 intp = va_arg (ap, int *);
1678 *intp = pwm->pinentry_timeout;
1679 break;
1682 n = va_arg (ap, int);
1684 if (n < 0)
1685 rc = GPG_ERR_INV_VALUE;
1686 else
1687 pwm->pinentry_timeout = n;
1688 break;
1689 case PWMD_OPTION_PINENTRY_TRIES:
1690 if (get)
1692 intp = va_arg (ap, int *);
1693 *intp = pwm->pinentry_tries;
1694 break;
1697 n = va_arg (ap, int);
1698 pwm->pinentry_tries = n;
1699 break;
1700 case PWMD_OPTION_PINENTRY_PATH:
1701 if (get)
1703 charpp = va_arg (ap, char **);
1704 *charpp = pwm->pinentry_path;
1705 break;
1708 arg1 = va_arg (ap, char *);
1709 pwmd_free (pwm->pinentry_path);
1710 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1711 break;
1712 case PWMD_OPTION_PINENTRY_TTY:
1713 if (get)
1715 charpp = va_arg (ap, char **);
1716 *charpp = pwm->pinentry_tty;
1717 break;
1720 arg1 = va_arg (ap, char *);
1721 pwmd_free (pwm->pinentry_tty);
1722 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1723 break;
1724 case PWMD_OPTION_PINENTRY_DISPLAY:
1725 if (get)
1727 charpp = va_arg (ap, char **);
1728 *charpp = pwm->pinentry_display;
1729 break;
1732 arg1 = va_arg (ap, char *);
1733 pwmd_free (pwm->pinentry_display);
1734 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1735 break;
1736 case PWMD_OPTION_PINENTRY_TERM:
1737 if (get)
1739 charpp = va_arg (ap, char **);
1740 *charpp = pwm->pinentry_term;
1741 break;
1744 arg1 = va_arg (ap, char *);
1745 pwmd_free (pwm->pinentry_term);
1746 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1747 break;
1748 case PWMD_OPTION_PINENTRY_ERROR:
1749 if (get)
1751 charpp = va_arg (ap, char **);
1752 *charpp = pwm->pinentry_error;
1753 break;
1756 arg1 = va_arg (ap, char *);
1757 pwmd_free (pwm->pinentry_error);
1758 if (pwm->disable_pinentry)
1759 pwm->pinentry_error = arg1 ? pwmd_strdup (arg1) : NULL;
1760 else
1761 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1762 break;
1763 case PWMD_OPTION_PINENTRY_PROMPT:
1764 if (get)
1766 charpp = va_arg (ap, char **);
1767 *charpp = pwm->pinentry_prompt;
1768 break;
1771 arg1 = va_arg (ap, char *);
1772 pwmd_free (pwm->pinentry_prompt);
1773 if (pwm->disable_pinentry)
1774 pwm->pinentry_prompt = arg1 ? pwmd_strdup (arg1) : NULL;
1775 else
1776 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1777 break;
1778 case PWMD_OPTION_PINENTRY_DESC:
1779 if (get)
1781 charpp = va_arg (ap, char **);
1782 *charpp = pwm->pinentry_desc;
1783 break;
1786 arg1 = va_arg (ap, char *);
1787 pwmd_free (pwm->pinentry_desc);
1788 if (pwm->disable_pinentry)
1789 pwm->pinentry_desc = arg1 ? pwmd_strdup (arg1) : NULL;
1790 else
1791 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1792 break;
1793 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1794 if (get)
1796 charpp = va_arg (ap, char **);
1797 *charpp = pwm->pinentry_lcctype;
1798 break;
1801 arg1 = va_arg (ap, char *);
1802 pwmd_free (pwm->pinentry_lcctype);
1803 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1804 break;
1805 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1806 if (get)
1808 charpp = va_arg (ap, char **);
1809 *charpp = pwm->pinentry_lcmessages;
1810 break;
1813 arg1 = va_arg (ap, char *);
1814 pwmd_free (pwm->pinentry_lcmessages);
1815 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1816 break;
1817 case PWMD_OPTION_KNOWNHOST_CB:
1818 if (get)
1820 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1822 *cb = pwm->kh_cb;
1823 break;
1826 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1827 break;
1828 case PWMD_OPTION_KNOWNHOST_DATA:
1829 if (get)
1831 void **data = va_arg (ap, void **);
1833 *data = pwm->kh_data;
1834 break;
1837 pwm->kh_data = va_arg (ap, void *);
1838 break;
1839 case PWMD_OPTION_SSH_AGENT:
1840 if (get)
1842 intp = va_arg (ap, int *);
1843 *intp = pwm->use_agent;
1844 break;
1847 pwm->use_agent = va_arg (ap, int);
1849 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1851 pwm->use_agent = 0;
1852 rc = GPG_ERR_INV_VALUE;
1854 break;
1855 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE:
1856 if (get)
1858 intp = va_arg (ap, int *);
1859 *intp = pwm->needs_passphrase;
1860 break;
1863 pwm->needs_passphrase = va_arg (ap, int);
1865 if (pwm->needs_passphrase < 0 || pwm->needs_passphrase > 1)
1867 pwm->needs_passphrase = 0;
1868 rc = GPG_ERR_INV_VALUE;
1870 break;
1871 case PWMD_OPTION_TLS_VERIFY:
1872 if (get)
1874 intp = va_arg (ap, int *);
1875 *intp = pwm->tls_verify;
1876 break;
1879 pwm->tls_verify = va_arg (ap, int);
1881 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1883 pwm->tls_verify = 0;
1884 rc = GPG_ERR_INV_VALUE;
1886 break;
1887 case PWMD_OPTION_SOCKET_TIMEOUT:
1888 if (get)
1890 intp = va_arg (ap, int *);
1891 *intp = pwm->socket_timeout;
1892 break;
1895 pwm->socket_timeout = va_arg (ap, int);
1896 if (pwm->socket_timeout < 0)
1898 pwm->socket_timeout = 0;
1899 rc = GPG_ERR_INV_VALUE;
1902 #ifdef WITH_SSH
1903 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1905 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1906 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1907 pwm->socket_timeout * 1000);
1909 #endif
1910 #ifdef WITH_GNUTLS
1911 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1912 pwm->tcp->tls->timeout = pwm->socket_timeout;
1913 #endif
1914 break;
1915 case PWMD_OPTION_OVERRIDE_INQUIRE:
1916 if (get)
1918 intp = va_arg (ap, int *);
1919 *intp = pwm->override_inquire;
1920 break;
1923 pwm->override_inquire = va_arg (ap, int);
1925 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1927 pwm->override_inquire = 0;
1928 rc = GPG_ERR_INV_VALUE;
1930 break;
1931 default:
1932 rc = GPG_ERR_UNKNOWN_OPTION;
1933 break;
1936 return FINISH (rc);
1939 gpg_error_t
1940 pwmd_setopt (pwm_t * pwm, int opt, ...)
1942 va_list ap;
1943 gpg_error_t rc = 0;
1945 va_start (ap, opt);
1946 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1947 va_end (ap);
1948 return FINISH (rc);
1951 gpg_error_t
1952 pwmd_getopt (pwm_t *pwm, int opt, ...)
1954 va_list ap;
1955 gpg_error_t rc = 0;
1957 va_start (ap, opt);
1958 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1959 va_end (ap);
1960 return FINISH (rc);
1963 gpg_error_t
1964 pwmd_new (const char *name, pwm_t ** pwm)
1966 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1967 gpg_error_t rc;
1969 if (!h)
1970 return FINISH (GPG_ERR_ENOMEM);
1972 if (name)
1974 h->name = pwmd_strdup (name);
1975 if (!h->name)
1977 pwmd_free (h);
1978 return FINISH (GPG_ERR_ENOMEM);
1982 reset_handle (h);
1983 h->pinentry_timeout = -1;
1984 h->current_pinentry_timeout = -1;
1985 h->pinentry_tries = 3;
1986 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1987 h->prot = PWMD_IP_ANY;
1988 #endif
1990 if (isatty (STDOUT_FILENO))
1992 char buf[256];
1993 int err = ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
1995 if (!err)
1997 h->pinentry_tty = pwmd_strdup (buf);
1998 if (!h->pinentry_tty)
2000 rc = GPG_ERR_ENOMEM;
2001 goto fail;
2006 if (getenv ("TERM") && h->pinentry_tty)
2008 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
2009 if (!h->pinentry_term)
2011 rc = GPG_ERR_ENOMEM;
2012 goto fail;
2016 if (getenv ("DISPLAY"))
2018 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
2019 if (!h->pinentry_display)
2021 rc = GPG_ERR_ENOMEM;
2022 goto fail;
2026 update_pinentry_settings (h);
2027 *pwm = h;
2028 return 0;
2030 fail:
2031 pwmd_close (h);
2032 return FINISH (rc);
2035 void
2036 pwmd_free (void *ptr)
2038 _xfree (ptr);
2041 void *
2042 pwmd_malloc (size_t size)
2044 return _xmalloc (size);
2047 void *
2048 pwmd_calloc (size_t nmemb, size_t size)
2050 return _xcalloc (nmemb, size);
2053 void *
2054 pwmd_realloc (void *ptr, size_t size)
2056 return _xrealloc (ptr, size);
2059 char *
2060 pwmd_strdup (const char *str)
2062 char *t;
2063 size_t len;
2064 register size_t c;
2066 len = strlen (str);
2067 t = _xmalloc ((len + 1) * sizeof (char));
2068 if (!t)
2069 return NULL;
2071 for (c = 0; c < len; c++)
2072 t[c] = str[c];
2074 t[c] = 0;
2075 return t;
2078 char *
2079 pwmd_strdup_printf (const char *fmt, ...)
2081 va_list ap, ap2;
2082 int len;
2083 char *buf;
2085 if (!fmt)
2086 return NULL;
2088 va_start (ap, fmt);
2089 va_copy (ap2, ap);
2090 len = vsnprintf (NULL, 0, fmt, ap);
2091 va_end (ap);
2092 buf = pwmd_malloc (++len);
2093 if (buf)
2094 vsnprintf (buf, len, fmt, ap2);
2096 va_end (ap2);
2097 return buf;
2100 gpg_error_t
2101 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2102 size_t * len, pwmd_pinentry_t which)
2104 #ifndef WITH_PINENTRY
2105 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2106 #else
2107 gpg_error_t rc;
2109 command_start (pwm);
2110 if (which == PWMD_PINENTRY_CONFIRM && pwm->disable_pinentry)
2112 rc = get_password (pwm, NULL, NULL, which, 1);
2113 return FINISH (rc);
2116 rc = _pwmd_getpin (pwm, filename, result, len, which);
2117 return FINISH (rc);
2118 #endif
2121 const char *
2122 pwmd_version ()
2124 return LIBPWMD_VERSION_STR;
2127 unsigned int
2128 pwmd_features ()
2130 unsigned int n = 0;
2132 #ifdef WITH_PINENTRY
2133 n |= PWMD_FEATURE_PINENTRY;
2134 #endif
2135 #ifdef WITH_SSH
2136 n |= PWMD_FEATURE_SSH;
2137 #endif
2138 #ifdef WITH_QUALITY
2139 n |= PWMD_FEATURE_QUALITY;
2140 #endif
2141 #ifdef WITH_GNUTLS
2142 n |= PWMD_FEATURE_GNUTLS;
2143 #endif
2144 return n;
2147 gpg_error_t
2148 pwmd_fd (pwm_t * pwm, int *fd)
2150 if (!pwm || !fd)
2151 return FINISH (GPG_ERR_INV_ARG);
2153 if (pwm->fd == -1)
2154 return FINISH (GPG_ERR_INV_STATE);
2156 *fd = pwm->fd;
2157 return 0;
2160 void
2161 pwmd_set_pointer (pwm_t *pwm, void *data)
2163 pwm->user_data = data;
2166 void *
2167 pwmd_get_pointer (pwm_t *pwm)
2169 return pwm->user_data;
2173 pwmd_gnutls_error (pwm_t *pwm, const char **str)
2175 #ifndef WITH_GNUTLS
2176 return 0;
2177 #else
2178 if (str && pwm && pwm->tls_error)
2179 *str = gnutls_strerror (pwm->tls_error);
2181 return pwm ? pwm->tls_error : 0;
2182 #endif
2185 gpg_error_t
2186 pwmd_cancel (pwm_t *pwm)
2188 if (!pwm)
2189 return FINISH (GPG_ERR_INV_ARG);
2191 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2192 if (pwm->fd == -1 && !pwm->tcp)
2193 #else
2194 if (pwm->fd == -1)
2195 #endif
2196 return FINISH (GPG_ERR_INV_STATE);
2198 /* Can only cancel the connection for the time being. */
2199 if (pwm->connected)
2200 return FINISH (GPG_ERR_INV_STATE);
2202 pwm->cancel = 1;
2203 return 0;
2206 gpg_error_t
2207 pwmd_test_quality (const char *str, double *result)
2209 #ifndef WITH_QUALITY
2210 return GPG_ERR_NOT_IMPLEMENTED;
2211 #else
2212 if (!result)
2213 return GPG_ERR_INV_ARG;
2215 *result = ZxcvbnMatch (str, NULL, NULL);
2216 return 0;
2217 #endif