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;

View File

@ -1,3 +1,14 @@
2002-10-31 Neal H. Walfield <neal@g10code.de>
* isascii.c: New file.
* putc_unlocked.c: Likewise.
2002-10-28 Neal H. Walfield <neal@g10code.de>
* signal.c (caught_fatal_sig): Remove superfluous zero
initializer.
(caught_sigusr1): Likewise.
2002-09-04 Neal H. Walfield <neal@g10code.de>
* vasprintf.c (vasprintf) [va_copy]: Use va_copy.

29
common/isascii.c Normal file
View File

@ -0,0 +1,29 @@
/* isascii.c - Replacement for isascii.
* Copyright (C) 2002 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
int
isascii (int c)
{
return (((c) & ~0x7f) == 0);
}

31
common/putc_unlocked.c Normal file
View File

@ -0,0 +1,31 @@
/* putc_unlocked.c - Replacement for putc_unlocked.
* Copyright (C) 2002 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
int
putc_unlocked (int c, FILE *stream)
{
return putc (c, stream);
}

View File

@ -30,8 +30,8 @@
#include "util.h"
static volatile int caught_fatal_sig = 0;
static volatile int caught_sigusr1 = 0;
static volatile int caught_fatal_sig;
static volatile int caught_sigusr1;
static void (*cleanup_fnc)(void);

View File

@ -1,3 +1,12 @@
2002-11-14 Werner Koch <wk@gnupg.org>
* keybox-search.c (blob_cmp_name) <compare all names>: Fixed
length compare; there is no 0 stored since nearly a year.
2002-10-31 Neal H. Walfield <neal@g10code.de>
* Makefile.am (AM_CPPFLAGS): Fix ytpo.
2002-08-10 Werner Koch <wk@gnupg.org>
* keybox-search.c (blob_cmp_fpr_part): New.
@ -16,7 +25,7 @@
2002-06-19 Werner Koch <wk@gnupg.org>
* keybox-init.c (keybox_set_ephemeral): New.
* keybox-blob.c (create_blob_header): Store epheermal flag.
* keybox-blob.c (create_blob_header): Store ephemeral flag.
(_keybox_create_x509_blob): Pass epheermal flag on.
* keybox-update.c (keybox_insert_cert): Ditto.
* keybox-search.c (blob_get_blob_flags): New.

View File

@ -1,5 +1,5 @@
# Keybox Makefile
# Copyright (C) 2001 Free Software Foundation, Inc.
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
@ -23,7 +23,7 @@ localedir = $(datadir)/locale
INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
EXTRA_DIST = mkerrors
AM_CPPFLAGS = $(KSBA_CFLAGS) $(LIBGCRYPT_CLFAGS)
AM_CPPFLAGS = $(KSBA_CFLAGS) $(LIBGCRYPT_CFLAGS)
BUILT_SOURCES = keybox-errors.c
noinst_LIBRARIES = libkeybox.a

View File

@ -234,9 +234,8 @@ blob_cmp_name (KEYBOXBLOB blob, int idx,
len = get32 (buffer+mypos+4);
if (off+len > length)
return 0; /* error: better stop here out of bounds */
if (len < 2)
continue; /* empty name or 0 not stored */
len--;
if (len < 1)
continue; /* empty name */
if (substr)
{
if (ascii_memcasemem (buffer+off, len, name, namelen))

View File

@ -1,3 +1,35 @@
2002-12-03 Werner Koch <wk@gnupg.org>
* call-agent.c (gpgsm_agent_passwd): New.
* gpgsm.c (main): New command --passwd and --call-protect-tool
(run_protect_tool): New.
2002-11-25 Werner Koch <wk@gnupg.org>
* verify.c (gpgsm_verify): Handle content-type attribute.
2002-11-13 Werner Koch <wk@gnupg.org>
* call-agent.c (start_agent): Try to use $GPG_TTY instead of
ttyname. Changed ttyname to test stdin becuase it can be assumed
that output redirection is more common that input redirection.
2002-11-12 Werner Koch <wk@gnupg.org>
* gpgsm.c: New command --call-dirmngr.
* call-dirmngr.c (gpgsm_dirmngr_run_command)
(run_command_inq_cb,run_command_cb)
(run_command_status_cb): New.
2002-11-11 Werner Koch <wk@gnupg.org>
* certcheck.c (gpgsm_check_cms_signature): Don't double free
s_sig but free s_pkey at leave.
2002-11-10 Werner Koch <wk@gnupg.org>
* gpgsm.c: Removed duplicate --list-secret-key entry.
2002-09-19 Werner Koch <wk@gnupg.org>
* certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.

View File

@ -248,8 +248,12 @@ start_agent (void)
if (rc)
return map_assuan_err (rc);
}
if (!opt.ttyname && ttyname (1))
dft_ttyname = ttyname (1);
if (!opt.ttyname)
{
dft_ttyname = getenv ("GPG_TTY");
if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
dft_ttyname = ttyname (0);
}
if (opt.ttyname || dft_ttyname)
{
char *optstr;
@ -749,3 +753,25 @@ gpgsm_agent_learn ()
return learn_parm.error;
}
/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
int
gpgsm_agent_passwd (const char *hexkeygrip)
{
int rc;
char line[ASSUAN_LINELENGTH];
rc = start_agent ();
if (rc)
return rc;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
return GNUPG_Invalid_Value;
snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
return map_assuan_err (rc);
}

