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

« back to all changes in this revision

Viewing changes to agent/protect-tool.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
1
/* protect-tool.c - A tool to test the secret key protection
2
 
 *      Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
 
2
 * Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3
3
 *
4
4
 * This file is part of GnuPG.
5
5
 *
6
6
 * GnuPG is free software; you can redistribute it and/or modify
7
7
 * 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
 
8
 * the Free Software Foundation; either version 3 of the License, or
9
9
 * (at your option) any later version.
10
10
 *
11
11
 * GnuPG is distributed in the hope that it will be useful,
14
14
 * GNU General Public License for more details.
15
15
 *
16
16
 * 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
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
18
 */
20
19
 
21
20
#include <config.h>
64
63
 
65
64
  oP12Import,
66
65
  oP12Export,
 
66
  oP12Charset,
67
67
  oStore,
68
68
  oForce,
69
69
  oHaveCert,
95
95
static const char *opt_passphrase;
96
96
static char *opt_prompt;
97
97
static int opt_status_msg;
 
98
static const char *opt_p12_charset;
98
99
 
99
 
static char *get_passphrase (int promptno);
 
100
static char *get_passphrase (int promptno, int opt_check);
100
101
static char *get_new_passphrase (int promptno);
101
102
static void release_passphrase (char *pw);
102
103
static int store_private_key (const unsigned char *grip,
117
118
  { oShowShadowInfo,  "show-shadow-info", 256, "return the shadow info"},
118
119
  { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
119
120
 
120
 
  { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"},
121
 
  { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"},
 
121
  { oP12Import, "p12-import", 256, "import a pkcs#12 encoded private key"},
 
122
  { oP12Export, "p12-export", 256, "export a private key pkcs#12 encoded"},
 
123
  { oP12Charset,"p12-charset", 2,
 
124
    "|NAME|set charset for a new PKCS#12 passphrase to NAME" },
122
125
  { oHaveCert, "have-cert", 0,  "certificate to export provided on STDIN"},
123
126
  { oStore,     "store", 0, "store the created key in the appropriate place"},
124
127
  { oForce,     "force", 0, "force overwriting"},
126
129
  { oHomedir, "homedir", 2, "@" }, 
127
130
  { oPrompt,  "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"}, 
128
131
  { oStatusMsg, "enable-status-msg", 0, "@"},
 
132
 
129
133
  {0}
130
134
};
131
135
 
144
148
    case 1:
145
149
    case 40: p =  _("Usage: gpg-protect-tool [options] (-h for help)\n");
146
150
      break;
147
 
    case 41: p =  _("Syntax: gpg-protect-tool [options] [args]]\n"
 
151
    case 41: p =  _("Syntax: gpg-protect-tool [options] [args]\n"
148
152
                    "Secret key maintenance tool\n");
149
153
    break;
150
154
    
154
158
}
155
159
 
156
160
 
157
 
 
158
 
static void
159
 
i18n_init (void)
160
 
{
161
 
#ifdef USE_SIMPLE_GETTEXT
162
 
    set_gettext_file( PACKAGE_GT );
163
 
#else
164
 
#ifdef ENABLE_NLS
165
 
    setlocale (LC_ALL, "");
166
 
    bindtextdomain (PACKAGE_GT, LOCALEDIR);
167
 
    textdomain (PACKAGE_GT);
168
 
#endif
169
 
#endif
170
 
}
171
 
 
172
 
 
173
 
 
174
 
/* Used by gcry for logging */
175
 
static void
176
 
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
177
 
{
178
 
  /* translate the log levels */
179
 
  switch (level)
180
 
    {
181
 
    case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
182
 
    case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
183
 
    case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
184
 
    case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
185
 
    case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
186
 
    case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
187
 
    case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
188
 
    default:            level = JNLIB_LOG_ERROR; break;      }
189
 
  log_logv (level, fmt, arg_ptr);
190
 
}
191
 
 
 
161
/* Include the implementation of map_spwq_error.  */
 
162
MAP_SPWQ_ERROR_IMPL
192
163
 
193
164
/*  static void */
194
165
/*  print_mpi (const char *text, gcry_mpi_t a) */
362
333
  if (!key)
363
334
    return;
364
335
 
365
 
  pw = get_passphrase (1);
 
336
  pw = get_passphrase (1, 0);
366
337
  rc = agent_protect (key, pw, &result, &resultlen);
367
338
  release_passphrase (pw);
368
339
  xfree (key);
395
366
  unsigned char *result;
396
367
  size_t resultlen;
397
368
  char *pw;
398
 
  
 
369
  gnupg_isotime_t protected_at;
 
370
 
399
371
  key = read_key (fname);
400
372
  if (!key)
401
373
    return;
402
374
 
403
 
  rc = agent_unprotect (key, (pw=get_passphrase (1)), &result, &resultlen);
 
375
  rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), 
 
376
                        protected_at, &result, &resultlen);
404
377
  release_passphrase (pw);
405
378
  xfree (key);
406
379
  if (rc)
410
383
      log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc));
