diff options
author | Werner Koch <wk@gnupg.org> | 2007-01-25 09:30:47 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2007-01-25 09:30:47 +0100 |
commit | 6cee3e66c25871a8d94bf0fd22be3579a4d1b775 (patch) | |
tree | d1f9bf251aa5ff3c6f0daad99613051f637af809 /agent | |
parent | * gpg.texi, specify-user-id.texi: Only some of the mentions of (diff) | |
download | gnupg2-6cee3e66c25871a8d94bf0fd22be3579a4d1b775.tar.xz gnupg2-6cee3e66c25871a8d94bf0fd22be3579a4d1b775.zip |
agent/
* protect-tool.c (get_passphrase): New arg OPT_CHECK.
(get_new_passphrase): Enable OTP_CHECK on the first call.
* command.c (cmd_get_passphrase): Implement option --check.
* gpg-agent.c (MIN_PASSPHRASE_LEN): New
(parse_rereadable_options): New option --min-passphrase-len.
* genkey.c (check_passphrase_constraints): New.
(agent_genkey, agent_protect_and_store): Call new function. Fix
memory leak.
* call-pinentry.c (agent_askpin): Allow translation of the displayed
error message.
(agent_popup_message_start): Remove arg CANCEL_BTN.
(popup_message_thread): Use --one-button option.
* command.c (cmd_passwd): Now that we don't distinguish between
assuan and regular error codes we can jump to the end on error.
common/
* simple-pwquery.c (simple_pwquery): New arg OPT_CHECK.
Diffstat (limited to 'agent')
-rw-r--r-- | agent/ChangeLog | 22 | ||||
-rw-r--r-- | agent/agent.h | 7 | ||||
-rw-r--r-- | agent/call-pinentry.c | 24 | ||||
-rw-r--r-- | agent/command.c | 31 | ||||
-rw-r--r-- | agent/divert-scd.c | 2 | ||||
-rw-r--r-- | agent/genkey.c | 62 | ||||
-rw-r--r-- | agent/gpg-agent.c | 6 | ||||
-rw-r--r-- | agent/protect-tool.c | 25 |
8 files changed, 142 insertions, 37 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog index 2a14bda64..110b604ab 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,25 @@ +2007-01-25 Werner Koch <wk@g10code.com> + + * protect-tool.c (get_passphrase): New arg OPT_CHECK. + (get_new_passphrase): Enable OTP_CHECK on the first call. + * command.c (cmd_get_passphrase): Implement option --check. + +2007-01-24 Werner Koch <wk@g10code.com> + + * gpg-agent.c (MIN_PASSPHRASE_LEN): New + (parse_rereadable_options): New option --min-passphrase-len. + * genkey.c (check_passphrase_constraints): New. + (agent_genkey, agent_protect_and_store): Call new function. Fix + memory leak. + + * call-pinentry.c (agent_askpin): Allow translation of the displayed + error message. + (agent_popup_message_start): Remove arg CANCEL_BTN. + (popup_message_thread): Use --one-button option. + + * command.c (cmd_passwd): Now that we don't distinguish between + assuan and regular error codes we can jump to the end on error. + 2006-12-07 David Shaw <dshaw@jabberwocky.com> * Makefile.am: Link to iconv for jnlib dependency. diff --git a/agent/agent.h b/agent/agent.h index 883924cd9..c86ec1e5f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -78,6 +78,8 @@ struct unsigned long max_cache_ttl; /* Default. */ unsigned long max_cache_ttl_ssh; /* for SSH. */ + /* The require minmum length of a passphrase. */ + unsigned int min_passphrase_len; int running_detached; /* We are running detached from the tty. */ @@ -222,8 +224,8 @@ int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *errtext); int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, const char *cancel); -int agent_popup_message_start (ctrl_t ctrl, const char *desc, - const char *ok_btn, const char *cancel_btn); +int agent_popup_message_start (ctrl_t ctrl, + const char *desc, const char *ok_btn); void agent_popup_message_stop (ctrl_t ctrl); @@ -249,6 +251,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, membuf_t *outbuf); /*-- genkey.c --*/ +int check_passphrase_constraints (ctrl_t ctrl, const char *pw); int agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparmlen, membuf_t *outbuf); int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey); diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index f22136fd4..bb3b5deb5 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -434,8 +434,10 @@ agent_askpin (ctrl_t ctrl, if (errtext) { - /* fixme: should we show the try count? It must be translated */ - snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)", + /* TRANLATORS: The string is appended to an error message in + the pinentry. The %s is the actual error message, the + two %d give the current and maximum number of tries. */ + snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"), errtext, pininfo->failed_tries+1, pininfo->max_tries); line[DIM(line)-1] = 0; rc = assuan_transact (entry_ctx, line, @@ -627,7 +629,12 @@ agent_get_confirmation (ctrl_t ctrl, static void * popup_message_thread (void *arg) { - assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL); + /* We use the --one-button hack instead of the MESSAGE command to + allow the use of old Pinentries. Those old Pinentries will then + show an additional Cancel button but that is mostly a visual + annoyance. */ + assuan_transact (entry_ctx, "CONFIRM --one-button", + NULL, NULL, NULL, NULL, NULL, NULL); popup_finished = 1; return NULL; } @@ -640,8 +647,7 @@ popup_message_thread (void *arg) system modal and all other attempts to use the pinentry will fail (after a timeout). */ int -agent_popup_message_start (ctrl_t ctrl, const char *desc, - const char *ok_btn, const char *cancel_btn) +agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn) { int rc; char line[ASSUAN_LINELENGTH]; @@ -668,14 +674,6 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, if (rc) return unlock_pinentry (rc); } - if (cancel_btn) - { - snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL); - if (rc) - return unlock_pinentry (rc); - } tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1); diff --git a/agent/command.c b/agent/command.c index 63f41c369..8f1f126ed 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1,5 +1,6 @@ /* command.c - gpg-agent command handler - * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -804,7 +805,8 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw) } -/* GET_PASSPHRASE [--data] <cache_id> [<error_message> <prompt> <description>] +/* GET_PASSPHRASE [--data] [--check] <cache_id> + [<error_message> <prompt> <description>] This function is usually used to ask for a passphrase to be used for conventional encryption, but may also be used by programs which @@ -816,6 +818,10 @@ send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw) If the option "--data" is used the passphrase is returned by usual data lines and not on the okay line. + + If the option "--check" is used the passphrase constraints checks as + implemented by gpg-agent are applied. A check is not done if the + passphrase has been found in the cache. */ static int @@ -828,9 +834,10 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL; char *p; void *cache_marker; - int opt_data; + int opt_data, opt_check; opt_data = has_option (line, "--data"); + opt_check = has_option (line, "--check"); line = skip_options (line); cacheid = line; @@ -857,7 +864,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) desc = p; p = strchr (desc, ' '); if (p) - *p = 0; /* ignore garbage */ + *p = 0; /* Ignore trailing garbage. */ } } } @@ -895,7 +902,16 @@ cmd_get_passphrase (assuan_context_t ctx, char *line) if (desc) plus_to_blank (desc); - rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + response = NULL; + do + { + xfree (response); + rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + } + while (!rc + && opt_check + && check_passphrase_constraints (ctrl, response)); + if (!rc) { if (cacheid) @@ -1019,8 +1035,7 @@ cmd_passwd (assuan_context_t ctx, char *line) rc = parse_keygrip (ctx, line, grip); if (rc) - return rc; /* we can't jump to leave because this is already an - Assuan error code. */ + goto leave; rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc, grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey); @@ -1036,6 +1051,8 @@ cmd_passwd (assuan_context_t ctx, char *line) xfree (ctrl->server_local->keydesc); ctrl->server_local->keydesc = NULL; + + leave: gcry_sexp_release (s_skey); xfree (shadow_info); if (rc) diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 49768feed..81b4d7c4b 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -237,7 +237,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) } else if (maxbuf == 1) /* Open the pinentry. */ { - rc = agent_popup_message_start (ctrl, info, NULL, NULL); + rc = agent_popup_message_start (ctrl, info, NULL); } else rc = gpg_error (GPG_ERR_INV_VALUE); diff --git a/agent/genkey.c b/agent/genkey.c index a1f9f38f4..1ac7c6624 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -71,6 +71,43 @@ store_key (gcry_sexp_t private, const char *passphrase, int force) return rc; } + +/* Check whether the passphrase PW is suitable. Returns 0 if the + passphrase is suitable and true if it is not and the user should be + asked to provide a different one. */ +int +check_passphrase_constraints (ctrl_t ctrl, const char *pw) +{ + gpg_error_t err; + unsigned int minlen = opt.min_passphrase_len; + + if (!pw) + pw = ""; + + if (strlen (pw) < minlen ) /* FIXME: should be an utf-8 length. */ + { + char *desc = xtryasprintf + ( ngettext (_("Warning: You have entered a passphrase that%%0A" + "is obviously not secure. A passphrase should%%0A" + "be at least %u character long."), + _("Warning: You have entered a passphrase that%%0A" + "is obviously not secure. A passphrase should%%0A" + "be at least %u characters long."), minlen), minlen ); + if (!desc) + return gpg_error_from_syserror (); + + err = agent_get_confirmation (ctrl, desc, + _("Take this one anyway"), + _("Enter new passphrase")); + xfree (desc); + if (err) + return err; + } + + return 0; +} + + /* Callback function to compare the first entered PIN with the one currently being entered. */ static int @@ -125,6 +162,12 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen, initial_errtext = NULL; if (!rc) { + if (check_passphrase_constraints (ctrl, pi->pin)) + { + pi->failed_tries = 0; + pi2->failed_tries = 0; + goto next_try; + } rc = agent_askpin (ctrl, text2, NULL, NULL, pi2); if (rc == -1) { /* The re-entered one did not match and the user did not @@ -134,7 +177,11 @@ agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparamlen, } } if (rc) - return rc; + { + xfree (pi); + return rc; + } + if (!*pi->pin) { xfree (pi); @@ -230,8 +277,15 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey) next_try: rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi); + initial_errtext = NULL; if (!rc) { + if (check_passphrase_constraints (ctrl, pi->pin)) + { + pi->failed_tries = 0; + pi2->failed_tries = 0; + goto next_try; + } rc = agent_askpin (ctrl, text2, NULL, NULL, pi2); if (rc == -1) { /* The re-entered one did not match and the user did not @@ -241,7 +295,11 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey) } } if (rc) - return rc; + { + xfree (pi); + return rc; + } + if (!*pi->pin) { xfree (pi); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 75ffb70da..72a4013d6 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -88,6 +88,7 @@ enum cmd_and_opt_values oDefCacheTTLSSH, oMaxCacheTTL, oMaxCacheTTLSSH, + oMinPassphraseLen, oUseStandardSocket, oNoUseStandardSocket, @@ -148,6 +149,7 @@ static ARGPARSE_OPTS opts[] = { { oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" }, { oMaxCacheTTL, "max-cache-ttl", 4, "@" }, { oMaxCacheTTLSSH, "max-cache-ttl-ssh", 4, "@" }, + { oMinPassphraseLen, "min-passphrase-len", 4, "@" }, { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, { oAllowMarkTrusted, "allow-mark-trusted", 0, @@ -164,6 +166,7 @@ static ARGPARSE_OPTS opts[] = { #define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ #define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */ #define MAX_CACHE_TTL (120*60) /* 2 hours */ +#define MIN_PASSPHRASE_LEN (8) /* flag to indicate that a shutdown was requested */ @@ -403,6 +406,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH; opt.max_cache_ttl = MAX_CACHE_TTL; opt.max_cache_ttl_ssh = MAX_CACHE_TTL; + opt.min_passphrase_len = MIN_PASSPHRASE_LEN; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; opt.disable_scdaemon = 0; @@ -441,6 +445,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break; + case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break; + case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break; diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 4a0e53d3f..8f974e2da 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -1,5 +1,5 @@ /* protect-tool.c - A tool to test the secret key protection - * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -97,7 +97,7 @@ static const char *opt_passphrase; static char *opt_prompt; static int opt_status_msg; -static char *get_passphrase (int promptno); +static char *get_passphrase (int promptno, int opt_check); static char *get_new_passphrase (int promptno); static void release_passphrase (char *pw); static int store_private_key (const unsigned char *grip, @@ -363,7 +363,7 @@ read_and_protect (const char *fname) if (!key) return; - pw = get_passphrase (1); + pw = get_passphrase (1, 0); rc = agent_protect (key, pw, &result, &resultlen); release_passphrase (pw); xfree (key); @@ -401,7 +401,7 @@ read_and_unprotect (const char *fname) if (!key) return; - rc = agent_unprotect (key, (pw=get_passphrase (1)), &result, &resultlen); + rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), &result, &resultlen); release_passphrase (pw); xfree (key); if (rc) @@ -684,7 +684,7 @@ import_p12_file (const char *fname) if (!buf) return; - kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2)), + kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2, 0)), import_p12_cert_cb, NULL); release_passphrase (pw); xfree (buf); @@ -898,7 +898,7 @@ export_p12_file (const char *fname) unsigned char *tmpkey; size_t tmplen; - rc = agent_unprotect (key, (pw=get_passphrase (1)), &tmpkey, &tmplen); + rc = agent_unprotect (key, (pw=get_passphrase (1, 0)), &tmpkey, &tmplen); release_passphrase (pw); if (rc) { @@ -1162,10 +1162,11 @@ agent_exit (int rc) 3 = for protecting a new pkcs#12 object 4 = for protecting an imported pkcs#12 in our system 5 = reenter the passphrase - When adding 100 to the values, a "does not match - try again" errro message is shown. + When adding 100 to the values, a "does not match - try again" error + message is shown. */ static char * -get_passphrase (int promptno) +get_passphrase (int promptno, int opt_check) { char *pw; int err; @@ -1219,7 +1220,7 @@ get_passphrase (int promptno) pw = simple_pwquery (NULL, error_msgno == 1? _("does not match - try again"):NULL, - _("Passphrase:"), desc, &err); + _("Passphrase:"), desc, opt_check, &err); #ifdef ENABLE_NLS if (orig_codeset) @@ -1251,16 +1252,16 @@ get_new_passphrase (int promptno) char *pw; int i, secondpromptno; - pw = get_passphrase (promptno); + pw = get_passphrase (promptno, 1); if (!pw) return NULL; /* Canceled. */ if (!*pw) - return pw; /* Empty passphrase - no need to as for repeating it. */ + return pw; /* Empty passphrase - no need to ask for repeating it. */ secondpromptno = 5; for (i=0; i < 3; i++) { - char *pw2 = get_passphrase (secondpromptno); + char *pw2 = get_passphrase (secondpromptno, 0); if (!pw2) { xfree (pw); |