Add pwmd_cancel().
[libpwmd.git] / src / libpwmd.c
blob8967430fce0ef613fecc4a7a8a322c2b82d55a11
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 pwmd_free (tcp);
286 pwm->tcp = NULL;
288 #endif
290 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
291 gpg_error_t
292 tcp_connect_common (pwm_t * pwm)
294 struct addrinfo hints = { 0 };
295 int n;
296 char portstr[6];
297 gpg_error_t rc = 0;
299 switch (pwm->prot)
301 case PWMD_IP_ANY:
302 hints.ai_family = AF_UNSPEC;
303 break;
304 case PWMD_IPV4:
305 hints.ai_family = AF_INET;
306 break;
307 case PWMD_IPV6:
308 hints.ai_family = AF_INET6;
309 break;
312 hints.ai_socktype = SOCK_STREAM;
313 snprintf (portstr, sizeof (portstr), "%i", pwm->tcp->port);
314 n = getaddrinfo (pwm->tcp->host, portstr, &hints, &pwm->tcp->addrs);
315 if (n)
317 fprintf (stderr, "%s\n", gai_strerror (n));
318 return GPG_ERR_UNKNOWN_HOST; //FIXME
321 for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr;
322 pwm->tcp->addr = pwm->tcp->addrs->ai_next)
324 pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0);
325 if (pwm->fd == -1)
327 rc = gpg_error_from_syserror ();
328 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
329 break;
330 continue;
333 if (pwm->socket_timeout)
335 if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1)
337 rc = gpg_error_from_syserror ();
338 break;
342 if (connect (pwm->fd, pwm->tcp->addr->ai_addr,
343 pwm->tcp->addr->ai_family == AF_INET6
344 ? sizeof (struct sockaddr_in6)
345 : sizeof (struct sockaddr)) == -1)
347 int n;
348 struct timeval tv = { pwm->socket_timeout, 0 };
349 fd_set wfds;
351 rc = gpg_error_from_syserror ();
352 if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS)
354 close (pwm->fd);
355 pwm->fd = -1;
356 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next)
357 return rc;
358 continue;
361 FD_ZERO (&wfds);
362 FD_SET (pwm->fd, &wfds);
363 n = select (pwm->fd+1, NULL, &wfds, NULL, &tv);
364 rc = 0;
365 if (!n)
366 rc = gpg_error (GPG_ERR_ETIMEDOUT);
367 else if (n != -1)
369 socklen_t len = sizeof(int);
371 getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len);
372 if (n)
373 rc = gpg_error_from_errno (n);
375 else if (n == -1)
376 rc = gpg_error_from_syserror ();
378 if (rc)
380 close (pwm->fd);
381 pwm->fd = -1;
382 if (pwm->tcp->addr == pwm->tcp->addrs->ai_next
383 || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT)
384 return rc;
386 else
387 break;
389 else
390 break;
393 if (!rc && pwm->socket_timeout)
394 if (fcntl (pwm->fd, F_SETFL, 0) == -1)
395 rc = gpg_error_from_syserror ();
397 return rc;
399 #endif
401 gpg_error_t
402 pwmd_connect (pwm_t * pwm, const char *url, ...)
404 const char *p = url;
405 gpg_error_t rc;
407 if (!pwm)
408 return FINISH (GPG_ERR_INV_ARG);
409 else if (!pwm->ctx)
411 rc = init_handle (pwm);
412 if (rc)
413 return rc;
416 if (!(pwm->opts & OPT_SIGPIPE))
417 signal (SIGPIPE, SIG_IGN);
419 #ifdef WITH_GNUTLS
420 pwm->tls_error = 0;
421 #endif
422 rc = GPG_ERR_UNSUPPORTED_PROTOCOL;
424 if (p && (*p == '/' || *p == '~'))
425 rc = connect_uds (pwm, p);
426 else if (!p || !strncmp (p, "file://", 7))
428 if (p)
429 p += 7;
430 #ifdef DEFAULT_PWMD_SOCKET
431 else
432 p = DEFAULT_PWMD_SOCKET;
433 #endif
434 rc = connect_uds (pwm, p);
436 else if (!strncmp (p, "ssh://", 6) || !strncmp (p, "ssh6://", 7) ||
437 !strncmp (p, "ssh4://", 7))
439 #ifndef WITH_SSH
440 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
441 #else
442 char *host = NULL;
443 int port;
444 char *username = NULL;
446 if (!strncmp (p, "ssh6://", 7))
448 pwm->prot = PWMD_IPV6;
449 p += 7;
451 else if (!strncmp (p, "ssh4://", 7))
453 pwm->prot = PWMD_IPV4;
454 p += 7;
456 else
458 pwm->prot = PWMD_IP_ANY;
459 p += 6;
462 rc = _parse_ssh_url (p, &host, &port, &username);
463 if (!rc)
465 va_list ap;
466 char *identity = NULL;
467 char *knownhosts = NULL;
469 va_start (ap, url);
470 identity = va_arg (ap, char *);
472 if (!identity && !pwm->use_agent)
473 rc = GPG_ERR_INV_ARG;
474 else
475 knownhosts = va_arg (ap, char *);
477 va_end (ap);
479 if (!rc)
480 rc = _do_ssh_connect (pwm, host, port, identity, username,
481 knownhosts);
482 if (!rc)
484 rc = _connect_finalize (pwm);
485 if (rc)
486 free_tcp (pwm);
490 pwmd_free (host);
491 pwmd_free (username);
492 pwm->local_pinentry = 1;
493 return FINISH (rc);
494 #endif
496 else if (!strncmp (p, "tls://", 6) || !strncmp (p, "tls6://", 7) ||
497 !strncmp (p, "tls4://", 7))
499 #ifndef WITH_GNUTLS
500 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
501 #else
502 char *host = NULL;
503 int port;
505 if (!strncmp (p, "tls6://", 7))
507 pwm->prot = PWMD_IPV6;
508 p += 7;
510 else if (!strncmp (p, "tls4://", 7))
512 pwm->prot = PWMD_IPV4;
513 p += 7;
515 else
517 pwm->prot = PWMD_IP_ANY;
518 p += 6;
521 rc = _parse_tls_url (p, &host, &port);
522 if (!rc)
524 va_list ap;
525 char *clientcert = NULL;
526 char *clientkey = NULL;
527 char *cacert = NULL;
528 char *prio = NULL;
529 char *server_fp = NULL;
531 va_start (ap, url);
532 clientcert = va_arg (ap, char *);
534 if (!clientcert)
535 rc = GPG_ERR_INV_ARG;
536 else
538 clientkey = va_arg (ap, char *);
539 if (!clientkey)
540 rc = GPG_ERR_INV_ARG;
541 else
543 cacert = va_arg (ap, char *);
544 if (!cacert)
545 rc = GPG_ERR_INV_ARG;
546 else
548 prio = va_arg (ap, char *);
549 server_fp = va_arg (ap, char *);
554 va_end (ap);
556 if (!rc)
557 rc = _do_tls_connect (pwm, host, port, clientcert, clientkey,
558 cacert, prio, server_fp, pwm->tls_verify);
559 if (!rc)
561 rc = _connect_finalize (pwm);
562 if (rc)
563 free_tcp (pwm);
567 pwmd_free (host);
568 pwm->local_pinentry = 1;
569 return FINISH (rc);
570 #endif
573 return FINISH (rc);
576 static void
577 disconnect (pwm_t * pwm)
579 if (!pwm)
580 return;
582 if (pwm->ctx)
583 assuan_release (pwm->ctx);
585 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
586 free_tcp (pwm);
587 #endif
588 pwm->ctx = NULL;
589 pwm->fd = -1;
592 void
593 pwmd_close (pwm_t * pwm)
595 if (!pwm)
596 return;
598 disconnect (pwm);
599 pwmd_free (pwm->pinentry_error);
600 pwmd_free (pwm->pinentry_desc);
601 pwmd_free (pwm->pinentry_prompt);
602 pwmd_free (pwm->pinentry_tty);
603 pwmd_free (pwm->pinentry_display);
604 pwmd_free (pwm->pinentry_term);
605 pwmd_free (pwm->pinentry_lcctype);
606 pwmd_free (pwm->pinentry_lcmessages);
607 pwmd_free (pwm->filename);
608 pwmd_free (pwm->name);
609 pwmd_free (pwm->passphrase_info);
610 pwmd_free (pwm->passphrase_hint);
612 #ifdef WITH_PINENTRY
613 if (pwm->pctx)
614 _pinentry_disconnect (pwm);
615 #endif
617 pwmd_free (pwm);
620 static gpg_error_t
621 inquire_realloc_cb (void *data, const void *buffer, size_t len)
623 membuf_t *mem = (membuf_t *) data;
624 void *p;
626 if (!buffer)
627 return 0;
629 if ((p = pwmd_realloc (mem->buf, mem->len + len)) == NULL)
630 return gpg_error (GPG_ERR_ENOMEM);
632 mem->buf = p;
633 memcpy ((char *) mem->buf + mem->len, buffer, len);
634 mem->len += len;
635 return 0;
638 static gpg_error_t
639 get_password (pwm_t * pwm, char **result, size_t * len,
640 pwmd_pinentry_t w, int echo)
642 char buf[LINE_MAX] = { 0 }, *p;
643 struct termios told, tnew;
644 char *key = NULL;
646 if (result)
647 *result = NULL;
649 if (len)
650 *len = 0;
652 if (!isatty (STDIN_FILENO))
654 fprintf (stderr, N_("Input is not from a terminal! Failing.\n"));
655 return GPG_ERR_ENOTTY;
658 if (!echo)
660 if (tcgetattr (STDIN_FILENO, &told) == -1)
661 return gpg_error_from_syserror ();
663 memcpy (&tnew, &told, sizeof (struct termios));
664 tnew.c_lflag &= ~(ECHO);
665 tnew.c_lflag |= ICANON | ECHONL;
667 if (tcsetattr (STDIN_FILENO, TCSANOW, &tnew) == -1)
669 int n = errno;
671 tcsetattr (STDIN_FILENO, TCSANOW, &told);
672 return gpg_error_from_errno (n);
676 switch (w)
678 case PWMD_PINENTRY_OPEN:
679 fprintf (stderr, N_("Password for %s: "), pwm->filename);
680 break;
681 case PWMD_PINENTRY_OPEN_FAILED:
682 fprintf (stderr, N_("Invalid password. Password for %s: "),
683 pwm->filename);
684 break;
685 case PWMD_PINENTRY_SAVE:
686 fprintf (stderr, N_("New password for %s: "), pwm->filename);
687 break;
688 case PWMD_PINENTRY_SAVE_CONFIRM:
689 fprintf (stderr, N_("Confirm password: "));
690 break;
691 default:
692 break;
695 if ((p = fgets (buf, sizeof (buf), stdin)) == NULL)
697 if (!echo)
698 tcsetattr (STDIN_FILENO, TCSANOW, &told);
699 return 0;
702 if (!echo)
703 tcsetattr (STDIN_FILENO, TCSANOW, &told);
705 if (feof (stdin))
707 clearerr (stdin);
708 return GPG_ERR_CANCELED;
711 /* Strip the newline character. */
712 p[strlen (p) - 1] = 0;
714 if (buf[0])
716 key = pwmd_strdup_printf ("%s", p);
717 memset (buf, 0, sizeof (buf));
718 if (!key)
719 return GPG_ERR_ENOMEM;
721 if (result)
722 *result = key;
724 if (len)
725 *len = strlen (key);
727 else
729 if (result)
730 *result = pwmd_strdup ("");
732 if (len)
733 *len = 1;
736 return 0;
739 gpg_error_t
740 pwmd_password (pwm_t * pwm, const char *keyword, char **data, size_t * size)
742 gpg_error_t rc;
743 int new_password = 0;
744 char *password = NULL, *newpass = NULL;
745 int error = 0;
747 if (data)
748 *data = NULL;
750 if (size)
751 *size = 0;
753 if (!strcmp (keyword, "NEW_PASSPHRASE"))
754 new_password = 1;
756 if (!new_password && pwm->pinentry_try)
757 error = 1;
759 again:
760 if (pwm->disable_pinentry)
762 rc = get_password (pwm, &password, size,
763 new_password ? PWMD_PINENTRY_SAVE :
764 error ? PWMD_PINENTRY_OPEN_FAILED :
765 PWMD_PINENTRY_OPEN, 0);
766 if (!rc && new_password)
767 rc = get_password (pwm, &newpass, size, PWMD_PINENTRY_SAVE_CONFIRM,
770 else
772 pwmd_pinentry_t which;
774 if (error)
775 which = new_password
776 ? PWMD_PINENTRY_SAVE_FAILED : PWMD_PINENTRY_OPEN_FAILED;
777 else
778 which = new_password ? PWMD_PINENTRY_SAVE : PWMD_PINENTRY_OPEN;
780 rc = pwmd_getpin (pwm, pwm->filename, &password, size, which);
781 if (!rc && new_password)
782 rc = pwmd_getpin (pwm, pwm->filename, &newpass, size,
783 PWMD_PINENTRY_SAVE_CONFIRM);
786 if (!rc && new_password)
788 if ((!password && newpass) || (!newpass && password)
789 || (newpass && password && strcmp (newpass, password)))
791 if (pwm->disable_pinentry)
792 fprintf (stderr, N_("Passphrases do not match.\n"));
794 pwmd_free (password);
795 pwmd_free (newpass);
796 password = newpass = NULL;
797 error = 1;
798 goto again;
802 (void) pwmd_getpin (pwm, pwm->filename, NULL, NULL, PWMD_PINENTRY_CLOSE);
803 pwmd_free (newpass);
804 if (!rc && data)
805 *data = password;
807 return rc;
810 static gpg_error_t
811 inquire_cb (void *data, const char *keyword)
813 pwm_t *pwm = (pwm_t *) data;
814 gpg_error_t rc = 0;
815 int free_result = 0;
816 char *result = NULL;
817 int is_password = 0;
818 int new_password = 0;
820 if (!strcmp (keyword, "PASSPHRASE"))
821 is_password = 1;
822 else if (!strcmp (keyword, "NEW_PASSPHRASE") || !strcmp (keyword, "GENKEY"))
823 new_password = 1;
825 /* Shouldn't get this far without a callback. */
826 if (!pwm->override_inquire && !pwm->inquire_func
827 && !is_password && !new_password)
828 return gpg_error (GPG_ERR_ASS_NO_INQUIRE_CB);
830 for (;;)
832 size_t len = 0;
833 gpg_error_t arc;
835 result = NULL;
837 if (!pwm->override_inquire && (is_password || new_password))
839 free_result = 1;
840 rc = pwmd_password (data, keyword, &result, &len);
841 if (!rc)
842 rc = GPG_ERR_EOF;
844 else
845 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc, &result,
846 &len);
848 /* gpg will truncate a passphrase at the first nil byte which may be bad
849 * for generated key files. */
850 if ((!rc || gpg_err_code (rc) == GPG_ERR_EOF)
851 && (is_password || new_password))
853 if (len && result && *result)
855 for (size_t n = 0; n < len; n++)
857 if (result[n] == 0 && n+1 != len)
858 rc = GPG_ERR_INV_PASSPHRASE;
863 cancel:
864 if (rc && gpg_err_code (rc) != GPG_ERR_EOF)
866 #ifndef LIBASSUAN_2_1_0
867 gpg_error_t trc = rc;
869 /* Cancel this inquire. */
870 rc = assuan_send_data (pwm->ctx, NULL, 1);
871 if (!rc)
873 char *line;
874 size_t len;
876 /* There is a bug (or feature?) in assuan_send_data() that
877 * when cancelling an inquire the next read from the server is
878 * not done until the next command making the next command
879 * fail with GPG_ERR_ASS_UNEXPECTED_CMD.
881 rc = assuan_read_line (pwm->ctx, &line, &len);
883 /* Restore the original error. This differs from the error
884 * returned from the pwmd command (GPG_ERR_CANCELED). This
885 * error is returned to the calling function.
887 if (!rc)
888 rc = trc;
890 #endif
891 break;
894 if (gpg_err_code (rc) == GPG_ERR_EOF || !rc)
896 if (len <= 0 && !result)
898 rc = 0;
899 break;
901 else if ((len <= 0 && result) || (len && !result))
903 rc = gpg_error (GPG_ERR_INV_ARG);
904 break;
907 if (pwm->inquire_maxlen
908 && pwm->inquire_sent + len > pwm->inquire_maxlen)
910 rc = gpg_error (GPG_ERR_TOO_LARGE);
911 if (!free_result)
912 rc = pwm->inquire_func (pwm->inquire_data, keyword, rc,
913 &result, &len);
914 goto cancel;
917 arc = assuan_send_data (pwm->ctx, result, len);
918 if (gpg_err_code (rc) == GPG_ERR_EOF)
920 rc = arc;
921 break;
924 rc = arc;
926 else if (rc)
927 break;
929 if (!rc)
931 pwm->inquire_sent += len;
933 if (pwm->status_func)
935 char buf[ASSUAN_LINELENGTH];
937 snprintf (buf, sizeof (buf), "XFER %zu %zu", pwm->inquire_sent,
938 pwm->inquire_total);
939 rc = pwm->status_func (pwm->status_data, buf);
940 if (rc)
941 continue;
946 if (free_result)
947 pwmd_free (result);
949 return rc;
952 static gpg_error_t
953 parse_assuan_line (pwm_t * pwm)
955 gpg_error_t rc;
956 char *line;
957 size_t len;
959 rc = assuan_read_line (pwm->ctx, &line, &len);
960 if (!rc)
962 if (line[0] == 'O' && line[1] == 'K' &&
963 (line[2] == 0 || line[2] == ' '))
966 else if (line[0] == '#')
969 else if (line[0] == 'S' && (line[1] == 0 || line[1] == ' '))
971 if (pwm->status_func)
973 rc = pwm->status_func (pwm->status_data,
974 line[1] == 0 ? line + 1 : line + 2);
977 else if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' &&
978 (line[3] == 0 || line[3] == ' '))
980 line += 4;
981 rc = strtol (line, NULL, 10);
985 return rc;
988 static void
989 reset_handle (pwm_t *pwm)
991 pwm->fd = -1;
992 pwm->cancel = 0;
993 pwm->pinentry_disabled = 0;
994 #ifdef WITH_PINENTRY
995 if (pwm->pctx)
996 _pinentry_disconnect (pwm);
997 #endif
998 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
999 #ifdef WITH_GNUTLS
1000 pwm->tls_error = 0;
1001 #endif
1003 if (pwm->tcp)
1004 pwm->tcp->rc = 0;
1005 #endif
1008 gpg_error_t
1009 pwmd_disconnect (pwm_t * pwm)
1011 if (!pwm)
1012 return FINISH (GPG_ERR_INV_ARG);
1014 if (pwm->fd == -1)
1015 return FINISH (GPG_ERR_INV_STATE);
1017 disconnect (pwm);
1018 reset_handle (pwm);
1019 return 0;
1022 /* Note that this should only be called when not in a command. */
1023 gpg_error_t
1024 pwmd_process (pwm_t * pwm)
1026 gpg_error_t rc = 0;
1027 fd_set fds;
1028 struct timeval tv = { 0, 0 };
1029 int n;
1031 if (!pwm || pwm->fd == -1)
1032 return FINISH (GPG_ERR_INV_ARG);
1033 else if (!pwm->ctx)
1034 return FINISH (GPG_ERR_INV_STATE);
1036 FD_ZERO (&fds);
1037 FD_SET (pwm->fd, &fds);
1038 n = select (pwm->fd + 1, &fds, NULL, NULL, &tv);
1040 if (n == -1)
1041 return FINISH (gpg_error_from_syserror ());
1043 if (n > 0)
1045 if (FD_ISSET (pwm->fd, &fds))
1046 rc = parse_assuan_line (pwm);
1049 while (!rc && assuan_pending_line (pwm->ctx))
1050 rc = parse_assuan_line (pwm);
1052 #if defined (WITH_SSH) || defined (WITH_GNUTLS)
1053 if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp)
1055 close (pwm->fd);
1056 pwm->fd = -1;
1058 #endif
1060 return FINISH (rc);
1063 static gpg_error_t
1064 status_cb (void *data, const char *line)
1066 pwm_t *pwm = data;
1068 if (!strncmp (line, "INQUIRE_MAXLEN ", 15))
1069 pwm->inquire_maxlen = strtol (line + 15, NULL, 10);
1070 else if (!strncmp (line, "PASSPHRASE_HINT ", 16))
1072 pwmd_free (pwm->passphrase_hint);
1073 pwm->passphrase_hint = pwmd_strdup (line+16);
1075 else if (!strncmp (line, "PASSPHRASE_INFO ", 16))
1077 pwmd_free (pwm->passphrase_info);
1078 pwm->passphrase_info = pwmd_strdup (line+16);
1081 if (pwm->status_func)
1082 return pwm->status_func (pwm->status_data, line);
1084 return 0;
1087 gpg_error_t
1088 _assuan_command (pwm_t * pwm, assuan_context_t ctx,
1089 char **result, size_t * len, const char *cmd)
1091 membuf_t data;
1092 gpg_error_t rc;
1094 if (!cmd || !*cmd)
1095 return FINISH (GPG_ERR_INV_ARG);
1097 if (strlen (cmd) >= ASSUAN_LINELENGTH + 1)
1098 return FINISH (GPG_ERR_LINE_TOO_LONG);
1100 data.len = 0;
1101 data.buf = NULL;
1102 rc = assuan_transact (ctx, cmd, inquire_realloc_cb, &data,
1103 #ifdef WITH_QUALITY
1104 pwm->pctx == ctx ? pwm->_inquire_func : inquire_cb,
1105 pwm->pctx == ctx ? pwm->_inquire_data : pwm,
1106 #else
1107 inquire_cb, pwm,
1108 #endif
1109 status_cb, pwm);
1111 if (rc)
1113 if (data.buf)
1115 pwmd_free (data.buf);
1116 data.buf = NULL;
1119 else
1121 if (data.buf)
1123 inquire_realloc_cb (&data, "", 1);
1125 if (result)
1126 *result = (char *) data.buf;
1127 else
1128 pwmd_free (data.buf);
1130 if (len)
1131 *len = data.len;
1135 pwm->inquire_maxlen = 0;
1136 return rc;
1139 gpg_error_t
1140 pwmd_command_ap (pwm_t * pwm, char **result, size_t * rlen,
1141 pwmd_inquire_cb_t func, void *user, const char *cmd,
1142 va_list ap)
1144 char *buf;
1145 size_t len;
1146 va_list ap2;
1148 if (result)
1149 *result = NULL;
1151 if (rlen)
1152 *rlen = 0;
1154 if (!pwm || !cmd)
1155 return FINISH (GPG_ERR_INV_ARG);
1156 if (!pwm->ctx)
1157 return FINISH (GPG_ERR_INV_STATE);
1160 * C99 allows the dst pointer to be null which will calculate the length
1161 * of the would-be result and return it.
1163 va_copy (ap2, ap);
1164 len = vsnprintf (NULL, 0, cmd, ap) + 1;
1165 buf = (char *) pwmd_malloc (len);
1166 if (!buf)
1168 va_end (ap2);
1169 return FINISH (GPG_ERR_ENOMEM);
1172 len = vsnprintf (buf, len, cmd, ap2);
1173 va_end (ap2);
1175 if (buf[strlen (buf) - 1] == '\n')
1176 buf[strlen (buf) - 1] = 0;
1177 if (buf[strlen (buf) - 1] == '\r')
1178 buf[strlen (buf) - 1] = 0;
1180 pwm->inquire_func = func;
1181 pwm->inquire_data = user;
1182 pwm->inquire_sent = 0;
1183 gpg_error_t rc = _assuan_command (pwm, pwm->ctx, result, rlen, buf);
1184 pwmd_free (buf);
1185 return rc;
1188 gpg_error_t
1189 pwmd_command (pwm_t * pwm, char **result, size_t * len,
1190 pwmd_inquire_cb_t func, void *user, const char *cmd, ...)
1192 va_list ap;
1194 if (result)
1195 *result = NULL;
1197 if (len)
1198 *len = 0;
1200 if (!pwm || !cmd)
1201 return FINISH (GPG_ERR_INV_ARG);
1202 if (!pwm->ctx)
1203 return FINISH (GPG_ERR_INV_STATE);
1205 va_start (ap, cmd);
1206 gpg_error_t rc = pwmd_command_ap (pwm, result, len, func, user, cmd, ap);
1207 va_end (ap);
1208 return rc;
1211 static gpg_error_t
1212 send_pinentry_timeout (pwm_t *pwm)
1214 gpg_error_t rc = 0;
1216 if ((pwm->pinentry_timeout >= 0
1217 && pwm->pinentry_timeout != pwm->current_pinentry_timeout)
1218 || (pwm->pinentry_timeout == -1
1219 && pwm->pinentry_timeout != pwm->current_pinentry_timeout))
1221 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1222 "OPTION pinentry-timeout=%i",
1223 pwm->pinentry_timeout);
1224 if (!rc)
1225 pwm->current_pinentry_timeout = pwm->pinentry_timeout;
1228 return rc;
1231 static gpg_error_t
1232 send_pinentry_options (pwm_t * pwm)
1234 gpg_error_t rc;
1236 // Pwmd >= 3.1 uses gpgme to do the pinentry settings.
1237 if (pwm->version && pwm->version >= 0x030100)
1238 return 0;
1240 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL,
1241 "OPTION disable-pinentry=0");
1242 if (!rc && pwm->pinentry_tty)
1243 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYNAME=%s",
1244 pwm->pinentry_tty);
1246 if (!rc && pwm->pinentry_term)
1247 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION TTYTYPE=%s",
1248 pwm->pinentry_term);
1250 if (!rc && pwm->pinentry_display)
1251 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DISPLAY=%s",
1252 pwm->pinentry_display);
1254 if (!rc && pwm->pinentry_desc)
1255 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION DESC=%s",
1256 pwm->pinentry_desc);
1258 if (!rc && pwm->pinentry_lcctype)
1259 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_CTYPE=%s",
1260 pwm->pinentry_lcctype);
1262 if (!rc && pwm->pinentry_lcmessages)
1263 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION LC_MESSAGES=%s",
1264 pwm->pinentry_lcmessages);
1266 if (!rc)
1267 rc = send_pinentry_timeout (pwm);
1269 return rc;
1272 gpg_error_t
1273 pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result)
1275 if (!pwm || !result)
1276 return FINISH (GPG_ERR_INV_ARG);
1278 *result = PWMD_SOCKET_LOCAL;
1280 if (pwm->fd == -1)
1281 return FINISH (GPG_ERR_INV_STATE);
1283 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1284 #ifdef WITH_SSH
1285 if (pwm->tcp && pwm->tcp->ssh)
1286 *result = PWMD_SOCKET_SSH;
1287 #endif
1288 #ifdef WITH_GNUTLS
1289 if (pwm->tcp && pwm->tcp->tls)
1290 *result = PWMD_SOCKET_TLS;
1291 #endif
1292 #endif
1293 return 0;
1296 static gpg_error_t
1297 disable_pinentry (pwm_t *pwm, int *disable)
1299 gpg_error_t rc;
1300 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1301 int no_pinentry = pwm->disable_pinentry || pwm->tcp || pwm->local_pinentry;
1302 #else
1303 int no_pinentry = pwm->disable_pinentry || pwm->local_pinentry;
1304 #endif
1306 if (disable)
1307 *disable = no_pinentry;
1309 if (pwm->pinentry_disabled && no_pinentry)
1310 return 0;
1311 else if (!pwm->pinentry_disabled && !no_pinentry)
1312 return 0;
1314 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION disable-pinentry=%i",
1315 no_pinentry);
1316 if (!rc)
1317 pwm->pinentry_disabled = no_pinentry;
1319 return rc;
1322 gpg_error_t
1323 pwmd_open (pwm_t * pwm, const char *filename, pwmd_inquire_cb_t cb,
1324 void *data)
1326 gpg_error_t rc = 0;
1327 int no_pinentry = 0;
1329 if (!pwm || !filename || !*filename)
1330 return FINISH (GPG_ERR_INV_ARG);
1332 if (!pwm->ctx)
1333 return FINISH (GPG_ERR_INV_STATE);
1335 rc = disable_pinentry (pwm, &no_pinentry);
1336 if (!rc && !no_pinentry)
1337 rc = send_pinentry_options (pwm);
1339 if (!rc)
1341 pwm->pinentry_try = 0;
1342 pwmd_free (pwm->filename);
1343 pwm->filename = pwmd_strdup (filename);
1347 rc = pwmd_command (pwm, NULL, NULL, cb, data, "OPEN %s%s",
1348 (pwm->opts & OPT_LOCK_ON_OPEN) ? "--lock " : "",
1349 filename);
1351 while (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1352 && pwm->pinentry_disabled
1353 && ++pwm->pinentry_try < pwm->pinentry_tries);
1355 pwm->pinentry_try = 0;
1357 if (rc)
1359 pwmd_free (pwm->filename);
1360 pwm->filename = NULL;
1364 return FINISH (rc);
1367 static gpg_error_t
1368 do_pwmd_save_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb,
1369 void *data, int save)
1371 gpg_error_t rc = 0;
1373 if (!pwm)
1374 return FINISH (GPG_ERR_INV_ARG);
1375 if (!pwm->ctx)
1376 return FINISH (GPG_ERR_INV_STATE);
1378 rc = disable_pinentry (pwm, NULL);
1379 if (!rc)
1380 rc = pwmd_command (pwm, NULL, NULL, cb, data,
1381 save ? "SAVE %s" : "PASSWD %s", args ? args : "");
1383 return FINISH (rc);
1386 gpg_error_t
1387 pwmd_passwd (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1389 return do_pwmd_save_passwd (pwm, args, cb, data, 0);
1392 gpg_error_t
1393 pwmd_save (pwm_t * pwm, const char *args, pwmd_inquire_cb_t cb, void *data)
1395 return do_pwmd_save_passwd (pwm, args, cb, data, 1);
1398 static gpg_error_t
1399 pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap)
1401 int n, *intp;
1402 size_t *sizetp;
1403 char *arg1, **charpp;
1404 gpg_error_t rc = 0;
1406 if (!pwm)
1407 return GPG_ERR_INV_ARG;
1409 switch (opt)
1411 case PWMD_OPTION_SERVER_VERSION:
1412 if (!get)
1413 return GPG_ERR_NOT_SUPPORTED;
1415 if (!pwm)
1416 rc = GPG_ERR_INV_ARG;
1417 else if (!pwm->ctx)
1418 rc = GPG_ERR_INV_STATE;
1419 else
1421 unsigned *u = va_arg (ap, unsigned *);
1422 *u = pwm->version;
1425 break;
1426 case PWMD_OPTION_SIGPIPE:
1427 if (get)
1429 intp = va_arg (ap, int *);
1430 *intp = pwm->opts & OPT_SIGPIPE ? 1 : 0;
1431 break;
1434 n = va_arg (ap, int);
1435 if (n < 0 || n > 1)
1436 rc = GPG_ERR_INV_VALUE;
1438 if (n)
1439 pwm->opts |= OPT_SIGPIPE;
1440 else
1441 pwm->opts &= ~OPT_SIGPIPE;
1443 break;
1444 case PWMD_OPTION_LOCK_ON_OPEN:
1445 if (get)
1447 intp = va_arg (ap, int *);
1448 *intp = pwm->opts & OPT_LOCK_ON_OPEN ? 1 : 0;
1449 break;
1452 n = va_arg (ap, int);
1454 if (n < 0 || n > 1)
1455 rc = GPG_ERR_INV_VALUE;
1457 if (n)
1458 pwm->opts |= OPT_LOCK_ON_OPEN;
1459 else
1460 pwm->opts &= ~OPT_LOCK_ON_OPEN;
1462 break;
1463 case PWMD_OPTION_INQUIRE_TOTAL:
1464 if (get)
1466 sizetp = va_arg (ap, size_t *);
1467 *sizetp = pwm->inquire_total;
1468 break;
1471 pwm->inquire_total = va_arg (ap, size_t);
1472 break;
1473 case PWMD_OPTION_STATUS_CB:
1474 if (get)
1476 pwmd_status_cb_t *cb = va_arg (ap, pwmd_status_cb_t *);
1478 *cb = pwm->status_func;
1479 break;
1482 pwm->status_func = va_arg (ap, pwmd_status_cb_t);
1483 break;
1484 case PWMD_OPTION_STATUS_DATA:
1485 if (get)
1487 void **data = va_arg (ap, void **);
1489 *data = pwm->status_data;
1490 break;
1493 pwm->status_data = va_arg (ap, void *);
1494 break;
1495 case PWMD_OPTION_NO_PINENTRY:
1496 if (get)
1498 intp = va_arg (ap, int *);
1499 *intp = pwm->disable_pinentry;
1500 break;
1503 n = va_arg (ap, int);
1505 if (n < 0 || n > 1)
1506 rc = GPG_ERR_INV_VALUE;
1507 else
1508 pwm->disable_pinentry = n;
1509 break;
1510 case PWMD_OPTION_LOCAL_PINENTRY:
1511 if (get)
1513 intp = va_arg (ap, int *);
1514 *intp = pwm->local_pinentry;
1515 break;
1518 n = va_arg (ap, int);
1520 if (n < 0 || n > 1)
1521 rc = GPG_ERR_INV_VALUE;
1522 else
1523 pwm->local_pinentry = n;
1525 break;
1526 case PWMD_OPTION_PINENTRY_TIMEOUT:
1527 if (get)
1529 intp = va_arg (ap, int *);
1530 *intp = pwm->pinentry_timeout;
1531 break;
1534 n = va_arg (ap, int);
1536 if (n < 0)
1537 rc = GPG_ERR_INV_VALUE;
1538 else
1539 pwm->pinentry_timeout = n;
1540 break;
1541 case PWMD_OPTION_PINENTRY_TRIES:
1542 if (get)
1544 intp = va_arg (ap, int *);
1545 *intp = pwm->pinentry_tries;
1546 break;
1549 n = va_arg (ap, int);
1550 pwm->pinentry_tries = n;
1551 break;
1552 case PWMD_OPTION_PINENTRY_PATH:
1553 if (get)
1555 charpp = va_arg (ap, char **);
1556 *charpp = pwm->pinentry_path;
1557 break;
1560 arg1 = va_arg (ap, char *);
1561 pwmd_free (pwm->pinentry_path);
1562 pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL;
1563 break;
1564 case PWMD_OPTION_PINENTRY_TTY:
1565 if (get)
1567 charpp = va_arg (ap, char **);
1568 *charpp = pwm->pinentry_tty;
1569 break;
1572 arg1 = va_arg (ap, char *);
1573 pwmd_free (pwm->pinentry_tty);
1574 pwm->pinentry_tty = arg1 ? pwmd_strdup (arg1) : NULL;
1575 break;
1576 case PWMD_OPTION_PINENTRY_DISPLAY:
1577 if (get)
1579 charpp = va_arg (ap, char **);
1580 *charpp = pwm->pinentry_display;
1581 break;
1584 arg1 = va_arg (ap, char *);
1585 pwmd_free (pwm->pinentry_display);
1586 pwm->pinentry_display = arg1 ? pwmd_strdup (arg1) : NULL;
1587 break;
1588 case PWMD_OPTION_PINENTRY_TERM:
1589 if (get)
1591 charpp = va_arg (ap, char **);
1592 *charpp = pwm->pinentry_term;
1593 break;
1596 arg1 = va_arg (ap, char *);
1597 pwmd_free (pwm->pinentry_term);
1598 pwm->pinentry_term = arg1 ? pwmd_strdup (arg1) : NULL;
1599 break;
1600 case PWMD_OPTION_PINENTRY_ERROR:
1601 if (get)
1603 charpp = va_arg (ap, char **);
1604 *charpp = pwm->pinentry_error;
1605 break;
1608 arg1 = va_arg (ap, char *);
1609 pwmd_free (pwm->pinentry_error);
1610 pwm->pinentry_error = arg1 ? _percent_escape (arg1) : NULL;
1611 break;
1612 case PWMD_OPTION_PINENTRY_PROMPT:
1613 if (get)
1615 charpp = va_arg (ap, char **);
1616 *charpp = pwm->pinentry_prompt;
1617 break;
1620 arg1 = va_arg (ap, char *);
1621 pwmd_free (pwm->pinentry_prompt);
1622 pwm->pinentry_prompt = arg1 ? _percent_escape (arg1) : NULL;
1623 break;
1624 case PWMD_OPTION_PINENTRY_DESC:
1625 if (get)
1627 charpp = va_arg (ap, char **);
1628 *charpp = pwm->pinentry_desc;
1629 break;
1632 arg1 = va_arg (ap, char *);
1633 pwmd_free (pwm->pinentry_desc);
1634 pwm->pinentry_desc = arg1 ? _percent_escape (arg1) : NULL;
1635 break;
1636 case PWMD_OPTION_PINENTRY_LC_CTYPE:
1637 if (get)
1639 charpp = va_arg (ap, char **);
1640 *charpp = pwm->pinentry_lcctype;
1641 break;
1644 arg1 = va_arg (ap, char *);
1645 pwmd_free (pwm->pinentry_lcctype);
1646 pwm->pinentry_lcctype = arg1 ? pwmd_strdup (arg1) : NULL;
1647 break;
1648 case PWMD_OPTION_PINENTRY_LC_MESSAGES:
1649 if (get)
1651 charpp = va_arg (ap, char **);
1652 *charpp = pwm->pinentry_lcmessages;
1653 break;
1656 arg1 = va_arg (ap, char *);
1657 pwmd_free (pwm->pinentry_lcmessages);
1658 pwm->pinentry_lcmessages = arg1 ? pwmd_strdup (arg1) : NULL;
1659 break;
1660 case PWMD_OPTION_KNOWNHOST_CB:
1661 if (get)
1663 pwmd_knownhost_cb_t *cb = va_arg (ap, pwmd_knownhost_cb_t *);
1665 *cb = pwm->kh_cb;
1666 break;
1669 pwm->kh_cb = va_arg (ap, pwmd_knownhost_cb_t);
1670 break;
1671 case PWMD_OPTION_KNOWNHOST_DATA:
1672 if (get)
1674 void **data = va_arg (ap, void **);
1676 *data = pwm->kh_data;
1677 break;
1680 pwm->kh_data = va_arg (ap, void *);
1681 break;
1682 case PWMD_OPTION_SSH_AGENT:
1683 if (get)
1685 intp = va_arg (ap, int *);
1686 *intp = pwm->use_agent;
1687 break;
1690 pwm->use_agent = va_arg (ap, int);
1692 if (pwm->use_agent < 0 || pwm->use_agent > 1)
1694 pwm->use_agent = 0;
1695 rc = GPG_ERR_INV_VALUE;
1697 break;
1698 case PWMD_OPTION_TLS_VERIFY:
1699 if (get)
1701 intp = va_arg (ap, int *);
1702 *intp = pwm->tls_verify;
1703 break;
1706 pwm->tls_verify = va_arg (ap, int);
1708 if (pwm->tls_verify < 0 || pwm->tls_verify > 1)
1710 pwm->tls_verify = 0;
1711 rc = GPG_ERR_INV_VALUE;
1713 break;
1714 case PWMD_OPTION_SOCKET_TIMEOUT:
1715 if (get)
1717 intp = va_arg (ap, int *);
1718 *intp = pwm->socket_timeout;
1719 break;
1722 pwm->socket_timeout = va_arg (ap, int);
1723 if (pwm->socket_timeout < 0)
1725 pwm->socket_timeout = 0;
1726 rc = GPG_ERR_INV_VALUE;
1729 #ifdef WITH_SSH
1730 if (pwm->tcp && pwm->tcp->ssh && pwm->tcp->ssh->session)
1732 pwm->tcp->ssh->timeout = pwm->socket_timeout;
1733 libssh2_session_set_timeout (pwm->tcp->ssh->session,
1734 pwm->socket_timeout * 1000);
1736 #endif
1737 #ifdef WITH_GNUTLS
1738 if (pwm->tcp && pwm->tcp->tls && pwm->tcp->tls->session)
1739 pwm->tcp->tls->timeout = pwm->socket_timeout;
1740 #endif
1741 break;
1742 case PWMD_OPTION_OVERRIDE_INQUIRE:
1743 if (get)
1745 intp = va_arg (ap, int *);
1746 *intp = pwm->override_inquire;
1747 break;
1750 pwm->override_inquire = va_arg (ap, int);
1752 if (pwm->override_inquire < 0 || pwm->override_inquire > 1)
1754 pwm->override_inquire = 0;
1755 rc = GPG_ERR_INV_VALUE;
1757 break;
1758 default:
1759 rc = GPG_ERR_UNKNOWN_OPTION;
1760 break;
1763 return FINISH (rc);
1766 gpg_error_t
1767 pwmd_setopt (pwm_t * pwm, pwmd_option_t opt, ...)
1769 va_list ap;
1770 gpg_error_t rc = 0;
1772 va_start (ap, opt);
1773 rc = pwmd_get_set_opt (pwm, opt, 0, ap);
1774 va_end (ap);
1775 return FINISH (rc);
1778 gpg_error_t
1779 pwmd_getopt (pwm_t *pwm, pwmd_option_t opt, ...)
1781 va_list ap;
1782 gpg_error_t rc = 0;
1784 va_start (ap, opt);
1785 rc = pwmd_get_set_opt (pwm, opt, 1, ap);
1786 va_end (ap);
1787 return FINISH (rc);
1790 gpg_error_t
1791 pwmd_new (const char *name, pwm_t ** pwm)
1793 pwm_t *h = pwmd_calloc (1, sizeof (pwm_t));
1794 gpg_error_t rc;
1796 if (!h)
1797 return FINISH (GPG_ERR_ENOMEM);
1799 if (name)
1801 h->name = pwmd_strdup (name);
1802 if (!h->name)
1804 pwmd_free (h);
1805 return FINISH (GPG_ERR_ENOMEM);
1809 reset_handle (h);
1810 h->pinentry_timeout = -1;
1811 h->current_pinentry_timeout = -1;
1812 h->pinentry_tries = 3;
1813 #if defined(WITH_SSH) || defined(WITH_GNUTLS)
1814 h->prot = PWMD_IP_ANY;
1815 #endif
1817 if (ttyname (STDOUT_FILENO))
1819 char buf[256];
1821 ttyname_r (STDOUT_FILENO, buf, sizeof (buf));
1822 h->pinentry_tty = pwmd_strdup (buf);
1823 if (!h->pinentry_tty)
1825 rc = GPG_ERR_ENOMEM;
1826 goto fail;
1830 if (getenv ("TERM") && h->pinentry_tty)
1832 h->pinentry_term = pwmd_strdup (getenv ("TERM"));
1833 if (!h->pinentry_term)
1835 rc = GPG_ERR_ENOMEM;
1836 goto fail;
1840 if (getenv ("DISPLAY"))
1842 h->pinentry_display = pwmd_strdup (getenv ("DISPLAY"));
1843 if (!h->pinentry_display)
1845 rc = GPG_ERR_ENOMEM;
1846 goto fail;
1850 update_pinentry_settings (h);
1851 *pwm = h;
1852 return 0;
1854 fail:
1855 pwmd_close (h);
1856 return FINISH (rc);
1859 void
1860 pwmd_free (void *ptr)
1862 _xfree (ptr);
1865 void *
1866 pwmd_malloc (size_t size)
1868 return _xmalloc (size);
1871 void *
1872 pwmd_calloc (size_t nmemb, size_t size)
1874 return _xcalloc (nmemb, size);
1877 void *
1878 pwmd_realloc (void *ptr, size_t size)
1880 return _xrealloc (ptr, size);
1883 char *
1884 pwmd_strdup (const char *str)
1886 char *t;
1887 size_t len;
1888 register size_t c;
1890 len = strlen (str);
1891 t = _xmalloc ((len + 1) * sizeof (char));
1892 if (!t)
1893 return NULL;
1895 for (c = 0; c < len; c++)
1896 t[c] = str[c];
1898 t[c] = 0;
1899 return t;
1902 char *
1903 pwmd_strdup_printf (const char *fmt, ...)
1905 va_list ap, ap2;
1906 int len;
1907 char *buf;
1909 if (!fmt)
1910 return NULL;
1912 va_start (ap, fmt);
1913 va_copy (ap2, ap);
1914 len = vsnprintf (NULL, 0, fmt, ap);
1915 va_end (ap);
1916 buf = pwmd_malloc (++len);
1917 if (buf)
1918 vsnprintf (buf, len, fmt, ap2);
1920 va_end (ap2);
1921 return buf;
1924 gpg_error_t
1925 pwmd_getpin (pwm_t * pwm, const char *filename, char **result,
1926 size_t * len, pwmd_pinentry_t which)
1928 #ifndef WITH_PINENTRY
1929 return FINISH (GPG_ERR_NOT_IMPLEMENTED);
1930 #else
1931 gpg_error_t rc = _pwmd_getpin (pwm, filename, result, len, which);
1933 return FINISH (rc);
1934 #endif
1937 const char *
1938 pwmd_version ()
1940 return LIBPWMD_VERSION_STR;
1943 unsigned int
1944 pwmd_features ()
1946 unsigned int n = 0;
1948 #ifdef WITH_PINENTRY
1949 n |= PWMD_FEATURE_PINENTRY;
1950 #endif
1951 #ifdef WITH_SSH
1952 n |= PWMD_FEATURE_SSH;
1953 #endif
1954 #ifdef WITH_QUALITY
1955 n |= PWMD_FEATURE_CRACK;
1956 #endif
1957 #ifdef WITH_GNUTLS
1958 n |= PWMD_FEATURE_GNUTLS;
1959 #endif
1960 return n;
1963 gpg_error_t
1964 pwmd_fd (pwm_t * pwm, int *fd)
1966 if (!pwm || !fd)
1967 return FINISH (GPG_ERR_INV_ARG);
1969 if (pwm->fd == -1)
1970 return FINISH (GPG_ERR_INV_STATE);
1972 *fd = pwm->fd;
1973 return 0;
1976 void
1977 pwmd_set_pointer (pwm_t *pwm, void *data)
1979 pwm->user_data = data;
1982 void *
1983 pwmd_get_pointer (pwm_t *pwm)
1985 return pwm->user_data;
1989 pwmd_tls_error (pwm_t *pwm)
1991 #ifndef WITH_GNUTLS
1992 return 0;
1993 #else
1994 return pwm ? pwm->tls_error : 0;
1995 #endif
1998 gpg_error_t
1999 pwmd_cancel (pwm_t *pwm)
2001 if (!pwm)
2002 return FINISH (GPG_ERR_INV_ARG);
2004 if (pwm->fd == -1)
2005 return FINISH (GPG_ERR_INV_STATE);
2007 pwm->cancel = 1;
2008 return 0;