411
384
      return;
412
385
    }
413
 
  
 
386
  if (opt.verbose)
 
387
    log_info ("key protection done at %.4s-%.2s-%.2s %.2s:%.2s:%s\n",
 
388
              protected_at, protected_at+4, protected_at+6,
 
389
              protected_at+9, protected_at+11, protected_at+13);
 
390
 
 
391
 
414
392
  if (opt_armor)
415
393
    {
416
394
      char *p = make_advanced (result, resultlen);
667
645
{
668
646
  char *buf;
669
647
  unsigned char *result;
670
 
  size_t buflen, resultlen;
 
648
  size_t buflen, resultlen, buf_off;
671
649
  int i;
672
650
  int rc;
673
651
  gcry_mpi_t *kparms;
683
661
  if (!buf)
684
662
    return;
685
663
 
686
 
  kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2)),
 
664
  /* GnuPG 2.0.4 accidently created binary P12 files with the string
 
665
     "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data.
 
666
     We fix that here.  */
 
667
  if (buflen > 29 && !memcmp (buf, "The passphrase is ", 18))
 
668
    {
 
669
      for (buf_off=18; buf_off < buflen && buf[buf_off] != '\n'; buf_off++)
 
670
        ;
 
671
      buf_off++;
 
672
      if (buf_off < buflen && buf[buf_off] == '\n')
 
673
        buf_off++;
 
674
    }
 
675
  else
 
676
    buf_off = 0;
 
677
 
 
678
  kparms = p12_parse ((unsigned char*)buf+buf_off, buflen-buf_off,
 
679
                      (pw=get_passphrase (2, 0)),
687
680
                      import_p12_cert_cb, NULL);
688
681
  release_passphrase (pw);
689
682
  xfree (buf);
897
890
      unsigned char *tmpkey;
898
891
      size_t tmplen;
899
892
 
900
 
      rc = agent_unprotect (key, (pw=get_passphrase (1)), &tmpkey, &tmplen);
 
893
      rc = agent_unprotect (key, (pw=get_passphrase (1, 0)),
 
894
                            NULL, &tmpkey, &tmplen);
901
895
      release_passphrase (pw);
902
896
      if (rc)
903
897
        {
986
980
  kparms[8] = NULL;
987
981
 
988
982
  key = p12_build (kparms, cert, certlen,
989
 
                   (pw=get_new_passphrase (3)), &keylen);
 
983
                   (pw=get_new_passphrase (3)), opt_p12_charset, &keylen);
990
984
  release_passphrase (pw);
991
985
  xfree (cert);
992
986
  for (i=0; i < 8; i++)
1062
1056
  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
1063
1057
  log_set_prefix ("gpg-protect-tool", 1); 
1064
1058
 
1065
 
  /* Try to auto set the character set.  */
1066
 
  set_native_charset (NULL); 
 
1059
  /* Make sure that our subsystems are ready.  */
 
1060
  init_common_subsystems ();
1067
1061
 
1068
1062
  i18n_init ();
1069
1063
 
1070
1064
  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
