The Cherry XX44 keyboard's PINpad does now work.

DINSIG and NKS card applications are now also PIN pad aware.
This commit is contained in:
Werner Koch 2007-03-07 20:55:14 +00:00
parent ed84b0f787
commit 634b4c31d2
15 changed files with 295 additions and 64 deletions

8
NEWS
View File

@ -11,7 +11,11 @@ Noteworthy changes in version 2.0.3
* New --verify-option show-primary-uid-only. * New --verify-option show-primary-uid-only.
* gpgconf may now read a global configuration file to select which * gpgconf may now read a global configuration file to select which
options are changeable by a frontend. options are changeable by a frontend. The new applygnupgdefaults
tool may be used by an admin to set default options for all users.
* The PIN pad of the Cherry XX44 keyboard is now supported. The
DINSIG and the NKS applications are now also aware of PIN pads.
Noteworthy changes in version 2.0.2 (2007-01-31) Noteworthy changes in version 2.0.2 (2007-01-31)
@ -471,7 +475,7 @@ Noteworthy changes in version 1.9.0 (2003-08-05)
development branch. development branch.
Copyright 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Copyright 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

5
TODO
View File

@ -121,3 +121,8 @@
* UTF-8 * UTF-8
UTF-8 specific TODO. UTF-8 specific TODO.
* Pinpad Reader
We do not yet support P15 applications. The trivial thing using
ASCII characters will be easy to implement but the otehr cases need
some more work.

View File

@ -1,3 +1,7 @@
2007-03-07 Werner Koch <wk@g10code.com>
* tools.texi (applygnupgdefaults): New.
2007-03-06 Werner Koch <wk@g10code.com> 2007-03-06 Werner Koch <wk@g10code.com>
* examples/gpgconf.conf: New. * examples/gpgconf.conf: New.

View File

@ -55,7 +55,7 @@ myman_sources = gnupg7.texi gpg.texi gpgsm.texi gpg-agent.texi \
myman_pages = gpg2.1 gpgsm.1 gpg-agent.1 scdaemon.1 gpgv2.1 \ myman_pages = gpg2.1 gpgsm.1 gpg-agent.1 scdaemon.1 gpgv2.1 \
watchgnupg.1 gpgconf.1 addgnupghome.8 gpg-preset-passphrase.1 \ watchgnupg.1 gpgconf.1 addgnupghome.8 gpg-preset-passphrase.1 \
gpg-connect-agent.1 gpgparsemail.1 symcryptrun.1 \ gpg-connect-agent.1 gpgparsemail.1 symcryptrun.1 \
gpgsm-gencert.sh.1 gpgsm-gencert.sh.1 applygnupgdefaults.8
man_MANS = $(myman_pages) man_MANS = $(myman_pages)
noinst_MANS = gnupg.7 noinst_MANS = gnupg.7

View File

