2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
26 #include <sys/types.h>
30 #include "pwmd-error.h"
36 #include "util-misc.h"
39 #include "util-string.h"
45 static gpg_error_t
set_pinentry_strings (struct pinentry_s
*pin
, int which
);
48 mem_realloc_cb (void *data
, const void *buffer
, size_t len
)
50 membuf_t
*mem
= (membuf_t
*) data
;
56 p
= xrealloc (mem
->buf
, mem
->len
+ len
);
61 memcpy ((char *) mem
->buf
+ mem
->len
, buffer
, len
);
68 quality_cb (void *data
, const char *line
)
70 struct pinentry_s
*pin
= data
;
75 if (strncmp (line
, "QUALITY ", 8) != 0)
76 return GPG_ERR_INV_ARG
;
78 tmp
= FascistCheck (line
+ 8, CRACKLIB_DICT
);
80 return assuan_send_data (pin
->ctx
, "100", 3);
82 if (!strcmp (tmp
, _("it's WAY too short")))
84 else if (!strcmp (tmp
, _("it is too short")))
86 else if (!strcmp (tmp
, _("it is all whitespace")))
88 else if (!strcmp (tmp
, _("it is based on your username")))
90 else if (!strcmp (tmp
, _("it is based on a dictionary word")))
92 else if (!strcmp (tmp
, _("it is based upon your password entry")))
94 else if (!strcmp (tmp
, _("it's derived from your password entry")))
96 else if (!strcmp (tmp
, _("it is based on a (reversed) dictionary word")))
98 else if (!strcmp (tmp
, _("it is derivable from your password entry")))
102 (tmp
, _("it does not contain enough DIFFERENT characters")))
104 else if (!strcmp (tmp
, _("it is too simplistic/systematic")))
109 snprintf (buf
, sizeof (buf
), "%i", score
);
111 return assuan_send_data (pin
->ctx
, tmp
, strlen (tmp
));
116 assuan_command (struct pinentry_s
*pin
, char **result
, const char *cmd
)
121 pin
->data
.buf
= NULL
;
123 rc
= assuan_transact (pin
->ctx
, cmd
, mem_realloc_cb
, &pin
->data
,
124 pin
->inquire_cb
, pin
->inquire_data
, NULL
, NULL
);
129 xfree (pin
->data
.buf
);
130 pin
->data
.buf
= NULL
;
137 mem_realloc_cb (&pin
->data
, "", 1);
138 *result
= (char *) pin
->data
.buf
;
146 set_pinentry_options (struct pinentry_s
*pin
)
148 char *display
= getenv ("DISPLAY");
149 int have_display
= 0;
150 char *tty
= NULL
, *ttytype
= NULL
;
154 char cmd
[ASSUAN_LINELENGTH
];
156 if (pin
->display
|| display
)
160 tty
= pin
->ttyname
? pin
->ttyname
: ttyname (STDOUT_FILENO
);
162 return gpg_error_from_syserror ();
165 if (!have_display
&& !tty
)
166 return GPG_ERR_CANCELED
;
170 char *p
= getenv ("TERM");
172 ttytype
= pin
->ttytype
? pin
->ttytype
: p
;
174 return GPG_ERR_ENOTTY
;
177 opt
= have_display
? str_dup ("DISPLAY") : str_dup ("TTYNAME");
178 val
= have_display
? pin
->display
? pin
->display
: display
: tty
;
179 snprintf (cmd
, sizeof (cmd
), "OPTION %s=%s", str_down (opt
), val
);
181 rc
= assuan_command (pin
, &result
, cmd
);
187 snprintf (cmd
, sizeof (cmd
), "OPTION ttytype=%s", ttytype
);
188 rc
= assuan_command (pin
, &result
, cmd
);
195 launch_pinentry (struct pinentry_s
*pin
)
198 assuan_context_t ctx
;
199 static struct assuan_malloc_hooks mhooks
= { xmalloc
, xrealloc
, xfree
};
200 int child_list
[] = { -1 };
202 const char **p
= argv
;
221 *p
++ = "--lc-messages";
222 *p
++ = pin
->lcmessages
;
226 rc
= assuan_new_ext (&ctx
, GPG_ERR_SOURCE_DEFAULT
, &mhooks
, NULL
, NULL
);
230 tmp
= config_get_string ("global", "pinentry_path");
231 rc
= assuan_pipe_connect (ctx
, pin
->path
? pin
->path
: tmp
, argv
,
232 child_list
, NULL
, NULL
, 0);
238 rc
= set_pinentry_options (pin
);
239 return rc
? rc
: set_pinentry_strings (pin
, pin
->which
);
243 pinentry_command (struct pinentry_s
*pin
, char **result
, const char *cmd
)
248 rc
= launch_pinentry (pin
);
250 return rc
? rc
: assuan_command (pin
, result
, cmd
);
254 set_pinentry_strings (struct pinentry_s
*pin
, int which
)
260 /* The initial prompt from launch_pinentry(). */
264 if (which
== PINENTRY_SAVE
)
266 rc
= pinentry_command (pin
, NULL
, "SETQUALITYBAR");
270 pin
->inquire_cb
= quality_cb
;
271 pin
->inquire_data
= pin
;
275 if (which
== PINENTRY_FAIL_CONFIRM
)
277 title
= str_dup (_("Passphrase mismatch, please try again."));
278 which
= PINENTRY_SAVE
;
280 else if (!pin
->title
)
281 title
= str_asprintf (_("Password Manager Daemon%s%s"),
282 pin
->name
? ": " : "",
283 pin
->name
? pin
->name
: "");
285 title
= str_dup (pin
->title
);
288 pin
->prompt
= str_dup (_("Passphrase:"));
291 pin
->desc
= str_asprintf (which
== PINENTRY_OPEN
?
292 _("A passphrase is required to open the file "
293 "\"%s\". Please enter the passphrase below.")
295 _("A passphrase is required to save to the file "
296 "\"%s\". Please enter the passphrase below."),
299 if (which
== PINENTRY_SAVE_CONFIRM
)
300 buf
= str_asprintf ("SETDESC %s",
301 _("Please enter the passphrase again for confirmation."));
303 buf
= str_asprintf ("SETDESC %s", pin
->desc
);
305 rc
= pinentry_command (pin
, NULL
, buf
);
310 buf
= str_asprintf ("SETPROMPT %s", pin
->prompt
);
311 rc
= pinentry_command (pin
, NULL
, buf
);
316 buf
= str_asprintf ("SETERROR %s", title
);
317 rc
= pinentry_command (pin
, NULL
, buf
);
326 pinentry_disconnect (struct pinentry_s
*pin
)
332 assuan_release (pin
->ctx
);
338 do_getpin (struct pinentry_s
*pin
, char **result
)
343 rc
= pinentry_command (pin
, result
, "GETPIN");
348 *result
= str_dup ("");
354 pinentry_getpin (struct pinentry_s
* pin
, char **result
, pinentry_cmd_t which
)
356 gpg_error_t rc
= set_pinentry_strings (pin
, which
);
357 char *result1
= NULL
;
363 rc
= do_getpin (pin
, result
);
367 if (which
== PINENTRY_SAVE
)
371 rc
= set_pinentry_strings (pin
, PINENTRY_SAVE_CONFIRM
);
375 result1
= str_dup (*result
);
379 if (strcmp (result1
, *result
))
383 result1
= *result
= NULL
;
384 rc
= set_pinentry_strings (pin
, PINENTRY_FAIL_CONFIRM
);
394 pinentry_disconnect (pin
);
399 lock_pin_mutex (struct client_s
* client
)
403 MUTEX_TRYLOCK (client
->ctx
, &pin_mutex
, rc
, client
->pinentry
->timeout
*10);
406 client
->pinentry
->has_lock
= 1;
412 unlock_pin_mutex (struct pinentry_s
*pin
)
414 if (pin
->has_lock
== 0)
417 MUTEX_UNLOCK (&pin_mutex
);
422 pinentry_deinit (struct pinentry_s
*pin
)
428 pinentry_disconnect (pin
);
434 xfree (pin
->ttyname
);
437 xfree (pin
->ttytype
);
452 xfree (pin
->display
);
455 xfree (pin
->filename
);
458 xfree (pin
->lcctype
);
461 xfree (pin
->lcmessages
);
467 reset_pin_defaults (struct pinentry_s
*pin
)
470 pin
->timeout
= config_get_integer (pin
->filename
, "pinentry_timeout");
474 set_pinentry_defaults (struct pinentry_s
*pin
)
480 snprintf (buf
, sizeof (buf
), "%s/.pwmd/pinentry.conf", get_home_dir ());
481 fp
= fopen (buf
, "r");
485 while ((p
= fgets (buf
, sizeof (buf
), fp
)) != NULL
)
487 char name
[32] = { 0 }, value
[256] = { 0 };
492 if (p
[strlen (p
) - 1] == '\n')
493 p
[strlen (p
) - 1] = 0;
495 if (sscanf (p
, " %31[a-zA-Z] = %255s", name
, value
) != 2)
498 if (strcasecmp ("TTYNAME", name
) == 0)
501 xfree (pin
->ttyname
);
503 pin
->ttyname
= str_dup (value
);
505 else if (strcasecmp ("TTYTYPE", name
) == 0)
508 xfree (pin
->ttytype
);
510 pin
->ttytype
= str_dup (value
);
512 else if (strcasecmp ("DISPLAY", name
) == 0)
515 xfree (pin
->display
);
517 pin
->display
= str_dup (value
);
519 else if (strcasecmp ("PATH", name
) == 0)
524 pin
->path
= str_dup (value
);
526 else if (strcasecmp ("LC_TYPE", name
) == 0)
529 xfree (pin
->lcctype
);
531 pin
->lcctype
= str_dup (value
);
533 else if (strcasecmp ("LC_MESSAGES", name
) == 0)
536 xfree (pin
->lcmessages
);
538 pin
->lcmessages
= str_dup (value
);
545 reset_pin_defaults (pin
);
549 pinentry_init (const char *filename
)
551 struct pinentry_s
*pin
= xcalloc (1, sizeof (struct pinentry_s
));
556 pin
->filename
= str_dup (filename
);
563 set_pinentry_defaults (pin
);