1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-23 10:29:58 +01:00
gnupg/agent/preset-passphrase.c
Werner Koch a028f24136
Backport of the new option parser from 2.3
* configure.ac (GPGRT_ENABLE_ARGPARSE_MACROS): Define.
* common/argparse.c, common/argparse.h: Rewrite.
* tests/gpgscm/main.c: Switch to the new option parser.

* g10/gpg.c: Switch to the new option parser and enable a global conf
file.
* g10/gpgv.c: Ditto.
* agent/gpg-agent.c: Ditto.
* agent/preset-passphrase.c: Ditto.
* agent/protect-tool.c: Ditto.
* scd/scdaemon.c: Ditto.
* dirmngr/dirmngr.c: Ditto.
* dirmngr/dirmngr_ldap.c: Ditto
* dirmngr/dirmngr-client.c: Ditto.
* kbx/kbxutil.c: Ditto.
* tools/gpg-card.c: Ditto.
* tools/gpg-check-pattern.c: Ditto.
* tools/gpg-connect-agent.c: Ditto.
* tools/gpg-pair-tool.c: Ditto.
* tools/gpg-wks-client.c: Ditto.
* tools/gpg-wks-server.c: Ditto.
* tools/gpgconf.c: Ditto.
* tools/gpgsplit.c: Ditto.
* tools/gpgtar.c: Ditto.
* g13/g13.c: Ditto.
* g13/g13-syshelp.c: Ditto.  Do not force verbose mode.
* sm/gpgsm.c: Ditto. Add option --no-options.
--

This is backport from master

commit cdbe10b762f38449b86da69076209324b0c99982
commit ba463128ce65a0f347643f7246a8e097c5be19f1
commit 3bc004decd289810bc1b6ad6fb8f47e45c770ce6
commit 2c823bd878fcdbcc4f6c34993e1d0539d9a6b237
commit 0e8f6e2aa98c212442001036fb5178cd6cd8af59

but without changing all functions names to gpgrt.  Instead we use
wrapper functions which, when building against old Libgpg-error
versions, are implemented in argparse.c using code from the current
libgpg-error.  This allows to keep the dependency requirement at
libgpg-error 1.27 to support older distributions.  Tested builds
against 1.27 and 1.40-beta.

Note that g13-syshelp does not anymore default to --verbose because
that can now be enabled in /etc/gnupg/g13-syshelp.conf.

GnuPG-bug-id: 4788
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-12-04 12:12:20 +01:00

273 lines
6.1 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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 3 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, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#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
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h> /* To initialize the sockets. fixme */
#endif
#define INCLUDED_BY_MAIN_MODULE 1
#include "agent.h"
#include "../common/simple-pwquery.h"
#include "../common/i18n.h"
#include "../common/sysutils.h"
#include "../common/init.h"
enum cmd_and_opt_values
{ aNull = 0,
oVerbose = 'v',
oPassphrase = 'P',
oPreset = 'c',
oForget = 'f',
oNoVerbose = 500,
oHomedir,
aTest };
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, "@" },
ARGPARSE_end ()
};
static const char *
my_strusage (int level)
{
const char *p;
switch (level)
{
case 9: p = "GPL-3.0-or-later"; break;
case 11: p = "gpg-preset-passphrase (@GNUPG@)";
break;
case 13: p = VERSION; break;
case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <@EMAIL@>.\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
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_syserror ()));
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? */
}
{
const char *s = opt_passphrase ? opt_passphrase : passphrase;
passphrase_esc = bin2hex (s, strlen (s), NULL);
}
if (!passphrase_esc)
{
log_error ("can not escape string: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
return;
}
rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip,
passphrase_esc);
wipememory (passphrase_esc, strlen (passphrase_esc));
xfree (passphrase_esc);
if (rc < 0)
{
log_error ("caching passphrase failed: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
return;
}
if (!opt_passphrase)
wipememory (passphrase, sizeof (passphrase));
rc = simple_query (line);
if (rc)
{
log_error ("caching passphrase failed: %s\n", gpg_strerror (rc));
return;
}
wipememory (line, strlen (line));
xfree (line);
}
static void
forget_passphrase (const char *keygrip)
{
int rc;
char *line;
rc = asprintf (&line, "CLEAR_PASSPHRASE %s\n", keygrip);
if (rc < 0)
rc = gpg_error_from_syserror ();
else
rc = simple_query (line);
if (rc)
{
log_error ("clearing passphrase failed: %s\n", gpg_strerror (rc));
return;
}
xfree (line);
}
int
main (int argc, char **argv)
{
ARGPARSE_ARGS pargs;
int cmd = 0;
const char *keygrip = NULL;
early_system_init ();
set_strusage (my_strusage);
log_set_prefix ("gpg-preset-passphrase", GPGRT_LOG_WITH_PREFIX);
/* Make sure that our subsystems are ready. */
i18n_init ();
init_common_subsystems (&argc, &argv);
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= ARGPARSE_FLAG_KEEP;
while (gnupg_argparse (NULL, &pargs, opts))
{
switch (pargs.r_opt)
{
case oVerbose: opt.verbose++; break;
case oHomedir: gnupg_set_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;
}
}
gnupg_argparse (NULL, &pargs, NULL); /* Release internal state. */
if (log_get_errorcount(0))
exit(2);
if (argc == 1)
keygrip = *argv;
else
usage (1);
/* Tell simple-pwquery about the standard socket name. */
{
char *tmp = make_filename (gnupg_socketdir (), GPG_AGENT_SOCK_NAME, NULL);
simple_pw_set_socket (tmp);
xfree (tmp);
}
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);
}