2002-04-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / agent / protect-tool.c
blobd783556de8e0c61971ac4d77dc57900b108ca39e
1 /* protect-tool.c - A tool to text the secret key protection
2 * Copyright (C) 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
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
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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
21 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
33 #include <gcrypt.h>
35 #define JNLIB_NEED_LOG_LOGV
36 #include "agent.h"
38 #define N_(a) a
39 #define _(a) a
42 enum cmd_and_opt_values
43 { aNull = 0,
44 oVerbose = 'v',
45 oArmor = 'a',
46 oPassphrase = 'P',
48 oProtect = 'p',
49 oUnprotect = 'u',
51 oNoVerbose = 500,
52 oShadow,
53 oShowShadowInfo,
55 aTest };
58 static int opt_armor;
59 static const char *passphrase = "abc";
61 static ARGPARSE_OPTS opts[] = {
63 { 301, NULL, 0, N_("@Options:\n ") },
65 { oVerbose, "verbose", 0, "verbose" },
66 { oArmor, "armor", 0, "write output in advanced format" },
67 { oPassphrase, "passphrase", 2, "|STRING| Use passphrase STRING" },
68 { oProtect, "protect", 256, "protect a private key"},
69 { oUnprotect, "unprotect", 256, "unprotect a private key"},
70 { oShadow, "shadow", 256, "create a shadow entry for a priblic key"},
71 { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
73 {0}
76 static const char *
77 my_strusage (int level)
79 const char *p;
80 switch (level)
82 case 11: p = "protect-tool (GnuPG)";
83 break;
84 case 13: p = VERSION; break;
85 case 17: p = PRINTABLE_OS_NAME; break;
86 case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
87 break;
88 case 1:
89 case 40: p = _("Usage: protect-tool [options] (-h for help)\n");
90 break;
91 case 41: p = _("Syntax: protect-tool [options] [args]]\n"
92 "INTERNAL USE ONLY!\n");
93 break;
95 default: p = NULL;
97 return p;
102 static void
103 i18n_init (void)
105 #ifdef USE_SIMPLE_GETTEXT
106 set_gettext_file( PACKAGE );
107 #else
108 #ifdef ENABLE_NLS
109 /* gtk_set_locale (); HMMM: We have not yet called gtk_init */
110 bindtextdomain( PACKAGE, GNUPG_LOCALEDIR );
111 textdomain( PACKAGE );
112 #endif
113 #endif
118 /* Used by gcry for logging */
119 static void
120 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
122 /* translate the log levels */
123 switch (level)
125 case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
126 case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
127 case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
128 case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
129 case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
130 case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
131 case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
132 default: level = JNLIB_LOG_ERROR; break; }
133 log_logv (level, fmt, arg_ptr);
137 static unsigned char *
138 make_canonical (const char *fname, const char *buf, size_t buflen)
140 int rc;
141 size_t erroff, len;
142 GCRY_SEXP sexp;
143 unsigned char *result;
145 rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
146 if (rc)
148 log_error ("invalid S-Expression in `%s' (off=%u): %s\n",
149 fname, (unsigned int)erroff, gcry_strerror (rc));
150 return NULL;
152 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
153 assert (len);
154 result = xmalloc (len);
155 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
156 assert (len);
157 gcry_sexp_release (sexp);
158 return result;
161 static char *
162 make_advanced (const unsigned char *buf, size_t buflen)
164 int rc;
165 size_t erroff, len;
166 GCRY_SEXP sexp;
167 unsigned char *result;
169 rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
170 if (rc)
172 log_error ("invalid canonical S-Expression (off=%u): %s\n",
173 (unsigned int)erroff, gcry_strerror (rc));
174 return NULL;
176 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
177 assert (len);
178 result = xmalloc (len);
179 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
180 assert (len);
181 gcry_sexp_release (sexp);
182 return result;
186 static unsigned char *
187 read_key (const char *fname)
189 FILE *fp;
190 struct stat st;
191 char *buf;
192 size_t buflen;
193 unsigned char *key;
195 fp = fopen (fname, "rb");
196 if (!fp)
198 log_error ("can't open `%s': %s\n", fname, strerror (errno));
199 return NULL;
202 if (fstat (fileno(fp), &st))
204 log_error ("can't stat `%s': %s\n", fname, strerror (errno));
205 fclose (fp);
206 return NULL;
209 buflen = st.st_size;
210 buf = xmalloc (buflen+1);
211 if (fread (buf, buflen, 1, fp) != 1)
213 log_error ("error reading `%s': %s\n", fname, strerror (errno));
214 fclose (fp);
215 xfree (buf);
216 return NULL;
218 fclose (fp);
220 key = make_canonical (fname, buf, buflen);
221 xfree (buf);
222 return key;
227 static void
228 read_and_protect (const char *fname)
230 int rc;
231 unsigned char *key;
232 unsigned char *result;
233 size_t resultlen;
235 key = read_key (fname);
236 if (!key)
237 return;
239 rc = agent_protect (key, passphrase, &result, &resultlen);
240 xfree (key);
241 if (rc)
243 log_error ("protecting the key failed: %s\n", gnupg_strerror (rc));
244 return;
247 if (opt_armor)
249 char *p = make_advanced (result, resultlen);
250 xfree (result);
251 if (!p)
252 return;
253 result = p;
254 resultlen = strlen (p);
257 fwrite (result, resultlen, 1, stdout);
258 xfree (result);
262 static void
263 read_and_unprotect (const char *fname)
265 int rc;
266 unsigned char *key;
267 unsigned char *result;
268 size_t resultlen;
270 key = read_key (fname);
271 if (!key)
272 return;
274 rc = agent_unprotect (key, passphrase, &result, &resultlen);
275 xfree (key);
276 if (rc)
278 log_error ("unprotecting the key failed: %s\n", gnupg_strerror (rc));
279 return;
282 if (opt_armor)
284 char *p = make_advanced (result, resultlen);
285 xfree (result);
286 if (!p)
287 return;
288 result = p;
289 resultlen = strlen (p);
292 fwrite (result, resultlen, 1, stdout);
293 xfree (result);
298 static void
299 read_and_shadow (const char *fname)
301 int rc;
302 unsigned char *key;
303 unsigned char *result;
304 size_t resultlen;
306 key = read_key (fname);
307 if (!key)
308 return;
310 rc = agent_shadow_key (key, "(8:313233342:43)", &result);
311 xfree (key);
312 if (rc)
314 log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc));
315 return;
317 resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
318 assert (resultlen);
320 if (opt_armor)
322 char *p = make_advanced (result, resultlen);
323 xfree (result);
324 if (!p)
325 return;
326 result = p;
327 resultlen = strlen (p);
330 fwrite (result, resultlen, 1, stdout);
331 xfree (result);
334 static void
335 show_shadow_info (const char *fname)
337 int rc;
338 unsigned char *key;
339 const unsigned char *info;
340 size_t infolen;
342 key = read_key (fname);
343 if (!key)
344 return;
346 rc = agent_get_shadow_info (key, &info);
347 xfree (key);
348 if (rc)
350 log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc));
351 return;
353 infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
354 assert (infolen);
356 if (opt_armor)
358 char *p = make_advanced (info, infolen);
359 if (!p)
360 return;
361 fwrite (p, strlen (p), 1, stdout);
362 xfree (p);
364 else
365 fwrite (info, infolen, 1, stdout);
369 static void
370 show_file (const char *fname)
372 unsigned char *key;
373 size_t keylen;
374 char *p;
376 key = read_key (fname);
377 if (!key)
378 return;
379 keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
380 assert (keylen);
382 p = make_advanced (key, keylen);
383 xfree (key);
384 if (p)
386 fwrite (p, strlen (p), 1, stdout);
387 xfree (p);
395 main (int argc, char **argv )
397 ARGPARSE_ARGS pargs;
398 int cmd = 0;
400 set_strusage (my_strusage);
401 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
402 log_set_prefix ("protect-tool", 1);
403 i18n_init ();
405 if (!gcry_check_version ( "1.1.5" ) )
407 log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
408 "1.1.5", gcry_check_version (NULL) );
411 gcry_set_log_handler (my_gcry_logger, NULL);
413 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
415 pargs.argc = &argc;
416 pargs.argv = &argv;
417 pargs.flags= 1; /* do not remove the args */
418 while (arg_parse (&pargs, opts) )
420 switch (pargs.r_opt)
422 case oVerbose: opt.verbose++; break;
423 case oArmor: opt_armor=1; break;
425 case oProtect: cmd = oProtect; break;
426 case oUnprotect: cmd = oUnprotect; break;
427 case oShadow: cmd = oShadow; break;
428 case oShowShadowInfo: cmd = oShowShadowInfo; break;
430 case oPassphrase: passphrase = pargs.r.ret_str; break;
432 default : pargs.err = 2; break;
435 if (log_get_errorcount(0))
436 exit(2);
438 if (argc != 1)
439 usage (1);
441 if (cmd == oProtect)
442 read_and_protect (*argv);
443 else if (cmd == oUnprotect)
444 read_and_unprotect (*argv);
445 else if (cmd == oShadow)
446 read_and_shadow (*argv);
447 else if (cmd == oShowShadowInfo)
448 show_shadow_info (*argv);
449 else
450 show_file (*argv);
452 return 0;
455 void
456 agent_exit (int rc)
458 rc = rc? rc : log_get_errorcount(0)? 2 : 0;
459 exit (rc);