mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
Updated from latest NewPG project
This commit is contained in:
parent
254225ac37
commit
c13b76ca6a
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
199
agent/command.c
199
agent/command.c
@ -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)
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
@ -466,6 +515,21 @@ main (int argc, char **argv )
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
29
common/isascii.c
Normal 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
31
common/putc_unlocked.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
32
sm/ChangeLog
32
sm/ChangeLog
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
86
sm/gpgsm.c
86
sm/gpgsm.c
@ -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,6 +743,16 @@ 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;
|
||||
@ -745,6 +766,8 @@ main ( int argc, char **argv)
|
||||
|
||||
case aLearnCard: set_cmd (&cmd, aLearnCard); break;
|
||||
|
||||
case aPasswd: set_cmd (&cmd, aPasswd); break;
|
||||
|
||||
case aDeleteKey:
|
||||
set_cmd (&cmd, aDeleteKey);
|
||||
/*greeting=1;*/
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
30
sm/verify.c
30
sm/verify.c
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user