@ -12,6 +12,7 @@ GnuPG comes with a couple of smaller tools:
* gpgv:: Verify OpenPGP signatures. * gpgv:: Verify OpenPGP signatures.
* addgnupghome:: Create .gnupg home directories. * addgnupghome:: Create .gnupg home directories.
* gpgconf:: Modify .gnupg home directories. * gpgconf:: Modify .gnupg home directories.
* applygnupgdefaults:: Run gpgconf for all users.
* gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpgsm-gencert.sh:: Generate an X.509 certificate request.
* gpg-preset-passphrase:: Put a passphrase into the cache. * gpg-preset-passphrase:: Put a passphrase into the cache.
* gpg-connect-agent:: Communicate with a running agent. * gpg-connect-agent:: Communicate with a running agent.
@ -82,10 +83,12 @@ Display a brief help page and exit
@end table @end table
@mansect see also @mansect see also
@ifset isman
@command{gpg}(1), @command{gpg}(1),
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1), @command{gpg-agent}(1),
@command{scdaemon}(1) @command{scdaemon}(1)
@end ifset
@include see-also-note.texi @include see-also-note.texi
@ -680,7 +683,7 @@ effect.
@table @file @table @file
@item /etc/gnupg/gpg-agent.conf @item /etc/gnupg/gpgconf.conf
@cindex gpgconf.conf @cindex gpgconf.conf
If this file exists, it is processed as a global configuration file. If this file exists, it is processed as a global configuration file.
A commented example can be found in the @file{examples} directory of A commented example can be found in the @file{examples} directory of
@ -689,15 +692,51 @@ effect.
@mansect see also @mansect see also
@ifset isman
@command{gpg}(1), @command{gpg}(1),
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1), @command{gpg-agent}(1),
@command{scdaemon}(1), @command{scdaemon}(1),
@command{dirmngr}(1) @command{dirmngr}(1)
@end ifset
@include see-also-note.texi @include see-also-note.texi
@manpause
@c
@c APPLYGNUPGDEFAULTS
@c
@manpage applygnupgdefaults.8
@node applygnupgdefaults
@section Run gpgconf for all users.
@ifset manverb
.B applygnupgdefaults
\- Run gpgconf --apply-defaults for all users.
@end ifset
@mansect synopsis
@ifset manverb
.B applygnupgdefaults
@end ifset
@mansect description
This script is a wrapper around @command{gpgconf} to run it with the
command @code{--apply-defaults} for all real users with an existing
GnuPG home directory. Admins might want to use this script to update he
GnuPG configuration files for all users after
@file{/etc/gnupg/gpgconf.conf} has been changed. This allows to enforce
certain policies for all users. Note, that this is not a bulletproof of
forcing a user to use certain options. A user may always directly edit
the configuration files and bypass gpgconf.
@noindent
@command{applygnupgdefaults} is invoked by root as:
@example
applygnupgdefaults
@end example
@c @c
@c GPGSM-GENCERT.SH @c GPGSM-GENCERT.SH
@c @c
@ -725,9 +764,11 @@ which will be printed to stdout.
@samp{gpgsm-cencert.sh} @samp{gpgsm-cencert.sh}
@mansect see also @mansect see also
@ifset isman
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1), @command{gpg-agent}(1),
@command{scdaemon}(1) @command{scdaemon}(1)
@end ifset
@include see-also-note.texi @include see-also-note.texi
@ -818,10 +859,12 @@ for other users.
@end table @end table
@mansect see also @mansect see also
@ifset isman
@command{gpg}(1), @command{gpg}(1),
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1), @command{gpg-agent}(1),
@command{scdaemon}(1) @command{scdaemon}(1)
@end ifset
@include see-also-note.texi @include see-also-note.texi
@ -1103,8 +1146,10 @@ The possible exit status codes of @command{symcryptrun} are:
@end table @end table
@mansect see also @mansect see also
@ifset isman
@command{gpg}(1), @command{gpg}(1),
@command{gpgsm}(1), @command{gpgsm}(1),
@command{gpg-agent}(1), @command{gpg-agent}(1),
@end ifset
@include see-also-note.texi @include see-also-note.texi

View File

@ -1,3 +1,7 @@
2007-03-07 Werner Koch <wk@g10code.com>
* argparse.c (strusage): Set copyright year to 2007.
2007-01-25 Werner Koch <wk@g10code.com> 2007-01-25 Werner Koch <wk@g10code.com>
* stringhelp.c (utf8_charcount): New. * stringhelp.c (utf8_charcount): New.

View File