View File

@ -26,6 +26,7 @@
#include <unistd.h>
#include <time.h>
#include <assert.h>
#include <ctype.h>
#include <gcrypt.h>
@ -59,7 +60,9 @@ struct lookup_parm_s {
int error;
};
struct run_command_parm_s {
ASSUAN_CONTEXT ctx;
};
/* A simple implementation of a dynamic buffer. Use init_membuf() to
@ -452,7 +455,7 @@ lookup_status_cb (void *opaque, const char *line)
}
/* Run the Directroy Managers lookup command using the apptern
/* Run the Directroy Managers lookup command using the pattern
compiled from the strings given in NAMES. The caller must provide
the callback CB which will be passed cert by cert. Note that CTRL
is optional. */
@ -493,3 +496,136 @@ gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
}
/* Run Command helpers*/
/* Fairly simple callback to write all output of dirmngr to stdout. */
static AssuanError
run_command_cb (void *opaque, const void *buffer, size_t length)
{
if (buffer)
{
if ( fwrite (buffer, length, 1, stdout) != 1 )
log_error ("error writing to stdout: %s\n", strerror (errno));
}
return 0;
}
/* Handle inquiries from the dirmngr COMMAND. */
static AssuanError
run_command_inq_cb (void *opaque, const char *line)
{
struct run_command_parm_s *parm = opaque;
AssuanError rc = 0;
if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
{ /* send the given certificate */
int err;
KsbaCert cert;
const unsigned char *der;
size_t derlen;
line += 8;
if (!*line)
return ASSUAN_Inquire_Error;
err = gpgsm_find_cert (line, &cert);
if (err)
{
log_error ("certificate not found: %s\n", gnupg_strerror (err));
rc = ASSUAN_Inquire_Error;
}
else
{
der = ksba_cert_get_image (cert, &derlen);
if (!der)
rc = ASSUAN_Inquire_Error;
else
rc = assuan_send_data (parm->ctx, der, derlen);
ksba_cert_release (cert);
}
}
else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
{ /* Simply show the message given in the argument. */
line += 9;
log_info ("dirmngr: %s\n", line);
}
else
{
log_error ("unsupported inquiry `%s'\n", line);
rc = ASSUAN_Inquire_Unknown;
}
return rc;
}
static AssuanError
run_command_status_cb (void *opaque, const char *line)
{
if (opt.verbose)
{
log_info ("dirmngr status: %s\n", line);
}
return 0;
}
/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
to stdout. A couple of inquiries are defined (see above). ARGC
arguments in ARGV are given to the Dirmngr. Spaces, plus and
percent characters within the argument strings are percent escaped
so that blanks can act as delimiters. */
int
gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
int argc, char **argv)
{
int rc;
int i;
const char *s;
char *line, *p;
size_t len;
struct run_command_parm_s parm;
rc = start_dirmngr ();
if (rc)
return rc;
parm.ctx = dirmngr_ctx;
len = strlen (command) + 1;
for (i=0; i < argc; i++)
len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
line = xtrymalloc (len);
if (!line)
return GNUPG_Out_Of_Core;
p = stpcpy (line, command);
for (i=0; i < argc; i++)
{
*p++ = ' ';
for (s=argv[i]; *s; s++)
{
if (!isascii (*s))
*p++ = *s;
else if (*s == ' ')
*p++ = '+';
else if (!isprint (*s) || *s == '+')
{
sprintf (p, "%%%02X", *s);
p += 3;
}
else
*p++ = *s;
}
}
*p = 0;
rc = assuan_transact (dirmngr_ctx, line,
run_command_cb, NULL,
run_command_inq_cb, &parm,
run_command_status_cb, NULL);
xfree (line);
log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
return map_assuan_err (rc);
}

