Disable gpg-error memory allocator callback for now.
[libpwmd.git] / src / libpwmd.c
bloba45c87870c9ef71059cf1e7c098d0d73942a8b43
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of libpwmd.
8 Libpwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Libpwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/un.h>
35 #include <signal.h>
36 #include <stdarg.h>
37 #include <string.h>
38 #include <sys/wait.h>
39 #include <fcntl.h>
40 #include <pwd.h>
41 #include <time.h>
42 #include <limits.h>
43 #include <sys/select.h>
44 #include <termios.h>
45 #include <libpwmd.h>
47 #ifdef HAVE_STRINGS_H
48 #include <strings.h>
49 #endif
51 #ifndef LINE_MAX
52 #define LINE_MAX 2048
53 #endif
55 #include "mem.h"
56 #include "misc.h"
57 #include "types.h"
59 #ifdef WITH_PINENTRY
60 #include "pinentry.h"
61 #endif
63 #ifdef WITH_QUALITY
64 #include "zxcvbn.h"
65 #endif
67 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
68 #include <sys/types.h>
69 #include <sys/socket.h>
70 #include <netdb.h>
71 #include <netinet/in.h>
72 #endif
74 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
75 ? gpg_error(rc) : rc
77 typedef struct
79 size_t len;
80 void *buf;
81 } membuf_t;
83 static gpg_error_t status_cb (void *data, const char *line);
85 ssize_t
86 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
88 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
89 pwm_t *pwm = assuan_get_pointer (ctx);
91 #ifdef WITH_SSH
92 if (pwm && pwm->tcp && pwm->tcp->ssh)
93 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
94 #endif
95 #ifdef WITH_GNUTLS
96 if (pwm && pwm->tcp && pwm->tcp->tls)
97 return tls_read_hook (pwm, fd, data, len);
98 #endif
99 #endif
101 return read ((int) fd, data, len);
104 ssize_t
105 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
106 size_t len)
108 ssize_t wrote;
109 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
110 pwm_t *pwm = assuan_get_pointer (ctx);
112 #ifdef WITH_SSH
113 if (pwm && pwm->tcp && pwm->tcp->ssh)
114 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
115 #endif
116 #ifdef WITH_GNUTLS
117 if (pwm && pwm->tcp && pwm->tcp->tls)
118 return tls_write_hook (pwm, fd, data, len);
119 #endif
120 #endif
122 /* libassuan cannot handle EAGAIN when doing writes. */
125 wrote = write ((int) fd, data, len);
126 if (wrote == -1 && errno == EAGAIN)
127 usleep (50000);
129 while (wrote == -1 && errno == EAGAIN);
131 return wrote;
134 pid_t
135 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
136 int options)
138 return waitpid (pid, status, options);
141 gpg_error_t
142 pwmd_init ()
144 static int initialized;
146 #ifdef WITH_GNUTLS
147 // May be called more than once.
148 gnutls_global_init ();
149 #endif
151 if (initialized)
152 return 0;
154 #ifdef ENABLE_NLS
155 bindtextdomain ("libpwmd", LOCALEDIR);
156 #endif
157 #ifdef WITH_SSH
158 libssh2_init (0);
159 #endif
160 gpgrt_init ();
161 //gpgrt_set_alloc_func (_xrealloc_gpgrt);
163 #ifdef WITH_QUALITY
164 ZxcvbnInit (NULL);
165 #endif
167 initialized = 1;
168 return 0;
171 void
172 pwmd_deinit ()
174 #ifdef WITH_GNUTLS
175 gnutls_global_deinit ();
176 #endif
177 #ifdef WITH_QUALITY
178 ZxcvbnUnInit();
179 #endif
182 gpg_error_t
183 _connect_finalize (pwm_t * pwm)
185 gpg_error_t rc = 0;
186 char *result = NULL;
187 int active[2];
188 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
190 if (n <= 0)
191 return GPG_ERR_EBADFD;
193 pwm->fd = active[0];
194 #ifdef WITH_PINENTRY
195 pwm->pinentry_pid = -1;
196 #endif
198 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
199 if (!rc)
201 pwm->version = strtoul (result, NULL, 16);
202 pwmd_free (result);
205 if (!rc && pwm->name)
206 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
207 pwm->name);
209 return rc;
212 static gpg_error_t
213 connect_uds (pwm_t * pwm, const char *path)
215 char *socketpath = NULL;
216 struct passwd pw;
217 char *pwbuf;
218 gpg_error_t rc;
220 if (!pwm)
221 return GPG_ERR_INV_ARG;
223 pwbuf = _getpwuid (&pw);
224 if (!pwbuf)
225 return gpg_error_from_syserror ();
227 if (!path || !*path)
228 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
229 else
230 socketpath = _expand_homedir ((char *) path, &pw);
232 pwmd_free (pwbuf);
233 if (!socketpath)
234 return GPG_ERR_ENOMEM;
236 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
237 pwmd_free (socketpath);
238 return rc ? rc : _connect_finalize (pwm);
241 static gpg_error_t
242 init_handle (pwm_t * pwm)
244 gpg_error_t rc;
245 static struct assuan_malloc_hooks mhooks = {
246 pwmd_malloc, pwmd_realloc, pwmd_free
248 static struct assuan_system_hooks shooks = {
249 ASSUAN_SYSTEM_HOOKS_VERSION,
250 __assuan_usleep,
251 __assuan_pipe,
252 __assuan_close,
253 hook_read,
254 hook_write,
255 //FIXME
256 NULL, //recvmsg
257 NULL, //sendmsg both are used for FD passing
258 __assuan_spawn,
259 hook_waitpid,
260 __assuan_socketpair,
261 __assuan_socket,
262 __assuan_connect
265 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
266 NULL);
267 if (rc)
268 return rc;
270 assuan_set_pointer (pwm->ctx, pwm);
271 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
272 return 0;
275 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
276 void
277 free_tcp (pwm_t *pwm)
279 struct tcp_s *tcp = pwm->tcp;
281 if (!tcp)
282 return;
284 #ifdef WITH_SSH
285 _free_ssh_conn (tcp->ssh);
286 #endif
287 #ifdef WITH_GNUTLS
288 tls_free (pwm);
289 #endif
291 pwmd_free (tcp->host);
292 if (tcp->addrs)
294 freeaddrinfo (tcp->addrs);
295 tcp->addrs = NULL;
298 pthread_cond_destroy (&tcp->dns_cond);
299 pthread_mutex_destroy (&tcp->dns_mutex);
300 pwmd_free (tcp);
301 pwm->tcp = NULL;
303 #endif
305 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
306 static void *
307 resolve_host_thread (void *arg)
309 pwm_t *pwm = arg;
310 struct addrinfo hints = { 0 };
311 char portstr[6];
313 switch (pwm->prot)
315 case PWMD_IP_ANY:
316 hints.ai_family = AF_UNSPEC;
317 break;
318 case PWMD_IPV4:
319 hints.ai_family = AF_INET;
320 break;
321 case PWMD_IPV6:
322 hints.ai_family = AF_INET6;
323 break;
326 hints.ai_socktype = SOCK_STREAM;
327 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
328 int *n = pwmd_malloc (sizeof (int));
329 pthread_cleanup_push (pwmd_free, n);
330 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
331 pthread_cleanup_pop (0);
332 pthread_cond_broadcast (&pwm->tcp->dns_cond);
333 pthread_exit (n);
334 return NULL;
337 gpg_error_t
338 tcp_connect_common (pwm_t * pwm)
340 #define TS_TIMEOUT 50000000L
341 int n;
342 gpg_error_t rc = 0;
343 pthread_t tid;
344 time_t now;
346 time (&now);
347 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
348 if (n)
349 return gpg_error_from_errno (n);
351 pthread_mutex_lock (&pwm->tcp->dns_mutex);
353 for (;;)
355 struct timespec ts;
356 int *result = NULL;
358 clock_gettime (CLOCK_REALTIME, &ts);
359 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
360 ts.tv_sec++;
361 ts.tv_nsec = 0;
363 else
364 ts.tv_nsec += TS_TIMEOUT;
366 if (pwm->cancel)
368 #ifdef HAVE_PTHREAD_CANCEL
369 pthread_cancel (tid);
370 pthread_join (tid, NULL);
371 #else
372 pthread_join (tid, (void **)&result);
373 pwmd_free (result);
374 #endif
375 return GPG_ERR_CANCELED;
378 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
379 &ts);
380 if (n == ETIMEDOUT)
382 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
384 #ifdef HAVE_PTHREAD_CANCEL
385 pthread_cancel (tid);
386 pthread_join (tid, NULL);
387 #else
388 pthread_join (tid, (void **)&result);
389 pwmd_free (result);
390 #endif
391 return GPG_ERR_ETIMEDOUT;
394 continue;
396 else if (n)
398 #ifdef HAVE_PTHREAD_CANCEL
399 pthread_cancel (tid);
400 pthread_join (tid, NULL);
401 #else
402 pthread_join (tid, (void **)&result);
403 pwmd_free (result);
404 #endif
405 return gpg_error_from_errno (n);
408 pthread_join (tid, (void **)&result);
409 n = *result;
410 pwmd_free (result);
411 break;
414 if (n)
415 return GPG_ERR_UNKNOWN_HOST; //FIXME
417 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
418 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
420 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
421 if (pwm->fd == -1)
423 rc = gpg_error_from_syserror ();
424 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
425 break;
426 continue;
429 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
431 rc = gpg_error_from_syserror ();
432 break;
435 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
436 pwm->tcp->addr->ai_family == AF_INET6
437 ? sizeof (struct sockaddr_in6)
438 : sizeof (struct sockaddr)) == -1)
440 int n;
441 struct timeval tv;
442 fd_set wfds;
443 unsigned elapsed = 0;
445 rc = gpg_error_from_syserror ();
446 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
448 close (pwm->fd);
449 pwm->fd = -1;
450 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
451 return rc;
452 continue;
455 again:
456 tv.tv_sec = 1;
457 tv.tv_usec = 0;
458 FD_ZERO (&wfds);
459 FD_SET (pwm->fd, &wfds);
460 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
461 rc = 0;
462 if (!n || pwm->cancel)
464 if (pwm->cancel)
465 rc = gpg_error (GPG_ERR_CANCELED);
466 else if (++elapsed >= pwm->socket_timeout)
467 rc = gpg_error (GPG_ERR_ETIMEDOUT);
468 else
469 goto again;
471 else if (n != -1)
473 socklen_t len = sizeof(int);
475 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
476 if (n)
477 rc = gpg_error_from_errno (n);
479 else if (n == -1)
480 rc = gpg_error_from_syserror ();
482 if (rc)
484 close (pwm->fd);
485 pwm->fd = -1;
486 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
487 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
488 || pwm->cancel)
489 return rc;
491 else
492 break;
494 else
495 break;
498 if (!rc)
499 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
500 rc = gpg_error_from_syserror ();
502 return rc;
504 #endif
506 static void
507 command_start (pwm_t *pwm)
509 pwm->cancel = 0;
512 gpg_error_t
513 pwmd_connect (pwm_t * pwm, const char *url, ...)
515 const char *p = url;
516 gpg_error_t rc;
518 if (!pwm)
519 return FINISH (GPG_ERR_INV_ARG);
520 else if (!pwm->ctx)
522 rc = init_handle (pwm);
523 if (rc)
524 return rc;
527 command_start (pwm);
529 if (!(pwm->opts & OPT_SIGPIPE))
530 signal (SIGPIPE, SIG_IGN);
532 #ifdef WITH_GNUTLS
533 pwm->tls_error = 0;
534 #endif
535 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
537 if (p && (*p == '/' || *p == '~'))
538 rc = connect_uds (pwm, p);
539 else if (!p || !strncmp (p, "file://", 7))
541 if (p)
542 p += 7;
543 #ifdef DEFAULT_PWMD_SOCKET
544 else
545 p = DEFAULT_PWMD_SOCKET;
546 #endif
547 rc = connect_uds (pwm, p);
549 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
550 !strncmp (p, "ssh4://", 7))
552 #ifndef WITH_SSH
553 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
554 #else
555 char *host = NULL;
556 int port;
557 char *username = NULL;
559 if (!strncmp (p, "ssh6://", 7))
561 pwm->prot = PWMD_IPV6;
562 p += 7;
564 else if (!strncmp (p, "ssh4://", 7))
566 pwm->prot = PWMD_IPV4;
567 p += 7;
569 else
571 pwm->prot = PWMD_IP_ANY;
572 p += 6;
575 rc = _parse_ssh_url (p, &host, &port, &username);
576 if (!rc)
578 va_list ap;
579 char *identity = NULL;
580 char *knownhosts = NULL;
582 va_start (ap, url);
583 identity = va_arg (ap, char *);
585 if (!identity && !pwm->use_agent)
586 rc = GPG_ERR_INV_ARG;
587 else
588 knownhosts = va_arg (ap, char *);
590 va_end (ap);
592 if (!rc)
593 rc = _do_ssh_connect (pwm, host, port, identity, username,
594 knownhosts);
595 if (!rc)
597 rc = _connect_finalize (pwm);
598 if (rc)
599 free_tcp (pwm);
603 pwmd_free (host);
604 pwmd_free (username);
605 pwm->local_pinentry = 1;
606 pwmd_free (pwm->ssh_passphrase);
607 pwm->ssh_passphrase = NULL;
608 #endif
610 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
611 !strncmp (p, "tls4://", 7))
613 #ifndef WITH_GNUTLS
614 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
615 #else
616 char *host = NULL;
617 int port;
619 if (!strncmp (p, "tls6://", 7))
621 pwm->prot = PWMD_IPV6;
622 p += 7;
624 else if (!strncmp (p, "tls4://", 7))
626 pwm->prot = PWMD_IPV4;
627 p += 7;
629 else
631 pwm->prot = PWMD_IP_ANY;
632 p += 6;
635 rc = tls_parse_url (p, &host, &port);
636 if (!rc)
638 va_list ap;
639 char *clientcert = NULL;
640 char *clientkey = NULL;
641 char *cacert = NULL;
642 char *prio = NULL;
643 char *server_fp = NULL;
645 va_start (ap, url);
646 clientcert = va_arg (ap, char *);
648 if (!clientcert)
649 rc = GPG_ERR_INV_ARG;
650 else
652 clientkey = va_arg (ap, char *);
653 if (!clientkey)
654 rc = GPG_ERR_INV_ARG;
655 else
657 cacert = va_arg (ap, char *);
658 if (!cacert)
659 rc = GPG_ERR_INV_ARG;
660 else
662 prio = va_arg (ap, char *);
663 server_fp = va_arg (ap, char *);
668 va_end (ap);
670 if (!rc)
671 rc = tls_connect (pwm, host, port, clientcert, clientkey, cacert,
672 prio, server_fp, pwm->tls_verify);
673 if (!rc)
675 rc = _connect_finalize (pwm);
676 if (rc)
677 free_tcp (pwm);
681 pwmd_free (host);
682 pwm->local_pinentry = 1;
683 #endif
686 if (!rc)
687 pwm->connected = 1;
689 return FINISH (rc);
692 static void
693 disconnect (pwm_t * pwm)
695 if (!pwm)
696 return;
698 if (pwm->ctx)
699 assuan_release (pwm->ctx);
701 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
702 free_tcp (pwm);
703 #endif
704 pwm->ctx = NULL;
705 pwm->fd = -1;
706 pwm->connected = 0;
709 void
710 pwmd_close (pwm_t * pwm)
712 if (!pwm)
713 return;
715 disconnect (pwm);
716 pwmd_free (pwm->pinentry_error);
717 pwmd_free (pwm->pinentry_desc);
718 pwmd_free (pwm->pinentry_prompt);
719 pwmd_free (pwm->pinentry_tty);
720 pwmd_free (pwm->pinentry_display);
721 pwmd_free (pwm->pinentry_term);
722 pwmd_free (pwm->pinentry_lcctype);
723 pwmd_free (pwm->pinentry_lcmessages);
724 pwmd_free (pwm->filename);
725 pwmd_free (pwm->name);
726 pwmd_free (pwm->passphrase_info);
727 pwmd_free (pwm->passphrase_hint);
728 pwmd_free (pwm->ssh_passphrase);
730 #ifdef WITH_PINENTRY
731 if (pwm->pctx)
732 _pinentry_disconnect (pwm);
733 #endif
735 pwmd_free (pwm);
738 static gpg_error_t
739 inquire_realloc_cb (void *data, const void *buffer, size_t len)
741 membuf_t *mem = (membuf_t *) data;
742 void *p;
744 if (!buffer)
745 return 0;
747 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
748 return gpg_error (GPG_ERR_ENOMEM);
750 mem->buf = p;
751 memcpy ((char *) mem->buf + mem->len, buffer, len);
752 mem->len += len;
753 return 0;
756 static gpg_error_t
757 get_password (pwm_t * pwm, char **result, size_t * len,
758 pwmd_pinentry_t w, int echo)
760 char buf[ASSUAN_LINELENGTH+1] = { 0 }, *p;
761 struct termios told, tnew;
762 char *key = NULL;
764 if (result)
765 *result = NULL;
767 if (len)
768 *len = 0;
770 if (!isatty (STDIN_FILENO))
772 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
773 return GPG_ERR_ENOTTY;
776 if (!echo)
778 if (tcgetattr (STDIN_FILENO, &told) == -1)
779 return gpg_error_from_syserror ();
781 memcpy (&tnew, &told, sizeof (struct termios));
782 tnew.c_lflag &= ~(ECHO);
783 tnew.c_lflag |= ICANON | ECHONL;
785 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
787 int n = errno;
789 tcsetattr (STDIN_FILENO, TCSANOW, &told);
790 return gpg_error_from_errno (n);
794 if (pwm->passphrase_hint)
795 fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint);
797 switch (w)
799 case PWMD_PINENTRY_OPEN:
800 fprintf (stderr, N_("Passphrase for %s: "), pwm->filename);
801 break;
802 case PWMD_PINENTRY_OPEN_FAILED:
803 fprintf (stderr, N_("Invalid passphrase. Passphrase for %s: "),
804 pwm->filename);
805 break;
806 case PWMD_PINENTRY_SAVE:
807 fprintf (stderr, N_("New passphrase for %s: "), pwm->filename);
808 break;
809 case PWMD_PINENTRY_SAVE_CONFIRM:
810 fprintf (stderr, N_("Repeat passphrase: "));
811 break;
812 case PWMD_PINENTRY_CONFIRM:
813 if (pwm->pinentry_desc)
814 fprintf (stderr, "%s", pwm->pinentry_desc);
816 if (pwm->pinentry_prompt)
817 fprintf (stderr, "%s", pwm->pinentry_prompt);
818 else
819 fprintf(stderr, N_("Confirm [y/N]:"));
820 default:
821 break;
824 p = fgets (buf, sizeof (buf), stdin);
826 if (!echo)
827 tcsetattr (STDIN_FILENO, TCSANOW, &told);
829 if (!p || feof (stdin))
831 clearerr (stdin);
832 return GPG_ERR_CANCELED;
835 /* Strip the newline character. */
836 p[strlen (p) - 1] = 0;
838 if (buf[0])
840 if (w == PWMD_PINENTRY_CONFIRM)
842 if (*p != 'y' && *p != 'Y')
843 return GPG_ERR_CANCELED;
844 return 0;
847 key = pwmd_strdup_printf ("%s", p);
848 wipememory (buf, 0, sizeof (buf));
849 if (!key)
850 return GPG_ERR_ENOMEM;
852 if (result)
853 *result = key;
855 if (len)
856 *len = strlen (key);
858 else
860 if (w == PWMD_PINENTRY_CONFIRM)
861 return GPG_ERR_CANCELED;
863 /* To satisfy inquire_cb(). */
864 if (result)
865 *result = pwmd_strdup ("");
867 if (len)
868 *len = 1;
871 return 0;
874 gpg_error_t
875 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
877 gpg_error_t rc;
878 int new_password = 0;
879 char *password = NULL, *newpass = NULL;
880 int error = 0;
882 command_start (pwm);
884 if (data)
885 *data = NULL;
887 if (size)
888 *size = 0;
890 if (!strcmp (keyword, "NEW_PASSPHRASE"))
891 new_password = 1;
893 if (!new_password && pwm->pinentry_try)
894 error = 1;
896 again:
897 if (pwm->disable_pinentry)
899 rc = get_password (pwm, &password, size,
900 new_password ? PWMD_PINENTRY_SAVE :
901 error ? PWMD_PINENTRY_OPEN_FAILED :
902 PWMD_PINENTRY_OPEN, 0);
903 if (!rc && new_password)
904 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
907 else
909 pwmd_pinentry_t which;
911 if (error)
912 which = new_password
913 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
914 else
915 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
917 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
918 if (!rc && new_password)
919 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
920 PWMD_PINENTRY_SAVE_CONFIRM);
923 if (!rc && new_password)
925 if ((!password && newpass) || (!newpass && password)
926 || (newpass && password && strcmp (newpass, password)))
928 if (pwm->disable_pinentry)
929 fprintf (stderr, N_("Passphrases do not match.\n"));
931 pwmd_free (password);
932 pwmd_free (newpass);
933 password = newpass = NULL;
934 error = 1;
935 goto again;
939 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
940 pwmd_free (newpass);
941 if (!rc && data)
942 *data = password;
943 else
944 pwmd_free (password);
946 return rc;
949 static gpg_error_t
950 inquire_cb (void *data, const char *keyword)
952 pwm_t *pwm = (pwm_t *) data;
953 gpg_error_t rc = 0;
954 int free_result = 0;
955 char *result = NULL;
956 int is_password = 0;
957 int new_password = 0;
959 if (!strcmp (keyword, "PASSPHRASE") || !strcmp (keyword, "SIGN_PASSPHRASE"))
960 is_password = 1;
961 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
962 new_password = 1;
964 /* Shouldn't get this far without a callback. */
965 if (!pwm->override_inquire && !pwm->inquire_func
966 && !is_password && !new_password)
967 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
969 for (;;)
971 size_t len = 0;
972 gpg_error_t arc;
974 result = NULL;
976 if (!pwm->override_inquire && (is_password || new_password))
978 free_result = 1;
979 rc = pwmd_password (data, keyword, &result, &len);
980 if (!rc)
981 rc = GPG_ERR_EOF;
983 else
984 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
985 &len);
987 /* gpg will truncate a passphrase at the first nil byte which may be bad
988 * for generated key files. */
989 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
990 && (is_password || new_password))
992 if (len && result && *result)
994 for (size_t n = 0; n < len; n++)
996 if (result[n] == 0 && n+1 != len)
997 rc = GPG_ERR_INV_PASSPHRASE;
1002 cancel:
1003 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
1005 #ifndef LIBASSUAN_2_1_0
1006 gpg_error_t trc = rc;
1008 /* Cancel this inquire. */
1009 rc = assuan_send_data (pwm->ctx, NULL, 1);
1010 if (!rc)
1012 char *line;
1013 size_t len;
1015 /* There is a bug (or feature?) in assuan_send_data() that
1016 * when cancelling an inquire the next read from the server is
1017 * not done until the next command making the next command
1018 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
1020 rc = assuan_read_line (pwm->ctx, &line, &len);
1022 /* Restore the original error. This differs from the error
1023 * returned from the pwmd command (GPG_ERR_CANCELED). This
1024 * error is returned to the calling function.
1026 if (!rc)
1027 rc = trc;
1029 #endif
1030 break;
1033 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1035 if (len <= 0 && !result)
1037 rc = 0;
1038 break;
1040 else if ((len <= 0 && result) || (len && !result))
1042 rc = gpg_error (GPG_ERR_INV_ARG);
1043 break;
1046 if (pwm->inquire_maxlen
1047 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1049 rc = gpg_error (GPG_ERR_TOO_LARGE);
1050 if (!free_result)
1051 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1052 &result, &len);
1053 goto cancel;
1056 arc = assuan_send_data (pwm->ctx, result, len);
1057 if (gpg_err_code (rc) == GPG_ERR_EOF)
1059 rc = arc;
1060 break;
1063 rc = arc;
1065 else if (rc)
1066 break;
1068 if (!rc)
1070 pwm->inquire_sent += len;
1072 if (pwm->status_func)
1074 char buf[ASSUAN_LINELENGTH];
1076 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1077 pwm->inquire_total);
1078 rc = pwm->status_func (pwm->status_data, buf);
1079 if (rc)
1080 continue;
1085 if (free_result)
1086 pwmd_free (result);
1088 pwm->inquire_maxlen = pwm->inquire_sent = 0;
1089 return rc;
1092 static gpg_error_t
1093 parse_assuan_line (pwm_t * pwm)
1095 gpg_error_t rc;
1096 char *line;
1097 size_t len;
1099 rc = assuan_read_line (pwm->ctx, &line, &len);
1100 if (!rc)
1102 if (line[0] == 'O' && line[1] == 'K' &&
1103 (line[2] == 0 || line[2] == ' '))
1106 else if (line[0] == '#')
1109 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1111 rc = status_cb (pwm, line[1] == 0 ? line + 1 : line + 2);
1113 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1114 (line[3] == 0 || line[3] == ' '))
1116 line += 4;
1117 rc = strtol (line, NULL, 10);
1121 return rc;
1124 static void
1125 reset_handle (pwm_t *pwm)
1127 pwm->fd = -1;
1128 pwm->cancel = 0;
1129 pwm->pinentry_disabled = 0;
1130 #ifdef WITH_PINENTRY
1131 if (pwm->pctx)
1132 _pinentry_disconnect (pwm);
1133 #endif
1134 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1135 #ifdef WITH_GNUTLS
1136 pwm->tls_error = 0;
1137 #endif
1139 if (pwm->tcp)
1140 pwm->tcp->rc = 0;
1141 #endif
1144 gpg_error_t
1145 pwmd_disconnect (pwm_t * pwm)
1147 if (!pwm)
1148 return FINISH (GPG_ERR_INV_ARG);
1150 command_start (pwm);
1152 if (pwm->fd == -1)
1153 return FINISH (GPG_ERR_INV_STATE);
1155 disconnect (pwm);
1156 reset_handle (pwm);
1157 return 0;
1160 /* Note that this should only be called when not in a command. */
1161 gpg_error_t
1162 pwmd_process (pwm_t * pwm)
1164 gpg_error_t rc = 0;
1165 fd_set fds;
1166 struct timeval tv = { 0, 0 };
1167 int n;
1169 if (!pwm || pwm->fd == -1)
1170 return FINISH (GPG_ERR_INV_ARG);
1171 else if (!pwm->ctx)
1172 return FINISH (GPG_ERR_INV_STATE);
1174 FD_ZERO (&fds);
1175 FD_SET (pwm->fd, &fds);
1176 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1178 if (n == -1)
1179 return FINISH (gpg_error_from_syserror ());
1181 if (n > 0)
1183 if (FD_ISSET (pwm->fd, &fds))
1184 rc = parse_assuan_line (pwm);
1187 while (!rc && assuan_pending_line (pwm->ctx))
1188 rc = parse_assuan_line (pwm);
1190 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1191 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1193 close (pwm->fd);
1194 pwm->fd = -1;
1196 #endif
1198 return FINISH (rc);
1201 static gpg_error_t
1202 status_cb (void *data, const char *line)
1204 pwm_t *pwm = data;
1206 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1207 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1208 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1210 pwmd_free (pwm->passphrase_hint);
1211 pwm->passphrase_hint = pwmd_strdup (line+16);
1213 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1215 pwmd_free (pwm->passphrase_info);
1216 pwm->passphrase_info = pwmd_strdup (line+16);
1218 #ifdef WITH_GNUTLS
1219 else if (!strcmp (line, "REHANDSHAKE"))
1221 char buf[32];
1222 ssize_t ret;
1224 ret = tls_read_hook (pwm, pwm->fd, buf, sizeof (buf));
1225 if (ret < 0)
1227 pwm->tls_error = ret;
1228 return GPG_ERR_GENERAL;
1231 #endif
1233 if (pwm->status_func)
1234 return pwm->status_func (pwm->status_data, line);
1236 return 0;
1239 gpg_error_t
1240 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1241 char **result, size_t * len, const char *cmd)
1243 membuf_t data;
1244 gpg_error_t rc;
1246 if (!cmd || !*cmd)
1247 return FINISH (GPG_ERR_INV_ARG);
1249 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1250 return FINISH (GPG_ERR_LINE_TOO_LONG);
1252 data.len = 0;
1253 data.buf = NULL;
1254 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1255 #ifdef WITH_QUALITY
1256 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1257 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1258 #else
1259 inquire_cb, pwm,
1260 #endif
1261 status_cb, pwm);
1263 if (rc)
1265 if (data.buf)
1267 pwmd_free (data.buf);
1268 data.buf = NULL;
1271 else
1273 if (data.buf)
1275 inquire_realloc_cb (&data, "", 1);
1277 if (result)
1278 *result = (char *) data.buf;
1279 else
1280 pwmd_free (data.buf);
1282 if (len)
1283 *len = data.len;
1287 pwm->inquire_maxlen = 0;
1288 return rc;
1291 gpg_error_t
1292 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1293 pwmd_inquire_cb_t func, void *user, const char *cmd,
1294 va_list ap)
1296 char *buf;
1297 size_t len;
1298 va_list ap2;
1300 command_start (pwm);
1302 if (result)
1303 *result = NULL;
1305 if (rlen)
1306 *rlen = 0;
1308 if (!pwm || !cmd)
1309 return FINISH (GPG_ERR_INV_ARG);
1310 if (!pwm->ctx)
1311 return FINISH (GPG_ERR_INV_STATE);
1314 * C99 allows the dst pointer to be null which will calculate the length
1315 * of the would-be result and return it.
1317 va_copy (ap2, ap);
1318 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1319 buf = (char *) pwmd_malloc (len);
1320 if (!buf)
1322 va_end (ap2);
1323 return FINISH (GPG_ERR_ENOMEM);
1326 len = vsnprintf (buf, len, cmd, ap2);
1327 va_end (ap2);
1329 if (buf[strlen (buf) - 1] == '\n')
1330 buf[strlen (buf) - 1] = 0;
1331 if (buf[strlen (buf) - 1] == '\r')
1332 buf[strlen (buf) - 1] = 0;
1334 pwm->inquire_func = func;
1335 pwm->inquire_data = user;
1336 pwm->inquire_sent = 0;
1337 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1338 pwmd_free (buf);
1339 return rc;
1342 gpg_error_t
1343 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1344 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1346 va_list ap;
1348 if (result)
1349 *result = NULL;
1351 if (len)
1352 *len = 0;
1354 if (!pwm || !cmd)
1355 return FINISH (GPG_ERR_INV_ARG);
1356 if (!pwm->ctx)
1357 return FINISH (GPG_ERR_INV_STATE);
1359 va_start (ap, cmd);
1360 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1361 va_end (ap);
1362 return rc;
1365 static gpg_error_t
1366 send_pinentry_timeout (pwm_t *pwm)
1368 gpg_error_t rc = 0;
1370 if ((pwm->pinentry_timeout >= 0
1371 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1372 || (pwm->pinentry_timeout == -1
1373 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1375 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1376 "OPTION pinentry-timeout=%i",
1377 pwm->pinentry_timeout);
1378 if (!rc)
1379 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1382 return rc;
1385 static gpg_error_t
1386 send_pinentry_options (pwm_t * pwm)
1388 gpg_error_t rc;
1390 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1391 "OPTION disable-pinentry=0");
1392 if (!rc && pwm->pinentry_tty)
1393 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1394 pwm->pinentry_tty);
1396 if (!rc && pwm->pinentry_term)
1397 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1398 pwm->pinentry_term);
1400 if (!rc && pwm->pinentry_display)
1401 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1402 pwm->pinentry_display);
1404 if (!rc && pwm->pinentry_desc)
1405 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1406 pwm->pinentry_desc);
1408 if (!rc && pwm->pinentry_lcctype)
1409 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1410 pwm->pinentry_lcctype);
1412 if (!rc && pwm->pinentry_lcmessages)
1413 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1414 pwm->pinentry_lcmessages);
1416 if (!rc)
1417 rc = send_pinentry_timeout (pwm);
1419 return rc;
1422 gpg_error_t
1423 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1425 if (!pwm || !result)
1426 return FINISH (GPG_ERR_INV_ARG);
1428 *result = PWMD_SOCKET_LOCAL;
1430 if (pwm->fd == -1)
1431 return FINISH (GPG_ERR_INV_STATE);
1433 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1434 #ifdef WITH_SSH
1435 if (pwm->tcp && pwm->tcp->ssh)
1436 *result = PWMD_SOCKET_SSH;
1437 #endif
1438 #ifdef WITH_GNUTLS
1439 if (pwm->tcp && pwm->tcp->tls)
1440 *result = PWMD_SOCKET_TLS;
1441 #endif
1442 #endif
1443 return 0;
1446 static gpg_error_t
1447 disable_pinentry (pwm_t *pwm, int *disable)
1449 gpg_error_t rc;
1450 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1451 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1452 #else
1453 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1454 #endif
1456 if (disable)
1457 *disable = no_pinentry;
1459 if (pwm->pinentry_disabled && no_pinentry)
1460 return 0;
1461 else if (!pwm->pinentry_disabled && !no_pinentry)
1462 return 0;
1464 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1465 no_pinentry);
1466 if (!rc)
1467 pwm->pinentry_disabled = no_pinentry;
1469 return rc;
1472 gpg_error_t
1473 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1474 void *data)
1476 gpg_error_t rc = 0;
1477 int no_pinentry = 0;
1479 if (!pwm || !filename || !*filename)
1480 return FINISH (GPG_ERR_INV_ARG);
1482 if (!pwm->ctx)
1483 return FINISH (GPG_ERR_INV_STATE);
1485 command_start (pwm);
1486 rc = disable_pinentry (pwm, &no_pinentry);
1487 if (!rc && !no_pinentry)
1488 rc = send_pinentry_options (pwm);
1490 if (!rc)
1492 pwm->pinentry_try = 0;
1493 pwmd_free (pwm->filename);
1494 pwm->filename = pwmd_strdup (filename);
1498 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1499 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1500 filename);
1502 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1503 && pwm->pinentry_disabled
1504 && ++pwm->pinentry_try < pwm->pinentry_tries);
1506 pwm->pinentry_try = 0;
1508 if (rc)
1510 pwmd_free (pwm->filename);
1511 pwm->filename = NULL;
1515 pwmd_free (pwm->passphrase_hint);
1516 pwmd_free (pwm->passphrase_info);
1517 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1518 return FINISH (rc);
1521 static gpg_error_t
1522 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1523 void *data, int save)
1525 gpg_error_t rc = 0;
1526 int no_pinentry = 0;
1528 if (!pwm)
1529 return FINISH (GPG_ERR_INV_ARG);
1530 if (!pwm->ctx)
1531 return FINISH (GPG_ERR_INV_STATE);
1533 command_start (pwm);
1534 rc = disable_pinentry (pwm, &no_pinentry);
1535 if (!rc && !no_pinentry)
1536 rc = send_pinentry_options (pwm);
1538 if (!rc)
1539 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1540 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1542 pwmd_free (pwm->passphrase_hint);
1543 pwmd_free (pwm->passphrase_info);
1544 pwm->passphrase_info = pwm->passphrase_hint = NULL;
1545 return FINISH (rc);
1548 gpg_error_t
1549 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1551 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1554 gpg_error_t
1555 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1557 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1560 static gpg_error_t
1561 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1563 int n, *intp;
1564 size_t *sizetp;
1565 char *arg1, **charpp;
1566 gpg_error_t rc = 0;
1568 if (!pwm)
1569 return GPG_ERR_INV_ARG;
1571 command_start (pwm);
1572 switch (opt)
1574 case PWMD_OPTION_SERVER_VERSION:
1575 if (!get)
1576 return GPG_ERR_NOT_SUPPORTED;
1578 if (!pwm)
1579 rc = GPG_ERR_INV_ARG;
1580 else if (!pwm->ctx)
1581 rc = GPG_ERR_INV_STATE;
1582 else
1584 unsigned *u = va_arg (ap, unsigned *);
1585 *u = pwm->version;
1588 break;
1589 case PWMD_OPTION_SIGPIPE:
1590 if (get)
1592 intp = va_arg (ap, int *);
1593 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1594 break;
1597 n = va_arg (ap, int);
1598 if (n < 0 || n > 1)
1599 rc = GPG_ERR_INV_VALUE;
1601 if (n)
1602 pwm->opts |= OPT_SIGPIPE;
1603 else
1604 pwm->opts &= ~OPT_SIGPIPE;
1606 break;
1607 case PWMD_OPTION_LOCK_ON_OPEN:
1608 if (get)
1610 intp = va_arg (ap, int *);
1611 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1612 break;
1615 n = va_arg (ap, int);
1617 if (n < 0 || n > 1)
1618 rc = GPG_ERR_INV_VALUE;
1620 if (n)
1621 pwm->opts |= OPT_LOCK_ON_OPEN;
1622 else
1623 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1625 break;
1626 case PWMD_OPTION_INQUIRE_TOTAL:
1627 if (get)
1629 sizetp = va_arg (ap, size_t *);
1630 *sizetp = pwm->inquire_total;
1631 break;
1634 pwm->inquire_total = va_arg (ap, size_t);
1635 break;
1636 case PWMD_OPTION_STATUS_CB:
1637 if (get)
1639 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1641 *cb = pwm->status_func;
1642 break;
1645 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1646 break;
1647 case PWMD_OPTION_STATUS_DATA:
1648 if (get)
1650 void **data = va_arg (ap, void **);
1652 *data = pwm->status_data;
1653 break;
1656 pwm->status_data = va_arg (ap, void *);
1657 break;
1658 case PWMD_OPTION_NO_PINENTRY:
1659 if (get)
1661 intp = va_arg (ap, int *);
1662 *intp = pwm->disable_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->disable_pinentry = n;
1672 break;
1673 case PWMD_OPTION_LOCAL_PINENTRY:
1674 if (get)
1676 intp = va_arg (ap, int *);
1677 *intp = pwm->local_pinentry;
1678 break;
1681 n = va_arg (ap, int);
1683 if (n < 0 || n > 1)
1684 rc = GPG_ERR_INV_VALUE;
1685 else
1686 pwm->local_pinentry = n;
1688 break;
1689 case PWMD_OPTION_PINENTRY_TIMEOUT:
1690 if (get)
1692 intp = va_arg (ap, int *);
1693 *intp = pwm->pinentry_timeout;
1694 break;
1697 n = va_arg (ap, int);
1699 if (n < 0)
1700 rc = GPG_ERR_INV_VALUE;
1701 else
1702 pwm->pinentry_timeout = n;
1703 break;
1704 case PWMD_OPTION_PINENTRY_TRIES:
1705 if (get)
1707 intp = va_arg (ap, int *);
1708 *intp = pwm->pinentry_tries;
1709 break;
1712 n = va_arg (ap, int);
1713 pwm->pinentry_tries = n;
1714 break;
1715 case PWMD_OPTION_PINENTRY_PATH:
1716 if (get)
1718 charpp = va_arg (ap, char **);
1719 *charpp = pwm->pinentry_path;
1720 break;
1723 arg1 = va_arg (ap, char *);
1724 pwmd_free (pwm->pinentry_path);
1725 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1726 break;
1727 case PWMD_OPTION_PINENTRY_TTY:
1728 if (get)
1730 charpp = va_arg (ap, char **);
1731 *charpp = pwm->pinentry_tty;
1732 break;
1735 arg1 = va_arg (ap, char *);
1736 pwmd_free (pwm->pinentry_tty);
1737 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1738 break;
1739 case PWMD_OPTION_PINENTRY_DISPLAY:
1740 if (get)
1742 charpp = va_arg (ap, char **);
1743 *charpp = pwm->pinentry_display;
1744 break;
1747 arg1 = va_arg (ap, char *);
1748 pwmd_free (pwm->pinentry_display);
1749 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1750 break;
1751 case PWMD_OPTION_PINENTRY_TERM:
1752 if (get)
1754 charpp = va_arg (ap, char **);
1755 *charpp = pwm->pinentry_term;
1756 break;
1759 arg1 = va_arg (ap, char *);
1760 pwmd_free (pwm->pinentry_term);
1761 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1762 break;
1763 case PWMD_OPTION_PINENTRY_ERROR:
1764 if (get)
1766 charpp = va_arg (ap, char **);
1767 *charpp = pwm->pinentry_error;
1768 break;
1771 arg1 = va_arg (ap, char *);
1772 pwmd_free (pwm->pinentry_error);
1773 if (pwm->disable_pinentry)
1774 pwm->pinentry_error = arg1 ? pwmd_strdup (arg1) : NULL;
1775 else
1776 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1777 break;
1778 case PWMD_OPTION_PINENTRY_PROMPT:
1779 if (get)
1781 charpp = va_arg (ap, char **);
1782 *charpp = pwm->pinentry_prompt;
1783 break;
1786 arg1 = va_arg (ap, char *);
1787 pwmd_free (pwm->pinentry_prompt);
1788 if (pwm->disable_pinentry)
1789 pwm->pinentry_prompt = arg1 ? pwmd_strdup (arg1) : NULL;
1790 else
1791 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1792 break;
1793 case PWMD_OPTION_PINENTRY_DESC:
1794 if (get)
1796 charpp = va_arg (ap, char **);
1797 *charpp = pwm->pinentry_desc;
1798 break;
1801 arg1 = va_arg (ap, char *);
1802 pwmd_free (pwm->pinentry_desc);
1803 if (pwm->disable_pinentry)
1804 pwm->pinentry_desc = arg1 ? pwmd_strdup (arg1) : NULL;
1805 else
1806 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1807 break;
1808 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1809 if (get)
1811 charpp = va_arg (ap, char **);
1812 *charpp = pwm->pinentry_lcctype;
1813 break;
1816 arg1 = va_arg (ap, char *);
1817 pwmd_free (pwm->pinentry_lcctype);
1818 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1819 break;
1820 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1821 if (get)
1823 charpp = va_arg (ap, char **);
1824 *charpp = pwm->pinentry_lcmessages;
1825 break;
1828 arg1 = va_arg (ap, char *);
1829 pwmd_free (pwm->pinentry_lcmessages);
1830 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1831 break;
1832 case PWMD_OPTION_KNOWNHOST_CB:
1833 if (get)
1835 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1837 *cb = pwm->kh_cb;
1838 break;
1841 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1842 break;
1843 case PWMD_OPTION_KNOWNHOST_DATA:
1844 if (get)
1846 void **data = va_arg (ap, void **);
1848 *data = pwm->kh_data;
1849 break;
1852 pwm->kh_data = va_arg (ap, void *);
1853 break;
1854 case PWMD_OPTION_SSH_AGENT:
1855 if (get)
1857 intp = va_arg (ap, int *);
1858 *intp = pwm->use_agent;
1859 break;
1862 pwm->use_agent = va_arg (ap, int);
1864 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1866 pwm->use_agent = 0;
1867 rc = GPG_ERR_INV_VALUE;
1869 break;
1870 case PWMD_OPTION_SSH_PASSPHRASE:
1871 if (get)
1872 return GPG_ERR_NOT_SUPPORTED;
1873 pwmd_free (pwm->ssh_passphrase);
1874 pwm->ssh_passphrase = NULL;
1875 arg1 = va_arg (ap, char *);
1876 if (arg1)
1878 pwm->ssh_passphrase = pwmd_strdup (arg1);
1879 if (!pwm->ssh_passphrase)
1880 return GPG_ERR_ENOMEM;
1882 break;
1883 case PWMD_OPTION_SSH_NEEDS_PASSPHRASE:
1884 if (get)
1886 intp = va_arg (ap, int *);
1887 *intp = pwm->needs_passphrase;
1888 break;
1891 pwm->needs_passphrase = va_arg (ap, int);
1893 if (pwm->needs_passphrase < 0 || pwm->needs_passphrase > 1)
1895 pwm->needs_passphrase = 0;
1896 rc = GPG_ERR_INV_VALUE;
1898 break;
1899 case PWMD_OPTION_TLS_VERIFY:
1900 if (get)
1902 intp = va_arg (ap, int *);
1903 *intp = pwm->tls_verify;
1904 break;
1907 pwm->tls_verify = va_arg (ap, int);
1909 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1911 pwm->tls_verify = 0;
1912 rc = GPG_ERR_INV_VALUE;
1914 break;
1915 case PWMD_OPTION_SOCKET_TIMEOUT:
1916 if (get)
1918 intp = va_arg (ap, int *);
1919 *intp = pwm->socket_timeout;
1920 break;
1923 pwm->socket_timeout = va_arg (ap, int);
1924 if (pwm->socket_timeout < 0)
1926 pwm->socket_timeout = 0;
1927 rc = GPG_ERR_INV_VALUE;
1930 #ifdef WITH_SSH
1931 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1933 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1934 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1935 pwm->socket_timeout * 1000);
1937 #endif
1938 #ifdef WITH_GNUTLS
1939 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1940 pwm->tcp->tls->timeout = pwm->socket_timeout;
1941 #endif
1942 break;
1943 case PWMD_OPTION_OVERRIDE_INQUIRE:
1944 if (get)
1946 intp = va_arg (ap, int *);
1947 *intp = pwm->override_inquire;
1948 break;
1951 pwm->override_inquire = va_arg (ap, int);
1953 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1955 pwm->override_inquire = 0;
1956 rc = GPG_ERR_INV_VALUE;
1958 break;
1959 default:
1960 rc = GPG_ERR_UNKNOWN_OPTION;
1961 break;
1964 return FINISH (rc);
1967 gpg_error_t
1968 pwmd_setopt (pwm_t * pwm, int opt, ...)
1970 va_list ap;
1971 gpg_error_t rc = 0;
1973 va_start (ap, opt);
1974 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1975 va_end (ap);
1976 return FINISH (rc);
1979 gpg_error_t
1980 pwmd_getopt (pwm_t *pwm, int opt, ...)
1982 va_list ap;
1983 gpg_error_t rc = 0;
1985 va_start (ap, opt);
1986 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1987 va_end (ap);
1988 return FINISH (rc);
1991 gpg_error_t
1992 pwmd_new (const char *name, pwm_t ** pwm)
1994 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1995 gpg_error_t rc;
1997 if (!h)
1998 return FINISH (GPG_ERR_ENOMEM);
2000 if (name)
2002 h->name = pwmd_strdup (name);
2003 if (!h->name)
2005 pwmd_free (h);
2006 return FINISH (GPG_ERR_ENOMEM);
2010 reset_handle (h);
2011 h->pinentry_timeout = -1;
2012 h->current_pinentry_timeout = -1;
2013 h->pinentry_tries = 3;
2014 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2015 h->prot = PWMD_IP_ANY;
2016 #endif
2018 if (isatty (STDOUT_FILENO))
2020 char buf[256];
2021 int err = ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
2023 if (!err)
2025 h->pinentry_tty = pwmd_strdup (buf);
2026 if (!h->pinentry_tty)
2028 rc = GPG_ERR_ENOMEM;
2029 goto fail;
2034 if (getenv ("TERM") && h->pinentry_tty)
2036 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
2037 if (!h->pinentry_term)
2039 rc = GPG_ERR_ENOMEM;
2040 goto fail;
2044 if (getenv ("DISPLAY"))
2046 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
2047 if (!h->pinentry_display)
2049 rc = GPG_ERR_ENOMEM;
2050 goto fail;
2054 update_pinentry_settings (h);
2055 *pwm = h;
2056 return 0;
2058 fail:
2059 pwmd_close (h);
2060 return FINISH (rc);
2063 void
2064 pwmd_free (void *ptr)
2066 _xfree (ptr);
2069 void *
2070 pwmd_malloc (size_t size)
2072 return _xmalloc (size);
2075 void *
2076 pwmd_calloc (size_t nmemb, size_t size)
2078 return _xcalloc (nmemb, size);
2081 void *
2082 pwmd_realloc (void *ptr, size_t size)
2084 return _xrealloc (ptr, size);
2087 char *
2088 pwmd_strdup (const char *str)
2090 char *t;
2091 size_t len;
2092 register size_t c;
2094 len = strlen (str);
2095 t = _xmalloc ((len + 1) * sizeof (char));
2096 if (!t)
2097 return NULL;
2099 for (c = 0; c < len; c++)
2100 t[c] = str[c];
2102 t[c] = 0;
2103 return t;
2106 char *
2107 pwmd_strdup_printf (const char *fmt, ...)
2109 va_list ap, ap2;
2110 int len;
2111 char *buf;
2113 if (!fmt)
2114 return NULL;
2116 va_start (ap, fmt);
2117 va_copy (ap2, ap);
2118 len = vsnprintf (NULL, 0, fmt, ap);
2119 va_end (ap);
2120 buf = pwmd_malloc (++len);
2121 if (buf)
2122 vsnprintf (buf, len, fmt, ap2);
2124 va_end (ap2);
2125 return buf;
2128 gpg_error_t
2129 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2130 size_t * len, pwmd_pinentry_t which)
2132 #ifndef WITH_PINENTRY
2133 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2134 #else
2135 gpg_error_t rc;
2137 command_start (pwm);
2138 if (which == PWMD_PINENTRY_CONFIRM && pwm->disable_pinentry)
2140 rc = get_password (pwm, NULL, NULL, which, 1);
2141 return FINISH (rc);
2144 rc = _pwmd_getpin (pwm, filename, result, len, which);
2145 return FINISH (rc);
2146 #endif
2149 const char *
2150 pwmd_version ()
2152 return LIBPWMD_VERSION_STR;
2155 unsigned int
2156 pwmd_features ()
2158 unsigned int n = 0;
2160 #ifdef WITH_PINENTRY
2161 n |= PWMD_FEATURE_PINENTRY;
2162 #endif
2163 #ifdef WITH_SSH
2164 n |= PWMD_FEATURE_SSH;
2165 #endif
2166 #ifdef WITH_QUALITY
2167 n |= PWMD_FEATURE_QUALITY;
2168 #endif
2169 #ifdef WITH_GNUTLS
2170 n |= PWMD_FEATURE_GNUTLS;
2171 #endif
2172 return n;
2175 gpg_error_t
2176 pwmd_fd (pwm_t * pwm, int *fd)
2178 if (!pwm || !fd)
2179 return FINISH (GPG_ERR_INV_ARG);
2181 if (pwm->fd == -1)
2182 return FINISH (GPG_ERR_INV_STATE);
2184 *fd = pwm->fd;
2185 return 0;
2188 void
2189 pwmd_set_pointer (pwm_t *pwm, void *data)
2191 pwm->user_data = data;
2194 void *
2195 pwmd_get_pointer (pwm_t *pwm)
2197 return pwm->user_data;
2201 pwmd_gnutls_error (pwm_t *pwm, const char **str)
2203 #ifndef WITH_GNUTLS
2204 return 0;
2205 #else
2206 if (str && pwm && pwm->tls_error)
2207 *str = gnutls_strerror (pwm->tls_error);
2209 return pwm ? pwm->tls_error : 0;
2210 #endif
2213 gpg_error_t
2214 pwmd_cancel (pwm_t *pwm)
2216 if (!pwm)
2217 return FINISH (GPG_ERR_INV_ARG);
2219 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
2220 if (pwm->fd == -1 && !pwm->tcp)
2221 #else
2222 if (pwm->fd == -1)
2223 #endif
2224 return FINISH (GPG_ERR_INV_STATE);
2226 /* Can only cancel the connection for the time being. */
2227 if (pwm->connected)
2228 return FINISH (GPG_ERR_INV_STATE);
2230 pwm->cancel = 1;
2231 return 0;
2234 gpg_error_t
2235 pwmd_test_quality (const char *str, double *result)
2237 #ifndef WITH_QUALITY
2238 return GPG_ERR_NOT_IMPLEMENTED;
2239 #else
2240 if (!result)
2241 return GPG_ERR_INV_ARG;
2243 *result = ZxcvbnMatch (str, NULL, NULL);
2244 return 0;
2245 #endif