@ -905,7 +905,7 @@ strusage( int level )
switch( level ) { switch( level ) {
case 11: p = "foo"; break; case 11: p = "foo"; break;
case 13: p = "0.0"; break; case 13: p = "0.0"; break;
case 14: p = "Copyright (C) 2006 Free Software Foundation, Inc."; break; case 14: p = "Copyright (C) 2007 Free Software Foundation, Inc."; break;
case 15: p = case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n" "This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n" "This is free software, and you are welcome to redistribute it\n"

View File

@ -1,3 +1,14 @@
2007-03-07 Werner Koch <wk@g10code.com>
* app-dinsig.c: Include i18n.h.
(verify_pin): Support PIN pads.
* app-nks.c (verify_pin): Ditto.
* ccid-driver.c (bulk_in): Handle time extension before checking
the message type.
(ccid_transceive_secure): Support the Cherry XX44 keyboard.
Kudos to the nice folks at Cherry for helping with that.
2007-02-18 Werner Koch <wk@g10code.com> 2007-02-18 Werner Koch <wk@g10code.com>
* scdaemon.c (DEFAULT_PCSC_DRIVER): Add a default for OS X. * scdaemon.c (DEFAULT_PCSC_DRIVER): Add a default for OS X.

View File

@ -90,7 +90,7 @@
#define MAX_OPEN_FDS 20 #define MAX_OPEN_FDS 20
#endif #endif
/* Helper to pass patrameters related to keypad based operations. */ /* Helper to pass parameters related to keypad based operations. */
struct pininfo_s struct pininfo_s
{ {
int mode; int mode;

View File

@ -1,5 +1,5 @@
/* app-dinsig.c - The DINSIG (DIN V 66291-1) card application. /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
* Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. * Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -81,6 +81,7 @@
#include "scdaemon.h" #include "scdaemon.h"
#include "i18n.h"
#include "iso7816.h" #include "iso7816.h"
#include "app-common.h" #include "app-common.h"
#include "tlv.h" #include "tlv.h"
@ -279,11 +280,37 @@ verify_pin (app_t app,
gpg_error_t (*pincb)(void*, const char *, char **), gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg) void *pincb_arg)
{ {
if (!app->did_chv1 || app->force_chv1 ) const char *s;
int rc;
iso7816_pininfo_t pininfo;
if ( app->did_chv1 && !app->force_chv1 )
return 0; /* No need to verify it again. */
memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1;
pininfo.minlen = 6;
pininfo.maxlen = 8;
if (!opt.disable_keypad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
{
rc = pincb (pincb_arg,
_("||Please enter your PIN at the reader's keypad"),
NULL);
if (rc)
{
log_info (_("PIN callback returned error: %s\n"),
gpg_strerror (rc));
return rc;
}
rc = iso7816_verify_kp (app->slot, 0x81, "", 0, &pininfo);
/* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL);
}
else /* No Keypad. */
{ {
const char *s;
char *pinvalue; char *pinvalue;
int rc;
rc = pincb (pincb_arg, "PIN", &pinvalue); rc = pincb (pincb_arg, "PIN", &pinvalue);
if (rc) if (rc)
@ -303,15 +330,17 @@ verify_pin (app_t app,
return gpg_error (GPG_ERR_BAD_PIN); return gpg_error (GPG_ERR_BAD_PIN);
} }
if (strlen (pinvalue) < 6) if (strlen (pinvalue) < pininfo.minlen)
{ {
log_error ("PIN is too short; minimum length is 6\n"); log_error ("PIN is too short; minimum length is %d\n",
pininfo.minlen);
xfree (pinvalue); xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN); return gpg_error (GPG_ERR_BAD_PIN);
} }
else if (strlen (pinvalue) > 8) else if (strlen (pinvalue) > pininfo.maxlen)
{ {
log_error ("PIN is too large; maximum length is 8\n"); log_error ("PIN is too large; maximum length is %d\n",
pininfo.maxlen);
xfree (pinvalue); xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN); return gpg_error (GPG_ERR_BAD_PIN);
} }
@ -326,7 +355,7 @@ verify_pin (app_t app,
this. */ this. */
char paddedpin[8]; char paddedpin[8];
int i, ndigits; int i, ndigits;
for (ndigits=0, s=pinvalue; *s; ndigits++, s++) for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
; ;
i = 0; i = 0;
@ -336,19 +365,18 @@ verify_pin (app_t app,
if (i < sizeof paddedpin && *s) if (i < sizeof paddedpin && *s)
paddedpin[i++] = (((*s - '0') << 4) | 0x0f); paddedpin[i++] = (((*s - '0') << 4) | 0x0f);
while (i < sizeof paddedpin) while (i < sizeof paddedpin)
paddedpin[i++] = 0xff; paddedpin[i++] = 0xff;
rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin); rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin);
} }
if (rc)
{
log_error ("verify PIN failed\n");
xfree (pinvalue);
return rc;
}
app->did_chv1 = 1;
xfree (pinvalue); xfree (pinvalue);
} }
if (rc)
{
log_error ("verify PIN failed\n");
return rc;
}
app->did_chv1 = 1;
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* app-nks.c - The Telesec NKS 2.0 card application. /* app-nks.c - The Telesec NKS 2.0 card application.
* Copyright (C) 2004 Free Software Foundation, Inc. * Copyright (C) 2004, 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -306,14 +306,43 @@ verify_pin (app_t app,
gpg_error_t (*pincb)(void*, const char *, char **), gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg) void *pincb_arg)
{ {
iso7816_pininfo_t pininfo;
int rc;
/* Note that force_chv1 is never set but we do it here anyway so /* Note that force_chv1 is never set but we do it here anyway so
that other applications may reuse this function. For example it that other applications may reuse this function. For example it
makes sense to set force_chv1 for German signature law cards. makes sense to set force_chv1 for German signature law cards.
NKS is very similar to the DINSIG draft standard. */ NKS is very similar to the DINSIG draft standard. */
if (!app->did_chv1 || app->force_chv1 ) if ( app->did_chv1 && !app->force_chv1 )
return 0; /* No need to verify it again. */
memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1;
pininfo.minlen = 6;
pininfo.maxlen = 16;
if (!opt.disable_keypad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
{
rc = pincb (pincb_arg,
_("||Please enter your PIN at the reader's keypad"),
NULL);
if (rc)
{
log_info (_("PIN callback returned error: %s\n"),
gpg_strerror (rc));
return rc;
}
/* Although it is possible to use a local PIN, we use the global
PIN for this application. */
rc = iso7816_verify_kp (app->slot, 0, "", 0, &pininfo);
/* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL);
}
else
{ {
char *pinvalue; char *pinvalue;
int rc;
rc = pincb (pincb_arg, "PIN", &pinvalue); rc = pincb (pincb_arg, "PIN", &pinvalue);
if (rc) if (rc)
@ -324,35 +353,37 @@ verify_pin (app_t app,
/* The following limits are due to TCOS but also defined in the /* The following limits are due to TCOS but also defined in the
NKS specs. */ NKS specs. */
if (strlen (pinvalue) < 6) if (strlen (pinvalue) < pininfo.minlen)
{ {
log_error ("PIN is too short; minimum length is 6\n"); log_error ("PIN is too short; minimum length is %d\n",
pininfo.minlen);
xfree (pinvalue); xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN); return gpg_error (GPG_ERR_BAD_PIN);
} }
else if (strlen (pinvalue) > 16) else if (strlen (pinvalue) > pininfo.maxlen)
{ {
log_error ("PIN is too large; maximum length is 16\n"); log_error ("PIN is too large; maximum length is %d\n",
pininfo.maxlen);
xfree (pinvalue); xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN); return gpg_error (GPG_ERR_BAD_PIN);
} }
/* Also it is possible to use a local PIN, we use the gloabl /* Although it is possible to use a local PIN, we use the global
PIN for this application. */ PIN for this application. */
rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue)); rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue));
if (rc)
{
if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS )
log_error (_("the NullPIN has not yet been changed\n"));
else
log_error ("verify PIN failed\n");
xfree (pinvalue);
return rc;
}
app->did_chv1 = 1;
xfree (pinvalue); xfree (pinvalue);
} }
if (rc)
{
if ( gpg_err_code (rc) == GPG_ERR_USE_CONDITIONS )
log_error (_("the NullPIN has not yet been changed\n"));
else
log_error ("verify PIN failed\n");
return rc;
}
app->did_chv1 = 1;
return 0; return 0;
} }
@ -457,7 +488,7 @@ do_decipher (app_t app, const char *keyidstr,
if (!keyidstr || !*keyidstr || !indatalen) if (!keyidstr || !*keyidstr || !indatalen)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
/* Check that the provided ID is vaid. This is not really needed /* Check that the provided ID is valid. This is not really needed
but we do it to to enforce correct usage by the caller. */ but we do it to to enforce correct usage by the caller. */
if (strncmp (keyidstr, "NKS-DF01.", 9) ) if (strncmp (keyidstr, "NKS-DF01.", 9) )
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);

