diff options
Diffstat (limited to 'agent/preset-passphrase.c')
| -rw-r--r-- | agent/preset-passphrase.c | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/agent/preset-passphrase.c b/agent/preset-passphrase.c new file mode 100644 index 000000000..f876b0647 --- /dev/null +++ b/agent/preset-passphrase.c @@ -0,0 +1,337 @@ +/* preset-passphrase.c - A tool to preset a passphrase. + * Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * 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> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif +#ifdef HAVE_W32_SYSTEM +#include <windows.h> /* To initialize the sockets. fixme */ +#endif + +#define JNLIB_NEED_LOG_LOGV +#include "agent.h" +#include "minip12.h" +#include "simple-pwquery.h" +#include "i18n.h" +#include "sysutils.h" + + +enum cmd_and_opt_values +{ aNull = 0, + oVerbose = 'v', + oPassphrase = 'P', + + oPreset = 'c', + oForget = 'f', + + oNoVerbose = 500, + + oHomedir, + +aTest }; + + +static const char *opt_homedir; +static const char *opt_passphrase; + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oVerbose, "verbose", 0, "verbose" }, + { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, + { oPreset, "preset", 256, "preset passphrase"}, + { oForget, "forget", 256, "forget passphrase"}, + + { oHomedir, "homedir", 2, "@" }, + {0} +}; + + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-preset-passphrase (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-preset-passphrase [options] KEYGRIP (-h for help)\n"); + break; + case 41: + p = _("Syntax: gpg-preset-passphrase [options] KEYGRIP\n" + "Password cache maintenance\n"); + break; + + default: p = NULL; + } + return p; +} + + + +static void +i18n_init (void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE_GT ); +#else +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); +#endif +#endif +} + + +static gpg_error_t +map_spwq_error (int err) +{ + switch (err) + { + case 0: + return 0; + case SPWQ_OUT_OF_CORE: + return gpg_error_from_errno (ENOMEM); + case SPWQ_IO_ERROR: + return gpg_error_from_errno (EIO); + case SPWQ_PROTOCOL_ERROR: + return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); + case SPWQ_ERR_RESPONSE: + return gpg_error (GPG_ERR_INV_RESPONSE); + case SPWQ_NO_AGENT: + return gpg_error (GPG_ERR_NO_AGENT); + case SPWQ_SYS_ERROR: + return gpg_error_from_errno (errno); + case SPWQ_GENERAL_ERROR: + default: + return gpg_error (GPG_ERR_GENERAL); + } +} + + +/* Percent-Escape special characters. The string is valid until the + next invocation of the function. */ +static char * +make_hexstring (const char *src) +{ + int len = 2 * strlen (src) + 1; + char *dst; + char *res; + + res = dst = malloc (len); + if (!dst) + { + log_error ("can not escape string: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return NULL; + } + +#define _tohex(nr) ((nr) < 10 ? ((nr) + '0') : (((nr) - 10) + 'A')) +#define tohex1(p) _tohex (*((unsigned char *) p) & 15) +#define tohex2(p) _tohex ((*((unsigned char *) p) >> 4) & 15) + + while (*src) + { + *(dst++) = tohex2 (src); + *(dst++) = tohex1 (src); + src++; + } + *dst = '\0'; + return res; +} + + +static void +preset_passphrase (const char *keygrip) +{ + int rc; + char *line; + /* FIXME: Use secure memory. */ + char passphrase[500]; + char *passphrase_esc; + + if (!opt_passphrase) + { + rc = read (0, passphrase, sizeof (passphrase) - 1); + if (rc < 0) + { + log_error ("reading passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + passphrase[rc] = '\0'; + line = strchr (passphrase, '\n'); + if (line) + { + if (line > passphrase && line[-1] == '\r') + line--; + *line = '\0'; + } + + /* FIXME: How to handle empty passwords? */ + } + + passphrase_esc = make_hexstring (opt_passphrase + ? opt_passphrase : passphrase); + if (!passphrase_esc) + { + /* Error message printed by callee. */ + return; + } + + rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip, + passphrase_esc); + wipememory (passphrase_esc, strlen (passphrase_esc)); + free (passphrase_esc); + + if (rc < 0) + { + log_error ("caching passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + if (!opt_passphrase) + wipememory (passphrase, sizeof (passphrase)); + + rc = map_spwq_error (simple_query (line)); + if (rc) + { + log_error ("caching passphrase failed: %s\n", gpg_strerror (rc)); + return; + } + + wipememory (line, strlen (line)); + free (line); +} + + +static void +forget_passphrase (const char *keygrip) +{ + int rc; + char *line; + + rc = asprintf (&line, "CLEAR_PASSPHRASE %s\n", keygrip); + if (rc < 0) + { + log_error ("clearing passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + free (line); +} + + +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + int cmd = 0; + const char *keygrip = NULL; + + set_strusage (my_strusage); + log_set_prefix ("gpg-preset-passphrase", 1); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + +#ifdef HAVE_W32_SYSTEM + /* Fixme: Need to initialize the Windows sockets: This should be + moved to another place and we should make sure that it won't get + doen twice, like when Pth is used too. */ + { + WSADATA wsadat; + WSAStartup (0x202, &wsadat); + } +#endif + + i18n_init (); + + opt_homedir = default_homedir (); + + 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 oHomedir: opt_homedir = pargs.r.ret_str; break; + + case oPreset: cmd = oPreset; break; + case oForget: cmd = oForget; break; + case oPassphrase: opt_passphrase = pargs.r.ret_str; break; + + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (argc == 1) + keygrip = *argv; + else + usage (1); + + if (cmd == oPreset) + preset_passphrase (keygrip); + else if (cmd == oForget) + forget_passphrase (keygrip); + else + log_error ("one of the options --preset or --forget must be given\n"); + + agent_exit (0); + return 8; /*NOTREACHED*/ +} + + +void +agent_exit (int rc) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} |
