1
/* findkey.c - locate the secret key
2
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
1
/* findkey.c - Locate the secret key
2
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
3
* 2007 Free Software Foundation, Inc.
4
5
* This file is part of GnuPG.
6
7
* GnuPG is free software; you can redistribute it and/or modify
7
8
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* the Free Software Foundation; either version 3 of the License, or
9
10
* (at your option) any later version.
11
12
* GnuPG is distributed in the hope that it will be useful,
14
15
* GNU General Public License for more details.
16
17
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
* along with this program; if not, see <http://www.gnu.org/licenses/>.
21
21
#include <config.h>
29
29
#include <unistd.h>
30
30
#include <sys/stat.h>
31
31
#include <assert.h>
32
#include <pth.h> /* (we use pth_sleep) */
35
41
/* Helper to pass data to the check callback of the unprotect function. */
36
struct try_unprotect_arg_s {
42
struct try_unprotect_arg_s
37
45
const unsigned char *protected_key;
38
46
unsigned char *unprotected_key;
47
int change_required; /* Set by the callback to indicate that the
48
user should chnage the passphrase. */
42
52
/* Write an S-expression formatted key to our key storage. With FORCE
43
pased as true an existsing key with the given GRIP will get
53
pased as true an existing key with the given GRIP will get
46
56
agent_write_private_key (const unsigned char *grip,
70
80
POSIX (GNU provides the "x" opentype for fopen, however, this is
71
81
not portable). Thus, we use the more flexible open function and
72
82
then use fdopen to obtain a stream. */
73
fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY)
74
: (O_CREAT | O_EXCL | O_WRONLY),
83
fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY | O_BINARY)
84
: (O_CREAT | O_EXCL | O_WRONLY | O_BINARY),
76
86
#ifndef HAVE_W32_SYSTEM
129
139
struct try_unprotect_arg_s *arg = pi->check_cb_arg;
142
gnupg_isotime_t now, protected_at, tmptime;
132
145
assert (!arg->unprotected_key);
133
return agent_unprotect (arg->protected_key, pi->pin,
134
&arg->unprotected_key, &dummy);
147
arg->change_required = 0;
148
err = agent_unprotect (arg->protected_key, pi->pin, protected_at,
149
&arg->unprotected_key, &dummy);
152
if (!opt.max_passphrase_days || arg->ctrl->in_passwd)
153
return 0; /* No regular passphrase change required. */
157
/* No protection date known - must force passphrase change. */
158
desc = xtrystrdup (_("Note: This passphrase has never been changed.%0A"
159
"Please change it now."));
161
return gpg_error_from_syserror ();
165
gnupg_get_isotime (now);
166
gnupg_copy_time (tmptime, protected_at);
167
err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
170
if (strcmp (now, tmptime) > 0 )
172
/* Passphrase "expired". */
174
(_("This passphrase has not been changed%%0A"
175
"since %.4s-%.2s-%.2s. Please change it now."),
176
protected_at, protected_at+4, protected_at+6);
178
return gpg_error_from_syserror ();
184
/* Change required. */
185
if (opt.enforce_passphrase_constraints)
187
err = agent_get_confirmation (arg->ctrl, desc,
188
_("Change passphrase"), NULL);
190
arg->change_required = 1;
194
err = agent_get_confirmation (arg->ctrl, desc,
195
_("Change passphrase"),
196
_("I'll change it later"));
198
arg->change_required = 1;
199
else if (gpg_err_code (err) == GPG_ERR_CANCELED)
252
323
void *cache_marker;
255
327
pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
258
rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
330
rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
259
331
agent_unlock_cache_entry (&cache_marker);
341
/* If the pinentry is currently in use, we wait up to 60 seconds
342
for it to close and check the cache again. This solves a common
343
situation where several requests for unprotecting a key have
344
been made but the user is still entering the passphrase for
345
the first request. Because all requests to agent_askpin are
346
serialized they would then pop up one after the other to
347
request the passphrase - despite that the user has already
348
entered it and is then available in the cache. This
349
implementation is not race free but in the worst case the
350
user has to enter the passphrase only once more. */
351
if (pinentry_active_p (ctrl, 0))
354
if (!pinentry_active_p (ctrl, 60))
356
/* We need to give the other thread a chance to actually put
357
it into the cache. */
361
/* Timeout - better call pinentry now the plain way. */
270
365
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
272
return gpg_error_from_errno (errno);
367
return gpg_error_from_syserror ();
273
368
pi->max_length = 100;
274
369
pi->min_digits = 0; /* we want a real passphrase */
275
370
pi->max_digits = 8;
276
371
pi->max_tries = 3;
277
372
pi->check_cb = try_unprotect_cb;
278
374
arg.protected_key = *keybuf;
279
375
arg.unprotected_key = NULL;
376
arg.change_required = 0;
280
377
pi->check_cb_arg = &arg;
282
379
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
285
382
assert (arg.unprotected_key);
383
if (arg.change_required)
385
size_t canlen, erroff;
388
assert (arg.unprotected_key);
389
canlen = gcry_sexp_canon_len (arg.unprotected_key, 0, NULL, NULL);
390
rc = gcry_sexp_sscan (&s_skey, &erroff,
391
(char*)arg.unprotected_key, canlen);
394
log_error ("failed to build S-Exp (off=%u): %s\n",
395
(unsigned int)erroff, gpg_strerror (rc));
396
wipememory (arg.unprotected_key, canlen);
397
xfree (arg.unprotected_key);
401
rc = agent_protect_and_store (ctrl, s_skey);
402
gcry_sexp_release (s_skey);
405
log_error ("changing the passphrase failed: %s\n",
407
wipememory (arg.unprotected_key, canlen);
408
xfree (arg.unprotected_key);
286
413
agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
288
415
*keybuf = arg.unprotected_key;
336
463
buf = xtrymalloc (buflen+1);
337
464
if (!buf || fread (buf, buflen, 1, fp) != 1)
339
rc = gpg_error_from_errno (errno);
466
rc = gpg_error_from_syserror ();
340
467
log_error ("error reading `%s': %s\n", fname, strerror (errno));