~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to agent/findkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
3
4
 *
4
5
 * This file is part of GnuPG.
5
6
 *
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.
10
11
 *
11
12
 * GnuPG is distributed in the hope that it will be useful,
14
15
 * GNU General Public License for more details.
15
16
 *
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/>.
19
19
 */
20
20
 
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) */
32
33
 
33
34
#include "agent.h"
 
35
#include "i18n.h"
 
36
 
 
37
#ifndef O_BINARY
 
38
#define O_BINARY 0
 
39
#endif
34
40
 
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 
 
43
{
 
44
  ctrl_t ctrl;
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.  */
39
49
};
40
50
 
41
51
 
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
44
54
   overwritten.  */
45
55
int
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),
75
85
             S_IRUSR | S_IWUSR 
76
86
#ifndef HAVE_W32_SYSTEM
77
87
                 | S_IRGRP 
115
125
      xfree (fname);
116
126
      return tmperr;
117
127
    }
118
 
 
 
128
  bump_key_eventcounter ();
119
129
  xfree (fname);
120
130
  return 0;
121
131
}
128
138
{
129
139
  struct try_unprotect_arg_s *arg = pi->check_cb_arg;
130
140
  size_t dummy;
 
141
  gpg_error_t err;
 
142
  gnupg_isotime_t now, protected_at, tmptime;
 
143
  char *desc = NULL;
131
144
 
132
145
  assert (!arg->unprotected_key);
133
 
  return agent_unprotect (arg->protected_key, pi->pin,
134
 
                          &arg->unprotected_key, &dummy);
 
146
 
 
147
  arg->change_required = 0;
 
148
  err = agent_unprotect (arg->protected_key, pi->pin, protected_at,
 
149
                         &arg->unprotected_key, &dummy);
 
150
  if (err)
 
151
    return err;
 
152
  if (!opt.max_passphrase_days || arg->ctrl->in_passwd)
 
153
    return 0;  /* No regular passphrase change required.  */
 
154
 
 
155
  if (!*protected_at)
 
156
    {
 
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."));
 
160
      if (!desc)
 
161
        return gpg_error_from_syserror ();
 
162
    }
 
163
  else
 
164
    {
 
165
      gnupg_get_isotime (now);
 
166
      gnupg_copy_time (tmptime, protected_at);
 
167
      err = add_days_to_isotime (tmptime, opt.max_passphrase_days);
 
168
      if (err)
 
169
        return err;
 
170
      if (strcmp (now, tmptime) > 0 )
 
171
        {
 
172
          /* Passphrase "expired".  */
 
173
          desc = xtryasprintf 
 
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);
 
177
          if (!desc)
 
178
            return gpg_error_from_syserror ();
 
179
        }
 
180
    }
 
181
 
 
182
  if (desc)
 
183
    {
 
184
      /* Change required.  */
 
185
      if (opt.enforce_passphrase_constraints)
 
186
        {
 
187
          err = agent_get_confirmation (arg->ctrl, desc,
 
188
                                        _("Change passphrase"), NULL);
 
189
          if (!err)
 
190
            arg->change_required = 1;
 
191
        }
 
192
      else
 
193
        {
 
194
          err = agent_get_confirmation (arg->ctrl, desc,
 
195
                                        _("Change passphrase"),
 
196
                                        _("I'll change it later"));
 
197
          if (!err)
 
198
            arg->change_required = 1;
 
199
          else if (gpg_err_code (err) == GPG_ERR_CANCELED)
 
200
            err = 0;
 
201
        }
 
202
      xfree (desc);
 
203
    }
 
204
 
 
205
  return 0;
135
206
}
136
207
 
137
208
 
214
285
        {
215
286
          *result = out = xtrymalloc (out_len + 1);
216
287
          if (!out)
217
 
            return gpg_error_from_errno (errno);
 
288
            return gpg_error_from_syserror ();
218
289
        }
219
290
    }
220
291
 
252
323
      void *cache_marker;
253
324
      const char *pw;
254
325
      
 
326
    retry:
255
327
      pw = agent_get_cache (hexgrip, cache_mode, &cache_marker);
256
328
      if (pw)
257
329
        {
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);
260
332
          if (!rc)
261
333
            {
265
337
            }
