Add non-blocking DNS lookup.
[libpwmd.git] / src / libpwmd.c
blob49fff12caa456ffaca8b641868956139a813c74a
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of libpwmd.
7 Libpwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Libpwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <sys/wait.h>
38 #include <fcntl.h>
39 #include <pwd.h>
40 #include <time.h>
41 #include <limits.h>
42 #include <sys/select.h>
43 #include <termios.h>
44 #include <libpwmd.h>
46 #ifdef HAVE_STRINGS_H
47 #include <strings.h>
48 #endif
50 #ifndef LINE_MAX
51 #define LINE_MAX 2048
52 #endif
54 #include "mem.h"
55 #include "misc.h"
56 #include "types.h"
58 #ifdef WITH_PINENTRY
59 #include "pinentry.h"
60 #endif
62 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <netdb.h>
66 #include <netinet/in.h>
67 #endif
69 #define FINISH(rc) (gpg_err_source(rc) == GPG_ERR_SOURCE_UNKNOWN) \
70 ? gpg_error(rc) : rc
72 typedef struct
74 size_t len;
75 void *buf;
76 } membuf_t;
78 ssize_t
79 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
81 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
82 pwm_t *pwm = assuan_get_pointer (ctx);
84 #ifdef WITH_SSH
85 if (pwm && pwm->tcp && pwm->tcp->ssh)
86 return read_hook_ssh (pwm->tcp->ssh, fd, data, len);
87 #endif
88 #ifdef WITH_GNUTLS
89 if (pwm && pwm->tcp && pwm->tcp->tls)
90 return read_hook_tls (pwm, fd, data, len);
91 #endif
92 #endif
94 return read ((int) fd, data, len);
97 ssize_t
98 hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data,
99 size_t len)
101 ssize_t wrote;
102 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
103 pwm_t *pwm = assuan_get_pointer (ctx);
105 #ifdef WITH_SSH
106 if (pwm && pwm->tcp && pwm->tcp->ssh)
107 return write_hook_ssh (pwm->tcp->ssh, fd, data, len);
108 #endif
109 #ifdef WITH_GNUTLS
110 if (pwm && pwm->tcp && pwm->tcp->tls)
111 return write_hook_tls (pwm, fd, data, len);
112 #endif
113 #endif
115 /* libassuan cannot handle EAGAIN when doing writes. */
118 wrote = write ((int) fd, data, len);
119 if (wrote == -1 && errno == EAGAIN)
120 usleep (50000);
122 while (wrote == -1 && errno == EAGAIN);
124 return wrote;
127 pid_t
128 hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status,
129 int options)
131 return waitpid (pid, status, options);
134 gpg_error_t
135 pwmd_init ()
137 static int initialized;
139 #ifdef WITH_GNUTLS
140 // May be called more than once.
141 gnutls_global_init ();
142 #endif
144 if (initialized)
145 return 0;
147 #ifndef MEM_DEBUG
148 _xmem_init ();
149 #endif
150 #ifdef ENABLE_NLS
151 bindtextdomain ("libpwmd", LOCALEDIR);
152 #endif
153 #ifdef WITH_SSH
154 libssh2_init (0);
155 #endif
156 gpg_err_init ();
157 initialized = 1;
158 return 0;
161 void
162 pwmd_deinit ()
164 #ifdef WITH_GNUTLS
165 gnutls_global_deinit ();
166 #endif
169 gpg_error_t
170 _connect_finalize (pwm_t * pwm)
172 gpg_error_t rc = 0;
173 char *result = NULL;
174 int active[2];
175 int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active));
177 if (n <= 0)
178 return GPG_ERR_EBADFD;
180 pwm->fd = active[0];
181 #ifdef WITH_PINENTRY
182 pwm->pinentry_pid = -1;
183 #endif
185 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, "GETINFO VERSION");
186 if (!rc)
188 pwm->version = strtoul (result, NULL, 16);
189 pwmd_free (result);
192 if (!rc && pwm->name)
193 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION NAME=%s",
194 pwm->name);
196 return rc;
199 static gpg_error_t
200 connect_uds (pwm_t * pwm, const char *path)
202 char *socketpath = NULL;
203 struct passwd pw;
204 char *pwbuf;
205 gpg_error_t rc;
207 if (!pwm)
208 return GPG_ERR_INV_ARG;
210 pwbuf = _getpwuid (&pw);
211 if (!pwbuf)
212 return gpg_error_from_syserror ();
214 if (!path || !*path)
215 socketpath = pwmd_strdup_printf ("%s/.pwmd/socket", pw.pw_dir);
216 else
217 socketpath = _expand_homedir ((char *) path, &pw);
219 pwmd_free (pwbuf);
220 if (!socketpath)
221 return GPG_ERR_ENOMEM;
223 rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0);
224 pwmd_free (socketpath);
225 return rc ? rc : _connect_finalize (pwm);
228 static gpg_error_t
229 init_handle (pwm_t * pwm)
231 gpg_error_t rc;
232 static struct assuan_malloc_hooks mhooks = {
233 pwmd_malloc, pwmd_realloc, pwmd_free
235 static struct assuan_system_hooks shooks = {
236 ASSUAN_SYSTEM_HOOKS_VERSION,
237 __assuan_usleep,
238 __assuan_pipe,
239 __assuan_close,
240 hook_read,
241 hook_write,
242 //FIXME
243 NULL, //recvmsg
244 NULL, //sendmsg both are used for FD passing
245 __assuan_spawn,
246 hook_waitpid,
247 __assuan_socketpair,
248 __assuan_socket,
249 __assuan_connect
252 rc = assuan_new_ext (&pwm->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks, NULL,
253 NULL);
254 if (rc)
255 return rc;
257 assuan_set_pointer (pwm->ctx, pwm);
258 assuan_ctx_set_system_hooks (pwm->ctx, &shooks);
259 return 0;
262 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
263 void
264 free_tcp (pwm_t *pwm)
266 struct tcp_s *tcp = pwm->tcp;
268 if (!tcp)
269 return;
271 #ifdef WITH_SSH
272 _free_ssh_conn (tcp->ssh);
273 #endif
274 #ifdef WITH_GNUTLS
275 tls_free (pwm);
276 #endif
278 pwmd_free (tcp->host);
279 if (tcp->addrs)
281 freeaddrinfo (tcp->addrs);
282 tcp->addrs = NULL;
285 pthread_cond_destroy (&tcp->dns_cond);
286 pthread_mutex_destroy (&tcp->dns_mutex);
287 pwmd_free (tcp);
288 pwm->tcp = NULL;
290 #endif
292 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
293 static void *
294 resolve_host_thread (void *arg)
296 pwm_t *pwm = arg;
297 struct addrinfo hints = { 0 };
298 char portstr[6];
300 switch (pwm->prot)
302 case PWMD_IP_ANY:
303 hints.ai_family = AF_UNSPEC;
304 break;
305 case PWMD_IPV4:
306 hints.ai_family = AF_INET;
307 break;
308 case PWMD_IPV6:
309 hints.ai_family = AF_INET6;
310 break;
313 hints.ai_socktype = SOCK_STREAM;
314 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
315 int *n = pwmd_malloc (sizeof (int));
316 pthread_cleanup_push (pwmd_free, n);
317 *n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
318 pthread_cleanup_pop (0);
319 pthread_cond_broadcast (&pwm->tcp->dns_cond);
320 pthread_exit (n);
321 return NULL;
324 gpg_error_t
325 tcp_connect_common (pwm_t * pwm)
327 #define TS_TIMEOUT 50000000L
328 int n;
329 gpg_error_t rc = 0;
330 pthread_t tid;
331 time_t now;
333 time (&now);
334 n = pthread_create (&tid, NULL, resolve_host_thread, pwm);
335 if (n)
336 return gpg_error_from_errno (n);
338 pthread_mutex_lock (&pwm->tcp->dns_mutex);
340 for (;;)
342 struct timespec ts;
343 int *result = NULL;
345 clock_gettime (CLOCK_REALTIME, &ts);
346 if (ts.tv_nsec + TS_TIMEOUT >= 1000000000LL) {
347 ts.tv_sec++;
348 ts.tv_nsec = 0;
350 else
351 ts.tv_nsec += TS_TIMEOUT;
353 if (pwm->cancel)
355 #ifdef HAVE_PTHREAD_CANCEL
356 pthread_cancel (tid);
357 pthread_join (tid, NULL);
358 #else
359 pthread_join (tid, (void **)&result);
360 pwmd_free (result);
361 #endif
362 return GPG_ERR_CANCELED;
365 n = pthread_cond_timedwait (&pwm->tcp->dns_cond, &pwm->tcp->dns_mutex,
366 &ts);
367 if (n == ETIMEDOUT)
369 if (pwm->socket_timeout && ts.tv_sec - now >= pwm->socket_timeout)
371 #ifdef HAVE_PTHREAD_CANCEL
372 pthread_cancel (tid);
373 pthread_join (tid, NULL);
374 #else
375 pthread_join (tid, (void **)&result);
376 pwmd_free (result);
377 #endif
378 return GPG_ERR_ETIMEDOUT;
381 continue;
383 else if (n)
385 #ifdef HAVE_PTHREAD_CANCEL
386 pthread_cancel (tid);
387 pthread_join (tid, NULL);
388 #else
389 pthread_join (tid, (void **)&result);
390 pwmd_free (result);
391 #endif
392 return gpg_error_from_errno (n);
395 pthread_join (tid, (void **)&result);
396 n = *result;
397 pwmd_free (result);
398 break;
401 if (n)
402 return GPG_ERR_UNKNOWN_HOST; //FIXME
404 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
405 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
407 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
408 if (pwm->fd == -1)
410 rc = gpg_error_from_syserror ();
411 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
412 break;
413 continue;
416 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
418 rc = gpg_error_from_syserror ();
419 break;
422 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
423 pwm->tcp->addr->ai_family == AF_INET6
424 ? sizeof (struct sockaddr_in6)
425 : sizeof (struct sockaddr)) == -1)
427 int n;
428 struct timeval tv;
429 fd_set wfds;
430 unsigned elapsed = 0;
432 rc = gpg_error_from_syserror ();
433 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
435 close (pwm->fd);
436 pwm->fd = -1;
437 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
438 return rc;
439 continue;
442 again:
443 tv.tv_sec = 1;
444 tv.tv_usec = 0;
445 FD_ZERO (&wfds);
446 FD_SET (pwm->fd, &wfds);
447 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
448 rc = 0;
449 if (!n || pwm->cancel)
451 if (pwm->cancel)
452 rc = gpg_error (GPG_ERR_CANCELED);
453 else if (++elapsed >= pwm->socket_timeout)
454 rc = gpg_error (GPG_ERR_ETIMEDOUT);
455 else
456 goto again;
458 else if (n != -1)
460 socklen_t len = sizeof(int);
462 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
463 if (n)
464 rc = gpg_error_from_errno (n);
466 else if (n == -1)
467 rc = gpg_error_from_syserror ();
469 if (rc)
471 close (pwm->fd);
472 pwm->fd = -1;
473 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
474 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT
475 || pwm->cancel)
476 return rc;
478 else
479 break;
481 else
482 break;
485 if (!rc)
486 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
487 rc = gpg_error_from_syserror ();
489 return rc;
491 #endif
493 static void
494 command_start (pwm_t *pwm)
496 pwm->cancel = 0;
499 gpg_error_t
500 pwmd_connect (pwm_t * pwm, const char *url, ...)
502 const char *p = url;
503 gpg_error_t rc;
505 if (!pwm)
506 return FINISH (GPG_ERR_INV_ARG);
507 else if (!pwm->ctx)
509 rc = init_handle (pwm);
510 if (rc)
511 return rc;
514 command_start (pwm);
516 if (!(pwm->opts & OPT_SIGPIPE))
517 signal (SIGPIPE, SIG_IGN);
519 #ifdef WITH_GNUTLS
520 pwm->tls_error = 0;
521 #endif
522 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
524 if (p && (*p == '/' || *p == '~'))
525 rc = connect_uds (pwm, p);
526 else if (!p || !strncmp (p, "file://", 7))
528 if (p)
529 p += 7;
530 #ifdef DEFAULT_PWMD_SOCKET
531 else
532 p = DEFAULT_PWMD_SOCKET;
533 #endif
534 rc = connect_uds (pwm, p);
536 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
537 !strncmp (p, "ssh4://", 7))
539 #ifndef WITH_SSH
540 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
541 #else
542 char *host = NULL;
543 int port;
544 char *username = NULL;
546 if (!strncmp (p, "ssh6://", 7))
548 pwm->prot = PWMD_IPV6;
549 p += 7;
551 else if (!strncmp (p, "ssh4://", 7))
553 pwm->prot = PWMD_IPV4;
554 p += 7;
556 else
558 pwm->prot = PWMD_IP_ANY;
559 p += 6;
562 rc = _parse_ssh_url (p, &host, &port, &username);
563 if (!rc)
565 va_list ap;
566 char *identity = NULL;
567 char *knownhosts = NULL;
569 va_start (ap, url);
570 identity = va_arg (ap, char *);
572 if (!identity && !pwm->use_agent)
573 rc = GPG_ERR_INV_ARG;
574 else
575 knownhosts = va_arg (ap, char *);
577 va_end (ap);
579 if (!rc)
580 rc = _do_ssh_connect (pwm, host, port, identity, username,
581 knownhosts);
582 if (!rc)
584 rc = _connect_finalize (pwm);
585 if (rc)
586 free_tcp (pwm);
590 pwmd_free (host);
591 pwmd_free (username);
592 pwm->local_pinentry = 1;
593 #endif
595 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
596 !strncmp (p, "tls4://", 7))
598 #ifndef WITH_GNUTLS
599 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
600 #else
601 char *host = NULL;
602 int port;
604 if (!strncmp (p, "tls6://", 7))
606 pwm->prot = PWMD_IPV6;
607 p += 7;
609 else if (!strncmp (p, "tls4://", 7))
611 pwm->prot = PWMD_IPV4;
612 p += 7;
614 else
616 pwm->prot = PWMD_IP_ANY;
617 p += 6;
620 rc = _parse_tls_url (p, &host, &port);
621 if (!rc)
623 va_list ap;
624 char *clientcert = NULL;
625 char *clientkey = NULL;
626 char *cacert = NULL;
627 char *prio = NULL;
628 char *server_fp = NULL;
630 va_start (ap, url);
631 clientcert = va_arg (ap, char *);
633 if (!clientcert)
634 rc = GPG_ERR_INV_ARG;
635 else
637 clientkey = va_arg (ap, char *);
638 if (!clientkey)
639 rc = GPG_ERR_INV_ARG;
640 else
642 cacert = va_arg (ap, char *);
643 if (!cacert)
644 rc = GPG_ERR_INV_ARG;
645 else
647 prio = va_arg (ap, char *);
648 server_fp = va_arg (ap, char *);
653 va_end (ap);
655 if (!rc)
656 rc = _do_tls_connect (pwm, host, port, clientcert, clientkey,
657 cacert, prio, server_fp, pwm->tls_verify);
658 if (!rc)
660 rc = _connect_finalize (pwm);
661 if (rc)
662 free_tcp (pwm);
666 pwmd_free (host);
667 pwm->local_pinentry = 1;
668 #endif
671 if (!rc)
672 pwm->connected = 1;
674 return FINISH (rc);
677 static void
678 disconnect (pwm_t * pwm)
680 if (!pwm)
681 return;
683 if (pwm->ctx)
684 assuan_release (pwm->ctx);
686 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
687 free_tcp (pwm);
688 #endif
689 pwm->ctx = NULL;
690 pwm->fd = -1;
691 pwm->connected = 0;
694 void
695 pwmd_close (pwm_t * pwm)
697 if (!pwm)
698 return;
700 disconnect (pwm);
701 pwmd_free (pwm->pinentry_error);
702 pwmd_free (pwm->pinentry_desc);
703 pwmd_free (pwm->pinentry_prompt);
704 pwmd_free (pwm->pinentry_tty);
705 pwmd_free (pwm->pinentry_display);
706 pwmd_free (pwm->pinentry_term);
707 pwmd_free (pwm->pinentry_lcctype);
708 pwmd_free (pwm->pinentry_lcmessages);
709 pwmd_free (pwm->filename);
710 pwmd_free (pwm->name);
711 pwmd_free (pwm->passphrase_info);
712 pwmd_free (pwm->passphrase_hint);
714 #ifdef WITH_PINENTRY
715 if (pwm->pctx)
716 _pinentry_disconnect (pwm);
717 #endif
719 pwmd_free (pwm);
722 static gpg_error_t
723 inquire_realloc_cb (void *data, const void *buffer, size_t len)
725 membuf_t *mem = (membuf_t *) data;
726 void *p;
728 if (!buffer)
729 return 0;
731 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
732 return gpg_error (GPG_ERR_ENOMEM);
734 mem->buf = p;
735 memcpy ((char *) mem->buf + mem->len, buffer, len);
736 mem->len += len;
737 return 0;
740 static gpg_error_t
741 get_password (pwm_t * pwm, char **result, size_t * len,
742 pwmd_pinentry_t w, int echo)
744 char buf[LINE_MAX] = { 0 }, *p;
745 struct termios told, tnew;
746 char *key = NULL;
748 if (result)
749 *result = NULL;
751 if (len)
752 *len = 0;
754 if (!isatty (STDIN_FILENO))
756 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
757 return GPG_ERR_ENOTTY;
760 if (!echo)
762 if (tcgetattr (STDIN_FILENO, &told) == -1)
763 return gpg_error_from_syserror ();
765 memcpy (&tnew, &told, sizeof (struct termios));
766 tnew.c_lflag &= ~(ECHO);
767 tnew.c_lflag |= ICANON | ECHONL;
769 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
771 int n = errno;
773 tcsetattr (STDIN_FILENO, TCSANOW, &told);
774 return gpg_error_from_errno (n);
778 switch (w)
780 case PWMD_PINENTRY_OPEN:
781 fprintf (stderr, N_("Password for %s: "), pwm->filename);
782 break;
783 case PWMD_PINENTRY_OPEN_FAILED:
784 fprintf (stderr, N_("Invalid password. Password for %s: "),
785 pwm->filename);
786 break;
787 case PWMD_PINENTRY_SAVE:
788 fprintf (stderr, N_("New password for %s: "), pwm->filename);
789 break;
790 case PWMD_PINENTRY_SAVE_CONFIRM:
791 fprintf (stderr, N_("Confirm password: "));
792 break;
793 default:
794 break;
797 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
799 if (!echo)
800 tcsetattr (STDIN_FILENO, TCSANOW, &told);
801 return 0;
804 if (!echo)
805 tcsetattr (STDIN_FILENO, TCSANOW, &told);
807 if (feof (stdin))
809 clearerr (stdin);
810 return GPG_ERR_CANCELED;
813 /* Strip the newline character. */
814 p[strlen (p) - 1] = 0;
816 if (buf[0])
818 key = pwmd_strdup_printf ("%s", p);
819 memset (buf, 0, sizeof (buf));
820 if (!key)
821 return GPG_ERR_ENOMEM;
823 if (result)
824 *result = key;
826 if (len)
827 *len = strlen (key);
829 else
831 if (result)
832 *result = pwmd_strdup ("");
834 if (len)
835 *len = 1;
838 return 0;
841 gpg_error_t
842 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
844 gpg_error_t rc;
845 int new_password = 0;
846 char *password = NULL, *newpass = NULL;
847 int error = 0;
849 command_start (pwm);
851 if (data)
852 *data = NULL;
854 if (size)
855 *size = 0;
857 if (!strcmp (keyword, "NEW_PASSPHRASE"))
858 new_password = 1;
860 if (!new_password && pwm->pinentry_try)
861 error = 1;
863 again:
864 if (pwm->disable_pinentry)
866 rc = get_password (pwm, &password, size,
867 new_password ? PWMD_PINENTRY_SAVE :
868 error ? PWMD_PINENTRY_OPEN_FAILED :
869 PWMD_PINENTRY_OPEN, 0);
870 if (!rc && new_password)
871 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
874 else
876 pwmd_pinentry_t which;
878 if (error)
879 which = new_password
880 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
881 else
882 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
884 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
885 if (!rc && new_password)
886 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
887 PWMD_PINENTRY_SAVE_CONFIRM);
890 if (!rc && new_password)
892 if ((!password && newpass) || (!newpass && password)
893 || (newpass && password && strcmp (newpass, password)))
895 if (pwm->disable_pinentry)
896 fprintf (stderr, N_("Passphrases do not match.\n"));
898 pwmd_free (password);
899 pwmd_free (newpass);
900 password = newpass = NULL;
901 error = 1;
902 goto again;
906 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
907 pwmd_free (newpass);
908 if (!rc && data)
909 *data = password;
911 return rc;
914 static gpg_error_t
915 inquire_cb (void *data, const char *keyword)
917 pwm_t *pwm = (pwm_t *) data;
918 gpg_error_t rc = 0;
919 int free_result = 0;
920 char *result = NULL;
921 int is_password = 0;
922 int new_password = 0;
924 if (!strcmp (keyword, "PASSPHRASE"))
925 is_password = 1;
926 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
927 new_password = 1;
929 /* Shouldn't get this far without a callback. */
930 if (!pwm->override_inquire && !pwm->inquire_func
931 && !is_password && !new_password)
932 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
934 for (;;)
936 size_t len = 0;
937 gpg_error_t arc;
939 result = NULL;
941 if (!pwm->override_inquire && (is_password || new_password))
943 free_result = 1;
944 rc = pwmd_password (data, keyword, &result, &len);
945 if (!rc)
946 rc = GPG_ERR_EOF;
948 else
949 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
950 &len);
952 /* gpg will truncate a passphrase at the first nil byte which may be bad
953 * for generated key files. */
954 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
955 && (is_password || new_password))
957 if (len && result && *result)
959 for (size_t n = 0; n < len; n++)
961 if (result[n] == 0 && n+1 != len)
962 rc = GPG_ERR_INV_PASSPHRASE;
967 cancel:
968 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
970 #ifndef LIBASSUAN_2_1_0
971 gpg_error_t trc = rc;
973 /* Cancel this inquire. */
974 rc = assuan_send_data (pwm->ctx, NULL, 1);
975 if (!rc)
977 char *line;
978 size_t len;
980 /* There is a bug (or feature?) in assuan_send_data() that
981 * when cancelling an inquire the next read from the server is
982 * not done until the next command making the next command
983 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
985 rc = assuan_read_line (pwm->ctx, &line, &len);
987 /* Restore the original error. This differs from the error
988 * returned from the pwmd command (GPG_ERR_CANCELED). This
989 * error is returned to the calling function.
991 if (!rc)
992 rc = trc;
994 #endif
995 break;
998 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
1000 if (len <= 0 && !result)
1002 rc = 0;
1003 break;
1005 else if ((len <= 0 && result) || (len && !result))
1007 rc = gpg_error (GPG_ERR_INV_ARG);
1008 break;
1011 if (pwm->inquire_maxlen
1012 && pwm->inquire_sent + len > pwm->inquire_maxlen)
1014 rc = gpg_error (GPG_ERR_TOO_LARGE);
1015 if (!free_result)
1016 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
1017 &result, &len);
1018 goto cancel;
1021 arc = assuan_send_data (pwm->ctx, result, len);
1022 if (gpg_err_code (rc) == GPG_ERR_EOF)
1024 rc = arc;
1025 break;
1028 rc = arc;
1030 else if (rc)
1031 break;
1033 if (!rc)
1035 pwm->inquire_sent += len;
1037 if (pwm->status_func)
1039 char buf[ASSUAN_LINELENGTH];
1041 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
1042 pwm->inquire_total);
1043 rc = pwm->status_func (pwm->status_data, buf);
1044 if (rc)
1045 continue;
1050 if (free_result)
1051 pwmd_free (result);
1053 return rc;
1056 static gpg_error_t
1057 parse_assuan_line (pwm_t * pwm)
1059 gpg_error_t rc;
1060 char *line;
1061 size_t len;
1063 rc = assuan_read_line (pwm->ctx, &line, &len);
1064 if (!rc)
1066 if (line[0] == 'O' && line[1] == 'K' &&
1067 (line[2] == 0 || line[2] == ' '))
1070 else if (line[0] == '#')
1073 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
1075 if (pwm->status_func)
1077 rc = pwm->status_func (pwm->status_data,
1078 line[1] == 0 ? line + 1 : line + 2);
1081 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
1082 (line[3] == 0 || line[3] == ' '))
1084 line += 4;
1085 rc = strtol (line, NULL, 10);
1089 return rc;
1092 static void
1093 reset_handle (pwm_t *pwm)
1095 pwm->fd = -1;
1096 pwm->cancel = 0;
1097 pwm->pinentry_disabled = 0;
1098 #ifdef WITH_PINENTRY
1099 if (pwm->pctx)
1100 _pinentry_disconnect (pwm);
1101 #endif
1102 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1103 #ifdef WITH_GNUTLS
1104 pwm->tls_error = 0;
1105 #endif
1107 if (pwm->tcp)
1108 pwm->tcp->rc = 0;
1109 #endif
1112 gpg_error_t
1113 pwmd_disconnect (pwm_t * pwm)
1115 if (!pwm)
1116 return FINISH (GPG_ERR_INV_ARG);
1118 command_start (pwm);
1120 if (pwm->fd == -1)
1121 return FINISH (GPG_ERR_INV_STATE);
1123 disconnect (pwm);
1124 reset_handle (pwm);
1125 return 0;
1128 /* Note that this should only be called when not in a command. */
1129 gpg_error_t
1130 pwmd_process (pwm_t * pwm)
1132 gpg_error_t rc = 0;
1133 fd_set fds;
1134 struct timeval tv = { 0, 0 };
1135 int n;
1137 if (!pwm || pwm->fd == -1)
1138 return FINISH (GPG_ERR_INV_ARG);
1139 else if (!pwm->ctx)
1140 return FINISH (GPG_ERR_INV_STATE);
1142 FD_ZERO (&fds);
1143 FD_SET (pwm->fd, &fds);
1144 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1146 if (n == -1)
1147 return FINISH (gpg_error_from_syserror ());
1149 if (n > 0)
1151 if (FD_ISSET (pwm->fd, &fds))
1152 rc = parse_assuan_line (pwm);
1155 while (!rc && assuan_pending_line (pwm->ctx))
1156 rc = parse_assuan_line (pwm);
1158 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1159 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1161 close (pwm->fd);
1162 pwm->fd = -1;
1164 #endif
1166 return FINISH (rc);
1169 static gpg_error_t
1170 status_cb (void *data, const char *line)
1172 pwm_t *pwm = data;
1174 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1175 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1176 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1178 pwmd_free (pwm->passphrase_hint);
1179 pwm->passphrase_hint = pwmd_strdup (line+16);
1181 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1183 pwmd_free (pwm->passphrase_info);
1184 pwm->passphrase_info = pwmd_strdup (line+16);
1187 if (pwm->status_func)
1188 return pwm->status_func (pwm->status_data, line);
1190 return 0;
1193 gpg_error_t
1194 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1195 char **result, size_t * len, const char *cmd)
1197 membuf_t data;
1198 gpg_error_t rc;
1200 if (!cmd || !*cmd)
1201 return FINISH (GPG_ERR_INV_ARG);
1203 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1204 return FINISH (GPG_ERR_LINE_TOO_LONG);
1206 data.len = 0;
1207 data.buf = NULL;
1208 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1209 #ifdef WITH_QUALITY
1210 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1211 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1212 #else
1213 inquire_cb, pwm,
1214 #endif
1215 status_cb, pwm);
1217 if (rc)
1219 if (data.buf)
1221 pwmd_free (data.buf);
1222 data.buf = NULL;
1225 else
1227 if (data.buf)
1229 inquire_realloc_cb (&data, "", 1);
1231 if (result)
1232 *result = (char *) data.buf;
1233 else
1234 pwmd_free (data.buf);
1236 if (len)
1237 *len = data.len;
1241 pwm->inquire_maxlen = 0;
1242 return rc;
1245 gpg_error_t
1246 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1247 pwmd_inquire_cb_t func, void *user, const char *cmd,
1248 va_list ap)
1250 char *buf;
1251 size_t len;
1252 va_list ap2;
1254 command_start (pwm);
1256 if (result)
1257 *result = NULL;
1259 if (rlen)
1260 *rlen = 0;
1262 if (!pwm || !cmd)
1263 return FINISH (GPG_ERR_INV_ARG);
1264 if (!pwm->ctx)
1265 return FINISH (GPG_ERR_INV_STATE);
1268 * C99 allows the dst pointer to be null which will calculate the length
1269 * of the would-be result and return it.
1271 va_copy (ap2, ap);
1272 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1273 buf = (char *) pwmd_malloc (len);
1274 if (!buf)
1276 va_end (ap2);
1277 return FINISH (GPG_ERR_ENOMEM);
1280 len = vsnprintf (buf, len, cmd, ap2);
1281 va_end (ap2);
1283 if (buf[strlen (buf) - 1] == '\n')
1284 buf[strlen (buf) - 1] = 0;
1285 if (buf[strlen (buf) - 1] == '\r')
1286 buf[strlen (buf) - 1] = 0;
1288 pwm->inquire_func = func;
1289 pwm->inquire_data = user;
1290 pwm->inquire_sent = 0;
1291 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1292 pwmd_free (buf);
1293 return rc;
1296 gpg_error_t
1297 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1298 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1300 va_list ap;
1302 if (result)
1303 *result = NULL;
1305 if (len)
1306 *len = 0;
1308 if (!pwm || !cmd)
1309 return FINISH (GPG_ERR_INV_ARG);
1310 if (!pwm->ctx)
1311 return FINISH (GPG_ERR_INV_STATE);
1313 va_start (ap, cmd);
1314 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1315 va_end (ap);
1316 return rc;
1319 static gpg_error_t
1320 send_pinentry_timeout (pwm_t *pwm)
1322 gpg_error_t rc = 0;
1324 if ((pwm->pinentry_timeout >= 0
1325 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1326 || (pwm->pinentry_timeout == -1
1327 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1329 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1330 "OPTION pinentry-timeout=%i",
1331 pwm->pinentry_timeout);
1332 if (!rc)
1333 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1336 return rc;
1339 static gpg_error_t
1340 send_pinentry_options (pwm_t * pwm)
1342 gpg_error_t rc;
1344 // Pwmd >= 3.1 uses gpgme to do the pinentry settings.
1345 if (pwm->version && pwm->version >= 0x030100)
1346 return 0;
1348 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1349 "OPTION disable-pinentry=0");
1350 if (!rc && pwm->pinentry_tty)
1351 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1352 pwm->pinentry_tty);
1354 if (!rc && pwm->pinentry_term)
1355 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1356 pwm->pinentry_term);
1358 if (!rc && pwm->pinentry_display)
1359 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1360 pwm->pinentry_display);
1362 if (!rc && pwm->pinentry_desc)
1363 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1364 pwm->pinentry_desc);
1366 if (!rc && pwm->pinentry_lcctype)
1367 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1368 pwm->pinentry_lcctype);
1370 if (!rc && pwm->pinentry_lcmessages)
1371 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1372 pwm->pinentry_lcmessages);
1374 if (!rc)
1375 rc = send_pinentry_timeout (pwm);
1377 return rc;
1380 gpg_error_t
1381 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1383 if (!pwm || !result)
1384 return FINISH (GPG_ERR_INV_ARG);
1386 *result = PWMD_SOCKET_LOCAL;
1388 if (pwm->fd == -1)
1389 return FINISH (GPG_ERR_INV_STATE);
1391 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1392 #ifdef WITH_SSH
1393 if (pwm->tcp && pwm->tcp->ssh)
1394 *result = PWMD_SOCKET_SSH;
1395 #endif
1396 #ifdef WITH_GNUTLS
1397 if (pwm->tcp && pwm->tcp->tls)
1398 *result = PWMD_SOCKET_TLS;
1399 #endif
1400 #endif
1401 return 0;
1404 static gpg_error_t
1405 disable_pinentry (pwm_t *pwm, int *disable)
1407 gpg_error_t rc;
1408 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1409 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1410 #else
1411 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1412 #endif
1414 if (disable)
1415 *disable = no_pinentry;
1417 if (pwm->pinentry_disabled && no_pinentry)
1418 return 0;
1419 else if (!pwm->pinentry_disabled && !no_pinentry)
1420 return 0;
1422 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1423 no_pinentry);
1424 if (!rc)
1425 pwm->pinentry_disabled = no_pinentry;
1427 return rc;
1430 gpg_error_t
1431 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1432 void *data)
1434 gpg_error_t rc = 0;
1435 int no_pinentry = 0;
1437 if (!pwm || !filename || !*filename)
1438 return FINISH (GPG_ERR_INV_ARG);
1440 if (!pwm->ctx)
1441 return FINISH (GPG_ERR_INV_STATE);
1443 command_start (pwm);
1444 rc = disable_pinentry (pwm, &no_pinentry);
1445 if (!rc && !no_pinentry)
1446 rc = send_pinentry_options (pwm);
1448 if (!rc)
1450 pwm->pinentry_try = 0;
1451 pwmd_free (pwm->filename);
1452 pwm->filename = pwmd_strdup (filename);
1456 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1457 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1458 filename);
1460 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1461 && pwm->pinentry_disabled
1462 && ++pwm->pinentry_try < pwm->pinentry_tries);
1464 pwm->pinentry_try = 0;
1466 if (rc)
1468 pwmd_free (pwm->filename);
1469 pwm->filename = NULL;
1473 return FINISH (rc);
1476 static gpg_error_t
1477 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1478 void *data, int save)
1480 gpg_error_t rc = 0;
1482 if (!pwm)
1483 return FINISH (GPG_ERR_INV_ARG);
1484 if (!pwm->ctx)
1485 return FINISH (GPG_ERR_INV_STATE);
1487 command_start (pwm);
1488 rc = disable_pinentry (pwm, NULL);
1489 if (!rc)
1490 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1491 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1493 return FINISH (rc);
1496 gpg_error_t
1497 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1499 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1502 gpg_error_t
1503 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1505 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1508 static gpg_error_t
1509 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1511 int n, *intp;
1512 size_t *sizetp;
1513 char *arg1, **charpp;
1514 gpg_error_t rc = 0;
1516 if (!pwm)
1517 return GPG_ERR_INV_ARG;
1519 command_start (pwm);
1520 switch (opt)
1522 case PWMD_OPTION_SERVER_VERSION:
1523 if (!get)
1524 return GPG_ERR_NOT_SUPPORTED;
1526 if (!pwm)
1527 rc = GPG_ERR_INV_ARG;
1528 else if (!pwm->ctx)
1529 rc = GPG_ERR_INV_STATE;
1530 else
1532 unsigned *u = va_arg (ap, unsigned *);
1533 *u = pwm->version;
1536 break;
1537 case PWMD_OPTION_SIGPIPE:
1538 if (get)
1540 intp = va_arg (ap, int *);
1541 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1542 break;
1545 n = va_arg (ap, int);
1546 if (n < 0 || n > 1)
1547 rc = GPG_ERR_INV_VALUE;
1549 if (n)
1550 pwm->opts |= OPT_SIGPIPE;
1551 else
1552 pwm->opts &= ~OPT_SIGPIPE;
1554 break;
1555 case PWMD_OPTION_LOCK_ON_OPEN:
1556 if (get)
1558 intp = va_arg (ap, int *);
1559 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1560 break;
1563 n = va_arg (ap, int);
1565 if (n < 0 || n > 1)
1566 rc = GPG_ERR_INV_VALUE;
1568 if (n)
1569 pwm->opts |= OPT_LOCK_ON_OPEN;
1570 else
1571 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1573 break;
1574 case PWMD_OPTION_INQUIRE_TOTAL:
1575 if (get)
1577 sizetp = va_arg (ap, size_t *);
1578 *sizetp = pwm->inquire_total;
1579 break;
1582 pwm->inquire_total = va_arg (ap, size_t);
1583 break;
1584 case PWMD_OPTION_STATUS_CB:
1585 if (get)
1587 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1589 *cb = pwm->status_func;
1590 break;
1593 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1594 break;
1595 case PWMD_OPTION_STATUS_DATA:
1596 if (get)
1598 void **data = va_arg (ap, void **);
1600 *data = pwm->status_data;
1601 break;
1604 pwm->status_data = va_arg (ap, void *);
1605 break;
1606 case PWMD_OPTION_NO_PINENTRY:
1607 if (get)
1609 intp = va_arg (ap, int *);
1610 *intp = pwm->disable_pinentry;
1611 break;
1614 n = va_arg (ap, int);
1616 if (n < 0 || n > 1)
1617 rc = GPG_ERR_INV_VALUE;
1618 else
1619 pwm->disable_pinentry = n;
1620 break;
1621 case PWMD_OPTION_LOCAL_PINENTRY:
1622 if (get)
1624 intp = va_arg (ap, int *);
1625 *intp = pwm->local_pinentry;
1626 break;
1629 n = va_arg (ap, int);
1631 if (n < 0 || n > 1)
1632 rc = GPG_ERR_INV_VALUE;
1633 else
1634 pwm->local_pinentry = n;
1636 break;
1637 case PWMD_OPTION_PINENTRY_TIMEOUT:
1638 if (get)
1640 intp = va_arg (ap, int *);
1641 *intp = pwm->pinentry_timeout;
1642 break;
1645 n = va_arg (ap, int);
1647 if (n < 0)
1648 rc = GPG_ERR_INV_VALUE;
1649 else
1650 pwm->pinentry_timeout = n;
1651 break;
1652 case PWMD_OPTION_PINENTRY_TRIES:
1653 if (get)
1655 intp = va_arg (ap, int *);
1656 *intp = pwm->pinentry_tries;
1657 break;
1660 n = va_arg (ap, int);
1661 pwm->pinentry_tries = n;
1662 break;
1663 case PWMD_OPTION_PINENTRY_PATH:
1664 if (get)
1666 charpp = va_arg (ap, char **);
1667 *charpp = pwm->pinentry_path;
1668 break;
1671 arg1 = va_arg (ap, char *);
1672 pwmd_free (pwm->pinentry_path);
1673 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1674 break;
1675 case PWMD_OPTION_PINENTRY_TTY:
1676 if (get)
1678 charpp = va_arg (ap, char **);
1679 *charpp = pwm->pinentry_tty;
1680 break;
1683 arg1 = va_arg (ap, char *);
1684 pwmd_free (pwm->pinentry_tty);
1685 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1686 break;
1687 case PWMD_OPTION_PINENTRY_DISPLAY:
1688 if (get)
1690 charpp = va_arg (ap, char **);
1691 *charpp = pwm->pinentry_display;
1692 break;
1695 arg1 = va_arg (ap, char *);
1696 pwmd_free (pwm->pinentry_display);
1697 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1698 break;
1699 case PWMD_OPTION_PINENTRY_TERM:
1700 if (get)
1702 charpp = va_arg (ap, char **);
1703 *charpp = pwm->pinentry_term;
1704 break;
1707 arg1 = va_arg (ap, char *);
1708 pwmd_free (pwm->pinentry_term);
1709 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1710 break;
1711 case PWMD_OPTION_PINENTRY_ERROR:
1712 if (get)
1714 charpp = va_arg (ap, char **);
1715 *charpp = pwm->pinentry_error;
1716 break;
1719 arg1 = va_arg (ap, char *);
1720 pwmd_free (pwm->pinentry_error);
1721 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1722 break;
1723 case PWMD_OPTION_PINENTRY_PROMPT:
1724 if (get)
1726 charpp = va_arg (ap, char **);
1727 *charpp = pwm->pinentry_prompt;
1728 break;
1731 arg1 = va_arg (ap, char *);
1732 pwmd_free (pwm->pinentry_prompt);
1733 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1734 break;
1735 case PWMD_OPTION_PINENTRY_DESC:
1736 if (get)
1738 charpp = va_arg (ap, char **);
1739 *charpp = pwm->pinentry_desc;
1740 break;
1743 arg1 = va_arg (ap, char *);
1744 pwmd_free (pwm->pinentry_desc);
1745 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1746 break;
1747 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1748 if (get)
1750 charpp = va_arg (ap, char **);
1751 *charpp = pwm->pinentry_lcctype;
1752 break;
1755 arg1 = va_arg (ap, char *);
1756 pwmd_free (pwm->pinentry_lcctype);
1757 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1758 break;
1759 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1760 if (get)
1762 charpp = va_arg (ap, char **);
1763 *charpp = pwm->pinentry_lcmessages;
1764 break;
1767 arg1 = va_arg (ap, char *);
1768 pwmd_free (pwm->pinentry_lcmessages);
1769 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1770 break;
1771 case PWMD_OPTION_KNOWNHOST_CB:
1772 if (get)
1774 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1776 *cb = pwm->kh_cb;
1777 break;
1780 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1781 break;
1782 case PWMD_OPTION_KNOWNHOST_DATA:
1783 if (get)
1785 void **data = va_arg (ap, void **);
1787 *data = pwm->kh_data;
1788 break;
1791 pwm->kh_data = va_arg (ap, void *);
1792 break;
1793 case PWMD_OPTION_SSH_AGENT:
1794 if (get)
1796 intp = va_arg (ap, int *);
1797 *intp = pwm->use_agent;
1798 break;
1801 pwm->use_agent = va_arg (ap, int);
1803 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1805 pwm->use_agent = 0;
1806 rc = GPG_ERR_INV_VALUE;
1808 break;
1809 case PWMD_OPTION_TLS_VERIFY:
1810 if (get)
1812 intp = va_arg (ap, int *);
1813 *intp = pwm->tls_verify;
1814 break;
1817 pwm->tls_verify = va_arg (ap, int);
1819 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1821 pwm->tls_verify = 0;
1822 rc = GPG_ERR_INV_VALUE;
1824 break;
1825 case PWMD_OPTION_SOCKET_TIMEOUT:
1826 if (get)
1828 intp = va_arg (ap, int *);
1829 *intp = pwm->socket_timeout;
1830 break;
1833 pwm->socket_timeout = va_arg (ap, int);
1834 if (pwm->socket_timeout < 0)
1836 pwm->socket_timeout = 0;
1837 rc = GPG_ERR_INV_VALUE;
1840 #ifdef WITH_SSH
1841 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1843 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1844 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1845 pwm->socket_timeout * 1000);
1847 #endif
1848 #ifdef WITH_GNUTLS
1849 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1850 pwm->tcp->tls->timeout = pwm->socket_timeout;
1851 #endif
1852 break;
1853 case PWMD_OPTION_OVERRIDE_INQUIRE:
1854 if (get)
1856 intp = va_arg (ap, int *);
1857 *intp = pwm->override_inquire;
1858 break;
1861 pwm->override_inquire = va_arg (ap, int);
1863 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1865 pwm->override_inquire = 0;
1866 rc = GPG_ERR_INV_VALUE;
1868 break;
1869 default:
1870 rc = GPG_ERR_UNKNOWN_OPTION;
1871 break;
1874 return FINISH (rc);
1877 gpg_error_t
1878 pwmd_setopt (pwm_t * pwm, pwmd_option_t opt, ...)
1880 va_list ap;
1881 gpg_error_t rc = 0;
1883 va_start (ap, opt);
1884 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1885 va_end (ap);
1886 return FINISH (rc);
1889 gpg_error_t
1890 pwmd_getopt (pwm_t *pwm, pwmd_option_t opt, ...)
1892 va_list ap;
1893 gpg_error_t rc = 0;
1895 va_start (ap, opt);
1896 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1897 va_end (ap);
1898 return FINISH (rc);
1901 gpg_error_t
1902 pwmd_new (const char *name, pwm_t ** pwm)
1904 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1905 gpg_error_t rc;
1907 if (!h)
1908 return FINISH (GPG_ERR_ENOMEM);
1910 if (name)
1912 h->name = pwmd_strdup (name);
1913 if (!h->name)
1915 pwmd_free (h);
1916 return FINISH (GPG_ERR_ENOMEM);
1920 reset_handle (h);
1921 h->pinentry_timeout = -1;
1922 h->current_pinentry_timeout = -1;
1923 h->pinentry_tries = 3;
1924 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1925 h->prot = PWMD_IP_ANY;
1926 #endif
1928 if (ttyname (STDOUT_FILENO))
1930 char buf[256];
1932 ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
1933 h->pinentry_tty = pwmd_strdup (buf);
1934 if (!h->pinentry_tty)
1936 rc = GPG_ERR_ENOMEM;
1937 goto fail;
1941 if (getenv ("TERM") && h->pinentry_tty)
1943 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
1944 if (!h->pinentry_term)
1946 rc = GPG_ERR_ENOMEM;
1947 goto fail;
1951 if (getenv ("DISPLAY"))
1953 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
1954 if (!h->pinentry_display)
1956 rc = GPG_ERR_ENOMEM;
1957 goto fail;
1961 update_pinentry_settings (h);
1962 *pwm = h;
1963 return 0;
1965 fail:
1966 pwmd_close (h);
1967 return FINISH (rc);
1970 void
1971 pwmd_free (void *ptr)
1973 _xfree (ptr);
1976 void *
1977 pwmd_malloc (size_t size)
1979 return _xmalloc (size);
1982 void *
1983 pwmd_calloc (size_t nmemb, size_t size)
1985 return _xcalloc (nmemb, size);
1988 void *
1989 pwmd_realloc (void *ptr, size_t size)
1991 return _xrealloc (ptr, size);
1994 char *
1995 pwmd_strdup (const char *str)
1997 char *t;
1998 size_t len;
1999 register size_t c;
2001 len = strlen (str);
2002 t = _xmalloc ((len + 1) * sizeof (char));
2003 if (!t)
2004 return NULL;
2006 for (c = 0; c < len; c++)
2007 t[c] = str[c];
2009 t[c] = 0;
2010 return t;
2013 char *
2014 pwmd_strdup_printf (const char *fmt, ...)
2016 va_list ap, ap2;
2017 int len;
2018 char *buf;
2020 if (!fmt)
2021 return NULL;
2023 va_start (ap, fmt);
2024 va_copy (ap2, ap);
2025 len = vsnprintf (NULL, 0, fmt, ap);
2026 va_end (ap);
2027 buf = pwmd_malloc (++len);
2028 if (buf)
2029 vsnprintf (buf, len, fmt, ap2);
2031 va_end (ap2);
2032 return buf;
2035 gpg_error_t
2036 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
2037 size_t * len, pwmd_pinentry_t which)
2039 #ifndef WITH_PINENTRY
2040 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
2041 #else
2042 command_start (pwm);
2043 gpg_error_t rc = _pwmd_getpin (pwm, filename, result, len, which);
2045 return FINISH (rc);
2046 #endif
2049 const char *
2050 pwmd_version ()
2052 return LIBPWMD_VERSION_STR;
2055 unsigned int
2056 pwmd_features ()
2058 unsigned int n = 0;
2060 #ifdef WITH_PINENTRY
2061 n |= PWMD_FEATURE_PINENTRY;
2062 #endif
2063 #ifdef WITH_SSH
2064 n |= PWMD_FEATURE_SSH;
2065 #endif
2066 #ifdef WITH_QUALITY
2067 n |= PWMD_FEATURE_CRACK;
2068 #endif
2069 #ifdef WITH_GNUTLS
2070 n |= PWMD_FEATURE_GNUTLS;
2071 #endif
2072 return n;
2075 gpg_error_t
2076 pwmd_fd (pwm_t * pwm, int *fd)
2078 if (!pwm || !fd)
2079 return FINISH (GPG_ERR_INV_ARG);
2081 if (pwm->fd == -1)
2082 return FINISH (GPG_ERR_INV_STATE);
2084 *fd = pwm->fd;
2085 return 0;
2088 void
2089 pwmd_set_pointer (pwm_t *pwm, void *data)
2091 pwm->user_data = data;
2094 void *
2095 pwmd_get_pointer (pwm_t *pwm)
2097 return pwm->user_data;
2101 pwmd_tls_error (pwm_t *pwm)
2103 #ifndef WITH_GNUTLS
2104 return 0;
2105 #else
2106 return pwm ? pwm->tls_error : 0;
2107 #endif
2110 gpg_error_t
2111 pwmd_cancel (pwm_t *pwm)
2113 if (!pwm)
2114 return FINISH (GPG_ERR_INV_ARG);
2116 if (pwm->fd == -1 && !pwm->tcp)
2117 return FINISH (GPG_ERR_INV_STATE);
2119 /* Can only cancel the connection for the time being. */
2120 if (pwm->connected)
2121 return FINISH (GPG_ERR_INV_STATE);
2123 pwm->cancel = 1;
2124 return 0;