1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-18 14:17:03 +01:00

* gpgv.c (tty_fprintf): New stub.

* card-util.c (card_status): Create asecret key stub on the fly
and print more information about a card key.
* import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New.
* getkey.c (get_seckeyblock_byfprint): New.
* keylist.c (print_card_key_info): New.
This commit is contained in:
Werner Koch 2005-01-20 17:21:40 +00:00
parent fa284bae3f
commit b2b2786be1
10 changed files with 396 additions and 33 deletions

31
NEWS
View File

@ -1,15 +1,6 @@
Noteworthy changes in version 1.4.1 Noteworthy changes in version 1.4.1
------------------------------------------------- -------------------------------------------------
* [W32] The algorithm for the default home directory changed:
First we look at the environment variable GNUPGHOME, if this one
is not set, we check whether the registry entry
HKCU\Software\GNU\GnuPG:HomeDir has been set and if this fails
we use a GnuPG directory below the standard application data
directory (APPDATA) of the current user. Only in the case that
this directory cannot be determined, the old default of c:\gnupg
will be used. The option --homedir still overrides all of them.
* New --rfc2440-text option which controls how text is handled in * New --rfc2440-text option which controls how text is handled in
signatures. This is in response to some problems seen with signatures. This is in response to some problems seen with
certain PGP/MIME mail clients and GnuPG version 1.4.0. More certain PGP/MIME mail clients and GnuPG version 1.4.0. More
@ -27,6 +18,28 @@ Noteworthy changes in version 1.4.1
option --with-libcurl. Without this option, the existing HTTP option --with-libcurl. Without this option, the existing HTTP
code is used for HTTP, and HTTPS and FTP are not supported. code is used for HTTP, and HTTPS and FTP are not supported.
* When running a --card-status or --card-edit and a public key is
available, missing secret key stubs will be created on the fly.
Details of the key are listed too.
* [W32] The algorithm for the default home directory changed:
First we look at the environment variable GNUPGHOME, if this one
is not set, we check whether the registry entry
{HKCU,HKLM}\Software\GNU\GnuPG:HomeDir has been set. If this
fails we use a GnuPG directory below the standard application
data directory (APPDATA) of the current user. Only in the case
that this directory cannot be determined, the old default of
c:\gnupg will be used. The option --homedir still overrides all
of them.
* [W32] The locale selection under Windows changed. You need to
enter the locale in the registry at HKCU\Software\GNU\GnuPG:Lang.
For German you would use "de". If it is not set, GnupG falls
back to HKLM. The languages files "*.mo" are expected in a
directory named "gnupg.nls" below the installation directory;
that directory must be stored in the registry at the same key as
above with the name "Install Directory".
Noteworthy changes in version 1.4.0 (2004-12-16) Noteworthy changes in version 1.4.0 (2004-12-16)
------------------------------------------------- -------------------------------------------------

View File