View File

@ -266,13 +266,12 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
BUG ();
gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_hash);
gcry_sexp_release (s_sig);
gcry_sexp_release (s_pkey);
return map_gcry_err (rc);
}

View File

@ -77,6 +77,9 @@ enum cmd_and_opt_values {
aCheckKeys, /* nyi */
aServer,
aLearnCard,
aCallDirmngr,
aCallProtectTool,
aPasswd,
oOptions,
oDebug,
@ -139,7 +142,6 @@ enum cmd_and_opt_values {
oCipherAlgo,
oDigestAlgo,
oCompressAlgo,
oPasswdFD,
oCommandFD,
oNoVerbose,
oTrustDBName,
@ -219,7 +221,6 @@ static ARGPARSE_OPTS opts[] = {
{ aListSigs, "list-sigs", 256, N_("list certificate chain")},
{ aListSigs, "check-sigs",256, "@"},
{ oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
{ aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
{ aKeygen, "gen-key", 256, N_("generate a new key pair")},
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
{ aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
@ -228,7 +229,10 @@ static ARGPARSE_OPTS opts[] = {
{ aExport, "export", 256 , N_("export certificates")},
{ aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
{ aServer, "server", 256, N_("run in server mode")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")},
{ aCallProtectTool, "call-protect-tool", 256,
N_("invoke gpg-protect-tool")},
{ aPasswd, "passwd", 256, N_("change a passphrase")},
{ 301, NULL, 0, N_("@\nOptions:\n ") },
@ -283,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
#if 0
{ oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
{ oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
@ -406,6 +411,7 @@ static void emergency_cleanup (void);
static int check_special_filename (const char *fname);
static int open_read (const char *filename);
static FILE *open_fwrite (const char *filename);
static void run_protect_tool (int argc, char **argv);
static int
@ -589,6 +595,7 @@ main ( int argc, char **argv)
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
int no_more_options = 0;
int default_config =1;
int default_keyring = 1;
char *logfile = NULL;
@ -666,6 +673,9 @@ main ( int argc, char **argv)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
opt.homedir = pargs.r.ret_str;
else if (pargs.r_opt == aCallProtectTool)
break; /* This break makes sure that --version and --help are
passed to the protect-tool. */
}
@ -724,7 +734,8 @@ main ( int argc, char **argv)
default_config = 0;
}
while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
while (!no_more_options
&& optfile_parse (configfp, configname, &configlineno, &pargs, opts))
{
switch (pargs.r_opt)
{
@ -732,7 +743,17 @@ main ( int argc, char **argv)
opt.batch = 1;
set_cmd (&cmd, aServer);
break;
case aCallDirmngr:
opt.batch = 1;
set_cmd (&cmd, aCallDirmngr);
break;
case aCallProtectTool:
opt.batch = 1;
set_cmd (&cmd, aCallProtectTool);
no_more_options = 1; /* Stop parsing. */
break;
case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
case aImport: set_cmd (&cmd, aImport); break;
case aSendKeys: set_cmd (&cmd, aSendKeys); break;
@ -744,6 +765,8 @@ main ( int argc, char **argv)
case aListSigs: set_cmd (&cmd, aListSigs); break;
case aLearnCard: set_cmd (&cmd, aLearnCard); break;
case aPasswd: set_cmd (&cmd, aPasswd); break;
case aDeleteKey:
set_cmd (&cmd, aDeleteKey);
@ -1128,6 +1151,18 @@ main ( int argc, char **argv)
gpgsm_server ();
break;
case aCallDirmngr:
if (!argc)
wrong_args (_("--call-dirmngr <command> {args}"));
else
if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1))
gpgsm_exit (1);
break;
case aCallProtectTool:
run_protect_tool (argc, argv);
break;
case aEncr: /* encrypt the given file */
if (!argc)
gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
@ -1258,6 +1293,28 @@ main ( int argc, char **argv)
}
break;
case aPasswd:
if (argc != 1)
wrong_args ("--passwd <key-Id>");
else
{
int rc;
KsbaCert cert = NULL;
char *grip = NULL;
rc = gpgsm_find_cert (*argv, &cert);
if (rc)
;
else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
rc = GNUPG_Bug;
else
rc = gpgsm_agent_passwd (grip);
if (rc)
log_error ("error changing passphrase: %s\n", gnupg_strerror (rc));
xfree (grip);
ksba_cert_release (cert);
}
break;
default:
log_error ("invalid command (there is no implicit command)\n");
@ -1386,3 +1443,24 @@ open_fwrite (const char *filename)
}
return fp;
}
static void
run_protect_tool (int argc, char **argv)
{
char *pgm = GNUPG_PROTECT_TOOL;
char **av;
int i;
av = xcalloc (argc+2, sizeof *av);
av[0] = strrchr (pgm, '/');
if (!av[0])
av[0] = pgm;
for (i=1; argc; i++, argc--, argv++)
av[i] = *argv;
av[i] = NULL;
execv (pgm, av);
log_error ("error executing `%s': %s\n", pgm, strerror (errno));
gpgsm_exit (2);
}

View File

@ -248,11 +248,14 @@ int gpgsm_agent_istrusted (KsbaCert cert);
int gpgsm_agent_havekey (const char *hexkeygrip);
int gpgsm_agent_marktrusted (KsbaCert cert);
int gpgsm_agent_learn (void);
int gpgsm_agent_passwd (const char *hexkeygrip);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (KsbaCert cert);
int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
void (*cb)(void*, KsbaCert), void *cb_value);
int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
int argc, char **argv);

View File

@ -257,6 +257,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
KsbaSexp serial;
char *msgdigest = NULL;
size_t msgdigestlen;
char *ctattr;
err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached)
@ -313,6 +314,35 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
else /* real error */
break;
err = ksba_cms_get_sigattr_oids (cms, signer,
"1.2.840.113549.1.9.3",&ctattr);
if (!err)
{
const char *s;
if (DBG_X509)
log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
s = ksba_cms_get_content_oid (cms, 1);
if (!s || strcmp (ctattr, s))
{
log_error ("content-type attribute does not match "
"actual content-type\n");
ksba_free (ctattr);
ctattr = NULL;
goto next_signer;
}
ksba_free (ctattr);
ctattr = NULL;
}
else if (err != -1)
{
log_error ("error getting content-type attribute: %s\n",
ksba_strerror (err));
goto next_signer;
}
err = 0;
sigval = ksba_cms_get_sig_val (cms, signer);
if (!sigval)
{