View File

@ -1,6 +1,6 @@
/* ccid-driver.c - USB ChipCardInterfaceDevices driver /* ccid-driver.c - USB ChipCardInterfaceDevices driver
* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
* Written by Werner Koch. * Written by Werner Koch.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -1458,11 +1458,6 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen); DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen);
return CCID_DRIVER_ERR_INV_VALUE; return CCID_DRIVER_ERR_INV_VALUE;
} }
if (buffer[0] != expected_type)
{
DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
return CCID_DRIVER_ERR_INV_VALUE;
}
if (buffer[5] != 0) if (buffer[5] != 0)
{ {
DEBUGOUT_1 ("unexpected bulk-in slot (%d)\n", buffer[5]); DEBUGOUT_1 ("unexpected bulk-in slot (%d)\n", buffer[5]);
@ -1475,6 +1470,10 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
return CCID_DRIVER_ERR_INV_VALUE; return CCID_DRIVER_ERR_INV_VALUE;
} }
/* We need to handle the time extension request before we check that
we go the expected message type. This is in particular required
for the Cherry keyboard which sends a time extension request for
each key hit. */
if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80) if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80)
{ {
/* Card present and active, time extension requested. */ /* Card present and active, time extension requested. */
@ -1483,6 +1482,13 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
goto retry; goto retry;
} }
if (buffer[0] != expected_type)
{
DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]);
return CCID_DRIVER_ERR_INV_VALUE;
}
if (!no_debug) if (!no_debug)
{ {
DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n" DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n"
@ -2330,6 +2336,7 @@ ccid_transceive_secure (ccid_driver_t handle,
int i; int i;
size_t dummy_nresp; size_t dummy_nresp;
int testmode; int testmode;
int cherry_mode = 0;
testmode = !resp && !nresp; testmode = !resp && !nresp;
@ -2368,14 +2375,16 @@ ccid_transceive_secure (ccid_driver_t handle,
case VENDOR_SCM: /* Tested with SPR 532. */ case VENDOR_SCM: /* Tested with SPR 532. */
case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */ case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
break; break;
/* The CHERRY XX44 does not yet work. I have not investigated it case VENDOR_CHERRY:
closer because there is another problem: It echos a "*" for /* The CHERRY XX44 keyboard echos an asterisk for each entered
each entered character and we somehow need to arrange that it character on the keyboard channel. We use a special variant
doesn't get to the tty at all. Given that we are running of PC_to_RDR_Secure which directs these characters to the
without a control terminal there is not much we can do about. smart card's bulk-in channel. We also need to append a zero
A weird hack using pinentry comes in mind but I doubt that Lc byte to the APDU. It seems that it will be replaced with
this is a clean solution. Need to contact Cherry. the actual length instead of being appended before the APDU
*/ is send to the card. */
cherry_mode = 1;
break;
default: default:
return CCID_DRIVER_ERR_NOT_SUPPORTED; return CCID_DRIVER_ERR_NOT_SUPPORTED;
} }
@ -2393,7 +2402,7 @@ ccid_transceive_secure (ccid_driver_t handle,
return rc; return rc;
} }
msg[0] = PC_to_RDR_Secure; msg[0] = cherry_mode? 0x89 : PC_to_RDR_Secure;
msg[5] = 0; /* slot */ msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++; msg[6] = seqno = handle->seqno++;
msg[7] = 0; /* bBWI */ msg[7] = 0; /* bBWI */
@ -2405,7 +2414,7 @@ ccid_transceive_secure (ccid_driver_t handle,
if (handle->id_vendor == VENDOR_SCM) if (handle->id_vendor == VENDOR_SCM)
{ {
/* For the SPR532 the next 2 bytes need to be zero. We do this /* For the SPR532 the next 2 bytes need to be zero. We do this
for all SCM product. Kudos to Martin Paljak for this for all SCM products. Kudos to Martin Paljak for this
hint. */ hint. */
msg[13] = msg[14] = 0; msg[13] = msg[14] = 0;
} }
@ -2419,7 +2428,7 @@ ccid_transceive_secure (ccid_driver_t handle,
} }
/* The following is a little endian word. */ /* The following is a little endian word. */
msg[15] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ msg[15] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
msg[16] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ msg[16] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
msg[17] = 0x02; /* bEntryValidationCondition: msg[17] = 0x02; /* bEntryValidationCondition:
@ -2440,6 +2449,8 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[27] = apdu_buf[2]; /* P1 */ msg[27] = apdu_buf[2]; /* P1 */
msg[28] = apdu_buf[3]; /* P2 */ msg[28] = apdu_buf[3]; /* P2 */
msglen = 29; msglen = 29;
if (cherry_mode)
msg[msglen++] = 0;
/* An EDC is not required. */ /* An EDC is not required. */
set_msg_len (msg, msglen - 10); set_msg_len (msg, msglen - 10);

View File

@ -1,3 +1,8 @@
2007-03-07 Werner Koch <wk@g10code.com>
* applygnupgdefaults: New.
* Makefile.am (sbin_SCRIPTS): Add it
2007-03-06 Werner Koch <wk@g10code.com> 2007-03-06 Werner Koch <wk@g10code.com>
* gpgconf-comp.c: Include pwd.h and grp.h. * gpgconf-comp.c: Include pwd.h and grp.h.

View File

@ -1,5 +1,5 @@
# Makefile.am - Tools directory # Makefile.am - Tools directory
# Copyright (C) 2003 Free Software Foundation, Inc. # Copyright (C) 2003, 2007 Free Software Foundation, Inc.
# #
# This file is part of GnuPG. # This file is part of GnuPG.
# #
@ -20,7 +20,7 @@
EXTRA_DIST = \ EXTRA_DIST = \
Manifest watchgnupg.c \ Manifest watchgnupg.c \
addgnupghome gpgsm-gencert.sh \ addgnupghome applygnupgdefaults gpgsm-gencert.sh \
lspgpot mail-signed-keys convert-from-106 lspgpot mail-signed-keys convert-from-106
@ -29,7 +29,7 @@ include $(top_srcdir)/am/cmacros.am
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS)
sbin_SCRIPTS = addgnupghome sbin_SCRIPTS = addgnupghome applygnupgdefaults
bin_SCRIPTS = gpgsm-gencert.sh bin_SCRIPTS = gpgsm-gencert.sh
if HAVE_USTAR if HAVE_USTAR