@ -30,18 +30,10 @@ Installation instructions:
Internationalization support: Internationalization support:
----------------------------- -----------------------------
1. Decide where to store the translation files for your language. 1
Here we assume the directory "c:/gnu/locale/fr"
2. Set the directory with the translations into the Registry under Store the locale id (like "de") into the registry under the key
the key: HKEY_CURRENT_USER\Software\GNU\GnuPG with the name "Lang".
HKEY_CURRENT_USER -> Control Panel -> Mingw32 -> NLS
(you probably need to create the keys Mingw32 and NLS) using a string
entry with the name "MoDir".
3. Select which language to use and copy the currect translation file
under the name "gnupg.mo" into the directory set in step 2
(Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo")
4. Done.
How to build it from the source: How to build it from the source:

View File

@ -1,5 +1,13 @@
2005-01-20 Werner Koch <wk@g10code.com> 2005-01-20 Werner Koch <wk@g10code.com>
* gpgv.c (tty_fprintf): New stub.
* card-util.c (card_status): Create asecret key stub on the fly
and print more information about a card key.
* import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New.
* getkey.c (get_seckeyblock_byfprint): New.
* keylist.c (print_card_key_info): New.
* g10.c (i18n_init) [W32]: Pass registry key to gettext * g10.c (i18n_init) [W32]: Pass registry key to gettext
initialization. initialization.
* gpgv.c (i18n_init) [W32]: Ditto. * gpgv.c (i18n_init) [W32]: Ditto.

View File

@ -1,5 +1,5 @@
/* card-util.c - Utility functions for the OpenPGP card. /* card-util.c - Utility functions for the OpenPGP card.
* Copyright (C) 2003 Free Software Foundation, Inc. * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -270,6 +270,7 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
PKT_public_key *pk = xcalloc (1, sizeof *pk); PKT_public_key *pk = xcalloc (1, sizeof *pk);
int rc; int rc;
unsigned int uval; unsigned int uval;
const unsigned char *thefpr;
if (serialno && serialnobuflen) if (serialno && serialnobuflen)
*serialno = 0; *serialno = 0;
@ -425,8 +426,34 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
tty_fprintf (fp, " created ....: %s\n", tty_fprintf (fp, " created ....: %s\n",
asctimestamp (info.fpr3time)); asctimestamp (info.fpr3time));
tty_fprintf (fp, "General key info..: "); tty_fprintf (fp, "General key info..: ");
if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
print_pubkey_info (fp, pk); thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
info.fpr3valid? info.fpr3 : NULL);
if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20))
{
KBNODE keyblock = NULL;
print_pubkey_info (fp, pk);
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) )
{
release_kbnode (keyblock);
keyblock = NULL;
if (!auto_create_card_key_stub (info.serialno,
info.fpr1valid? info.fpr1:NULL,
info.fpr2valid? info.fpr2:NULL,
info.fpr3valid? info.fpr3:NULL))
{
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock);
}
}
release_kbnode (keyblock);
}
else else
tty_fprintf (fp, "[none]\n"); tty_fprintf (fp, "[none]\n");
} }
@ -1037,7 +1064,7 @@ generate_card_keys (const char *serialno)
} }
/* This fucntion is used by the key edit menu to generate an arbitrary /* This function is used by the key edit menu to generate an arbitrary
subkey. */ subkey. */
int int
card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)

View File

@ -1,6 +1,6 @@
/* getkey.c - Get a key from the database /* getkey.c - Get a key from the database
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004 Free Software Foundation, Inc. * 2004, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -1139,13 +1139,41 @@ get_seckey_byfprint( PKT_secret_key *sk,
if (!rc && sk ) if (!rc && sk )
sk_from_block ( &ctx, sk, kb ); sk_from_block ( &ctx, sk, kb );
release_kbnode ( kb ); release_kbnode ( kb );
get_pubkey_end( &ctx ); get_seckey_end( &ctx );
} }
else else
rc = G10ERR_GENERAL; /* Oops */ rc = G10ERR_GENERAL; /* Oops */
return rc; return rc;
} }
/* Search for a secret key with the given fingerprint and return the
complete keyblock which may have more than only this key. */
int
get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint,
size_t fprint_len )
{
int rc;
struct getkey_ctx_s ctx;
if (fprint_len != 20 && fprint_len == 16)
return G10ERR_GENERAL; /* Oops */
memset (&ctx, 0, sizeof ctx);
ctx.not_allocated = 1;
ctx.kr_handle = keydb_new (1);
ctx.nitems = 1;
ctx.items[0].mode = (fprint_len==16
? KEYDB_SEARCH_MODE_FPR16
: KEYDB_SEARCH_MODE_FPR20);
memcpy (ctx.items[0].u.fpr, fprint, fprint_len);
rc = lookup (&ctx, ret_keyblock, 1);
get_seckey_end (&ctx);
return rc;
}
/************************************************ /************************************************
************* Merging stuff ******************** ************* Merging stuff ********************

View File

@ -380,6 +380,7 @@ void rndlinux_constructor(void) {}
/* Stubs to avoid linking to ../util/ttyio.c */ /* Stubs to avoid linking to ../util/ttyio.c */
int tty_batchmode( int onoff ) { return 0; } int tty_batchmode( int onoff ) { return 0; }
void tty_printf( const char *fmt, ... ) { } void tty_printf( const char *fmt, ... ) { }
void tty_fprintf (FILE *fp, const char *fmt, ... ) { }
void tty_print_string( const byte *p, size_t n ) { } void tty_print_string( const byte *p, size_t n ) { }
void tty_print_utf8_string( const byte *p, size_t n ) {} void tty_print_utf8_string( const byte *p, size_t n ) {}
void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {} void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {}