266
338
          rc  = 0;
267
339
        }
 
340
 
 
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))
 
352
        {
 
353
          /* Active - wait */
 
354
          if (!pinentry_active_p (ctrl, 60))
 
355
            {
 
356
              /* We need to give the other thread a chance to actually put
 
357
                 it into the cache. */
 
358
              pth_sleep (1); 
 
359
              goto retry;
 
360
            }
 
361
          /* Timeout - better call pinentry now the plain way. */
 
362
        }
268
363
    }
269
 
  
 
364
 
270
365
  pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
271
366
  if (!pi)
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;
 
373
  arg.ctrl = ctrl;
278
374
  arg.protected_key = *keybuf;
279
375
  arg.unprotected_key = NULL;
 
376
  arg.change_required = 0;
280
377
  pi->check_cb_arg = &arg;
281
378
 
282
379
  rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
283
380
  if (!rc)
284
381
    {
285
382
      assert (arg.unprotected_key);
 
383
      if (arg.change_required)
 
384
        {
 
385
          size_t canlen, erroff;
 
386
          gcry_sexp_t s_skey;
 
387
          
 
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);
 
392
          if (rc)
 
393
            {
 
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);
 
398
              xfree (pi);
 
399
              return rc;
 
400
            }
 
401
          rc = agent_protect_and_store (ctrl, s_skey);
 
402
          gcry_sexp_release (s_skey);
 
403
          if (rc)
 
404
            {
 
405
              log_error ("changing the passphrase failed: %s\n", 
 
406
                         gpg_strerror (rc));
 
407
              wipememory (arg.unprotected_key, canlen);
 
408
              xfree (arg.unprotected_key);
 
409
              xfree (pi);
 
410
              return rc;
 
411
            }
 
412
        }
286
413
      agent_put_cache (hexgrip, cache_mode, pi->pin, 0);
287
414
      xfree (*keybuf);
288
415
      *keybuf = arg.unprotected_key;
317
444
  fp = fopen (fname, "rb");
318
445
  if (!fp)
319
446
    {
320
 
      rc = gpg_error_from_errno (errno);
 
447
      rc = gpg_error_from_syserror ();
321
448
      log_error ("can't open `%s': %s\n", fname, strerror (errno));
322
449
      xfree (fname);
323
450
      return rc;
325
452
  
326
453
  if (fstat (fileno(fp), &st))
327
454
    {
328
 
      rc = gpg_error_from_errno (errno);
 
455
      rc = gpg_error_from_syserror ();
329
456
      log_error ("can't stat `%s': %s\n", fname, strerror (errno));
330
457
      xfree (fname);
331
458
      fclose (fp);
336
463
  buf = xtrymalloc (buflen+1);
337
464
  if (!buf || fread (buf, buflen, 1, fp) != 1)
338
465
    {
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));
341
468
      xfree (fname);
342
469
      fclose (fp);
393
520
  buf = xtrymalloc (len);
394
521
  if (!buf)
395
522
    {
396
 
      rc = gpg_error_from_errno (errno);
 
523
      rc = gpg_error_from_syserror ();
397
524
      gcry_sexp_release (s_skey);
398
525
      return rc;
399
526
    }
434
561
                   shouldn't be a problem.  */
435
562
                char *tmp = xtrymalloc (comment_length+1);
436
563
                if (!tmp)
437
 
                  rc = gpg_error_from_errno (errno);
 
564
                  rc = gpg_error_from_syserror ();
438
565
                else
439
566
                  {
440
567
                    memcpy (tmp, comment, comment_length);
592
719
  array = xtrycalloc (strlen(elems) + 1, sizeof *array);
593
720
  if (!array)
594
721
    {
595
 
      rc = gpg_error_from_errno (errno);
 
722
      rc = gpg_error_from_syserror ();
596
723
      gcry_sexp_release (list);
597
724
      gcry_sexp_release (s_skey);
598
725
      return rc;
654
781
  format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
655
782
  if (!format)
656
783
    {
657
 
      rc = gpg_error_from_errno (errno);
 
784
      rc = gpg_error_from_syserror ();
658
785
      for (i=0; array[i]; i++)
659
786
        gcry_mpi_release (array[i]);
660
787
      xfree (array);