83
tools/applygnupgdefaults Executable file
View File

@ -0,0 +1,83 @@
#!/bin/sh
# Apply defaults from/etc/gnupg/gpg.conf to all users -*- sh -*-
#
# Copyright 2007 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
PGM=applygnupgdefaults
errorfile=
error () {
echo "$PGM: $*" >&2
echo "$PGM: $*" >>$errorfile
}
info () {
echo "$PGM: $*" >&2
}
if [ -n "$1" ]; then
echo "usage: $PGM" >&2
exit 1
fi
# Cleanup on exit
cleanup ()
{
[ -n "$errorfile" -a -f "$errorfile" ] && rm "$errorfile"
}
trap cleanup EXIT SIGINT SIGHUP SIGPIPE
errorfile="/tmp/$PGM.$$.log"
: >$errorfile
# Check whether we can use getent
if getent --help </dev/null >/dev/null 2>&1 ; then
cat_passwd='getent passwd'
else
cat_passwd='cat /etc/passwd'
info "please note that only users from /etc/passwd are processed"
fi
if [ ! -f /etc/gnupg/gpgconf.conf ]; then
error "global configuration file \`/etc/gnupg/gpgconf.conf' does not exist"
exit 1
fi
if [ ! -f /etc/shells ]; then
error "missing file \`/etc/shells'"
exit 1
fi
if [ $(id -u) -ne 0 ]; then
error "needs to be run as root"
exit 1
fi
${cat_passwd} \
| while IFS=: read -r user dmy_a uid dmy_c dmy_d home shell dmy_rest; do
# Process only entires with a valid login shell
grep </etc/shells "^$shell" 2>/dev/null >/dev/null || continue
# and with an existant gnupg home directory
[ -d "$home/.gnupg" ] || continue
# but not root
[ "${uid:-0}" -eq 0 ] && continue
info "running \"gpgconf --apply-defaults\" for $user"
if su -l -s /bin/sh \
-c 'gpgconf --apply-defaults && echo SUCCESS' $user \
| tail -1 | grep ^SUCCESS >/dev/null ; then
:
else
error "failed to update gnupg defaults for $user"
fi
done
[ "$(wc -c <$errorfile)" -gt 0 ] && exit 1
exit 0