View File

@ -1,6 +1,6 @@
/* import.c /* import.c - import a key into our key storage.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004 Free Software Foundation, Inc. * 2004, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -2118,3 +2118,232 @@ append_key( KBNODE keyblock, KBNODE node, int *n_sigs,
return 0; return 0;
} }
/* Walk a public keyblock and produce a secret keyblock out of it.
Instead of inserting the secret key parameters (which we don't
have), we insert a stub. */
static KBNODE
pub_to_sec_keyblock (KBNODE pub_keyblock)
{
KBNODE pubnode, secnode;
KBNODE sec_keyblock = NULL;
KBNODE walkctx = NULL;
while((pubnode = walk_kbnode (pub_keyblock,&walkctx,0)))
{
if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY
|| pubnode->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
/* Make a secret key. We only need to convert enough to
write the keyblock out. */
PKT_public_key *pk = pubnode->pkt->pkt.public_key;
PACKET *pkt = m_alloc_clear (sizeof *pkt);
PKT_secret_key *sk = m_alloc_clear (sizeof *sk);
int i, n;
if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY)
pkt->pkttype = PKT_SECRET_KEY;
else
pkt->pkttype = PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
copy_public_parts_to_secret_key ( pk, sk );
sk->version = pk->version;
sk->timestamp = pk->timestamp;
n = pubkey_get_npkey (pk->pubkey_algo);
if (!n)
n = 1; /* Unknown number of parameters, however the data
is stored in the first mpi. */
for (i=0; i < n; i++ )
sk->skey[i] = mpi_copy (pk->pkey[i]);
sk->is_protected = 1;
sk->protect.s2k.mode = 1001;
secnode = new_kbnode (pkt);
}
else
{
secnode = clone_kbnode (pubnode);
}
if(!sec_keyblock)
sec_keyblock = secnode;
else
add_kbnode (sec_keyblock, secnode);
}
return sec_keyblock;
}
/* Walk over the secret keyring SEC_KEYBLOCK and update any simple
stub keys with the serial number SNNUM of the card if one of the
fingerprints FPR1, FPR2 or FPR3 match. Print a note if the key is
a duplicate (may happen in case of backed uped keys).
Returns: True if anything changed.
*/
static int
update_sec_keyblock_with_cardinfo (KBNODE sec_keyblock,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3,
const char *serialnostr)
{
KBNODE node;
KBNODE walkctx = NULL;
PKT_secret_key *sk;
byte array[MAX_FINGERPRINT_LEN];
size_t n;
int result = 0;
const char *s;
while((node = walk_kbnode (sec_keyblock, &walkctx, 0)))
{
if (node->pkt->pkttype != PKT_SECRET_KEY
&& node->pkt->pkttype != PKT_SECRET_SUBKEY)
continue;
sk = node->pkt->pkt.secret_key;
fingerprint_from_sk (sk, array, &n);
if (n != 20)
continue; /* Can't be a card key. */
if ( !((fpr1 && !memcmp (array, fpr1, 20))
|| (fpr2 && !memcmp (array, fpr2, 20))
|| (fpr3 && !memcmp (array, fpr3, 20))) )
continue; /* No match. */
if (sk->is_protected == 1 && sk->protect.s2k.mode == 1001)
{
/* Standard case: migrate that stub to a key stub. */
sk->protect.s2k.mode = 1002;
s = serialnostr;
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
sk->protect.ivlen++, s += 2)
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
result = 1;
}
else if (sk->is_protected == 1 && sk->protect.s2k.mode == 1002)
{
s = serialnostr;
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
sk->protect.ivlen++, s += 2)
if (sk->protect.iv[sk->protect.ivlen] != xtoi_2 (s))
{
log_info (_("NOTE: a key's S/N does not "
"match the card's one\n"));
break;
}
}
else
{
if (node->pkt->pkttype != PKT_SECRET_KEY)
log_info (_("NOTE: primary key is online and stored on card\n"));
else
log_info (_("NOTE: secondary key is online and stored on card\n"));
}
}
return result;
}
/* Check whether a secret key stub exists for the public key PK. If
not create such a stub key and store it into the secring. If it
exists, add appropriate subkey stubs and update the secring.
Return 0 if the key could be created. */
int
auto_create_card_key_stub ( const char *serialnostr,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3)
{
KBNODE pub_keyblock;
KBNODE sec_keyblock;
KEYDB_HANDLE hd;
int rc;
/* We only want to do this for an OpenPGP card. */
if (!serialnostr || strncmp (serialnostr, "D27600012401", 12)
|| strlen (serialnostr) != 32 )
return G10ERR_GENERAL;
/* First get the public keyring from any of the provided fingerprints. */
if ( (fpr1 && !get_keyblock_byfprint (&pub_keyblock, fpr1, 20))
|| (fpr2 && !get_keyblock_byfprint (&pub_keyblock, fpr2, 20))
|| (fpr3 && !get_keyblock_byfprint (&pub_keyblock, fpr3, 20)))
;
else
return G10ERR_GENERAL;
hd = keydb_new (1);
/* Now check whether there is a secret keyring. */
{
PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk (pk, afp, &an);
memset (afp, 0, MAX_FINGERPRINT_LEN);
rc = keydb_search_fpr (hd, afp);
}
if (!rc)
{
rc = keydb_get_keyblock (hd, &sec_keyblock);
if (rc)
{
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
rc = G10ERR_GENERAL;
}
else
{
merge_keys_and_selfsig (sec_keyblock);
/* FIXME: We need to add new subkeys first. */
if (update_sec_keyblock_with_cardinfo (sec_keyblock,
fpr1, fpr2, fpr3,
serialnostr))
{
rc = keydb_update_keyblock (hd, sec_keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
}
}
}
else /* A secret key does not exists - create it. */
{
sec_keyblock = pub_to_sec_keyblock (pub_keyblock);
update_sec_keyblock_with_cardinfo (sec_keyblock,
fpr1, fpr2, fpr3,
serialnostr);
rc = keydb_locate_writable (hd, NULL);
if (rc)
{
log_error (_("no default secret keyring: %s\n"), g10_errstr (rc));
rc = G10ERR_GENERAL;
}
else
{
rc = keydb_insert_keyblock (hd, sec_keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
}
}
release_kbnode (sec_keyblock);
release_kbnode (pub_keyblock);
keydb_release (hd);
return rc;
}

View File

@ -224,10 +224,15 @@ int seckey_available( u32 *keyid );
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ); int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk, int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
STRLIST names, KBNODE *ret_keyblock ); STRLIST names, KBNODE *ret_keyblock );
int get_seckey_next (GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock);
void get_seckey_end( GETKEY_CTX ctx );
int get_seckey_byfprint( PKT_secret_key *sk, int get_seckey_byfprint( PKT_secret_key *sk,
const byte *fprint, size_t fprint_len); const byte *fprint, size_t fprint_len);
int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ); int get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint,
void get_seckey_end( GETKEY_CTX ctx ); size_t fprint_len );
int enum_secret_keys( void **context, PKT_secret_key *sk, int enum_secret_keys( void **context, PKT_secret_key *sk,
int with_subkeys, int with_spm ); int with_subkeys, int with_spm );
void merge_keys_and_selfsig( KBNODE keyblock ); void merge_keys_and_selfsig( KBNODE keyblock );

