From 5a92c6052f4cc72e7f0ea0e0f2ea2ad8c3ba59ba Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sun, 20 Jan 2002 18:33:04 +0000 Subject: [PATCH] * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be used with the agent. Changed all callers. (agent_get_passphrase): Likewise and send it to the agent * seckey-cert.c (do_check): New arg tryagain_text. (check_secret_key): Pass the string to do_check. * keygen.c (ask_passphrase): Set the error text is required. * keyedit.c (change_passphrase): Ditto. * passphrase.c (agent_open): Disable opt.use_agent in case of a problem with the agent. (agent_get_passphrase): Ditto. (passphrase_clear_cache): Ditto. --- g10/ChangeLog | 15 ++++++++++ g10/encode.c | 4 +-- g10/gpgv.c | 3 +- g10/keydb.h | 3 +- g10/keyedit.c | 7 +++-- g10/keygen.c | 10 ++++--- g10/mainproc.c | 4 +-- g10/passphrase.c | 70 +++++++++++++++++++++++++++++++++++++++-------- g10/seckey-cert.c | 13 +++++---- g10/sign.c | 2 +- 10 files changed, 101 insertions(+), 30 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 9eb7e56ca..706f6b72f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,18 @@ +2002-01-20 Werner Koch + + * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be + used with the agent. Changed all callers. + (agent_get_passphrase): Likewise and send it to the agent + * seckey-cert.c (do_check): New arg tryagain_text. + (check_secret_key): Pass the string to do_check. + * keygen.c (ask_passphrase): Set the error text is required. + * keyedit.c (change_passphrase): Ditto. + + * passphrase.c (agent_open): Disable opt.use_agent in case of a + problem with the agent. + (agent_get_passphrase): Ditto. + (passphrase_clear_cache): Ditto. + 2002-01-19 Werner Koch * passphrase.c (agent_open): Add support for the new Assuan based diff --git a/g10/encode.c b/g10/encode.c index cd3d29a0d..b5a4c0678 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -112,8 +112,8 @@ encode_simple( const char *filename, int mode ) s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo : opt.s2k_digest_algo; cfx.dek = passphrase_to_dek( NULL, 0, - opt.def_cipher_algo ? opt.def_cipher_algo - : opt.s2k_cipher_algo , s2k, 2 ); + opt.def_cipher_algo ? opt.def_cipher_algo + : opt.s2k_cipher_algo , s2k, 2, NULL ); if( !cfx.dek || !cfx.dek->keylen ) { rc = G10ERR_PASSPHRASE; m_free(cfx.dek); diff --git a/g10/gpgv.c b/g10/gpgv.c index 7a220f331..007d44ebf 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -295,7 +295,8 @@ check_secret_key( PKT_secret_key *sk, int n ) */ DEK * passphrase_to_dek( u32 *keyid, int pubkey_algo, - int cipher_algo, STRING2KEY *s2k, int mode ) + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tmp) { return NULL; } diff --git a/g10/keydb.h b/g10/keydb.h index 0e5e87289..6bddf1065 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -174,7 +174,8 @@ int have_static_passphrase(void); void read_passphrase_from_fd( int fd ); void passphrase_clear_cache ( u32 *keyid, int algo ); DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo, - int cipher_algo, STRING2KEY *s2k, int mode); + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tryagain_text); void set_next_passphrase( const char *s ); char *get_last_passphrase(void); diff --git a/g10/keyedit.c b/g10/keyedit.c index 1b7260d0c..f74a2fc84 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -641,6 +641,7 @@ change_passphrase( KBNODE keyblock ) else { DEK *dek = NULL; STRING2KEY *s2k = m_alloc_secure( sizeof *s2k ); + const char *errtext = NULL; tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); @@ -648,9 +649,11 @@ change_passphrase( KBNODE keyblock ) for(;;) { s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, + s2k, 2, errtext); if( !dek ) { - tty_printf(_("passphrase not correctly repeated; try again.\n")); + errtext = _("passphrase not correctly repeated; try again"); + tty_printf ("%s.\n", errtext); } else if( !dek->keylen ) { rc = 0; diff --git a/g10/keygen.c b/g10/keygen.c index 80a52b4ac..4625c8435 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1184,6 +1184,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) { DEK *dek = NULL; STRING2KEY *s2k; + const char *errtext = NULL; tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); @@ -1191,9 +1192,10 @@ ask_passphrase( STRING2KEY **ret_s2k ) for(;;) { s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,errtext); if( !dek ) { - tty_printf(_("passphrase not correctly repeated; try again.\n")); + errtext = _("passphrase not correctly repeated; try again"); + tty_printf(_("%s.\n"), errtext); } else if( !dek->keylen ) { m_free(dek); dek = NULL; @@ -1448,7 +1450,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; set_next_passphrase( r->u.value ); - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL ); set_next_passphrase( NULL ); assert( dek ); memset( r->u.value, 0, strlen(r->u.value) ); @@ -2080,7 +2082,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; set_next_passphrase( passphrase ); - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL ); } rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, diff --git a/g10/mainproc.c b/g10/mainproc.c index 6c06da079..0f4342730 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -257,7 +257,7 @@ proc_symkey_enc( CTX c, PACKET *pkt ) log_info(_("encrypted with unknown algorithm %d\n"), algo ); c->last_was_session_key = 2; - c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0 ); + c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL ); if (c->dek) c->dek->algo_info_printed = 1; } @@ -448,7 +448,7 @@ proc_encrypted( CTX c, PACKET *pkt ) log_info (_("assuming %s encrypted data\n"), "IDEA"); } - c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0 ); + c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL ); if (c->dek) c->dek->algo_info_printed = 1; } diff --git a/g10/passphrase.c b/g10/passphrase.c index 12a507692..64a43d4eb 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -371,6 +371,7 @@ agent_open (int *ret_prot) infostr = getenv ( "GPG_AGENT_INFO" ); if ( !infostr ) { log_error (_("gpg-agent is not available in this session\n")); + opt.use_agent = 0; return -1; } infostr = m_strdup ( infostr ); @@ -378,6 +379,7 @@ agent_open (int *ret_prot) || (p-infostr)+1 >= sizeof client_addr.sun_path ) { log_error( _("malformed GPG_AGENT_INFO environment variable\n")); m_free (infostr ); + opt.use_agent = 0; return -1; } *p++ = 0; @@ -390,6 +392,7 @@ agent_open (int *ret_prot) if ( prot < 0 || prot > 1) { log_error (_("gpg-agent protocol version %d is not supported\n"),prot); m_free (infostr ); + opt.use_agent = 0; return -1; } *ret_prot = prot; @@ -397,6 +400,7 @@ agent_open (int *ret_prot) if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { log_error ("can't create socket: %s\n", strerror(errno) ); m_free (infostr ); + opt.use_agent = 0; return -1; } @@ -411,6 +415,7 @@ agent_open (int *ret_prot) infostr, strerror (errno) ); m_free (infostr ); close (fd ); + opt.use_agent = 0; return -1; } m_free (infostr); @@ -430,6 +435,7 @@ agent_open (int *ret_prot) && (line[2] == '\n' || line[2] == ' ')) ) { log_error ( _("communication problem with gpg-agent\n")); close (fd ); + opt.use_agent = 0; return -1; } @@ -460,7 +466,7 @@ agent_close ( int fd ) * 2: Ditto, but change the text to "repeat entry" */ static char * -agent_get_passphrase ( u32 *keyid, int mode ) +agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text ) { #if defined(__riscos__) return NULL; @@ -602,15 +608,35 @@ agent_get_passphrase ( u32 *keyid, int mode ) char *line, *p; int i; + if (!tryagain_text) + tryagain_text = "X"; + /* We allocate 2 time the needed space for atext so that there is nenough space for escaping */ - line = m_alloc (15 + 46 + 3*strlen (atext) + 2); + line = m_alloc (15 + 46 + + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); strcpy (line, "GET_PASSPHRASE "); p = line+15; - for (i=0; i < 20; i++, p +=2 ) - sprintf (p, "%02X", fpr[i]); + if (!mode) + { + for (i=0; i < 20; i++, p +=2 ) + sprintf (p, "%02X", fpr[i]); + } + else + *p++ = 'X'; /* no caching */ *p++ = ' '; - *p++ = 'X'; /* No error prompt */ + for (i=0; tryagain_text[i]; i++) + { + if (tryagain_text[i] < ' ' || tryagain_text[i] == '+') + { + sprintf (p, "%%%02X", tryagain_text[i]); + p += 3; + } + else if (tryagain_text[i] == ' ') + *p++ = '+'; + else + *p++ = tryagain_text[i]; + } *p++ = ' '; *p++ = 'X'; /* Use the standard prompt */ *p++ = ' '; @@ -655,7 +681,10 @@ agent_get_passphrase ( u32 *keyid, int mode ) && (pw[7] == ' ' || pw[7] == '\n') ) log_info (_("cancelled by user\n") ); else - log_error (_("problem with the agent\n")); + { + log_error (_("problem with the agent - disabling agent use\n")); + opt.use_agent = 0; + } } @@ -760,7 +789,10 @@ passphrase_clear_cache ( u32 *keyid, int algo ) if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) ; else - log_error (_("problem with the agent\n")); + { + log_error (_("problem with the agent - disabling agent use\n")); + opt.use_agent = 0; + } } failure: @@ -786,7 +818,8 @@ passphrase_clear_cache ( u32 *keyid, int algo ) */ DEK * passphrase_to_dek( u32 *keyid, int pubkey_algo, - int cipher_algo, STRING2KEY *s2k, int mode ) + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tryagain_text) { char *pw = NULL; DEK *dek; @@ -863,18 +896,31 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, free_public_key( pk ); } + agent_died: if( next_pw ) { pw = next_pw; next_pw = NULL; } else if ( opt.use_agent ) { - pw = agent_get_passphrase ( keyid, mode == 2? 1: 0 ); - if ( !pw ) + pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, tryagain_text ); + if (!pw) + { + if (!opt.use_agent) + goto agent_died; pw = m_strdup (""); + } if( *pw && mode == 2 ) { - char *pw2 = agent_get_passphrase ( keyid, 2 ); - if ( !pw2 ) + char *pw2 = agent_get_passphrase ( keyid, 2, NULL ); + if (!pw2) + { + if (!opt.use_agent) + { + m_free (pw); + pw = NULL; + goto agent_died; + } pw2 = m_strdup (""); + } if( strcmp(pw, pw2) ) { m_free(pw2); m_free(pw); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 5b5f23cb6..b1780b1f9 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -36,7 +36,7 @@ static int -do_check( PKT_secret_key *sk ) +do_check( PKT_secret_key *sk, const char *tryagain_text ) { byte *buffer; u16 csum=0; @@ -68,7 +68,7 @@ do_check( PKT_secret_key *sk ) keyid[3] = sk->main_keyid[1]; } dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo, - &sk->protect.s2k, 0 ); + &sk->protect.s2k, 0, tryagain_text ); cipher_hd = cipher_open( sk->protect.algo, CIPHER_MODE_AUTO_CFB, 1); cipher_setkey( cipher_hd, dek->key, dek->keylen ); @@ -181,9 +181,12 @@ check_secret_key( PKT_secret_key *sk, int n ) n = opt.batch? 1 : 3; /* use the default value */ for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) { - if( i ) - log_info(_("Invalid passphrase; please try again ...\n")); - rc = do_check( sk ); + const char *tryagain = NULL; + if (i) { + tryagain = _("Invalid passphrase; please try again"); + log_info (_("%s ...\n"), tryagain); + } + rc = do_check( sk, tryagain ); if( rc == G10ERR_BAD_PASS && is_status_enabled() ) { u32 kid[2]; char buf[50]; diff --git a/g10/sign.c b/g10/sign.c index f2f1ec45c..59c94a37d 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -914,7 +914,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) if (!opt.quiet || !opt.batch) log_info (_("%s encryption will be used\n"), cipher_algo_to_string(algo) ); - cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2 ); + cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL ); if (!cfx.dek || !cfx.dek->keylen) { rc = G10ERR_PASSPHRASE;