1071
1065
    {
1072
 
      log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
 
1066
      log_fatal( _("%s is too old (need %s, have %s)\n"), "libgcrypt",
1073
1067
                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
1074
1068
    }
1075
1069
 
1076
 
  gcry_set_log_handler (my_gcry_logger, NULL);
1077
 
  
 
1070
  setup_libgcrypt_logging ();
1078
1071
  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1079
1072
 
1080
1073
 
1100
1093
        case oShowKeygrip: cmd = oShowKeygrip; break;
1101
1094
        case oP12Import: cmd = oP12Import; break;
1102
1095
        case oP12Export: cmd = oP12Export; break;
 
1096
        case oP12Charset: opt_p12_charset = pargs.r.ret_str; break;
1103
1097
 
1104
1098
        case oPassphrase: opt_passphrase = pargs.r.ret_str; break;
1105
1099
        case oStore: opt_store = 1; break;
1121
1115
  else if (argc > 1)
1122
1116
    usage (1);
1123
1117
 
 
1118
  /* Tell simple-pwquery about the the standard socket name.  */
 
1119
  {
 
1120
    char *tmp = make_filename (opt_homedir, "S.gpg-agent", NULL);
 
1121
    simple_pw_set_socket (tmp);
 
1122
    xfree (tmp);
 
1123
  }
 
1124
 
1124
1125
  if (opt_prompt)
1125
1126
    opt_prompt = percent_plus_unescape_string (xstrdup (opt_prompt));
1126
1127
 
1161
1162
     3 = for protecting a new pkcs#12 object
1162
1163
     4 = for protecting an imported pkcs#12 in our system
1163
1164
     5 = reenter the passphrase
1164
 
   When adding 100 to the values, a "does not match - try again" errro message is shown.
 
1165
   When adding 100 to the values, a "does not match - try again" error
 
1166
   message is shown.
1165
1167
*/
1166
1168
static char *
1167
 
get_passphrase (int promptno)
 
1169
get_passphrase (int promptno, int opt_check)
1168
1170
{
1169
1171
  char *pw;
1170
1172
  int err;
1171
1173
  const char *desc;
1172
 
#ifdef HAVE_LANGINFO_CODESET
1173
 
  char *orig_codeset = NULL;
1174
 
#endif
 
1174
  char *orig_codeset;
1175
1175
  int error_msgno;
1176
1176
  
1177
 
 
1178
1177
  if (opt_passphrase)
1179
1178
    return xstrdup (opt_passphrase);
1180
1179
 
1181
1180
  error_msgno = promptno / 100;
1182
1181
  promptno %= 100;
1183
1182
 
1184
 
#ifdef ENABLE_NLS
1185
 
  /* The Assuan agent protocol requires us to transmit utf-8 strings */
1186
 
  orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL);
1187
 
#ifdef HAVE_LANGINFO_CODESET
1188
 
  if (!orig_codeset)
1189
 
    orig_codeset = nl_langinfo (CODESET);
1190
 
#endif
1191
 
  if (orig_codeset && !strcmp (orig_codeset, "UTF-8"))
1192
 
    orig_codeset = NULL;
1193
 
  if (orig_codeset)
1194
 
    {
1195
 
      /* We only switch when we are able to restore the codeset later. */
1196
 
      orig_codeset = xstrdup (orig_codeset);
1197
 
      if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8"))
1198
 
        orig_codeset = NULL; 
1199
 
    }
1200
 
#endif
 
1183
  orig_codeset = i18n_switchto_utf8 ();
1201
1184
 
1202
1185
  if (promptno == 1 && opt_prompt)
1203
1186
    desc = opt_prompt;
1218
1201
 
1219
1202
  pw = simple_pwquery (NULL,
1220
1203
                       error_msgno == 1? _("does not match - try again"):NULL,
1221
 
                       _("Passphrase:"), desc, &err);
 
1204
                       _("Passphrase:"), desc, opt_check, &err);
 
1205
  err = map_spwq_error (err);
1222
1206
 
1223
 
#ifdef ENABLE_NLS
1224
 
  if (orig_codeset)
1225
 
    {
1226
 
      bind_textdomain_codeset (PACKAGE_GT, orig_codeset);
1227
 
      xfree (orig_codeset);
1228
 
    }
1229
 
#endif
 
1207
  i18n_switchback (orig_codeset);
1230
1208
 
1231
1209
  if (!pw)
1232
1210
    {
1250
1228
  char *pw;
1251
1229
  int i, secondpromptno;
1252
1230
  
1253
 
  pw = get_passphrase (promptno);
 
1231
  pw = get_passphrase (promptno, 1);
1254
1232
  if (!pw)
1255
1233
    return NULL; /* Canceled. */
1256
1234
  if (!*pw)
1257
 
    return pw; /* Empty passphrase - no need to as for repeating it. */
 
1235
    return pw;   /* Empty passphrase - no need to ask for repeating it. */
1258
1236
 
1259
1237
  secondpromptno = 5;
1260
1238
  for (i=0; i < 3; i++)
1261
1239
    {
1262
 
      char *pw2 = get_passphrase (secondpromptno);
 
1240
      char *pw2 = get_passphrase (secondpromptno, 0);
1263
1241
      if (!pw2)
1264
1242
        {
1265
1243
          xfree (pw);