diff options
Diffstat (limited to '')
-rw-r--r-- | agent/protect-tool.c | 977 |
1 files changed, 0 insertions, 977 deletions
diff --git a/agent/protect-tool.c b/agent/protect-tool.c deleted file mode 100644 index e518c5672..000000000 --- a/agent/protect-tool.c +++ /dev/null @@ -1,977 +0,0 @@ -/* protect-tool.c - A tool to test the secret key protection - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <sys/stat.h> -#include <unistd.h> - -#define JNLIB_NEED_LOG_LOGV -#include "agent.h" -#include "minip12.h" -#include "simple-pwquery.h" -#include "i18n.h" - -enum cmd_and_opt_values -{ aNull = 0, - oVerbose = 'v', - oArmor = 'a', - oPassphrase = 'P', - - oProtect = 'p', - oUnprotect = 'u', - - oNoVerbose = 500, - oShadow, - oShowShadowInfo, - oShowKeygrip, - - oP12Import, - oP12Export, - oStore, - oForce, - -aTest }; - -struct rsa_secret_key_s - { - gcry_mpi_t n; /* public modulus */ - gcry_mpi_t e; /* public exponent */ - gcry_mpi_t d; /* exponent */ - gcry_mpi_t p; /* prime p. */ - gcry_mpi_t q; /* prime q. */ - gcry_mpi_t u; /* inverse of p mod q. */ - }; - - -static int opt_armor; -static int opt_store; -static int opt_force; -static const char *passphrase; - -static const char *get_passphrase (void); -static int store_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force); - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, N_("@Options:\n ") }, - - { oVerbose, "verbose", 0, "verbose" }, - { oArmor, "armor", 0, "write output in advanced format" }, - { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, - { oProtect, "protect", 256, "protect a private key"}, - { oUnprotect, "unprotect", 256, "unprotect a private key"}, - { oShadow, "shadow", 256, "create a shadow entry for a priblic key"}, - { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"}, - { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""}, - - { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"}, - { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, - { oStore, "store", 0, "store the created key in the appropriate place"}, - { oForce, "force", 0, "force overwriting"}, - {0} -}; - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "gpg-protect-tool (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n"); - break; - case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n" - "Secret key maintenance tool\n"); - break; - - default: p = NULL; - } - return p; -} - - - -static void -i18n_init (void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); -#else -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -#endif -#endif -} - - - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; } - log_logv (level, fmt, arg_ptr); -} - - -/* static void */ -/* print_mpi (const char *text, gcry_mpi_t a) */ -/* { */ -/* char *buf; */ -/* void *bufaddr = &buf; */ -/* int rc; */ - -/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */ -/* if (rc) */ -/* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */ -/* else */ -/* { */ -/* log_info ("%s: %s\n", text, buf); */ -/* gcry_free (buf); */ -/* } */ -/* } */ - - - -static unsigned char * -make_canonical (const char *fname, const char *buf, size_t buflen) -{ - int rc; - size_t erroff, len; - gcry_sexp_t sexp; - unsigned char *result; - - rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); - if (rc) - { - log_error ("invalid S-Expression in `%s' (off=%u): %s\n", - fname, (unsigned int)erroff, gpg_strerror (rc)); - return NULL; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - result = xmalloc (len); - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len); - assert (len); - gcry_sexp_release (sexp); - return result; -} - -static char * -make_advanced (const unsigned char *buf, size_t buflen) -{ - int rc; - size_t erroff, len; - gcry_sexp_t sexp; - unsigned char *result; - - rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); - if (rc) - { - log_error ("invalid canonical S-Expression (off=%u): %s\n", - (unsigned int)erroff, gpg_strerror (rc)); - return NULL; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); - assert (len); - result = xmalloc (len); - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len); - assert (len); - gcry_sexp_release (sexp); - return result; -} - - -static char * -read_file (const char *fname, size_t *r_length) -{ - FILE *fp; - struct stat st; - char *buf; - size_t buflen; - - fp = fopen (fname, "rb"); - if (!fp) - { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - return NULL; - } - - if (fstat (fileno(fp), &st)) - { - log_error ("can't stat `%s': %s\n", fname, strerror (errno)); - fclose (fp); - return NULL; - } - - buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) - { - log_error ("error reading `%s': %s\n", fname, strerror (errno)); - fclose (fp); - xfree (buf); - return NULL; - } - fclose (fp); - - *r_length = buflen; - return buf; -} - - -static unsigned char * -read_key (const char *fname) -{ - char *buf; - size_t buflen; - unsigned char *key; - - buf = read_file (fname, &buflen); - if (!buf) - return NULL; - key = make_canonical (fname, buf, buflen); - xfree (buf); - return key; -} - - - -static void -read_and_protect (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_protect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("protecting the key failed: %s\n", gpg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - - -static void -read_and_unprotect (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_unprotect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - - - -static void -read_and_shadow (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_shadow_key (key, "(8:313233342:43)", &result); - xfree (key); - if (rc) - { - log_error ("shadowing the key failed: %s\n", gpg_strerror (rc)); - return; - } - resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL); - assert (resultlen); - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - -static void -show_shadow_info (const char *fname) -{ - int rc; - unsigned char *key; - const unsigned char *info; - size_t infolen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_get_shadow_info (key, &info); - xfree (key); - if (rc) - { - log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc)); - return; - } - infolen = gcry_sexp_canon_len (info, 0, NULL,NULL); - assert (infolen); - - if (opt_armor) - { - char *p = make_advanced (info, infolen); - if (!p) - return; - fwrite (p, strlen (p), 1, stdout); - xfree (p); - } - else - fwrite (info, infolen, 1, stdout); -} - - -static void -show_file (const char *fname) -{ - unsigned char *key; - size_t keylen; - char *p; - - key = read_key (fname); - if (!key) - return; - - keylen = gcry_sexp_canon_len (key, 0, NULL,NULL); - assert (keylen); - - p = make_advanced (key, keylen); - xfree (key); - if (p) - { - fwrite (p, strlen (p), 1, stdout); - xfree (p); - } -} - -static void -show_keygrip (const char *fname) -{ - unsigned char *key; - gcry_sexp_t private; - unsigned char grip[20]; - int i; - - key = read_key (fname); - if (!key) - return; - - if (gcry_sexp_new (&private, key, 0, 0)) - { - log_error ("gcry_sexp_new failed\n"); - return; - } - xfree (key); - - if (!gcry_pk_get_keygrip (private, grip)) - { - log_error ("can't calculate keygrip\n"); - return; - } - gcry_sexp_release (private); - - for (i=0; i < 20; i++) - printf ("%02X", grip[i]); - putchar ('\n'); -} - - -static int -rsa_key_check (struct rsa_secret_key_s *skey) -{ - int err = 0; - gcry_mpi_t t = gcry_mpi_snew (0); - gcry_mpi_t t1 = gcry_mpi_snew (0); - gcry_mpi_t t2 = gcry_mpi_snew (0); - gcry_mpi_t phi = gcry_mpi_snew (0); - - /* check that n == p * q */ - gcry_mpi_mul (t, skey->p, skey->q); - if (gcry_mpi_cmp( t, skey->n) ) - { - log_error ("RSA oops: n != p * q\n"); - err++; - } - - /* check that p is less than q */ - if (gcry_mpi_cmp (skey->p, skey->q) > 0) - { - gcry_mpi_t tmp; - - log_info ("swapping secret primes\n"); - tmp = gcry_mpi_copy (skey->p); - gcry_mpi_set (skey->p, skey->q); - gcry_mpi_set (skey->q, tmp); - gcry_mpi_release (tmp); - /* and must recompute u of course */ - gcry_mpi_invm (skey->u, skey->p, skey->q); - } - - /* check that e divides neither p-1 nor q-1 */ - gcry_mpi_sub_ui (t, skey->p, 1 ); - gcry_mpi_div (NULL, t, t, skey->e, 0); - if (!gcry_mpi_cmp_ui( t, 0) ) - { - log_error ("RSA oops: e divides p-1\n"); - err++; - } - gcry_mpi_sub_ui (t, skey->q, 1); - gcry_mpi_div (NULL, t, t, skey->e, 0); - if (!gcry_mpi_cmp_ui( t, 0)) - { - log_info ( "RSA oops: e divides q-1\n" ); - err++; - } - - /* check that d is correct. */ - gcry_mpi_sub_ui (t1, skey->p, 1); - gcry_mpi_sub_ui (t2, skey->q, 1); - gcry_mpi_mul (phi, t1, t2); - gcry_mpi_invm (t, skey->e, phi); - if (gcry_mpi_cmp (t, skey->d)) - { /* no: try universal exponent. */ - gcry_mpi_gcd (t, t1, t2); - gcry_mpi_div (t, NULL, phi, t, 0); - gcry_mpi_invm (t, skey->e, t); - if (gcry_mpi_cmp (t, skey->d)) - { - log_error ("RSA oops: bad secret exponent\n"); - err++; - } - } - - /* check for correctness of u */ - gcry_mpi_invm (t, skey->p, skey->q); - if (gcry_mpi_cmp (t, skey->u)) - { - log_info ( "RSA oops: bad u parameter\n"); - err++; - } - - if (err) - log_info ("RSA secret key check failed\n"); - - gcry_mpi_release (t); - gcry_mpi_release (t1); - gcry_mpi_release (t2); - gcry_mpi_release (phi); - - return err? -1:0; -} - - -static void -import_p12_file (const char *fname) -{ - char *buf; - unsigned char *result; - size_t buflen, resultlen; - int i; - int rc; - gcry_mpi_t *kparms; - struct rsa_secret_key_s sk; - gcry_sexp_t s_key; - unsigned char *key; - unsigned char grip[20]; - - /* fixme: we should release some stuff on error */ - - buf = read_file (fname, &buflen); - if (!buf) - return; - - kparms = p12_parse (buf, buflen, get_passphrase ()); - xfree (buf); - if (!kparms) - { - log_error ("error parsing or decrypting the PKCS-1 file\n"); - return; - } - for (i=0; kparms[i]; i++) - ; - if (i != 8) - { - log_error ("invalid structure of private key\n"); - return; - } - - -/* print_mpi (" n", kparms[0]); */ -/* print_mpi (" e", kparms[1]); */ -/* print_mpi (" d", kparms[2]); */ -/* print_mpi (" p", kparms[3]); */ -/* print_mpi (" q", kparms[4]); */ -/* print_mpi ("dmp1", kparms[5]); */ -/* print_mpi ("dmq1", kparms[6]); */ -/* print_mpi (" u", kparms[7]); */ - - sk.n = kparms[0]; - sk.e = kparms[1]; - sk.d = kparms[2]; - sk.q = kparms[3]; - sk.p = kparms[4]; - sk.u = kparms[7]; - if (rsa_key_check (&sk)) - return; -/* print_mpi (" n", sk.n); */ -/* print_mpi (" e", sk.e); */ -/* print_mpi (" d", sk.d); */ -/* print_mpi (" p", sk.p); */ -/* print_mpi (" q", sk.q); */ -/* print_mpi (" u", sk.u); */ - - /* Create an S-expresion from the parameters. */ - rc = gcry_sexp_build (&s_key, NULL, - "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", - sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL); - for (i=0; i < 8; i++) - gcry_mpi_release (kparms[i]); - gcry_free (kparms); - if (rc) - { - log_error ("failed to created S-expression from key: %s\n", - gpg_strerror (rc)); - return; - } - - /* Compute the keygrip. */ - if (!gcry_pk_get_keygrip (s_key, grip)) - { - log_error ("can't calculate keygrip\n"); - return; - } - log_info ("keygrip: "); - for (i=0; i < 20; i++) - log_printf ("%02X", grip[i]); - log_printf ("\n"); - - /* convert to canonical encoding */ - buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0); - assert (buflen); - key = gcry_xmalloc_secure (buflen); - buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, key, buflen); - assert (buflen); - gcry_sexp_release (s_key); - - - rc = agent_protect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("protecting the key failed: %s\n", gpg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - if (opt_store) - store_private_key (grip, result, resultlen, opt_force); - else - fwrite (result, resultlen, 1, stdout); - - xfree (result); -} - - - -static gcry_mpi_t * -sexp_to_kparms (gcry_sexp_t sexp) -{ - gcry_sexp_t list, l2; - const char *name; - const char *s; - size_t n; - int i, idx; - const char *elems; - gcry_mpi_t *array; - - list = gcry_sexp_find_token (sexp, "private-key", 0 ); - if(!list) - return NULL; - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - name = gcry_sexp_nth_data (list, 0, &n); - if(!name || n != 3 || memcmp (name, "rsa", 3)) - { - gcry_sexp_release (list); - return NULL; - } - - /* Parameter names used with RSA. */ - elems = "nedpqu"; - array = xcalloc (strlen(elems) + 1, sizeof *array); - for (idx=0, s=elems; *s; s++, idx++ ) - { - l2 = gcry_sexp_find_token (list, s, 1); - if (!l2) - { - for (i=0; i<idx; i++) - gcry_mpi_release (array[i]); - xfree (array); - gcry_sexp_release (list); - return NULL; /* required parameter not found */ - } - array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l2); - if (!array[idx]) - { - for (i=0; i<idx; i++) - gcry_mpi_release (array[i]); - xfree (array); - gcry_sexp_release (list); - return NULL; /* required parameter is invalid */ - } - } - - gcry_sexp_release (list); - return array; -} - - - - -static void -export_p12_file (const char *fname) -{ - gcry_mpi_t kparms[9], *kp; - unsigned char *key; - size_t keylen; - gcry_sexp_t private; - struct rsa_secret_key_s sk; - int i; - - key = read_key (fname); - if (!key) - return; - - if (gcry_sexp_new (&private, key, 0, 0)) - { - log_error ("gcry_sexp_new failed\n"); - return; - } - xfree (key); - - kp = sexp_to_kparms (private); - gcry_sexp_release (private); - if (!kp) - { - log_error ("error converting key parameters\n"); - return; - } - sk.n = kp[0]; - sk.e = kp[1]; - sk.d = kp[2]; - sk.p = kp[3]; - sk.q = kp[4]; - sk.u = kp[5]; - xfree (kp); - - - kparms[0] = sk.n; - kparms[1] = sk.e; - kparms[2] = sk.d; - kparms[3] = sk.q; - kparms[4] = sk.p; - kparms[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */ - gcry_mpi_sub_ui (kparms[5], kparms[3], 1); - gcry_mpi_mod (kparms[5], sk.d, kparms[5]); - kparms[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */ - gcry_mpi_sub_ui (kparms[6], kparms[4], 1); - gcry_mpi_mod (kparms[6], sk.d, kparms[6]); - kparms[7] = sk.u; - kparms[8] = NULL; - - key = p12_build (kparms, get_passphrase (), &keylen); - for (i=0; i < 8; i++) - gcry_mpi_release (kparms[i]); - if (!key) - return; - - fwrite (key, keylen, 1, stdout); - xfree (key); -} - - -int -main (int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - int cmd = 0; - - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - log_set_prefix ("gpg-protect-tool", 1); - i18n_init (); - - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - gcry_set_log_handler (my_gcry_logger, NULL); - - gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - while (arg_parse (&pargs, opts) ) - { - switch (pargs.r_opt) - { - case oVerbose: opt.verbose++; break; - case oArmor: opt_armor=1; break; - - case oProtect: cmd = oProtect; break; - case oUnprotect: cmd = oUnprotect; break; - case oShadow: cmd = oShadow; break; - case oShowShadowInfo: cmd = oShowShadowInfo; break; - case oShowKeygrip: cmd = oShowKeygrip; break; - case oP12Import: cmd = oP12Import; break; - case oP12Export: cmd = oP12Export; break; - - case oPassphrase: passphrase = pargs.r.ret_str; break; - case oStore: opt_store = 1; break; - case oForce: opt_force = 1; break; - - default : pargs.err = 2; break; - } - } - if (log_get_errorcount(0)) - exit(2); - - if (argc != 1) - usage (1); - - if (cmd == oProtect) - read_and_protect (*argv); - else if (cmd == oUnprotect) - read_and_unprotect (*argv); - else if (cmd == oShadow) - read_and_shadow (*argv); - else if (cmd == oShowShadowInfo) - show_shadow_info (*argv); - else if (cmd == oShowKeygrip) - show_keygrip (*argv); - else if (cmd == oP12Import) - import_p12_file (*argv); - else if (cmd == oP12Export) - export_p12_file (*argv); - else - show_file (*argv); - - agent_exit (0); - return 8; /*NOTREACHED*/ -} - -void -agent_exit (int rc) -{ - rc = rc? rc : log_get_errorcount(0)? 2 : 0; - exit (rc); -} - - -/* Return the passphrase string and ask the agent if it has not been - set from the command line. */ -static const char * -get_passphrase (void) -{ - char *pw; - int err; - - if (passphrase) - return passphrase; - - pw = simple_pwquery (NULL,NULL, - _("Enter passphrase:"), - _("Please enter the passphrase or the PIN\n" - "needed to complete this operation."), - &err); - if (!pw) - { - if (err) - log_error ("error while asking for the passphrase\n"); - else - log_info ("cancelled\n"); - agent_exit (0); - } - passphrase = pw; - return passphrase; -} - - -static int -store_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force) -{ - int i; - const char *homedir; - char *fname; - FILE *fp; - char hexgrip[40+4+1]; - - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - strcpy (hexgrip+40, ".key"); - - homedir = getenv("GNUPGHOME"); - if (!homedir || !*homedir) - homedir = GNUPG_DEFAULT_HOMEDIR; - - fname = make_filename (homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - if (force) - fp = fopen (fname, "wb"); - else - { - if (!access (fname, F_OK)) - { - log_error ("secret key file `%s' already exists\n", fname); - xfree (fname); - return -1; - } - fp = fopen (fname, "wbx"); /* FIXME: the x is a GNU extension - let - configure check whether this actually - works */ - } - - if (!fp) - { - log_error ("can't create `%s': %s\n", fname, strerror (errno)); - xfree (fname); - return -1; - } - - if (fwrite (buffer, length, 1, fp) != 1) - { - log_error ("error writing `%s': %s\n", fname, strerror (errno)); - fclose (fp); - remove (fname); - xfree (fname); - return -1; - } - if ( fclose (fp) ) - { - log_error ("error closing `%s': %s\n", fname, strerror (errno)); - remove (fname); - xfree (fname); - return -1; - } - log_info ("secret key stored as `%s'\n", fname); - - xfree (fname); - return 0; -} |