View File

@ -1,6 +1,6 @@
/* keylist.c /* keylist.c
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2004 Free Software Foundation, Inc. * 2004, 2005 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -167,6 +167,60 @@ print_pubkey_info (FILE *fp, PKT_public_key *pk)
m_free (p); m_free (p);
} }
/* Print basic information of a secret key including the card serial
number information. */
void
print_card_key_info (FILE *fp, KBNODE keyblock)
{
KBNODE node;
int i;
for (node = keyblock; node; node = node->next )
{
if (node->pkt->pkttype == PKT_SECRET_KEY
|| (node->pkt->pkttype == PKT_SECRET_SUBKEY) )
{
PKT_secret_key *sk = node->pkt->pkt.secret_key;
tty_fprintf (fp, "%s%c %4u%c/%s ",
node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
(sk->protect.s2k.mode==1001)?'#':
(sk->protect.s2k.mode==1002)?'>':' ',
nbits_from_sk (sk),
pubkey_letter (sk->pubkey_algo),
keystr_from_sk(sk));
tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
tty_fprintf (fp, " ");
tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{
tty_fprintf (fp, "\n ");
tty_fprintf (fp, _("card-no: "));
if (sk->protect.ivlen == 16
&& !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
{
/* This is an OpenPGP card. */
for (i=8; i < 14; i++)
{
if (i == 10)
tty_fprintf (fp, " ");
tty_fprintf (fp, "%02X", sk->protect.iv[i]);
}
}
else
{ /* Something is wrong: Print all. */
for (i=0; i < sk->protect.ivlen; i++)
tty_fprintf (fp, "%02X", sk->protect.iv[i]);
}
}
tty_fprintf (fp, "\n");
}
}
}
/* Flags = 0x01 hashed 0x02 critical */ /* Flags = 0x01 hashed 0x02 critical */
static void static void
status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf) status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf)
@ -1437,9 +1491,9 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode )
} }
else if (mode == 2) { else if (mode == 2) {
fp = NULL; /* use tty */ fp = NULL; /* use tty */
/* Translators: this should fit into 24 bytes to that the fingerprint
* data is properly aligned with the user ID */
if(primary) if(primary)
/* TRANSLATORS: this should fit into 24 bytes to that the
* fingerprint data is properly aligned with the user ID */
text = _(" Primary key fingerprint:"); text = _(" Primary key fingerprint:");
else else
text = _(" Subkey fingerprint:"); text = _(" Subkey fingerprint:");

View File

@ -211,6 +211,11 @@ void import_print_stats (void *hd);
int collapse_uids( KBNODE *keyblock ); int collapse_uids( KBNODE *keyblock );
int auto_create_card_key_stub ( const char *serialnostr,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3);
/*-- export.c --*/ /*-- export.c --*/
int parse_export_options(char *str,unsigned int *options,int noisy); int parse_export_options(char *str,unsigned int *options,int noisy);
int export_pubkeys( STRLIST users, unsigned int options ); int export_pubkeys( STRLIST users, unsigned int options );
@ -247,6 +252,7 @@ void dump_attribs(const PKT_user_id *uid,
void set_attrib_fd(int fd); void set_attrib_fd(int fd);
void print_seckey_info (PKT_secret_key *sk); void print_seckey_info (PKT_secret_key *sk);
void print_pubkey_info (FILE *fp, PKT_public_key *pk); void print_pubkey_info (FILE *fp, PKT_public_key *pk);
void print_card_key_info (FILE *fp, KBNODE keyblock);
/*-- verify.c --*/ /*-- verify.c --*/
void print_file_status( int status, const char *name, int what ); void print_file_status( int status, const char *name, int what );