1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Updated from latest NewPG project

This commit is contained in:
Werner Koch 2003-01-09 12:59:25 +00:00
parent 254225ac37
commit c13b76ca6a
28 changed files with 902 additions and 175 deletions

View file

@ -1,3 +1,76 @@
2002-12-04 Werner Koch <wk@gnupg.org>
* gpg-agent.c: New variable config_filename.
(parse_rereadable_options): New.
(main): Use it here. Add setting of default values, set
config_filename.
(reread_configuration): Filled with actual code.
2002-12-03 Werner Koch <wk@gnupg.org>
* protect-tool.c (read_key): Don't run make_canonical on a NULL buffer.
* command.c (parse_hexstring): New.
(cmd_sethash): Use it.
(parse_keygrip): New.
(cmd_havekey, cmd_sigkey): Use it.
(cmd_passwd): New.
* genkey.c (agent_protect_and_store): New.
(store_key): Add arg FORCE.
(agent_genkey): Pass false to this force of store_key.
2002-11-13 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Switch all messages to utf-8.
* simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and
stdin with ttyname.
* cache.c (new_data): Uiih - /sizeof d/sizeof *d/.
2002-11-10 Werner Koch <wk@gnupg.org>
* command.c (option_handler): Fix keep_tty check.
2002-11-06 Werner Koch <wk@gnupg.org>
* gpg-agent.c (main): Make sure we have a default ttyname.
* command.c (option_handler): Check opt.keep_tty here
* query.c (start_pinentry): but not anymore here.
2002-11-05 Werner Koch <wk@gnupg.org>
* agent.h (opt,server_control_s): Move display and lc_ variables
to the control struct so that they are per connection.
* gpg-agent.c (agent_init_default_ctrl): New.
(main): Assign those command line options to new default_* variables.
Reset DISPLAY in server mode so that tehre is no implicit default.
* command.c (start_command_handler): Initialize and deinitialize
the control values.
(option_handler): Work on the ctrl values and not on the opt.
* query.c (start_pinentry): New argument CTRL to set the display
connection specific. Changed all callers to pass this value.
(agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
CTRL arg and pass it ot start_pinentry.
* command.c (cmd_get_passphrase): Pass CTRL argument.
* trustlist.c (agent_marktrusted): Add CTRL argument
* command.c (cmd_marktrusted): Pass CTRL argument
* divert-scd.c (ask_for_card): Add CTRL arg.
(divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
(getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
users.
* findkey.c (unprotect): Add CTRL arg.
(agent_key_from_file): Ditto.
* query.c (unlock_pinentry): Disconnect the pinentry so that we
start a new one for each request. This is required to support
clients with different environments (e.g. X magic cookies).
2002-09-05 Neal H. Walfield <neal@cs.uml.edu>
* gpg-agent.c (main) [USE_GNU_PTH]: No need to call
assuan_set_io_func as assuan is smart.
2002-09-25 Werner Koch <wk@gnupg.org>
* gpg-agent.c (handle_signal): Flush cache on SIGHUP.

View file

@ -1,5 +1,5 @@
/* agent.h - Global definitions for the agent
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -36,11 +36,6 @@ struct {
int batch; /* batch mode */
const char *homedir; /* configuration directory name */
const char *pinentry_program;
char *display;
char *ttyname;
char *ttytype;
char *lc_ctype;
char *lc_messages;
const char *scdaemon_program;
int no_grab; /* don't let the pinentry grab the keyboard */
unsigned long def_cache_ttl;
@ -73,6 +68,11 @@ struct server_local_s;
struct server_control_s {
struct server_local_s *server_local;
char *display;
char *ttyname;
char *ttytype;
char *lc_ctype;
char *lc_messages;
struct {
int algo;
unsigned char value[MAX_DIGEST_LEN];
@ -107,6 +107,7 @@ enum {
/*-- gpg-agent.c --*/
void agent_exit (int rc); /* also implemented in other tools */
void agent_init_default_ctrl (struct server_control_s *ctrl);
/*-- command.c --*/
void start_command_handler (int, int);
@ -114,16 +115,17 @@ void start_command_handler (int, int);
/*-- findkey.c --*/
int agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force);
GCRY_SEXP agent_key_from_file (const unsigned char *grip,
GCRY_SEXP agent_key_from_file (CTRL ctrl, const unsigned char *grip,
unsigned char **shadow_info, int ignore_cache);
int agent_key_available (const unsigned char *grip);
/*-- query.c --*/
int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
int agent_get_passphrase (char **retpass,
int agent_askpin (CTRL ctrl,
const char *desc_text, struct pin_entry_info_s *pininfo);
int agent_get_passphrase (CTRL ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext);
int agent_get_confirmation (const char *desc, const char *ok,
int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok,
const char *cancel);
/*-- cache.c --*/
@ -143,6 +145,7 @@ int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
/*-- genkey.c --*/
int agent_genkey (CTRL ctrl,
const char *keyparam, size_t keyparmlen, FILE *outfp);
int agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey);
/*-- protect.c --*/
int agent_protect (const unsigned char *plainkey, const char *passphrase,
@ -160,13 +163,15 @@ int agent_get_shadow_info (const unsigned char *shadowkey,
/*-- trustlist.c --*/
int agent_istrusted (const char *fpr);
int agent_listtrusted (void *assuan_context);
int agent_marktrusted (const char *name, const char *fpr, int flag);
int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag);
/*-- divert-scd.c --*/
int divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
int divert_pksign (CTRL ctrl,
const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig);
int divert_pkdecrypt (const unsigned char *cipher,
int divert_pkdecrypt (CTRL ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
char **r_buf, size_t *r_len);

View file

@ -67,7 +67,7 @@ new_data (const void *data, size_t length)
secure storage provider*/
total = length + 32 - (length % 32);
d = gcry_malloc_secure (sizeof d + total - 1);
d = gcry_malloc_secure (sizeof *d + total - 1);
if (d)
{
d->totallen = total;

View file

@ -77,6 +77,48 @@ has_option (const char *line, const char *name)
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
}
/* Parse a hex string. Return an Assuan error code or 0 on success and the
length of the parsed string in LEN. */
static int
parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
{
const char *p;
size_t n;
/* parse the hash value */
for (p=string, n=0; hexdigitp (p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
*len = n;
return 0;
}
/* Parse the keygrip in STRING into the provided buffer BUF. BUF must
provide space for 20 bytes. BUF is not changed if the fucntions
returns an error. */
static int
parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
{
int rc;
size_t n;
const unsigned char *p;
rc = parse_hexstring (ctx, string, &n);
if (rc)
return rc;
n /= 2;
if (n != 20)
return set_error (Parameter_Error, "invalid length of keygrip");
for (p=string, n=0; n < 20; p += 2, n++)
buf[n] = xtoi_2 (p);
return 0;
}
@ -136,6 +178,7 @@ cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc, n, i;
char *p;
char fpr[41];
@ -164,7 +207,7 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
while (spacep (p))
p++;
rc = agent_marktrusted (p, fpr, flag);
rc = agent_marktrusted (ctrl, p, fpr, flag);
if (rc)
log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc));
return map_to_assuan_status (rc);
@ -179,23 +222,12 @@ cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
{
int n;
char *p;
int rc;
unsigned char buf[20];
/* parse the hash value */
for (p=line,n=0; hexdigitp (p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
n /= 2;
if (n != 20)
return set_error (Parameter_Error, "invalid length of keygrip");
for (p=line, n=0; n < 20; p += 2, n++)
buf[n] = xtoi_2 (p);
rc = parse_keygrip (ctx, line, buf);
if (rc)
return rc;
if (agent_key_available (buf))
return ASSUAN_No_Secret_Key;
@ -211,29 +243,17 @@ cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
{
int n;
char *p;
int rc;
CTRL ctrl = assuan_get_pointer (ctx);
unsigned char *buf;
/* parse the hash value */
for (p=line,n=0; hexdigitp (p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
n /= 2;
if (n != 20)
return set_error (Parameter_Error, "invalid length of keygrip");
buf = ctrl->keygrip;
for (p=line, n=0; n < 20; p += 2, n++)
buf[n] = xtoi_2 (p);
rc = parse_keygrip (ctx, line, ctrl->keygrip);
if (rc)
return rc;
ctrl->have_keygrip = 1;
return 0;
}
/* SETHASH <algonumber> <hexstring>
The client can use this command to tell the server about the data
@ -241,7 +261,8 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
static int
cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
{
int n;
int rc;
size_t n;
char *p;
CTRL ctrl = assuan_get_pointer (ctx);
unsigned char *buf;
@ -257,12 +278,9 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
ctrl->digest.algo = algo;
/* parse the hash value */
for (p=line,n=0; hexdigitp (p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
rc = parse_hexstring (ctx, line, &n);
if (rc)
return rc;
n /= 2;
if (n != 16 && n != 20 && n != 24 && n != 32)
return set_error (Parameter_Error, "unsupported length of hash");
@ -386,6 +404,7 @@ plus_to_blank (char *s)
static int
cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
const char *pw;
char *response;
@ -459,7 +478,7 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
if (desc)
plus_to_blank (desc);
rc = agent_get_passphrase (&response, desc, prompt, errtext);
rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
if (!rc)
{
if (cacheid)
@ -519,53 +538,93 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
}
/* PASSWD <hexstring_with_keygrip>
Change the passphrase/PID for the key identified by keygrip in LINE. */
static int
cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
unsigned char grip[20];
GCRY_SEXP s_skey = NULL;
unsigned char *shadow_info = NULL;
rc = parse_keygrip (ctx, line, grip);
if (rc)
return rc; /* we can't jump to leave because this is already an
Assuan error code. */
s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1);
if (!s_skey && !shadow_info)
rc = seterr (No_Secret_Key);
else if (!s_skey)
{
log_error ("changing a smartcard PIN is not yet supported\n");
rc = seterr (Not_Implemented);
}
else
rc = agent_protect_and_store (ctrl, s_skey);
gcry_sexp_release (s_skey);
xfree (shadow_info);
if (rc)
log_error ("command passwd failed: %s\n", gnupg_strerror (rc));
return map_to_assuan_status (rc);
}
static int
option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
{
CTRL ctrl = assuan_get_pointer (ctx);
/* FIXME: We should not change opt. here. It is not a problem right
now but as soon as we are allowing concurrent connections we mess
things up */
if (!strcmp (key, "display"))
{
if (opt.display)
free (opt.display);
opt.display = strdup (value);
if (!opt.display)
if (ctrl->display)
free (ctrl->display);
ctrl->display = strdup (value);
if (!ctrl->display)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "ttyname"))
{
if (opt.ttyname)
free (opt.ttyname);
opt.ttyname = strdup (value);
if (!opt.ttyname)
return ASSUAN_Out_Of_Core;
if (!opt.keep_tty)
{
if (ctrl->ttyname)
free (ctrl->ttyname);
ctrl->ttyname = strdup (value);
if (!ctrl->ttyname)
return ASSUAN_Out_Of_Core;
}
}
else if (!strcmp (key, "ttytype"))
{
if (opt.ttytype)
free (opt.ttytype);
opt.ttytype = strdup (value);
if (!opt.ttytype)
return ASSUAN_Out_Of_Core;
if (!opt.keep_tty)
{
if (ctrl->ttytype)
free (ctrl->ttytype);
ctrl->ttytype = strdup (value);
if (!ctrl->ttytype)
return ASSUAN_Out_Of_Core;
}
}
else if (!strcmp (key, "lc-ctype"))
{
if (opt.lc_ctype)
free (opt.lc_ctype);
opt.lc_ctype = strdup (value);
if (!opt.lc_ctype)
if (ctrl->lc_ctype)
free (ctrl->lc_ctype);
ctrl->lc_ctype = strdup (value);
if (!ctrl->lc_ctype)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "lc-messages"))
{
if (opt.lc_messages)
free (opt.lc_messages);
opt.lc_messages = strdup (value);
if (!opt.lc_messages)
if (ctrl->lc_messages)
free (ctrl->lc_messages);
ctrl->lc_messages = strdup (value);
if (!ctrl->lc_messages)
return ASSUAN_Out_Of_Core;
}
else if (!strcmp (key, "use-cache-for-signing"))
@ -599,6 +658,7 @@ register_commands (ASSUAN_CONTEXT ctx)
{ "LISTTRUSTED", 0, cmd_listtrusted },
{ "MARKTRUSTED", 0, cmd_marktrusted },
{ "LEARN", 0, cmd_learn },
{ "PASSWD", 0, cmd_passwd },
{ "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL },
{ NULL }
@ -630,6 +690,7 @@ start_command_handler (int listen_fd, int fd)
struct server_control_s ctrl;
memset (&ctrl, 0, sizeof ctrl);
agent_init_default_ctrl (&ctrl);
if (listen_fd == -1 && fd == -1)
{
@ -693,5 +754,15 @@ start_command_handler (int listen_fd, int fd)
assuan_deinit_server (ctx);
if (ctrl.display)
free (ctrl.display);
if (ctrl.ttyname)
free (ctrl.ttyname);
if (ctrl.ttytype)
free (ctrl.ttytype);
if (ctrl.lc_ctype)
free (ctrl.lc_ctype);
if (ctrl.lc_messages)
free (ctrl.lc_messages);
}

View file

@ -34,7 +34,7 @@
static int
ask_for_card (const unsigned char *shadow_info, char **r_kid)
ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
{
int rc, i;
const unsigned char *s;
@ -119,7 +119,7 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
}
else
{
rc = agent_get_confirmation (desc, NULL, NULL);
rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
free (desc);
}
}
@ -174,8 +174,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
struct pin_entry_info_s *pi;
int rc;
char *desc;
assert (!opaque);
CTRL ctrl = opaque;
if (maxbuf < 2)
return GNUPG_Invalid_Value;
@ -195,7 +194,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
info? info:"",
info? "')":"") < 0)
desc = NULL;
rc = agent_askpin (desc?desc:info, pi);
rc = agent_askpin (ctrl, desc?desc:info, pi);
free (desc);
if (!rc)
{
@ -210,7 +209,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
int
divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
divert_pksign (CTRL ctrl,
const unsigned char *digest, size_t digestlen, int algo,
const unsigned char *shadow_info, unsigned char **r_sig)
{
int rc;
@ -220,7 +220,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
unsigned char *data;
size_t ndata;
rc = ask_for_card (shadow_info, &kid);
rc = ask_for_card (ctrl, shadow_info, &kid);
if (rc)
return rc;
@ -229,7 +229,7 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
if (rc)
return rc;
rc = agent_card_pksign (kid, getpin_cb, NULL,
rc = agent_card_pksign (kid, getpin_cb, ctrl,
data, ndata, &sigval, &siglen);
if (!rc)
*r_sig = sigval;
@ -244,7 +244,8 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
key identified by SHADOW_INFO and return the plaintext in an
allocated buffer in R_BUF. */
int
divert_pkdecrypt (const unsigned char *cipher,
divert_pkdecrypt (CTRL ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
char **r_buf, size_t *r_len)
{
@ -288,11 +289,11 @@ divert_pkdecrypt (const unsigned char *cipher,
ciphertext = s;
ciphertextlen = n;
rc = ask_for_card (shadow_info, &kid);
rc = ask_for_card (ctrl, shadow_info, &kid);
if (rc)
return rc;
rc = agent_card_pkdecrypt (kid, getpin_cb, NULL,
rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl,
ciphertext, ciphertextlen,
&plaintext, &plaintextlen);
if (!rc)

View file

@ -131,9 +131,10 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
should be the hex encoded keygrip of that key to be used with the
cahing mechanism. */
caching mechanism. */
static int
unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
unprotect (CTRL ctrl,
unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
{
struct pin_entry_info_s *pi;
struct try_unprotect_arg_s arg;
@ -176,7 +177,7 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
arg.unprotected_key = NULL;
pi->check_cb_arg = &arg;
rc = agent_askpin (NULL, pi);
rc = agent_askpin (ctrl, NULL, pi);
if (!rc)
{
assert (arg.unprotected_key);
@ -197,7 +198,8 @@ unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
With IGNORE_CACHE passed as true the passphrase is not taken from
the cache.*/
GCRY_SEXP
agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
agent_key_from_file (CTRL ctrl,
const unsigned char *grip, unsigned char **shadow_info,
int ignore_cache)
{
int i, rc;
@ -271,7 +273,7 @@ agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
case PRIVATE_KEY_CLEAR:
break; /* no unprotection needed */
case PRIVATE_KEY_PROTECTED:
rc = unprotect (&buf, grip, ignore_cache);
rc = unprotect (ctrl, &buf, grip, ignore_cache);
if (rc)
log_error ("failed to unprotect the secret key: %s\n",
gnupg_strerror (rc));

View file

@ -30,7 +30,7 @@
#include "i18n.h"
static int
store_key (GCRY_SEXP private, const char *passphrase)
store_key (GCRY_SEXP private, const char *passphrase, int force)
{
int rc;
char *buf;
@ -65,13 +65,13 @@ store_key (GCRY_SEXP private, const char *passphrase)
buf = p;
}
rc = agent_write_private_key (grip, buf, len, 0);
rc = agent_write_private_key (grip, buf, len, force);
xfree (buf);
return rc;
}
/* Callback function to compare the first entered PIN with the one
currently beeing entered. */
currently being entered. */
static int
reenter_compare_cb (struct pin_entry_info_s *pi)
{
@ -119,9 +119,9 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
pi2->check_cb = reenter_compare_cb;
pi2->check_cb_arg = pi->pin;
rc = agent_askpin (text1, pi);
rc = agent_askpin (ctrl, text1, pi);
if (!rc)
rc = agent_askpin (text2, pi2);
rc = agent_askpin (ctrl, text2, pi2);
if (rc)
return rc;
if (!*pi->pin)
@ -162,7 +162,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
/* store the secret key */
log_debug ("storing private key\n");
rc = store_key (s_private, pi? pi->pin:NULL);
rc = store_key (s_private, pi? pi->pin:NULL, 0);
xfree (pi); pi = NULL;
gcry_sexp_release (s_private);
if (rc)
@ -198,3 +198,41 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
return 0;
}
/* Apply a new passpahrse to the key S_SKEY and store it. */
int
agent_protect_and_store (CTRL ctrl, GCRY_SEXP s_skey)
{
struct pin_entry_info_s *pi, *pi2;
int rc;
{
const char *text1 = _("Please enter the new passphrase");
const char *text2 = _("Please re-enter this passphrase");
pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
pi2 = pi + (sizeof *pi + 100);
pi->max_length = 100;
pi->max_tries = 3;
pi2->max_length = 100;
pi2->max_tries = 3;
pi2->check_cb = reenter_compare_cb;
pi2->check_cb_arg = pi->pin;
rc = agent_askpin (ctrl, text1, pi);
if (!rc)
rc = agent_askpin (ctrl, text2, pi2);
if (rc)
return rc;
if (!*pi->pin)
{
xfree (pi);
pi = NULL; /* User does not want a passphrase. */
}
}
rc = store_key (s_skey, pi? pi->pin:NULL, 1);
xfree (pi);
return 0;
}

View file

@ -137,6 +137,18 @@ static int maybe_setuid = 1;
/* Name of the communication socket */
static char socket_name[128];
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
static char *default_ttytype;
static char *default_lc_ctype;
static char *default_lc_messages;
/* Name of a config file, which will be reread on a HUP if it is not NULL. */
static char *config_filename;
/* Local prototypes. */
static void create_directories (void);
#ifdef USE_GNU_PTH
static void handle_connections (int listen_fd);
@ -248,6 +260,51 @@ cleanup_sh (int sig)
raise( sig );
}
/* Handle options which are allowed to be reset after program start.
Return true when the current option in PARGS could be handled and
false if not. As a special feature, passing a value of NULL for
PARGS, resets the options to the default. */
static int
parse_rereadable_options (ARGPARSE_ARGS *pargs)
{
if (!pargs)
{ /* reset mode */
opt.quiet = 0;
opt.verbose = 0;
opt.debug = 0;
opt.no_grab = 0;
opt.pinentry_program = NULL;
opt.scdaemon_program = NULL;
opt.def_cache_ttl = 10*60; /* default to 10 minutes */
opt.ignore_cache_for_signing = 0;
return 1;
}
switch (pargs->r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oDebug: opt.debug |= pargs->r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oNoGrab: opt.no_grab = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break;
case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break;
case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
default:
return 0; /* not handled */
}
return 1; /* handled */
}
int
main (int argc, char **argv )
{
@ -288,15 +345,14 @@ main (int argc, char **argv )
}
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
#ifdef USE_GNU_PTH
assuan_set_io_func (pth_read, pth_write);
#endif
gcry_set_log_handler (my_gcry_logger, NULL);
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = disable_core_dumps ();
parse_rereadable_options (NULL); /* Reset them to default values. */
shell = getenv ("SHELL");
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
csh_style = 1;
@ -304,7 +360,6 @@ main (int argc, char **argv )
opt.homedir = getenv("GNUPGHOME");
if (!opt.homedir || !*opt.homedir)
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
opt.def_cache_ttl = 10*60; /* default to 10 minutes */
/* check whether we have a config file on the commandline */
@ -375,14 +430,12 @@ main (int argc, char **argv )
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
{
if (parse_rereadable_options (&pargs))
continue; /* Already handled */
switch (pargs.r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oVerbose: opt.verbose++; break;
case oBatch: opt.batch=1; break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
@ -399,7 +452,6 @@ main (int argc, char **argv )
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoDetach: nodetach = 1; break;
case oNoGrab: opt.no_grab = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oCsh: csh_style = 1; break;
case oSh: csh_style = 0; break;
@ -407,16 +459,12 @@ main (int argc, char **argv )
case oDaemon: is_daemon = 1; break;
case oDisablePth: disable_pth = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break;
case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break;
case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break;
case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break;
case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break;
case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
@ -427,7 +475,8 @@ main (int argc, char **argv )
{
fclose( configfp );
configfp = NULL;
xfree(configname);
/* Keep a copy of the name so that it can be read on SIGHUP. */
config_filename = configname;
configname = NULL;
goto next_pass;
}
@ -465,7 +514,22 @@ main (int argc, char **argv )
sleep (debug_wait);
log_debug ("... okay\n");
}
if (!pipe_server && !is_daemon)
log_info (_("please use the option `--daemon'"
" to run the program in the background\n"));
#ifdef ENABLE_NLS
/* gpg-agent usdually does not ooutput any messages becuase it runs
in the background. For log files it is acceptable to have
messages always encoded in utf-8. We switch here to utf-8, so
that commands like --help still give native messages. It is far
easier to swicthnonly once instead of for every message and it
actually helps when more then one thread is active (avoids
required an extra copy step). */
bind_textdomain_codeset (PACKAGE, "UTF-8");
#endif
/* now start with logging to a file if this is desired */
if (logfile)
{
@ -473,16 +537,18 @@ main (int argc, char **argv )
log_set_prefix (NULL, 1|2|4);
}
/* Make sure that we have a default ttyname. */
if (!default_ttyname && ttyname (1))
default_ttyname = xstrdup (ttyname (1));
if (!default_ttytype && getenv ("TERM"))
default_ttytype = xstrdup (getenv ("TERM"));
if (pipe_server)
{ /* this is the simple pipe based server */
start_command_handler (-1, -1);
}
else if (!is_daemon)
{
log_info (_("please use the option `--daemon'"
" to run the program in the background\n"));
}
;
else
{ /* regular server mode */
int fd;
@ -491,6 +557,13 @@ main (int argc, char **argv )
struct sockaddr_un serv_addr;
char *p;
/* Remove the DISPLAY variable so that a pinentry does not
default to a specific display. There is still a default
display when gpg-agent weas started using --display or a
client requested this using an OPTION command. */
if (!opt.keep_display)
unsetenv ("DISPLAY");
*socket_name = 0;
snprintf (socket_name, DIM(socket_name)-1,
"/tmp/gpg-XXXXXX/S.gpg-agent");
@ -702,10 +775,76 @@ agent_exit (int rc)
}
void
agent_init_default_ctrl (struct server_control_s *ctrl)
{
/* Note we ignore malloc errors because we can't do much about it
and the request will fail anyway shortly after this
initialization. */
if (ctrl->display)
free (ctrl->display);
ctrl->display = default_display? strdup (default_display) : NULL;
if (ctrl->ttyname)
free (ctrl->ttyname);
ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL;
if (ctrl->ttytype)
free (ctrl->ttytype);
ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL;
if (ctrl->lc_ctype)
free (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL;
if (ctrl->lc_messages)
free (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL;
}
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
signal handler.
Fixme: Due to the way the argument parsing works, we create a
memory leak here for all string type arguments. There is currently
no clean way to tell whether the memory for the argument has been
allocated or points into the process' original arguments. Unless
we have a mechanism to tell this, we need to live on with this. */
static void
reread_configuration (void)
{
/* FIXME: Move parts of the option parsing to here. */
ARGPARSE_ARGS pargs;
FILE *fp;
unsigned int configlineno = 0;
int dummy;
if (!config_filename)
return; /* No config file. */
fp = fopen (config_filename, "r");
if (!fp)
{
log_error (_("option file `%s': %s\n"),
config_filename, strerror(errno) );
return;
}
parse_rereadable_options (NULL); /* Start from the default values. */
memset (&pargs, 0, sizeof pargs);
dummy = 0;
pargs.argc = &dummy;
pargs.flags = 1; /* do not remove the args */
while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) )
{
if (pargs.r_opt < -1)
pargs.err = 1; /* Print a warning. */
else /* Try to parse this option - ignore unchangeable ones. */
parse_rereadable_options (&pargs);
}
fclose (fp);
}

View file

@ -64,7 +64,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
log_printhex ("keygrip:", ctrl->keygrip, 20);
log_printhex ("cipher: ", ciphertext, ciphertextlen);
}
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0);
s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
@ -81,7 +81,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
goto leave;
}
rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len );
rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len );
if (rc)
{
log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc));

View file

@ -1,5 +1,5 @@
/* pksign.c - public key signing (well, acually using a secret key)
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -98,7 +98,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
if (!ctrl->have_keygrip)
return seterr (No_Secret_Key);
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache);
s_skey = agent_key_from_file (ctrl,
ctrl->keygrip, &shadow_info, ignore_cache);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
@ -110,7 +111,8 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
{ /* divert operation to the smartcard */
unsigned char *sigbuf;
rc = divert_pksign (ctrl->digest.value,
rc = divert_pksign (ctrl,
ctrl->digest.value,
ctrl->digest.valuelen,
ctrl->digest.algo,
shadow_info, &sigbuf);

View file

@ -275,6 +275,8 @@ read_key (const char *fname)
unsigned char *key;
buf = read_file (fname, &buflen);
if (!buf)
return NULL;
key = make_canonical (fname, buf, buflen);
xfree (buf);
return key;

View file

@ -1,5 +1,5 @@
/* query.c - fork of the pinentry to query stuff from the user
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -56,9 +56,15 @@ struct entry_parm_s {
/* Unlock the pinentry so that another thread can start one and
disconnect that pinentry - we do this after the unlock so that a
stalled pinentry does not block other threads. Fixme: We should
have a timeout in Assuan for the disconnetc operation. */
static int
unlock_pinentry (int rc)
{
ASSUAN_CONTEXT ctx = entry_ctx;
#ifdef USE_GNU_PTH
if (!pth_mutex_release (&entry_lock))
{
@ -67,6 +73,8 @@ unlock_pinentry (int rc)
rc = GNUPG_Internal_Error;
}
#endif
entry_ctx = NULL;
assuan_disconnect (ctx);
return rc;
}
@ -75,7 +83,7 @@ unlock_pinentry (int rc)
pinentry - we will serialize _all_ pinentry calls.
*/
static int
start_pinentry (void)
start_pinentry (CTRL ctrl)
{
int rc;
const char *pgmname;
@ -96,7 +104,7 @@ start_pinentry (void)
return 0;
if (opt.verbose)
log_info ("no running PIN Entry - starting it\n");
log_info ("starting a new PIN Entry\n");
if (fflush (NULL))
{
@ -111,12 +119,11 @@ start_pinentry (void)
else
pgmname++;
/* FIXME: We must do this thread specific */
argv[0] = pgmname;
if (opt.display && !opt.keep_display)
if (ctrl->display && !opt.keep_display)
{
argv[1] = "--display";
argv[2] = opt.display;
argv[2] = ctrl->display;
argv[3] = NULL;
}
else
@ -150,10 +157,10 @@ start_pinentry (void)
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
if (opt.ttyname && !opt.keep_tty)
if (ctrl->ttyname)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@ -161,30 +168,30 @@ start_pinentry (void)
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
if (opt.ttytype && !opt.keep_tty)
if (ctrl->ttytype)
{
char *optstr;
if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
if (opt.lc_ctype)
if (ctrl->lc_ctype)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
if (rc)
return unlock_pinentry (map_assuan_err (rc));
}
if (opt.lc_messages)
if (ctrl->lc_messages)
{
char *optstr;
if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
return unlock_pinentry (GNUPG_Out_Of_Core);
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@ -230,7 +237,8 @@ all_digitsp( const char *s)
number here and repeat it as long as we have invalid formed
numbers. */
int
agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
agent_askpin (CTRL ctrl,
const char *desc_text, struct pin_entry_info_s *pininfo)
{
int rc;
char line[ASSUAN_LINELENGTH];
@ -252,7 +260,7 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
is_pin = desc_text && strstr (desc_text, "PIN");
rc = start_pinentry ();
rc = start_pinentry (ctrl);
if (rc)
return rc;
@ -335,7 +343,8 @@ agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
passphrase is returned in RETPASS as an hex encoded string to be
freed by the caller */
int
agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
agent_get_passphrase (CTRL ctrl,
char **retpass, const char *desc, const char *prompt,
const char *errtext)
{
@ -349,7 +358,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
if (opt.batch)
return GNUPG_Bad_Passphrase;
rc = start_pinentry ();
rc = start_pinentry (ctrl);
if (rc)
return rc;
@ -417,12 +426,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
confirmed it, GNUPG_Not_Confirmed for what the text says or an
other error. */
int
agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
agent_get_confirmation (CTRL ctrl,
const char *desc, const char *ok, const char *cancel)
{
int rc;
char line[ASSUAN_LINELENGTH];
rc = start_pinentry ();
rc = start_pinentry (ctrl);
if (rc)
return rc;

View file

@ -177,9 +177,10 @@ agent_send_all_options (int fd)
return rc;
}
if (ttyname (1))
dft_ttyname = ttyname (1);
if (dft_ttyname)
dft_ttyname = getenv ("GPG_TTY");
if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
dft_ttyname = ttyname (0);
if (dft_ttyname && *dft_ttyname)
{
if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
return rc;

View file

@ -228,7 +228,7 @@ agent_listtrusted (void *assuan_context)
whether this is actual wants he want to do.
*/
int
agent_marktrusted (const char *name, const char *fpr, int flag)
agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag)
{
int rc;
static char key[41];
@ -254,7 +254,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
"has the fingerprint:%%0A"
" %s", name, fpr) < 0 )
return GNUPG_Out_Of_Core;
rc = agent_get_confirmation (desc, "Correct", "No");
rc = agent_get_confirmation (ctrl, desc, "Correct", "No");
free (desc);
if (rc)
return rc;
@ -265,7 +265,7 @@ agent_marktrusted (const char *name, const char *fpr, int flag)
"to correctly certify user certificates?",
name) < 0 )
return GNUPG_Out_Of_Core;
rc = agent_get_confirmation (desc, "Yes", "No");
rc = agent_get_confirmation (ctrl, desc, "Yes", "No");
free (desc);
if (rc)
return rc;