From cvs at cvs.gnupg.org Mon Mar 2 11:26:37 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 02 Mar 2009 11:26:37 +0100 Subject: [svn] GnuPG - r4935 - trunk/agent Message-ID: Author: wk Date: 2009-03-02 11:26:37 +0100 (Mon, 02 Mar 2009) New Revision: 4935 Modified: trunk/agent/ChangeLog trunk/agent/protect-tool.c Log: Fix bug#1003. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-02-27 14:36:59 UTC (rev 4934) +++ trunk/agent/ChangeLog 2009-03-02 10:26:37 UTC (rev 4935) @@ -1,3 +1,9 @@ +2009-03-02 Werner Koch + + * protect-tool.c (import_p12_file): Take care of canceled + passphrase entry. Fixes bug#1003. + (export_p12_file): Ditto. + 2008-12-17 Werner Koch * gpg-agent.c (handle_connections): Set action of all pth event Modified: trunk/agent/protect-tool.c =================================================================== --- trunk/agent/protect-tool.c 2009-02-27 14:36:59 UTC (rev 4934) +++ trunk/agent/protect-tool.c 2009-03-02 10:26:37 UTC (rev 4935) @@ -754,7 +754,11 @@ gcry_sexp_release (s_key); - rc = agent_protect (key, (pw=get_new_passphrase (4)), &result, &resultlen); + pw = get_new_passphrase (4); + if (!pw) + rc = gpg_error (GPG_ERR_CANCELED); + else + rc = agent_protect (key, pw, &result, &resultlen); release_passphrase (pw); xfree (key); if (rc) @@ -981,8 +985,11 @@ kparms[7] = sk.u; kparms[8] = NULL; - key = p12_build (kparms, cert, certlen, - (pw=get_new_passphrase (3)), opt_p12_charset, &keylen); + pw = get_new_passphrase (3); + if (!pw) + key = NULL; + else + key = p12_build (kparms, cert, certlen, pw, opt_p12_charset, &keylen); release_passphrase (pw); xfree (cert); for (i=0; i < 8; i++) From cvs at cvs.gnupg.org Mon Mar 2 12:53:32 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 02 Mar 2009 12:53:32 +0100 Subject: [svn] GnuPG - r4936 - in trunk: common doc Message-ID: Author: wk Date: 2009-03-02 12:53:32 +0100 (Mon, 02 Mar 2009) New Revision: 4936 Modified: trunk/common/homedir.c trunk/doc/ChangeLog trunk/doc/gpg-agent.texi Log: Modernized gpg-agent startup instructions Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2009-03-02 10:26:37 UTC (rev 4935) +++ trunk/doc/ChangeLog 2009-03-02 11:53:32 UTC (rev 4936) @@ -1,3 +1,7 @@ +2009-03-02 Werner Koch + + * gpg-agent.texi (Invoking GPG-AGENT): Modernized instructions. + 2009-01-12 Werner Koch * faq.raw: Fix bug reorting address. Modified: trunk/common/homedir.c =================================================================== --- trunk/common/homedir.c 2009-03-02 10:26:37 UTC (rev 4935) +++ trunk/common/homedir.c 2009-03-02 11:53:32 UTC (rev 4936) @@ -86,7 +86,7 @@ /* Get the standard home directory. In general this function should not be used as it does not consider a registry value (under W32) or - the GNUPGHOME encironment variable. It is better to use + the GNUPGHOME environment variable. It is better to use default_homedir(). */ const char * standard_homedir (void) Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2009-03-02 10:26:37 UTC (rev 4935) +++ trunk/doc/gpg-agent.texi 2009-03-02 11:53:32 UTC (rev 4936) @@ -61,23 +61,36 @@ sure that only one is running: @command{gpg-agent} uses an environment variable to inform clients about the communication parameters. You can write the content of this environment variable to a file so that you can -test for a running agent. This short script may do the job: +test for a running agent. Here is an example using Bourne shell synax: @smallexample -if test -f $HOME/.gpg-agent-info && \ - kill -0 $(cut -d: -f 2 $HOME/.gpg-agent-info) 2>/dev/null; then - GPG_AGENT_INFO=$(cat $HOME/.gpg-agent-info) - export GPG_AGENT_INFO -else - eval $(gpg-agent --daemon) - echo $GPG_AGENT_INFO >$HOME/.gpg-agent-info +gpg-agent --daemon --enable-ssh-support \ + --write-env-file "$@{HOME@}/.gpg-agent-info" + at end smallexample + +This code should only be run once per user session to initially fire up +the agent. In the example the optional support for the included Secure +Shell agent is enabled and the information about the agent is written to +a file in the HOME directory. Note that by running gpg-agent without +arguments you may test whether an agent is already running; however such +a test may lead to a race condition, thus it is not suggested. + + at noindent +The second script needs to be run for each interactive session: + + at smallexample +if [ -f "$@{HOME@}/.gpg-agent-info" ]; then + . "$@{HOME@}/.gpg-agent-info" + export GPG_AGENT_INFO + export SSH_AUTH_SOCK + export SSH_AGENT_PID fi @end smallexample @noindent -Note that the new option @option{--write-env-file} may be used instead. +It reads the data out of the file and exports the variables. If you +don't use Secure Shell, you don't need the last two export statements. - @noindent You should always add the following lines to your @code{.bashrc} or whatever initialization file is used for all shell invocations: From cvs at cvs.gnupg.org Mon Mar 2 13:32:55 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 02 Mar 2009 13:32:55 +0100 Subject: [svn] GnuPG - r4937 - in trunk: . agent doc Message-ID: Author: wk Date: 2009-03-02 13:32:54 +0100 (Mon, 02 Mar 2009) New Revision: 4937 Modified: trunk/THANKS trunk/agent/ChangeLog trunk/agent/gpg-agent.c trunk/doc/ChangeLog trunk/doc/gpg-agent.texi Log: Add missing option strings. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-02 11:53:32 UTC (rev 4936) +++ trunk/agent/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) @@ -1,5 +1,8 @@ 2009-03-02 Werner Koch + * gpg-agent.c: Add missing option strings for "--batch" and + "--homedir". Reported by Petr Uzel. + * protect-tool.c (import_p12_file): Take care of canceled passphrase entry. Fixes bug#1003. (export_p12_file): Ditto. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2009-03-02 11:53:32 UTC (rev 4936) +++ trunk/doc/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) @@ -1,6 +1,7 @@ 2009-03-02 Werner Koch * gpg-agent.texi (Invoking GPG-AGENT): Modernized instructions. + (Agent Options): Fix spelling of option --lc-ctype. 2009-01-12 Werner Koch Modified: trunk/THANKS =================================================================== --- trunk/THANKS 2009-03-02 11:53:32 UTC (rev 4936) +++ trunk/THANKS 2009-03-02 12:32:54 UTC (rev 4937) @@ -192,6 +192,7 @@ Peter Gutmann pgut001 at cs.auckland.ac.nz Peter Marschall Peter.Marschall at gedos.de Peter Valchev pvalchev at openbsd.org +Petr Uzel petr.uzel at suse cz Phong Nguyen Phong.Nguyen at ens.fr Piotr Krukowiecki piotr at pingu.ii.uj.edu.pl QingLong qinglong at bolizm.ihep.su Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2009-03-02 11:53:32 UTC (rev 4936) +++ trunk/agent/gpg-agent.c 2009-03-02 12:32:54 UTC (rev 4937) @@ -1,6 +1,6 @@ /* gpg-agent.c - The GnuPG Agent * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007 Free Software Foundation, Inc. + * 2006, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -141,6 +141,9 @@ { oDisableScdaemon, "disable-scdaemon", 0, N_("do not use the SCdaemon") }, { oFakedSystemTime, "faked-system-time", 2, "@" }, /* (epoch time) */ + { oBatch, "batch", 0, "@" }, + { oHomedir, "homedir", 2, "@"}, + { oDisplay, "display", 2, "@" }, { oTTYname, "ttyname", 2, "@" }, { oTTYtype, "ttytype", 2, "@" }, Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2009-03-02 11:53:32 UTC (rev 4936) +++ trunk/doc/gpg-agent.texi 2009-03-02 12:32:54 UTC (rev 4937) @@ -433,13 +433,13 @@ @item --display @var{string} @itemx --ttyname @var{string} @itemx --ttytype @var{string} - at itemx --lc-type @var{string} + at itemx --lc-ctype @var{string} @itemx --lc-messages @var{string} @itemx --xauthority @var{string} @opindex display @opindex ttyname @opindex ttytype - at opindex lc-type + at opindex lc-ctype @opindex lc-messages @opindex xauthority These options are used with the server mode to pass localization From cvs at cvs.gnupg.org Tue Mar 3 10:03:03 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 10:03:03 +0100 Subject: [svn] GnuPG - r4938 - in trunk: . agent common jnlib po tools Message-ID: Author: wk Date: 2009-03-03 10:02:58 +0100 (Tue, 03 Mar 2009) New Revision: 4938 Modified: trunk/ChangeLog trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/call-scd.c trunk/agent/command.c trunk/agent/gpg-agent.c trunk/common/ChangeLog trunk/common/exechelp.c trunk/configure.ac trunk/jnlib/argparse.c trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.po trunk/po/de.po trunk/po/el.po trunk/po/eo.po trunk/po/es.po trunk/po/et.po trunk/po/fi.po trunk/po/fr.po trunk/po/gl.po trunk/po/hu.po trunk/po/id.po trunk/po/it.po trunk/po/ja.po trunk/po/nb.po trunk/po/pl.po trunk/po/pt.po trunk/po/pt_BR.po trunk/po/ro.po trunk/po/ru.po trunk/po/sk.po trunk/po/sv.po trunk/po/tr.po trunk/po/zh_CN.po trunk/po/zh_TW.po trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c trunk/tools/gpgconf.c trunk/tools/gpgconf.h Log: Add --reload command to gpgconf. Fix a problem in exechelp.c Get ready for a release. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/ChangeLog 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,3 +1,7 @@ +2009-03-03 Werner Koch + + Release 2.0.11. + 2009-01-12 Werner Koch Release 2.0.10. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/agent/ChangeLog 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,5 +1,9 @@ 2009-03-02 Werner Koch + * command.c (cmd_getinfo): Add subcommand "scd_running". + + * call-scd.c (agent_scd_check_running): New. + * gpg-agent.c: Add missing option strings for "--batch" and "--homedir". Reported by Petr Uzel. Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/common/ChangeLog 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,3 +1,8 @@ +2009-03-03 Werner Koch + + * exechelp.c (do_exec): Make sure that /dev/null connected FDs are + not closed. + 2009-01-19 Werner Koch * audit.c (writeout_li): Translate a few more result strings. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/tools/ChangeLog 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,3 +1,14 @@ +2009-03-03 Werner Koch + + * gpgconf.c: New command --reload. + + * gpgconf-comp.c (gc_component_reload): New. + +2009-03-02 Werner Koch + + * gpgconf-comp.c (scdaemon_runtime_change): Killsc d only if it is + not running. + 2009-02-27 Werner Koch * gpgconf-comp.c (gpg_agent_runtime_change): Declare static. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/NEWS 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,4 +1,4 @@ -Noteworthy changes in version 2.0.11 (unreleased) +Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- * Fixed a problem in SCDAEMON which caused unexpected card resets. @@ -7,6 +7,8 @@ * The SCDAEMON option --allow-admin is now used by default. + * GPGCONF now restarts SCdaemon if necessary. + * The default cipher algorithm in GPGSM is now again 3DES. This is due to interoperability problems with Outlook 2003 which still can't cope with AES. Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/agent/agent.h 2009-03-03 09:02:58 UTC (rev 4938) @@ -320,6 +320,7 @@ /*-- call-scd.c --*/ void initialize_module_call_scd (void); void agent_scd_dump_state (void); +int agent_scd_check_running (void); void agent_scd_check_aliveness (void); int agent_reset_scd (ctrl_t ctrl); int agent_card_learn (ctrl_t ctrl, Modified: trunk/agent/call-scd.c =================================================================== --- trunk/agent/call-scd.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/agent/call-scd.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -409,6 +409,16 @@ } +/* Check whether the SCdaemon is active. This is a fast check without + any locking and might give a wrong result if another thread is about + to start the daemon or the daemon is about to be stopped.. */ +int +agent_scd_check_running (void) +{ + return !!primary_scd_ctx; +} + + /* Check whether the Scdaemon is still alive and clean it up if not. */ void agent_scd_check_aliveness (void) Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/agent/command.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -1396,7 +1396,7 @@ pid - Return the process id of the server. socket_name - Return the name of the socket. ssh_socket_name - Return the name of the ssh socket. - + scd_running - Return OK if the SCdaemon is already running. */ static int cmd_getinfo (assuan_context_t ctx, char *line) @@ -1433,6 +1433,10 @@ else rc = gpg_error (GPG_ERR_NO_DATA); } + else if (!strcmp (line, "scd_running")) + { + rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL); + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); return rc; Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/agent/gpg-agent.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -2022,7 +2022,7 @@ log_error ("socket is now serviced by another server\n"); rc = 1; } - else if (opt.verbose) + else if (opt.verbose > 1) log_error ("socket is still served by this server\n"); xfree (buffer); Modified: trunk/common/exechelp.c =================================================================== --- trunk/common/exechelp.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/common/exechelp.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -238,7 +238,7 @@ for (i=0,j=1; argv[i]; i++, j++) arg_list[j] = (char*)argv[i]; - /* Connect the standard files. */ + /* Assign /dev/null to unused FDs. */ for (i=0; i <= 2; i++) { if (fds[i] == -1 ) @@ -248,7 +248,12 @@ log_fatal ("failed to open `%s': %s\n", "/dev/null", strerror (errno)); } - else if (fds[i] != i && dup2 (fds[i], i) == -1) + } + + /* Connect the standard files. */ + for (i=0; i <= 2; i++) + { + if (fds[i] != i && dup2 (fds[i], i) == -1) log_fatal ("dup2 std%s failed: %s\n", i==0?"in":i==1?"out":"err", strerror (errno)); } Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/configure.ac 2009-03-03 09:02:58 UTC (rev 4938) @@ -25,7 +25,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [2.0.11]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) Modified: trunk/jnlib/argparse.c =================================================================== --- trunk/jnlib/argparse.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/jnlib/argparse.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -1023,7 +1023,7 @@ fputs (strusage (11), stdout); if ((s=strusage (12))) printf (" (%s)", s ); - printf (" %s\n", strusage (13) ); + printf (" %s %s\n", strusage (13), "(Gpg4win @PACKAGE_VERSION@)"); /* Additional version lines. */ for (i=20; i < 30; i++) if ((s=strusage (i))) Modified: trunk/po/be.po [not shown] Modified: trunk/po/ca.po [not shown] Modified: trunk/po/cs.po [not shown] Modified: trunk/po/da.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/el.po [not shown] Modified: trunk/po/eo.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/et.po [not shown] Modified: trunk/po/fi.po [not shown] Modified: trunk/po/fr.po [not shown] Modified: trunk/po/gl.po [not shown] Modified: trunk/po/hu.po [not shown] Modified: trunk/po/id.po [not shown] Modified: trunk/po/it.po [not shown] Modified: trunk/po/ja.po [not shown] Modified: trunk/po/nb.po [not shown] Modified: trunk/po/pl.po [not shown] Modified: trunk/po/pt.po [not shown] Modified: trunk/po/pt_BR.po [not shown] Modified: trunk/po/ro.po [not shown] Modified: trunk/po/ru.po [not shown] Modified: trunk/po/sk.po [not shown] Modified: trunk/po/sv.po [not shown] Modified: trunk/po/tr.po [not shown] Modified: trunk/po/zh_CN.po [not shown] Modified: trunk/po/zh_TW.po [not shown] Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/tools/gpgconf-comp.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,5 +1,5 @@ /* gpgconf-comp.c - Configuration utility for GnuPG. - * Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1051,12 +1051,21 @@ { gpg_error_t err; const char *pgmname; - const char *argv[2]; + const char *argv[6]; pid_t pid; + /* We use "GETINFO app_running" to see whether the agent is already + running and kill it only in this case. This avoids an explicit + starting of the agent in case it is not yet running. There is + obviously a race condition but that should not harm too much. */ + pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT); - argv[0] = "scd killscd"; - argv[1] = NULL; + argv[0] = "-s"; + argv[1] = "GETINFO scd_running"; + argv[2] = "/if ${! $?}"; + argv[3] = "scd killscd"; + argv[4] = "/end"; + argv[5] = NULL; err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid); if (!err) @@ -1067,6 +1076,44 @@ } +/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */ +void +gc_component_reload (int component) +{ + int runtime[GC_BACKEND_NR]; + gc_option_t *option; + gc_backend_t backend; + + /* Set a flag for the backends to be reloaded. */ + for (backend = 0; backend < GC_BACKEND_NR; backend++) + runtime[backend] = 0; + + if (component == -1) + { + for (component = 0; component < GC_COMPONENT_NR; component++) + { + option = gc_component[component].options; + for (; option && option->name; option++) + runtime[option->backend] = 1; + } + } + else + { + assert (component < GC_COMPONENT_NR); + option = gc_component[component].options; + for (; option && option->name; option++) + runtime[option->backend] = 1; + } + + /* Do the reload for all selected backends. */ + for (backend = 0; backend < GC_BACKEND_NR; backend++) + { + if (runtime[backend] && gc_backend[backend].runtime_change) + (*gc_backend[backend].runtime_change) (); + } +} + + /* More or less Robust version of dgettext. It has the side effect of switching the codeset to utf-8 because this is what we want to Modified: trunk/tools/gpgconf.c =================================================================== --- trunk/tools/gpgconf.c 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/tools/gpgconf.c 2009-03-03 09:02:58 UTC (rev 4938) @@ -1,5 +1,5 @@ /* gpgconf.c - Configuration utility for GnuPG - * Copyright (C) 2003, 2007 Free Software Foundation, Inc. + * Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -47,7 +47,8 @@ aApplyDefaults, aListConfig, aCheckConfig, - aListDirs + aListDirs, + aReload }; @@ -70,6 +71,7 @@ N_("list global configuration file") }, { aCheckConfig, "check-config", 256, N_("check global configuration file") }, + { aReload, "reload", 256, "@" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -176,6 +178,7 @@ case aApplyDefaults: case aListConfig: case aCheckConfig: + case aReload: cmd = pargs.r_opt; break; @@ -233,6 +236,31 @@ } break; + case aReload: + if (!fname) + { + /* Reload all. */ + gc_component_reload (-1); + } + else + { + /* Reload given component. */ + int idx; + + idx = gc_component_find (fname); + if (idx < 0) + { + fputs (_("Component not found"), stderr); + putc ('\n', stderr); + exit (1); + } + else + { + gc_component_reload (idx); + } + } + break; + case aListConfig: if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp))) exit (1); Modified: trunk/tools/gpgconf.h =================================================================== --- trunk/tools/gpgconf.h 2009-03-02 12:32:54 UTC (rev 4937) +++ trunk/tools/gpgconf.h 2009-03-03 09:02:58 UTC (rev 4938) @@ -44,6 +44,9 @@ void gc_error (int status, int errnum, const char *fmt, ...); +/* Reload given component. */ +void gc_component_reload (int component); + /* List all components that are available. */ void gc_component_list_components (FILE *out); From cvs at cvs.gnupg.org Tue Mar 3 10:21:28 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 10:21:28 +0100 Subject: [svn] GnuPG - r4939 - in trunk: po tests/pkits Message-ID: Author: wk Date: 2009-03-03 10:21:25 +0100 (Tue, 03 Mar 2009) New Revision: 4939 Modified: trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.po trunk/po/de.po trunk/po/el.po trunk/po/eo.po trunk/po/es.po trunk/po/et.po trunk/po/fi.po trunk/po/fr.po trunk/po/gl.po trunk/po/hu.po trunk/po/id.po trunk/po/it.po trunk/po/ja.po trunk/po/nb.po trunk/po/pl.po trunk/po/pt.po trunk/po/pt_BR.po trunk/po/ro.po trunk/po/ru.po trunk/po/sk.po trunk/po/sv.po trunk/po/tr.po trunk/po/zh_CN.po trunk/po/zh_TW.po trunk/tests/pkits/ChangeLog trunk/tests/pkits/Makefile.am Log: fix for pkits. Modified: trunk/tests/pkits/ChangeLog =================================================================== --- trunk/tests/pkits/ChangeLog 2009-03-03 09:02:58 UTC (rev 4938) +++ trunk/tests/pkits/ChangeLog 2009-03-03 09:21:25 UTC (rev 4939) @@ -1,3 +1,7 @@ +2009-03-03 Werner Koch + + * Makefile.am (run-all-tests): Also use /bin/pwd here. + 2009-02-19 Werner Koch * Makefile.am (TESTS_ENVIRONMENT): Use /bin/pwd Modified: trunk/po/be.po [not shown] Modified: trunk/po/ca.po [not shown] Modified: trunk/po/cs.po [not shown] Modified: trunk/po/da.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/el.po [not shown] Modified: trunk/po/eo.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/et.po [not shown] Modified: trunk/po/fi.po [not shown] Modified: trunk/po/fr.po [not shown] Modified: trunk/po/gl.po [not shown] Modified: trunk/po/hu.po [not shown] Modified: trunk/po/id.po [not shown] Modified: trunk/po/it.po [not shown] Modified: trunk/po/ja.po [not shown] Modified: trunk/po/nb.po [not shown] Modified: trunk/po/pl.po [not shown] Modified: trunk/po/pt.po [not shown] Modified: trunk/po/pt_BR.po [not shown] Modified: trunk/po/ro.po [not shown] Modified: trunk/po/ru.po [not shown] Modified: trunk/po/sk.po [not shown] Modified: trunk/po/sv.po [not shown] Modified: trunk/po/tr.po [not shown] Modified: trunk/po/zh_CN.po [not shown] Modified: trunk/po/zh_TW.po [not shown] Modified: trunk/tests/pkits/Makefile.am =================================================================== --- trunk/tests/pkits/Makefile.am 2009-03-03 09:02:58 UTC (rev 4938) +++ trunk/tests/pkits/Makefile.am 2009-03-03 09:21:25 UTC (rev 4939) @@ -64,7 +64,7 @@ run-all-tests: inittests.stamp @set -e; \ - GNUPGHOME=`pwd`; export GNUPGHOME;\ + GNUPGHOME=`/bin/pwd`; export GNUPGHOME;\ unset GPG_AGENT_INFO; \ for tst in $(testscripts); do \ if ./$${tst}; then : ; \ From cvs at cvs.gnupg.org Tue Mar 3 10:47:48 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 10:47:48 +0100 Subject: [svn] GnuPG - r4940 - trunk/tests/pkits Message-ID: Author: wk Date: 2009-03-03 10:47:48 +0100 (Tue, 03 Mar 2009) New Revision: 4940 Modified: trunk/tests/pkits/ChangeLog trunk/tests/pkits/inittests Log: Arggg, forgot one other place. Modified: trunk/tests/pkits/ChangeLog =================================================================== --- trunk/tests/pkits/ChangeLog 2009-03-03 09:21:25 UTC (rev 4939) +++ trunk/tests/pkits/ChangeLog 2009-03-03 09:47:48 UTC (rev 4940) @@ -1,5 +1,7 @@ 2009-03-03 Werner Koch + * inittests (clean_files): Use /bin/pwd here as well. + * Makefile.am (run-all-tests): Also use /bin/pwd here. 2009-02-19 Werner Koch Modified: trunk/tests/pkits/inittests =================================================================== --- trunk/tests/pkits/inittests 2009-03-03 09:21:25 UTC (rev 4939) +++ trunk/tests/pkits/inittests 2009-03-03 09:47:48 UTC (rev 4940) @@ -48,7 +48,7 @@ exit 0 fi -if [ "$GNUPGHOME" != "`pwd`" ]; then +if [ "$GNUPGHOME" != "`/bin/pwd`" ]; then echo "inittests: please set GNUPGHOME to the tests/pkits directory" >&2 exit 1 fi From cvs at cvs.gnupg.org Tue Mar 3 11:18:07 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 11:18:07 +0100 Subject: [svn] GnuPG - r4941 - trunk/jnlib Message-ID: Author: wk Date: 2009-03-03 11:18:07 +0100 (Tue, 03 Mar 2009) New Revision: 4941 Modified: trunk/jnlib/argparse.c Log: Argg again: Remove cruft from a test. Modified: trunk/jnlib/argparse.c =================================================================== --- trunk/jnlib/argparse.c 2009-03-03 09:47:48 UTC (rev 4940) +++ trunk/jnlib/argparse.c 2009-03-03 10:18:07 UTC (rev 4941) @@ -1023,7 +1023,7 @@ fputs (strusage (11), stdout); if ((s=strusage (12))) printf (" (%s)", s ); - printf (" %s %s\n", strusage (13), "(Gpg4win @PACKAGE_VERSION@)"); + printf (" %s\n", strusage (13) ); /* Additional version lines. */ for (i=20; i < 30; i++) if ((s=strusage (i))) From cvs at cvs.gnupg.org Tue Mar 3 13:02:42 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 13:02:42 +0100 Subject: [svn] GnuPG - r4942 - trunk/scd Message-ID: Author: wk Date: 2009-03-03 13:02:42 +0100 (Tue, 03 Mar 2009) New Revision: 4942 Modified: trunk/scd/ChangeLog trunk/scd/command.c Log: Fix segv. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-03 10:18:07 UTC (rev 4941) +++ trunk/scd/ChangeLog 2009-03-03 12:02:42 UTC (rev 4942) @@ -1,3 +1,8 @@ +2009-03-03 Werner Koch + + * command.c (scd_command_handler): Remove dereference of STOPME + after free. + 2009-02-27 Werner Koch * app.c (get_supported_applications): New. Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-03 10:18:07 UTC (rev 4941) +++ trunk/scd/command.c 2009-03-03 12:02:42 UTC (rev 4942) @@ -1857,6 +1857,7 @@ { int rc; assuan_context_t ctx; + int stopme; if (fd == -1) { @@ -1942,13 +1943,14 @@ BUG (); sl->next_session = ctrl->server_local->next_session; } + stopme = ctrl->server_local->stopme; xfree (ctrl->server_local); ctrl->server_local = NULL; /* Release the Assuan context. */ assuan_deinit_server (ctx); - if (ctrl->server_local->stopme) + if (stopme) scd_exit (0); /* If there are no more sessions return true. */ From cvs at cvs.gnupg.org Tue Mar 3 13:26:06 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 03 Mar 2009 13:26:06 +0100 Subject: [svn] GnuPG - r4943 - tags Message-ID: Author: wk Date: 2009-03-03 13:26:06 +0100 (Tue, 03 Mar 2009) New Revision: 4943 Added: tags/gnupg-2.0.11/ Log: Release tag. From cvs at cvs.gnupg.org Thu Mar 5 20:19:38 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 05 Mar 2009 20:19:38 +0100 Subject: [svn] GnuPG - r4944 - in trunk: . agent doc scd Message-ID: Author: wk Date: 2009-03-05 20:19:37 +0100 (Thu, 05 Mar 2009) New Revision: 4944 Modified: trunk/NEWS trunk/agent/ChangeLog trunk/agent/command.c trunk/agent/divert-scd.c trunk/agent/findkey.c trunk/configure.ac trunk/doc/ChangeLog trunk/doc/gpg.texi trunk/doc/help.txt trunk/scd/ChangeLog trunk/scd/app-nks.c trunk/scd/app-openpgp.c trunk/scd/command.c Log: New PIN Callback attributes in gpg-agent. Common prompts for keypad and simple card reader. More support for Netkey cards; PIN management works now. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/agent/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,3 +1,9 @@ +2009-03-05 Werner Koch + + * divert-scd.c (getpin_cb): Support flag 'P'. Change max_digits + from 8 to 16. Append a message about keypads. + * findkey.c (unprotect): Change max digits to 16. + 2009-03-02 Werner Koch * command.c (cmd_getinfo): Add subcommand "scd_running". Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/doc/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,3 +1,12 @@ +2009-03-04 Werner Koch + + * help.txt (gpg.keygen.size): Add a link to web page. + +2009-03-03 Werner Koch + + * gpg.texi (Operational GPG Commands): "merge-only" is an + import-option. Reported by Joseph Oreste Bruni. + 2009-03-02 Werner Koch * gpg-agent.texi (Invoking GPG-AGENT): Modernized instructions. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/scd/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,3 +1,30 @@ +2009-03-05 Werner Koch + + * app-openpgp.c (verify_a_chv): Remove special case for keypads. + (verify_chv3): Ditto. + + * app-nks.c (get_chv_status): New. + (parse_pwidstr): New. + (verify_pin): Add args PWID and DESC and use them. Remove the + CHV1 caching. + (do_change_pin): Allow PIN selection and add reset mode. + (do_learn_status): Use NKS-NKS3 tag for TCOS 3 cards. + (do_readcert, do_sign): Allow NKS-NKS3 tag. + +2009-03-04 Werner Koch + + * app-nks.c (do_getattr): New. + (app_select_nks): Register it. + (verify_pin): Factor some code out to... + (basic_pin_checks): New. + (do_change_pin): Call the basic check. + (app_select_nks): Move AID to .. + (aid_nks): .. new. + (aid_sigg): New. + (switch_application): New. + (do_getattr, do_learn_status, do_readcert, do_sign, do_decipher) + (do_change_pin, do_check_pin): Make sure we are in NKS mode. + 2009-03-03 Werner Koch * command.c (scd_command_handler): Remove dereference of STOPME Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/NEWS 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,3 +1,7 @@ +Noteworthy changes in version 2.0.12 +------------------------------------------------- + + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/agent/command.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -1061,7 +1061,7 @@ /* PASSWD - Change the passphrase/PID for the key identified by keygrip in LINE. */ + Change the passphrase/PIN for the key identified by keygrip in LINE. */ static int cmd_passwd (assuan_context_t ctx, char *line) { Modified: trunk/agent/divert-scd.c =================================================================== --- trunk/agent/divert-scd.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/agent/divert-scd.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,5 +1,5 @@ /* divert-scd.c - divert operations to the scdaemon - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -181,10 +181,11 @@ Flags: - 'N' = New PIN, this requests a second prompt to repeat the the + 'N' = New PIN, this requests a second prompt to repeat the PIN. If the PIN is not correctly repeated it starts from all over. - 'A' = The PIN is an Admin PIN, SO-PIN, PUK or alike. + 'A' = The PIN is an Admin PIN, SO-PIN or alike. + 'P' = The PIN is a PUK (Personal Unblocking Key). 'R' = The PIN is a Reset Code. Example: @@ -204,6 +205,7 @@ int any_flags = 0; int newpin = 0; int resetcode = 0; + int is_puk = 0; const char *again_text = NULL; const char *prompt = "PIN"; @@ -217,6 +219,13 @@ { if (*s == 'A') prompt = _("Admin PIN"); + else if (*s == 'P') + { + /* TRANSLATORS: A PUK is the Personal Unblocking Code + used to unblock a PIN. */ + prompt = _("PUK"); + is_puk = 1; + } else if (*s == 'N') newpin = 1; else if (*s == 'R') @@ -242,7 +251,22 @@ } else if (maxbuf == 1) /* Open the pinentry. */ { - rc = agent_popup_message_start (ctrl, info, NULL); + if (info) + { + char *desc; + + if ( asprintf (&desc, + _("%s%%0A%%0AUse the reader's keypad for input."), + info) < 0 ) + rc = gpg_error_from_syserror (); + else + { + rc = agent_popup_message_start (ctrl, desc, NULL); + xfree (desc); + } + } + else + rc = agent_popup_message_start (ctrl, NULL, NULL); } else rc = gpg_error (GPG_ERR_INV_VALUE); @@ -258,7 +282,7 @@ return gpg_error_from_syserror (); pi->max_length = maxbuf-1; pi->min_digits = 0; /* we want a real passphrase */ - pi->max_digits = 8; + pi->max_digits = 16; pi->max_tries = 3; if (any_flags) @@ -277,17 +301,21 @@ } pi2->max_length = maxbuf-1; pi2->min_digits = 0; - pi2->max_digits = 8; + pi2->max_digits = 16; pi2->max_tries = 1; rc = agent_askpin (ctrl, (resetcode? _("Repeat this Reset Code"): + is_puk? + _("Repeat this PUK"): _("Repeat this PIN")), prompt, NULL, pi2); if (!rc && strcmp (pi->pin, pi2->pin)) { again_text = (resetcode? N_("Reset Code not correctly repeated; try again"): + is_puk? + N_("PUK not correctly repeated; try again"): N_("PIN not correctly repeated; try again")); xfree (pi2); xfree (pi); Modified: trunk/agent/findkey.c =================================================================== --- trunk/agent/findkey.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/agent/findkey.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -367,7 +367,7 @@ return gpg_error_from_syserror (); pi->max_length = 100; pi->min_digits = 0; /* we want a real passphrase */ - pi->max_digits = 8; + pi->max_digits = 16; pi->max_tries = 3; pi->check_cb = try_unprotect_cb; arg.ctrl = ctrl; Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/configure.ac 2009-03-05 19:19:37 UTC (rev 4944) @@ -24,8 +24,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.0.11]) -m4_define([my_issvn], [no]) +m4_define([my_version], [2.0.12]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) Modified: trunk/doc/gpg.texi =================================================================== --- trunk/doc/gpg.texi 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/doc/gpg.texi 2009-03-05 19:19:37 UTC (rev 4944) @@ -425,7 +425,7 @@ keyring. The fast version is currently just a synonym. There are a few other options which control how this command works. -Most notable here is the @option{--keyserver-options merge-only} option +Most notable here is the @option{--import-options merge-only} option which does not insert new keys but does only the merging of new signatures, user-IDs and subkeys. Modified: trunk/doc/help.txt =================================================================== --- trunk/doc/help.txt 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/doc/help.txt 2009-03-05 19:19:37 UTC (rev 4944) @@ -135,7 +135,13 @@ .gpg.keygen.size -Enter the size of the key. +Enter the size of the key. + +The suggested default is usually a good choice. + +If you want to use a large key size, for example 4096 bit, please +think again whether it really makes sense for you. You may want +to view the web page http://www.xkcd.com/538/ . . .gpg.keygen.size.huge.okay Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/scd/app-nks.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -17,6 +17,27 @@ * along with this program; if not, see . */ +/* Notes: + + - This is still work in progress. We are now targeting TCOS 3 cards + but try to keep compatibility to TCOS 2. Both are not fully + working as of now. TCOS 3 PIN management seems to work. Use GPA + from SVN trunk to test it. + + - If required, we automagically switch between the NKS application + and the SigG application. This avoids to use the DINSIG + application which is somewhat limited, has no support for Secure + Messaging as required by TCOS 3 and has no way to change the PIN + or even set the NullPIN. + + - We use the prefix NKS-DF01 for TCOS 2 cards and NKS-NKS3 for newer + cards. This is because the NKS application has moved to DF02 with + TCOS 3 and thus we better use a DF independent tag. + + - We use only the global PINs for the NKS application. + + */ + #include #include #include @@ -30,9 +51,15 @@ #include "iso7816.h" #include "app-common.h" #include "tlv.h" +#include "apdu.h" +static char const aid_nks[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 }; +static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 }; + + static struct { + int is_sigg; /* Valid for SigG application. */ int fid; /* File ID. */ int nks_ver; /* 0 for NKS version 2, 3 for version 3. */ int certtype; /* Type of certificate or 0 if it is not a certificate. */ @@ -40,20 +67,23 @@ int issignkey; /* True if file is a key usable for signing. */ int isenckey; /* True if file is a key usable for decryption. */ } filelist[] = { - { 0x4531, 0, 0, 0xC000, 1, 0 }, /* EF_PK.NKS.SIG */ - { 0xC000, 0, 101 }, /* EF_C.NKS.SIG */ - { 0x4331, 0, 100 }, - { 0x4332, 0, 100 }, - { 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */ - { 0x45B1, 0, 0, 0xC200, 0, 1 }, /* EF_PK.NKS.ENC */ - { 0xC200, 0, 101 }, /* EF_C.NKS.ENC */ - { 0x43B1, 0, 100 }, - { 0x43B2, 0, 100 }, - { 0x4571, 3, 0, 0xc500, 0, 0 }, /* EF_PK.NKS.AUT */ - { 0xC500, 3, 101 }, /* EF_C.NKS.AUT */ - { 0x45B2, 3, 0, 0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */ - { 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */ - { 0 } + { 0, 0x4531, 0, 0, 0xC000, 1, 0 }, /* EF_PK.NKS.SIG */ + { 1, 0x4531, 3, 0, 0x0000, 1, 1 }, /* EF_PK.CH.SIG */ + { 0, 0xC000, 0, 101 }, /* EF_C.NKS.SIG */ + { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */ + { 0, 0x4331, 0, 100 }, + { 0, 0x4332, 0, 100 }, + { 0, 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */ + { 0, 0x45B1, 0, 0, 0xC200, 0, 1 }, /* EF_PK.NKS.ENC */ + { 0, 0xC200, 0, 101 }, /* EF_C.NKS.ENC */ + { 0, 0x43B1, 0, 100 }, + { 0, 0x43B2, 0, 100 }, + { 0, 0x4571, 3, 0, 0xc500, 0, 0 }, /* EF_PK.NKS.AUT */ + { 0, 0xC500, 3, 101 }, /* EF_C.NKS.AUT */ + { 0, 0x45B2, 3, 0, 0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */ + { 0, 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */ +/* { 1, 0xB000, 3, ... */ + { 0, 0 } }; @@ -62,10 +92,14 @@ struct app_local_s { int nks_version; /* NKS version. */ + int sigg_active; /* True if switched to the SigG application. */ }; + +static gpg_error_t switch_application (app_t app, int enable_sigg); + /* Release local data. */ static void @@ -146,7 +180,135 @@ } +/* TCOS responds to a verify with empty data (i.e. without the Lc + byte) with the status of the PIN. PWID is the PIN ID, If SIGG is + true, the application is switched into SigG mode. + Returns: + -1 = Error retrieving the data, + -2 = No such PIN, + -3 = PIN blocked, + -4 = NullPIN activ, + n >= 0 = Number of verification attempts left. */ +static int +get_chv_status (app_t app, int sigg, int pwid) +{ + unsigned char *result = NULL; + size_t resultlen; + char command[4]; + int rc; + if (switch_application (app, sigg)) + return sigg? -2 : -1; /* No such PIN / General error. */ + + command[0] = 0x00; + command[1] = 0x20; + command[2] = 0x00; + command[3] = pwid; + + if (apdu_send_direct (app->slot, command, 4, 0, &result, &resultlen)) + rc = -1; /* Error. */ + else if (resultlen < 2) + rc = -1; /* Error. */ + else + { + unsigned int sw = ((result[resultlen-2] << 8) | result[resultlen-1]); + + if (sw == 0x6a88) + rc = -2; /* No such PIN. */ + else if (sw == 0x6983) + rc = -3; /* PIN is blocked. */ + else if (sw == 0x6985) + rc = -4; /* NullPIN is activ. */ + else if ((sw & 0xfff0) == 0x63C0) + rc = (sw & 0x000f); /* PIN has N tries left. */ + else + rc = -1; /* Other error. */ + } + xfree (result); + + return rc; +} + + +/* Implement the GETATTR command. This is similar to the LEARN + command but returns just one value via the status interface. */ +static gpg_error_t +do_getattr (app_t app, ctrl_t ctrl, const char *name) +{ + static struct { + const char *name; + int special; + } table[] = { + { "$AUTHKEYID", 1 }, + { "NKS-VERSION", 2 }, + { "CHV-STATUS", 3 }, + { NULL, 0 } + }; + gpg_error_t err = 0; + int idx; + char buffer[100]; + + err = switch_application (app, 0); + if (err) + return err; + + for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++) + ; + if (!table[idx].name) + return gpg_error (GPG_ERR_INV_NAME); + + switch (table[idx].special) + { + case 1: /* $AUTHKEYID */ + { + /* NetKey 3.0 cards define this key for authentication. + FIXME: We don't have the readkey command, so this + information is pretty useless. */ + char const tmp[] = "NKS-NKS3.4571"; + send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); + } + break; + + case 2: /* NKS-VERSION */ + snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version); + send_status_info (ctrl, table[idx].name, + buffer, strlen (buffer), NULL, 0); + break; + + case 3: /* CHV-STATUS */ + { + /* Returns: PW1.CH PW2.CH PW1.CH.SIG PW2.CH.SIG That are the + two global passwords followed by the two SigG passwords. + For the values, see the function get_chv_status. */ + int tmp[4]; + + /* We use a helper array so that we can control that there is + no superfluous application switch. Note that PW2.CH.SIG + really has the identifier 0x83 and not 0x82 as one would + expect. */ + tmp[0] = get_chv_status (app, 0, 0x00); + tmp[1] = get_chv_status (app, 0, 0x01); + tmp[2] = get_chv_status (app, 1, 0x81); + tmp[3] = get_chv_status (app, 1, 0x83); + snprintf (buffer, sizeof buffer, + "%d %d %d %d", tmp[0], tmp[1], tmp[2], tmp[3]); + send_status_info (ctrl, table[idx].name, + buffer, strlen (buffer), NULL, 0); + } + break; + + + default: + err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + break; + } + + return err; +} + + + + static gpg_error_t do_learn_status (app_t app, ctrl_t ctrl) { @@ -154,12 +316,19 @@ char ct_buf[100], id_buf[100]; int i; - /* Output information about all useful objects. */ + err = switch_application (app, 0); + if (err) + return err; + + /* Output information about all useful objects in the NKS application. */ for (i=0; filelist[i].fid; i++) { if (filelist[i].nks_ver > app->app_local->nks_version) continue; + if (filelist[i].is_sigg) + continue; + if (filelist[i].certtype) { size_t len; @@ -171,8 +340,10 @@ /* FIXME: We should store the length in the application's context so that a following readcert does only need to read that many bytes. */ - sprintf (ct_buf, "%d", filelist[i].certtype); - sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid); + snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype); + snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X", + app->app_local->nks_version < 3? "DF01":"NKS3", + filelist[i].fid); send_status_info (ctrl, "CERTINFO", ct_buf, strlen (ct_buf), id_buf, strlen (id_buf), @@ -189,7 +360,9 @@ filelist[i].fid, gpg_strerror (err)); else { - sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid); + snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X", + app->app_local->nks_version < 3? "DF01":"NKS3", + filelist[i].fid); send_status_info (ctrl, "KEYPAIRINFO", gripstr, 40, id_buf, strlen (id_buf), @@ -198,6 +371,59 @@ } } + err = switch_application (app, 1); + if (err) + return 0; /* Silently ignore if we can't swicth to SigG. */ + + for (i=0; filelist[i].fid; i++) + { + if (filelist[i].nks_ver > app->app_local->nks_version) + continue; + + if (!filelist[i].is_sigg) + continue; + + if (filelist[i].certtype) + { + size_t len; + + len = app_help_read_length_of_cert (app->slot, + filelist[i].fid, NULL); + if (len) + { + /* FIXME: We should store the length in the application's + context so that a following readcert does only need to + read that many bytes. */ + snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype); + snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X", + filelist[i].fid); + send_status_info (ctrl, "CERTINFO", + ct_buf, strlen (ct_buf), + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + else if (filelist[i].iskeypair) + { + char gripstr[40+1]; + + err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr); + if (err) + log_error ("can't get keygrip from FID 0x%04X: %s\n", + filelist[i].fid, gpg_strerror (err)); + else + { + snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X", + filelist[i].fid); + send_status_info (ctrl, "KEYPAIRINFO", + gripstr, 40, + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + } + + return 0; } @@ -223,7 +449,16 @@ *cert = NULL; *certlen = 0; - if (strncmp (certid, "NKS-DF01.", 9) ) + + err = switch_application (app, 0); + if (err) + return err; + + if (!strncmp (certid, "NKS-NKS3.", 9)) + ; + else if (!strncmp (certid, "NKS-DF01.", 9)) + ; + else return gpg_error (GPG_ERR_INV_ID); certid += 9; if (!hexdigitp (certid) || !hexdigitp (certid+1) @@ -331,21 +566,34 @@ } +static gpg_error_t +basic_pin_checks (const char *pinvalue, int minlen, int maxlen) +{ + if (strlen (pinvalue) < minlen) + { + log_error ("PIN is too short; minimum length is %d\n", minlen); + return gpg_error (GPG_ERR_BAD_PIN); + } + if (strlen (pinvalue) > maxlen) + { + log_error ("PIN is too large; maximum length is %d\n", maxlen); + return gpg_error (GPG_ERR_BAD_PIN); + } + return 0; +} + + /* Verify the PIN if required. */ static gpg_error_t -verify_pin (app_t app, +verify_pin (app_t app, int pwid, const char *desc, gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { iso7816_pininfo_t pininfo; int rc; - /* Note that force_chv1 is never set but we do it here anyway so - that other applications may reuse this function. For example it - makes sense to set force_chv1 for German signature law cards. - NKS is very similar to the DINSIG draft standard. */ - if ( app->did_chv1 && !app->force_chv1 ) - return 0; /* No need to verify it again. */ + if (!desc) + desc = "PIN"; memset (&pininfo, 0, sizeof pininfo); pininfo.mode = 1; @@ -375,7 +623,7 @@ { char *pinvalue; - rc = pincb (pincb_arg, "PIN", &pinvalue); + rc = pincb (pincb_arg, desc, &pinvalue); if (rc) { log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); @@ -384,24 +632,14 @@ /* The following limits are due to TCOS but also defined in the NKS specs. */ - if (strlen (pinvalue) < pininfo.minlen) + rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen); + if (rc) { - log_error ("PIN is too short; minimum length is %d\n", - pininfo.minlen); xfree (pinvalue); - return gpg_error (GPG_ERR_BAD_PIN); + return rc; } - else if (strlen (pinvalue) > pininfo.maxlen) - { - log_error ("PIN is too large; maximum length is %d\n", - pininfo.maxlen); - xfree (pinvalue); - return gpg_error (GPG_ERR_BAD_PIN); - } - /* Although it is possible to use a local PIN, we use the global - PIN for this application. */ - rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue)); + rc = iso7816_verify (app->slot, pwid, pinvalue, strlen (pinvalue)); xfree (pinvalue); } @@ -413,7 +651,6 @@ log_error ("verify PIN failed\n"); return rc; } - app->did_chv1 = 1; return 0; } @@ -447,9 +684,17 @@ if (indatalen != 20 && indatalen != 16 && indatalen != 35) return gpg_error (GPG_ERR_INV_VALUE); + rc = switch_application (app, 0); + if (rc) + return rc; + /* Check that the provided ID is valid. This is not really needed but we do it to enforce correct usage by the caller. */ - if (strncmp (keyidstr, "NKS-DF01.", 9) ) + if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) + ; + else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) + ; + else return gpg_error (GPG_ERR_INV_ID); keyidstr += 9; if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) @@ -490,7 +735,7 @@ memcpy (data+15, indata, indatalen); } - rc = verify_pin (app, pincb, pincb_arg); + rc = verify_pin (app, 0, NULL, pincb, pincb_arg); if (!rc) rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); return rc; @@ -519,9 +764,17 @@ if (!keyidstr || !*keyidstr || !indatalen) return gpg_error (GPG_ERR_INV_VALUE); + rc = switch_application (app, 0); + if (rc) + return rc; + /* Check that the provided ID is valid. This is not really needed but we do it to to enforce correct usage by the caller. */ - if (strncmp (keyidstr, "NKS-DF01.", 9) ) + if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) + ; + else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) + ; + else return gpg_error (GPG_ERR_INV_ID); keyidstr += 9; if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) @@ -542,7 +795,7 @@ 0xC1, 0xB8, mse_parm, sizeof mse_parm); if (!rc) - rc = verify_pin (app, pincb, pincb_arg); + rc = verify_pin (app, 0, NULL, pincb, pincb_arg); if (!rc) rc = iso7816_decipher (app->slot, indata, indatalen, 0x81, outdata, outdatalen); @@ -550,67 +803,221 @@ } -/* Handle the PASSWD command. CHVNOSTR is currently ignored; we - always use VHV0. RESET_MODE is not yet implemented. */ + +/* Parse a password ID string. Returns NULL on error or a string + suitable as passpahrse prompt on success. On success stores the + reference value for the password at R_PWID and a flag indicating + that the SigG application is to be used at R_SIGG. If NEW_MODE is + true, the returned description is suitable for a new Password. + Supported values for PWIDSTR are: + + PW1.CH - Global password 1 + PW2.CH - Global password 2 + PW1.CH.SIG - SigG password 1 + PW2.CH.SIG - SigG password 2 + */ +static const char * +parse_pwidstr (const char *pwidstr, int new_mode, int *r_sigg, int *r_pwid) +{ + const char *desc; + + if (!pwidstr) + desc = NULL; + else if (!strcmp (pwidstr, "PW1.CH")) + { + *r_sigg = 0; + *r_pwid = 0x00; + /* TRANSLATORS: Do not translate the "|*|" prefixes but keep + them verbatim at the start of the string. */ + desc = (new_mode + ? _("|N|Please enter a new PIN for the standard keys.") + : _("||Please enter the PIN for the standard keys.")); + } + else if (!strcmp (pwidstr, "PW2.CH")) + { + *r_pwid = 0x01; + desc = (new_mode + ? _("|NP|Please enter a new PIN Unblocking Code (PUK) " + "for the standard keys.") + : _("|P|Please enter the PIN Unblocking Code (PUK) " + "for the standard keys.")); + } + else if (!strcmp (pwidstr, "PW1.CH.SIG")) + { + *r_pwid = 0x81; + *r_sigg = 1; + desc = (new_mode + ? _("|N|Please enter a new PIN for the key to create " + "qualified signatures.") + : _("||Please enter the PIN for the key to create " + "qualified signatures.")); + } + else if (!strcmp (pwidstr, "PW2.CH.SIG")) + { + *r_pwid = 0x83; /* Yes, that is 83 and not 82. */ + *r_sigg = 1; + desc = (new_mode + ? _("|NP|Please enter a new PIN Unblocking Code (PUK) " + "for the key to create qualified signatures.") + : _("|P|Please enter the PIN Unblocking Code (PUK) " + "for the key to create qualified signatures.")); + } + else + desc = NULL; + + return desc; +} + + +/* Handle the PASSWD command. See parse_pwidstr() for allowed values + for CHVNOSTR. */ static gpg_error_t -do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, +do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr, unsigned int flags, gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { gpg_error_t err; - char *pinvalue; - const char *oldpin; + char *newpin = NULL; + char *oldpin = NULL; + size_t newpinlen; size_t oldpinlen; + int is_sigg; + const char *newdesc; + int pwid; + iso7816_pininfo_t pininfo; (void)ctrl; - (void)chvnostr; - if ((flags & APP_CHANGE_FLAG_RESET)) - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + /* The minimum length is enforced by TCOS, the maximum length is + just a reasonable value. */ + memset (&pininfo, 0, sizeof pininfo); + pininfo.minlen = 6; + pininfo.maxlen = 16; + + newdesc = parse_pwidstr (pwidstr, 1, &is_sigg, &pwid); + if (!newdesc) + return gpg_error (GPG_ERR_INV_ID); + err = switch_application (app, is_sigg); + if (err) + return err; + if ((flags & APP_CHANGE_FLAG_NULLPIN)) { - /* With the nullpin flag, we do not verify the PIN - it would fail - if the Nullpin is still set. */ - oldpin = "\0\0\0\0\0"; + /* With the nullpin flag, we do not verify the PIN - it would + fail if the Nullpin is still set. */ + oldpin = xtrycalloc (1, 6); + if (!oldpin) + { + err = gpg_error_from_syserror (); + goto leave; + } oldpinlen = 6; } else { - err = verify_pin (app, pincb, pincb_arg); + const char *desc; + int dummy1, dummy2; + + if ((flags & APP_CHANGE_FLAG_RESET)) + { + /* Reset mode: Ask for the alternate PIN. */ + const char *altpwidstr; + + if (!strcmp (pwidstr, "PW1.CH")) + altpwidstr = "PW2.CH"; + else if (!strcmp (pwidstr, "PW2.CH")) + altpwidstr = "PW1.CH"; + else if (!strcmp (pwidstr, "PW1.CH.SIG")) + altpwidstr = "PW2.CH.SIG"; + else if (!strcmp (pwidstr, "PW2.CH.SIG")) + altpwidstr = "PW1.CH.SIG"; + else + { + err = gpg_error (GPG_ERR_BUG); + goto leave; + } + desc = parse_pwidstr (altpwidstr, 0, &dummy1, &dummy2); + } + else + { + /* Regular change mode: Ask for the old PIN. */ + desc = parse_pwidstr (pwidstr, 0, &dummy1, &dummy2); + } + err = pincb (pincb_arg, desc, &oldpin); if (err) - return err; - oldpin = NULL; - oldpinlen = 0; + { + log_error ("error getting old PIN: %s\n", gpg_strerror (err)); + goto leave; + } + oldpinlen = strlen (oldpin); + err = basic_pin_checks (oldpin, pininfo.minlen, pininfo.maxlen); + if (err) + goto leave; } - /* TRANSLATORS: Do not translate the "|*|" prefixes but - keep it at the start of the string. We need this elsewhere - to get some infos on the string. */ - err = pincb (pincb_arg, _("|N|New PIN"), &pinvalue); + err = pincb (pincb_arg, newdesc, &newpin); if (err) { log_error (_("error getting new PIN: %s\n"), gpg_strerror (err)); - return err; + goto leave; } + newpinlen = strlen (newpin); + + err = basic_pin_checks (newpin, pininfo.minlen, pininfo.maxlen); + if (err) + goto leave; - err = iso7816_change_reference_data (app->slot, 0x00, - oldpin, oldpinlen, - pinvalue, strlen (pinvalue)); - xfree (pinvalue); + if ((flags & APP_CHANGE_FLAG_RESET)) + { + char *data; + size_t datalen = oldpinlen + newpinlen; + + data = xtrymalloc (datalen); + if (!data) + { + err = gpg_error_from_syserror (); + goto leave; + } + memcpy (data, oldpin, oldpinlen); + memcpy (data+oldpinlen, newpin, newpinlen); + err = iso7816_reset_retry_counter_with_rc (app->slot, pwid, + data, datalen); + wipememory (data, datalen); + xfree (data); + } + else + err = iso7816_change_reference_data (app->slot, pwid, + oldpin, oldpinlen, + newpin, newpinlen); + leave: + xfree (oldpin); + xfree (newpin); return err; } /* Perform a simple verify operation. KEYIDSTR should be NULL or empty. */ static gpg_error_t -do_check_pin (app_t app, const char *keyidstr, +do_check_pin (app_t app, const char *pwidstr, gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { - (void)keyidstr; - return verify_pin (app, pincb, pincb_arg); + gpg_error_t err; + int pwid; + int is_sigg; + const char *desc; + + desc = parse_pwidstr (pwidstr, 0, &is_sigg, &pwid); + if (!desc) + return gpg_error (GPG_ERR_INV_ID); + + err = switch_application (app, is_sigg); + if (err) + return err; + + return verify_pin (app, pwid, desc, pincb, pincb_arg); } @@ -647,15 +1054,42 @@ } +/* If ENABLE_SIGG is true switch to the SigG application if not yet + active. If false switch to the NKS application if not yet active. + Returns 0 on success. */ +static gpg_error_t +switch_application (app_t app, int enable_sigg) +{ + gpg_error_t err; + + if ((app->app_local->sigg_active && enable_sigg) + || (!app->app_local->sigg_active && !enable_sigg) ) + return 0; /* Already switched. */ + + log_info ("app-nks: switching to %s\n", enable_sigg? "SigG":"NKS"); + if (enable_sigg) + err = iso7816_select_application (app->slot, aid_sigg, sizeof aid_sigg, 0); + else + err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0); + + if (!err) + app->app_local->sigg_active = enable_sigg; + else + log_error ("app-nks: error switching to %s: %s\n", + enable_sigg? "SigG":"NKS", gpg_strerror (err)); + + return err; +} + + /* Select the NKS application. */ gpg_error_t app_select_nks (app_t app) { - static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 }; int slot = app->slot; int rc; - rc = iso7816_select_application (slot, aid, sizeof aid, 0); + rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0); if (!rc) { app->apptype = "NKS"; @@ -674,7 +1108,7 @@ app->fnc.deinit = do_deinit; app->fnc.learn_status = do_learn_status; app->fnc.readcert = do_readcert; - app->fnc.getattr = NULL; + app->fnc.getattr = do_getattr; app->fnc.setattr = NULL; app->fnc.genkey = NULL; app->fnc.sign = do_sign; Modified: trunk/scd/app-openpgp.c =================================================================== --- trunk/scd/app-openpgp.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/scd/app-openpgp.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -1,5 +1,6 @@ /* app-openpgp.c - The OpenPGP card application. - * Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2007, 2008, + * 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1402,7 +1403,8 @@ int chvno, unsigned long sigcount, char **pinvalue) { int rc = 0; - char *prompt; + char *prompt_buffer = NULL; + const char *prompt; iso7816_pininfo_t pininfo; int minlen = 6; @@ -1432,30 +1434,34 @@ memset (&pininfo, 0, sizeof pininfo); pininfo.mode = 1; pininfo.minlen = minlen; + + + if (chvno == 1) + { +#define PROMPTSTRING _("||Please enter the PIN%%0A[sigs done: %lu]") + size_t promptsize = strlen (PROMPTSTRING) + 50; + + prompt_buffer = xtrymalloc (promptsize); + if (!prompt_buffer) + return gpg_error_from_syserror (); + snprintf (prompt_buffer, promptsize-1, PROMPTSTRING, sigcount); + prompt = prompt_buffer; +#undef PROMPTSTRING + } + else + prompt = _("||Please enter the PIN"); + if (!opt.disable_keypad && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) { - /* The reader supports the verify command through the keypad. */ - - if (chvno == 1) - { -#define PROMPTSTRING _("||Please enter your PIN at the reader's keypad%%0A" \ - "[sigs done: %lu]") - size_t promptsize = strlen (PROMPTSTRING) + 50; - - prompt = xmalloc (promptsize); - if (!prompt) - return gpg_error_from_syserror (); - snprintf (prompt, promptsize-1, PROMPTSTRING, sigcount); - rc = pincb (pincb_arg, prompt, NULL); - xfree (prompt); -#undef PROMPTSTRING - } - else - rc = pincb (pincb_arg, - _("||Please enter your PIN at the reader's keypad"), - NULL); + /* The reader supports the verify command through the keypad. + Note that the pincb appends a text to the prompt telling the + user to use the keypad. */ + rc = pincb (pincb_arg, prompt, NULL); + prompt = NULL; + xfree (prompt_buffer); + prompt_buffer = NULL; if (rc) { log_info (_("PIN callback returned error: %s\n"), @@ -1471,23 +1477,10 @@ else { /* The reader has no keypad or we don't want to use it. */ - - if (chvno == 1) - { -#define PROMPTSTRING _("||Please enter the PIN%%0A[sigs done: %lu]") - size_t promptsize = strlen (PROMPTSTRING) + 50; - - prompt = xtrymalloc (promptsize); - if (!prompt) - return gpg_error_from_syserror (); - snprintf (prompt, promptsize-1, PROMPTSTRING, sigcount); - rc = pincb (pincb_arg, prompt, pinvalue); - xfree (prompt); -#undef PROMPTSTRING - } - else - rc = pincb (pincb_arg, _("||Please enter the PIN"), pinvalue); - + rc = pincb (pincb_arg, prompt, pinvalue); + prompt = NULL; + xfree (prompt_buffer); + prompt_buffer = NULL; if (rc) { log_info (_("PIN callback returned error: %s\n"), @@ -1586,6 +1579,8 @@ iso7816_pininfo_t pininfo; int minlen = 8; int remaining; + char *prompt_buffer = NULL; + const char *prompt; memset (&pininfo, 0, sizeof pininfo); pininfo.mode = 1; @@ -1610,31 +1605,33 @@ log_info(_("%d Admin PIN attempts remaining before card" " is permanently locked\n"), remaining); - if (!opt.disable_keypad - && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) + if (remaining < 3) { - /* The reader supports the verify command through the keypad. */ - - if (remaining < 3) - { -#define PROMPTSTRING _("|A|Please enter the Admin PIN" \ - " at the reader's keypad%%0A" \ + /* TRANSLATORS: Do not translate the "|A|" prefix but keep + it at the start of the string. Use %%0A to force a + lienfeed. */ +#define PROMPTSTRING _("|A|Please enter the Admin PIN%%0A" \ "[remaining attempts: %d]") - size_t promptsize = strlen (PROMPTSTRING) + 50; - char *prompt; - - prompt = xmalloc (promptsize); - if (!prompt) - return gpg_error_from_syserror (); - snprintf (prompt, promptsize-1, PROMPTSTRING, remaining); - rc = pincb (pincb_arg, prompt, NULL); - xfree (prompt); + size_t promptsize = strlen (PROMPTSTRING) + 50; + + prompt_buffer = xtrymalloc (promptsize); + if (!prompt_buffer) + return gpg_error_from_syserror (); + snprintf (prompt_buffer, promptsize-1, PROMPTSTRING, remaining); + prompt = prompt_buffer; #undef PROMPTSTRING - } - else - rc = pincb (pincb_arg, _("|A|Please enter the Admin PIN" - " at the reader's keypad"), NULL); + } + else + prompt = _("|A|Please enter the Admin PIN"); + if (!opt.disable_keypad + && !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) + { + /* The reader supports the verify command through the keypad. */ + rc = pincb (pincb_arg, prompt, NULL); + prompt = NULL; + xfree (prompt_buffer); + prompt_buffer = NULL; if (rc) { log_info (_("PIN callback returned error: %s\n"), @@ -1649,10 +1646,10 @@ { char *pinvalue; - /* TRANSLATORS: Do not translate the "|A|" prefix but keep - it at the start of the string. We need this elsewhere to - get some infos on the string. */ - rc = pincb (pincb_arg, _("|A|Admin PIN"), &pinvalue); + rc = pincb (pincb_arg, prompt, &pinvalue); + prompt = NULL; + xfree (prompt_buffer); + prompt_buffer = NULL; if (rc) { log_info (_("PIN callback returned error: %s\n"), Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-03 12:26:06 UTC (rev 4943) +++ trunk/scd/command.c 2009-03-05 19:19:37 UTC (rev 4944) @@ -1370,9 +1370,10 @@ /* PASSWD [--reset] [--nullpin] - Change the PIN or reset the retry counter of the card holder - verfication vector CHVNO. The option --nullpin is used for TCOS - cards to set the initial PIN. */ + Change the PIN or, if --reset is given, reset the retry counter of + the card holder verfication vector CHVNO. The option --nullpin is + used for TCOS cards to set the initial PIN. The format of CHVNO + depends on the card application. */ static int cmd_passwd (assuan_context_t ctx, char *line) { @@ -1435,13 +1436,27 @@ literal string "[CHV3]": In this case the Admin PIN is checked if and only if the retry counter is still at 3. + For Netkey: + + Any of the valid PIN Ids may be used. These are the strings: + + PW1.CH - Global password 1 + PW2.CH - Global password 2 + PW1.CH.SIG - SigG password 1 + PW2.CH.SIG - SigG password 2 + + For a definitive list, see the implementation in app-nks.c. + Note that we call a PW2.* PIN a "PUK" despite that since TCOS + 3.0 they are technically alternative PINs used to mutally + unblock each other. + */ static int cmd_checkpin (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc; - char *keyidstr; + char *idstr; if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); @@ -1455,14 +1470,12 @@ /* We have to use a copy of the key ID because the function may use the pin_cb which in turn uses the assuan line buffer and thus overwriting the original line with the keyid. */ - keyidstr = xtrystrdup (line); - if (!keyidstr) + idstr = xtrystrdup (line); + if (!idstr) return out_of_core (); - rc = app_check_pin (ctrl->app_ctx, - keyidstr, - pin_cb, ctx); - xfree (keyidstr); + rc = app_check_pin (ctrl->app_ctx, idstr, pin_cb, ctx); + xfree (idstr); if (rc) log_error ("app_check_pin failed: %s\n", gpg_strerror (rc)); @@ -1566,7 +1579,7 @@ deny_admin - Returns OK if admin commands are not allowed or GPG_ERR_GENERAL if admin commands are allowed. - app_list - Return a list of supported applciations. One + app_list - Return a list of supported applications. One application per line, fields delimited by colons, first field is the name. */ From cvs at cvs.gnupg.org Fri Mar 6 18:31:29 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 06 Mar 2009 18:31:29 +0100 Subject: [svn] GnuPG - r4945 - in trunk: . agent common doc kbx scd sm Message-ID: Author: wk Date: 2009-03-06 18:31:27 +0100 (Fri, 06 Mar 2009) New Revision: 4945 Modified: trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/command.c trunk/agent/divert-scd.c trunk/agent/findkey.c trunk/agent/protect.c trunk/common/ChangeLog trunk/common/sexputil.c trunk/common/util.h trunk/doc/gpgsm.texi trunk/kbx/keybox-search.c trunk/scd/ChangeLog trunk/scd/app-nks.c trunk/sm/ChangeLog trunk/sm/call-agent.c trunk/sm/export.c trunk/sm/fingerprint.c trunk/sm/gpgsm.h trunk/sm/keylist.c Log: New gpg-agent command to list key information. Gpgsm does now print the S/N of cards. Consider ephemeral keys during listing an export. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/ChangeLog 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,3 +1,16 @@ +2009-03-06 Werner Koch + + * command.c (cmd_keyinfo): New command. + (register_commands): Register it. + (agent_write_status): Make sure not to print LR or CR. + * divert-scd.c (ask_for_card): Factor shadow info parsing out to ... + * protect.c (parse_shadow_info): New. + * findkey.c (agent_key_from_file): Use make_canon_sexp. + (agent_write_private_key, unprotect, read_key_file) + (agent_key_available): Use bin2hex. + (agent_key_info_from_file): New. + (read_key_file): Log no error message for ENOENT. + 2009-03-05 Werner Koch * divert-scd.c (getpin_cb): Support flag 'P'. Change max_digits @@ -2227,7 +2240,7 @@ Copyright 2001, 2002, 2003, 2004, 2005, - 2007 Free Software Foundation, Inc. + 2007, 2008, 2009 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 Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/common/ChangeLog 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,3 +1,7 @@ +2009-03-06 Werner Koch + + * sexputil.c (make_canon_sexp): New. + 2009-03-03 Werner Koch * exechelp.c (do_exec): Make sure that /dev/null connected FDs are Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/scd/ChangeLog 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,3 +1,10 @@ +2009-03-06 Werner Koch + + * app-nks.c (do_learn_status): Factor code out to.. + (do_learn_status_core): .. new. + (do_readcert, do_sign, do_decipher): Switch to SigG if needed. + (verify_pin): Use DESC also for keypad based verify. + 2009-03-05 Werner Koch * app-openpgp.c (verify_a_chv): Remove special case for keypads. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/ChangeLog 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,3 +1,14 @@ +2009-03-06 Werner Koch + + * call-agent.c (gpgsm_agent_keyinfo, keyinfo_status_cb): New. + * keylist.c (list_cert_colon): Print card S/N. + + * keylist.c (list_internal_keys): Always list ephemeral keys if + specified by keygrip or fingerprint. + (list_cert_raw): Always show ephemeral flag. + * export.c (gpgsm_export): Export ephemeral keys if specified by + keygrip. + 2009-02-09 Werner Koch * gpgsm.c (main): Change default cipher back to 3DES. @@ -2451,7 +2462,7 @@ Copyright 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008 Free Software Foundation, Inc. + 2007, 2008, 2009 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 Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/NEWS 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,7 +1,13 @@ Noteworthy changes in version 2.0.12 ------------------------------------------------- + * GPGSM now always lists ephemeral certificates if specified by + fingerprint or keygrip. + * New command "KEYINFO" for GPG_AGENT. GPGSM now also returns + information about smartcards. + + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/agent.h 2009-03-06 17:31:27 UTC (rev 4945) @@ -233,6 +233,9 @@ const unsigned char *grip, gcry_sexp_t *result); int agent_key_available (const unsigned char *grip); +gpg_error_t agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, + int *r_keytype, + unsigned char **r_shadow_info); /*-- call-pinentry.c --*/ void initialize_module_call_pinentry (void); @@ -294,6 +297,8 @@ unsigned char **result); int agent_get_shadow_info (const unsigned char *shadowkey, unsigned char const **shadow_info); +gpg_error_t parse_shadow_info (const unsigned char *shadow_info, + char **r_hexsn, char **r_idstr); /*-- trustlist.c --*/ Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/command.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,6 +1,6 @@ /* command.c - gpg-agent command handler * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2006, 2008 Free Software Foundation, Inc. + * 2006, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include @@ -308,8 +311,21 @@ *p++ = ' '; n++; } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; + for ( ; *text && n < DIM (buf)-3; n++, text++) + { + if (*text == '\n') + { + *p++ = '\\'; + *p++ = 'n'; + } + else if (*text == '\r') + { + *p++ = '\\'; + *p++ = 'r'; + } + else + *p++ = *text; + } } *p = 0; err = assuan_write_status (ctx, keyword, buf); @@ -806,9 +822,147 @@ } + +/* KEYINFO [--list] + Return information about the key specified by the KEYGRIP. If the + key is not available GPG_ERR_NOT_FOUND is returned. If the option + --list is given the keygrip is ignored and information about all + available keys are returned. The information is returned as a + status line with this format: + KEYINFO + KEYGRIP is the keygrip. + + TYPE is describes the type of the key: + 'D' - Regular key stored on disk, + 'T' - Key is stored on a smartcard (token). + '-' - Unknown type. + + SERIALNO is an ASCII string with the serial number of the + smartcard. If the serial number is not known a single + dash '-' is used instead. + + IDSTR is the IDSTR used to distinguish keys on a smartcard. If it + is not known a dash is used instead. + + More information may be added in the future. +*/ +static gpg_error_t +do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip) +{ + gpg_error_t err; + char hexgrip[40+1]; + int keytype; + unsigned char *shadow_info = NULL; + char *serialno = NULL; + char *idstr = NULL; + const char *keytypestr; + + err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info); + if (err) + goto leave; + + /* Reformat the grip so that we use uppercase as good style. */ + bin2hex (grip, 20, hexgrip); + + if (keytype == PRIVATE_KEY_CLEAR + || keytype == PRIVATE_KEY_PROTECTED) + keytypestr = "D"; + else if (keytype == PRIVATE_KEY_SHADOWED) + keytypestr = "T"; + else + keytypestr = "-"; + + if (shadow_info) + { + err = parse_shadow_info (shadow_info, &serialno, &idstr); + if (err) + goto leave; + } + + err = agent_write_status (ctrl, "KEYINFO", + hexgrip, + keytypestr, + serialno? serialno : "-", + idstr? idstr : "-", + NULL); + leave: + xfree (shadow_info); + xfree (serialno); + xfree (idstr); + return err; +} + + +static int +cmd_keyinfo (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int err; + unsigned char grip[20]; + DIR *dir = NULL; + int list_mode; + + list_mode = has_option (line, "--list"); + line = skip_options (line); + + if (list_mode) + { + char *dirname; + struct dirent *dir_entry; + char hexgrip[41]; + + dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL); + if (!dirname) + { + err = gpg_error_from_syserror (); + goto leave; + } + dir = opendir (dirname); + if (!dir) + { + err = gpg_error_from_syserror (); + xfree (dirname); + goto leave; + } + xfree (dirname); + + while ( (dir_entry = readdir (dir)) ) + { + if (strlen (dir_entry->d_name) != 44 + || strcmp (dir_entry->d_name + 40, ".key")) + continue; + strncpy (hexgrip, dir_entry->d_name, 40); + hexgrip[40] = 0; + + if ( hex2bin (hexgrip, grip, 20) < 0 ) + continue; /* Bad hex string. */ + + err = do_one_keyinfo (ctrl, grip); + if (err) + goto leave; + } + err = 0; + } + else + { + err = parse_keygrip (ctx, line, grip); + if (err) + goto leave; + err = do_one_keyinfo (ctrl, grip); + } + + leave: + if (dir) + closedir (dir); + if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND) + log_error ("command keyinfo failed: %s\n", gpg_strerror (err)); + return err; +} + + static int send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw) @@ -1574,6 +1728,7 @@ { "GETEVENTCOUNTER",cmd_geteventcounter }, { "ISTRUSTED", cmd_istrusted }, { "HAVEKEY", cmd_havekey }, + { "KEYINFO", cmd_keyinfo }, { "SIGKEY", cmd_sigkey }, { "SETKEY", cmd_sigkey }, { "SETKEYDESC", cmd_setkeydesc }, Modified: trunk/agent/divert-scd.c =================================================================== --- trunk/agent/divert-scd.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/divert-scd.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -28,16 +28,14 @@ #include #include "agent.h" -#include "sexp-parse.h" #include "i18n.h" +#include "sexp-parse.h" static int ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid) { int rc, i; - const unsigned char *s; - size_t n; char *serialno; int no_card = 0; char *desc; @@ -45,39 +43,19 @@ int want_sn_displen; *r_kid = NULL; - s = shadow_info; - if (*s != '(') - return gpg_error (GPG_ERR_INV_SEXP); - s++; - n = snext (&s); - if (!n) - return gpg_error (GPG_ERR_INV_SEXP); - want_sn = xtrymalloc (n*2+1); - if (!want_sn) - return out_of_core (); - for (i=0; i < n; i++) - sprintf (want_sn+2*i, "%02X", s[i]); - s += n; + + rc = parse_shadow_info (shadow_info, &want_sn, &want_kid); + if (rc) + return rc; + /* We assume that a 20 byte serial number is a standard one which - seems to have the property to have a zero in the last nibble. We - don't display this '0' because it may confuse the user */ + has the property to have a zero in the last nibble (Due to BCD + representation). We don't display this '0' because it may + confuse the user. */ want_sn_displen = strlen (want_sn); if (want_sn_displen == 20 && want_sn[19] == '0') want_sn_displen--; - n = snext (&s); - if (!n) - return gpg_error (GPG_ERR_INV_SEXP); - want_kid = xtrymalloc (n+1); - if (!want_kid) - { - gpg_error_t tmperr = out_of_core (); - xfree (want_sn); - return tmperr; - } - memcpy (want_kid, s, n); - want_kid[n] = 0; - for (;;) { rc = agent_card_serialno (ctrl, &serialno); Modified: trunk/agent/findkey.c =================================================================== --- trunk/agent/findkey.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/findkey.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -56,14 +56,12 @@ agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force) { - int i; char *fname; FILE *fp; char hexgrip[40+4+1]; int fd; - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); + bin2hex (grip, 20, hexgrip); strcpy (hexgrip+40, ".key"); fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); @@ -307,14 +305,12 @@ { struct pin_entry_info_s *pi; struct try_unprotect_arg_s arg; - int rc, i; + int rc; unsigned char *result; size_t resultlen; char hexgrip[40+1]; - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - hexgrip[40] = 0; + bin2hex (grip, 20, hexgrip); /* First try to get it from the cache - if there is none or we can't unprotect it, we fall back to ask the user */ @@ -425,7 +421,7 @@ static gpg_error_t read_key_file (const unsigned char *grip, gcry_sexp_t *result) { - int i, rc; + int rc; char *fname; FILE *fp; struct stat st; @@ -436,8 +432,7 @@ *result = NULL; - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); + bin2hex (grip, 20, hexgrip); strcpy (hexgrip+40, ".key"); fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); @@ -445,7 +440,8 @@ if (!fp) { rc = gpg_error_from_syserror (); - log_error ("can't open `%s': %s\n", fname, strerror (errno)); + if (gpg_err_code (rc) != GPG_ERR_ENOENT) + log_error ("can't open `%s': %s\n", fname, strerror (errno)); xfree (fname); return rc; } @@ -488,11 +484,11 @@ /* Return the secret key as an S-Exp in RESULT after locating it using - the grip. Returns NULL in RESULT if the operation should be - diverted to a token; SHADOW_INFO will point then to an allocated - S-Expression with the shadow_info part from the file. CACHE_MODE - defines now the cache shall be used. DESC_TEXT may be set to - present a custom description for the pinentry. */ + the GRIP. Stores NULL at RESULT if the operation shall be diverted + to a token; in this case an allocated S-expression with the + shadow_info part from the file is stored at SHADOW_INFO. + CACHE_MODE defines now the cache shall be used. DESC_TEXT may be + set to present a custom description for the pinentry. */ gpg_error_t agent_key_from_file (ctrl_t ctrl, const char *desc_text, const unsigned char *grip, unsigned char **shadow_info, @@ -513,21 +509,12 @@ return rc; /* For use with the protection functions we also need the key as an - canonical encoded S-expression in abuffer. Create this buffer + canonical encoded S-expression in a buffer. Create this buffer now. */ - len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xtrymalloc (len); - if (!buf) - { - rc = gpg_error_from_syserror (); - gcry_sexp_release (s_skey); - return rc; - } - len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len); - assert (len); + rc = make_canon_sexp (s_skey, &buf, &len); + if (rc) + return rc; - switch (agent_private_key_type (buf)) { case PRIVATE_KEY_CLEAR: @@ -842,19 +829,94 @@ int agent_key_available (const unsigned char *grip) { - int i; + int result; char *fname; char hexgrip[40+4+1]; - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); + bin2hex (grip, 20, hexgrip); strcpy (hexgrip+40, ".key"); fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - i = !access (fname, R_OK)? 0 : -1; + result = !access (fname, R_OK)? 0 : -1; xfree (fname); - return i; + return result; } +/* Return the information about the secret key specified by the binary + keygrip GRIP. If the key is a shadowed one the shadow information + will be stored at the address R_SHADOW_INFO as an allocated + S-expression. */ +gpg_error_t +agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip, + int *r_keytype, unsigned char **r_shadow_info) +{ + gpg_error_t err; + unsigned char *buf; + size_t len; + int keytype; + + (void)ctrl; + + if (r_keytype) + *r_keytype = PRIVATE_KEY_UNKNOWN; + if (r_shadow_info) + *r_shadow_info = NULL; + + { + gcry_sexp_t sexp; + + err = read_key_file (grip, &sexp); + if (err) + { + if (gpg_err_code (err) == GPG_ERR_ENOENT) + return gpg_error (GPG_ERR_NOT_FOUND); + else + return err; + } + err = make_canon_sexp (sexp, &buf, &len); + gcry_sexp_release (sexp); + if (err) + return err; + } + + keytype = agent_private_key_type (buf); + switch (keytype) + { + case PRIVATE_KEY_CLEAR: + break; + case PRIVATE_KEY_PROTECTED: + /* If we ever require it we could retrieve the comment fields + from such a key. */ + break; + case PRIVATE_KEY_SHADOWED: + if (r_shadow_info) + { + const unsigned char *s; + size_t n; + + err = agent_get_shadow_info (buf, &s); + if (!err) + { + n = gcry_sexp_canon_len (s, 0, NULL, NULL); + assert (n); + *r_shadow_info = xtrymalloc (n); + if (!*r_shadow_info) + err = gpg_error_from_syserror (); + else + memcpy (*r_shadow_info, s, n); + } + } + break; + default: + err = gpg_error (GPG_ERR_BAD_SECKEY); + break; + } + + if (!err && r_keytype) + *r_keytype = keytype; + + xfree (buf); + return err; +} Modified: trunk/agent/protect.c =================================================================== --- trunk/agent/protect.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/agent/protect.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,6 +1,6 @@ /* protect.c - Un/Protect a secret key * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003, 2007 Free Software Foundation, Inc. + * 2003, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1105,3 +1105,68 @@ return 0; } + +/* Parse the canonical encoded SHADOW_INFO S-expression. On success + the hex encoded serial number is returned as a malloced strings at + R_HEXSN and the Id string as a malloced string at R_IDSTR. On + error an error code is returned and NULL is stored at the result + parameters addresses. If the serial number or the ID string is not + required, NULL may be passed for them. */ +gpg_error_t +parse_shadow_info (const unsigned char *shadow_info, + char **r_hexsn, char **r_idstr) +{ + const unsigned char *s; + size_t n; + + if (r_hexsn) + *r_hexsn = NULL; + if (r_idstr) + *r_idstr = NULL; + + s = shadow_info; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + if (r_hexsn) + { + *r_hexsn = bin2hex (s, n, NULL); + if (!*r_hexsn) + return gpg_error_from_syserror (); + } + s += n; + + n = snext (&s); + if (!n) + { + if (r_hexsn) + { + xfree (*r_hexsn); + *r_hexsn = NULL; + } + return gpg_error (GPG_ERR_INV_SEXP); + } + + if (r_idstr) + { + *r_idstr = xtrymalloc (n+1); + if (!*r_idstr) + { + if (r_hexsn) + { + xfree (*r_hexsn); + *r_hexsn = NULL; + } + return gpg_error_from_syserror (); + } + memcpy (*r_idstr, s, n); + (*r_idstr)[n] = 0; + } + + return 0; +} + Modified: trunk/common/sexputil.c =================================================================== --- trunk/common/sexputil.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/common/sexputil.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,5 +1,5 @@ /* sexputil.c - Utility functions for S-expressions. - * Copyright (C) 2005, 2007 Free Software Foundation, Inc. + * Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -34,6 +34,42 @@ #include "util.h" #include "sexp-parse.h" + +/* Helper function to create a a canonical encoded S-expression from a + Libgcrypt S-expression object. The function returns 0 on success + and the malloced canonical S-expression is stored at R_BUFFER and + the allocated length at R_BUFLEN. On error an error code is + returned and (NULL, 0) stored at R_BUFFER and R_BUFLEN. If the + allocated buffer length is not required, NULL by be used for + R_BUFLEN. */ +gpg_error_t +make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen) +{ + size_t len; + unsigned char *buf; + + *r_buffer = NULL; + if (r_buflen) + *r_buflen = 0;; + + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); + if (!len) + return gpg_error (GPG_ERR_BUG); + buf = xtrymalloc (len); + if (!buf) + return gpg_error_from_syserror (); + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len); + if (!len) + return gpg_error (GPG_ERR_BUG); + + *r_buffer = buf; + if (r_buflen) + *r_buflen = len; + + return 0; +} + + /* Return the so called "keygrip" which is the SHA-1 hash of the public key parameters expressed in a way depended on the algorithm. Modified: trunk/common/util.h =================================================================== --- trunk/common/util.h 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/common/util.h 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,5 +1,5 @@ /* util.h - Utility functions for GnuPG - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -183,6 +183,8 @@ /*-- sexputil.c */ +gpg_error_t make_canon_sexp (gcry_sexp_t sexp, + unsigned char **r_buffer, size_t *r_buflen); gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, unsigned char *grip); int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); Modified: trunk/doc/gpgsm.texi =================================================================== --- trunk/doc/gpgsm.texi 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/doc/gpgsm.texi 2009-03-06 17:31:27 UTC (rev 4945) @@ -240,10 +240,12 @@ (@pxref{how-to-specify-a-user-id}). When used along with the @option{--armor} option a few informational lines are prepended before each block. There is one limitation: As there is no commonly agreed -upon way to pack more than one certificate into an ASN.1 structure, the -binary export (i.e. without using @option{armor}) works only for the -export of one certificate. Thus it is required to specify a - at var{pattern} which yields exactly one certificate. +upon way to pack more than one certificate into an ASN.1 structure, +the binary export (i.e. without using @option{armor}) works only for +the export of one certificate. Thus it is required to specify a + at var{pattern} which yields exactly one certificate. Ephemeral +certificate are only exported if all @var{pattern} are given as +fingerprints or keygrips. @item --export-secret-key-p12 @var{key-id} @opindex export @@ -601,7 +603,9 @@ @item --with-ephemeral-keys @opindex with-ephemeral-keys -Include ephemeral flagged keys in the output of key listings. +Include ephemeral flagged keys in the output of key listings. Note +that they are included anyway if the key specification for a listing +is given as fingerprint or keygrip. @item --debug-level @var{level} @opindex debug-level Modified: trunk/kbx/keybox-search.c =================================================================== --- trunk/kbx/keybox-search.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/kbx/keybox-search.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -457,7 +457,7 @@ #ifdef KEYBOX_WITH_X509 /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP. - We don't have the keygrips as meta data, thus wen need to parse the + We don't have the keygrips as meta data, thus we need to parse the certificate. Fixme: We might want to return proper error codes instead of failing a search for invalid certificates etc. */ static int Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/scd/app-nks.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -308,17 +308,20 @@ - -static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +static void +do_learn_status_core (app_t app, ctrl_t ctrl, int is_sigg) { gpg_error_t err; char ct_buf[100], id_buf[100]; int i; + const char *tag; - err = switch_application (app, 0); - if (err) - return err; + if (is_sigg) + tag = "SIGG"; + else if (app->app_local->nks_version < 3) + tag = "DF01"; + else + tag = "NKS3"; /* Output information about all useful objects in the NKS application. */ for (i=0; filelist[i].fid; i++) @@ -326,7 +329,7 @@ if (filelist[i].nks_ver > app->app_local->nks_version) continue; - if (filelist[i].is_sigg) + if (!!filelist[i].is_sigg != !!is_sigg) continue; if (filelist[i].certtype) @@ -342,8 +345,7 @@ read that many bytes. */ snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype); snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X", - app->app_local->nks_version < 3? "DF01":"NKS3", - filelist[i].fid); + tag, filelist[i].fid); send_status_info (ctrl, "CERTINFO", ct_buf, strlen (ct_buf), id_buf, strlen (id_buf), @@ -361,8 +363,7 @@ else { snprintf (id_buf, sizeof id_buf, "NKS-%s.%04X", - app->app_local->nks_version < 3? "DF01":"NKS3", - filelist[i].fid); + tag, filelist[i].fid); send_status_info (ctrl, "KEYPAIRINFO", gripstr, 40, id_buf, strlen (id_buf), @@ -371,58 +372,26 @@ } } - err = switch_application (app, 1); - if (err) - return 0; /* Silently ignore if we can't swicth to SigG. */ - for (i=0; filelist[i].fid; i++) - { - if (filelist[i].nks_ver > app->app_local->nks_version) - continue; +} - if (!filelist[i].is_sigg) - continue; - if (filelist[i].certtype) - { - size_t len; +static gpg_error_t +do_learn_status (app_t app, ctrl_t ctrl) +{ + gpg_error_t err; - len = app_help_read_length_of_cert (app->slot, - filelist[i].fid, NULL); - if (len) - { - /* FIXME: We should store the length in the application's - context so that a following readcert does only need to - read that many bytes. */ - snprintf (ct_buf, sizeof ct_buf, "%d", filelist[i].certtype); - snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X", - filelist[i].fid); - send_status_info (ctrl, "CERTINFO", - ct_buf, strlen (ct_buf), - id_buf, strlen (id_buf), - NULL, (size_t)0); - } - } - else if (filelist[i].iskeypair) - { - char gripstr[40+1]; + err = switch_application (app, 0); + if (err) + return err; + + do_learn_status_core (app, ctrl, 0); - err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr); - if (err) - log_error ("can't get keygrip from FID 0x%04X: %s\n", - filelist[i].fid, gpg_strerror (err)); - else - { - snprintf (id_buf, sizeof id_buf, "NKS-SIGG.%04X", - filelist[i].fid); - send_status_info (ctrl, "KEYPAIRINFO", - gripstr, 40, - id_buf, strlen (id_buf), - NULL, (size_t)0); - } - } - } + err = switch_application (app, 1); + if (err) + return 0; /* Silently ignore if we can't switch to SigG. */ + do_learn_status_core (app, ctrl, 1); return 0; } @@ -446,20 +415,24 @@ int class, tag, constructed, ndef; size_t totobjlen, objlen, hdrlen; int rootca = 0; + int is_sigg = 0; *cert = NULL; *certlen = 0; - err = switch_application (app, 0); - if (err) - return err; - if (!strncmp (certid, "NKS-NKS3.", 9)) ; else if (!strncmp (certid, "NKS-DF01.", 9)) ; + else if (!strncmp (certid, "NKS-SIGG.", 9)) + is_sigg = 1; else return gpg_error (GPG_ERR_INV_ID); + + err = switch_application (app, is_sigg); + if (err) + return err; + certid += 9; if (!hexdigitp (certid) || !hexdigitp (certid+1) || !hexdigitp (certid+2) || !hexdigitp (certid+3) @@ -603,9 +576,7 @@ 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); + rc = pincb (pincb_arg, desc, NULL); if (rc) { log_info (_("PIN callback returned error: %s\n"), @@ -613,11 +584,8 @@ 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); + rc = iso7816_verify_kp (app->slot, pwid, "", 0, &pininfo); + pincb (pincb_arg, NULL, NULL); /* Dismiss the prompt. */ } else { @@ -630,8 +598,6 @@ return rc; } - /* The following limits are due to TCOS but also defined in the - NKS specs. */ rc = basic_pin_checks (pinvalue, pininfo.minlen, pininfo.maxlen); if (rc) { @@ -675,6 +641,7 @@ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; int rc, i; + int is_sigg = 0; int fid; unsigned char data[35]; /* Must be large enough for a SHA-1 digest + the largest OID _prefix above. */ @@ -684,19 +651,22 @@ if (indatalen != 20 && indatalen != 16 && indatalen != 35) return gpg_error (GPG_ERR_INV_VALUE); - rc = switch_application (app, 0); - if (rc) - return rc; - /* Check that the provided ID is valid. This is not really needed but we do it to enforce correct usage by the caller. */ if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) ; else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) ; + else if (!strncmp (keyidstr, "NKS-SIGG.", 9) ) + is_sigg = 1; else return gpg_error (GPG_ERR_INV_ID); keyidstr += 9; + + rc = switch_application (app, is_sigg); + if (rc) + return rc; + if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) || keyidstr[4]) @@ -743,7 +713,6 @@ - /* Decrypt the data in INDATA and return the allocated result in OUTDATA. If a PIN is required the PINCB will be used to ask for the PIN; it should return the PIN in an allocated buffer and put it into PIN. */ @@ -759,24 +728,28 @@ 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */ }; int rc, i; + int is_sigg = 0; int fid; if (!keyidstr || !*keyidstr || !indatalen) return gpg_error (GPG_ERR_INV_VALUE); - rc = switch_application (app, 0); - if (rc) - return rc; - /* Check that the provided ID is valid. This is not really needed but we do it to to enforce correct usage by the caller. */ if (!strncmp (keyidstr, "NKS-NKS3.", 9) ) ; else if (!strncmp (keyidstr, "NKS-DF01.", 9) ) ; + else if (!strncmp (keyidstr, "NKS-SIGG.", 9) ) + is_sigg = 1; else return gpg_error (GPG_ERR_INV_ID); keyidstr += 9; + + rc = switch_application (app, is_sigg); + if (rc) + return rc; + if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) || keyidstr[4]) Modified: trunk/sm/call-agent.c =================================================================== --- trunk/sm/call-agent.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/call-agent.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,6 +1,6 @@ /* call-agent.c - Divert GPGSM operations to the agent * Copyright (C) 2001, 2002, 2003, 2005, 2007, - * 2008 Free Software Foundation, Inc. + * 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -836,3 +836,68 @@ } + +static int +keyinfo_status_cb (void *opaque, const char *line) +{ + char **serialno = opaque; + const char *s, *s2; + + if (!strncmp (line, "KEYINFO ", 8) && !*serialno) + { + s = strchr (line+8, ' '); + if (s && s[1] == 'T' && s[2] == ' ' && s[3]) + { + s += 3; + s2 = strchr (s, ' '); + if ( s2 > s ) + { + *serialno = xtrymalloc ((s2 - s)+1); + if (*serialno) + { + memcpy (*serialno, s, s2 - s); + (*serialno)[s2 - s] = 0; + } + } + } + } + return 0; +} + +/* Return the serial number for a secret key. If the returned serial + number is NULL, the key is not stored on a smartcard. Caller needs + to free R_SERIALNO. */ +gpg_error_t +gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +{ + gpg_error_t err; + char line[ASSUAN_LINELENGTH]; + char *serialno = NULL; + + *r_serialno = NULL; + + err = start_agent (ctrl); + if (err) + return err; + + if (!hexkeygrip || strlen (hexkeygrip) != 40) + return gpg_error (GPG_ERR_INV_VALUE); + + snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip); + line[DIM(line)-1] = 0; + + err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, + keyinfo_status_cb, &serialno); + if (!err && serialno) + { + /* Sanity check for bad characters. */ + if (strpbrk (serialno, ":\n\r")) + err = GPG_ERR_INV_VALUE; + } + if (err) + xfree (serialno); + else + *r_serialno = serialno; + return err; +} + Modified: trunk/sm/export.c =================================================================== --- trunk/sm/export.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/export.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,5 +1,5 @@ /* export.c - Export certificates and private keys. - * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -37,11 +37,11 @@ /* A table to store a fingerprint as used in a duplicates table. We - don't need to hash here because a fingerprint is alrady a perfect + don't need to hash here because a fingerprint is already a perfect hash value. This we use the most significant bits to index the table and then use a linked list for the overflow. Possible - enhancement for very large number of certictates: Add a second - level table and then resort to a linked list. */ + enhancement for very large number of certificates: Add a second + level table and then resort to a linked list. */ struct duptable_s { struct duptable_s *next; @@ -192,18 +192,16 @@ } } - /* If all specifications are done by fingerprint, we switch to - ephemeral mode so that _all_ currently available and matching - certificates are exported. - - fixme: we should in this case keep a list of certificates to - avoid accidential export of duplicate certificates. */ + /* If all specifications are done by fingerprint or keygrip, we + switch to ephemeral mode so that _all_ currently available and + matching certificates are exported. */ if (names && ndesc) { for (i=0; (i < ndesc && (desc[i].mode == KEYDB_SEARCH_MODE_FPR || desc[i].mode == KEYDB_SEARCH_MODE_FPR20 - || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++) + || desc[i].mode == KEYDB_SEARCH_MODE_FPR16 + || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++) ; if (i == ndesc) keydb_set_ephemeral (hd, 1); @@ -228,7 +226,7 @@ rc = insert_duptable (dtable, fpr, &exists); if (rc) { - log_error ("inserting into duplicates table fauiled: %s\n", + log_error ("inserting into duplicates table failed: %s\n", gpg_strerror (rc)); goto leave; } Modified: trunk/sm/fingerprint.c =================================================================== --- trunk/sm/fingerprint.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/fingerprint.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -196,8 +196,8 @@ return array; } -/* Return an allocated buffer with the keygrip of CERT in from of an - hexstring. NULL is returned in case of error */ +/* Return an allocated buffer with the keygrip of CERT encoded as a + hexstring. NULL is returned in case of error. */ char * gpgsm_get_keygrip_hexstring (ksba_cert_t cert) { Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/gpgsm.h 2009-03-06 17:31:27 UTC (rev 4945) @@ -395,6 +395,8 @@ int gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc); gpg_error_t gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc); gpg_error_t gpgsm_agent_send_nop (ctrl_t ctrl); +gpg_error_t gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip, + char **r_serialno); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ctrl_t ctrl, Modified: trunk/sm/keylist.c =================================================================== --- trunk/sm/keylist.c 2009-03-05 19:19:37 UTC (rev 4944) +++ trunk/sm/keylist.c 2009-03-06 17:31:27 UTC (rev 4945) @@ -1,6 +1,6 @@ /* keylist.c - Print certificates in various formats. * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004, 2005, 2008 Free Software Foundation, Inc. + * 2004, 2005, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -481,7 +481,24 @@ es_putc (':', fp); /* Field 12, capabilities: */ print_capabilities (cert, fp); + /* Field 13, not used: */ es_putc (':', fp); + if (have_secret) + { + char *cardsn; + + p = gpgsm_get_keygrip_hexstring (cert); + if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn) + { + /* Field 14, not used: */ + es_putc (':', fp); + /* Field 15: Token serial number. */ + es_fputs (cardsn, fp); + es_putc (':', fp); + } + xfree (cardsn); + xfree (p); + } es_putc ('\n', fp); /* FPR record */ @@ -989,7 +1006,7 @@ es_fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err)); } - if (opt.with_ephemeral_keys && hd) + if (hd) { unsigned int blobflags; @@ -1275,6 +1292,7 @@ gpg_error_t rc = 0; const char *lastresname, *resname; int have_secret; + int want_ephemeral = opt.with_ephemeral_keys; hd = keydb_new (0); if (!hd) @@ -1319,7 +1337,24 @@ } - if (opt.with_ephemeral_keys) + /* If all specifications are done by fingerprint or keygrip, we + switch to ephemeral mode so that _all_ currently available and + matching certificates are listed. */ + if (!want_ephemeral && names && ndesc) + { + int i; + + for (i=0; (i < ndesc + && (desc[i].mode == KEYDB_SEARCH_MODE_FPR + || desc[i].mode == KEYDB_SEARCH_MODE_FPR20 + || desc[i].mode == KEYDB_SEARCH_MODE_FPR16 + || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++) + ; + if (i == ndesc) + want_ephemeral = 1; + } + + if (want_ephemeral) keydb_set_ephemeral (hd, 1); /* It would be nice to see which of the given users did actually From cvs at cvs.gnupg.org Fri Mar 6 23:29:49 2009 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 06 Mar 2009 23:29:49 +0100 Subject: [svn] gpgme - r1358 - in trunk: . assuan src Message-ID: Author: marcus Date: 2009-03-06 23:29:49 +0100 (Fri, 06 Mar 2009) New Revision: 1358 Modified: trunk/ChangeLog trunk/assuan/ChangeLog trunk/assuan/assuan-buffer.c trunk/assuan/assuan-client.c trunk/assuan/assuan-connect.c trunk/assuan/assuan-defs.h trunk/assuan/assuan-handler.c trunk/assuan/assuan-inquire.c trunk/assuan/assuan-io.c trunk/assuan/assuan-listen.c trunk/assuan/assuan-logging.c trunk/assuan/assuan-pipe-connect.c trunk/assuan/assuan-pipe-server.c trunk/assuan/assuan-socket-connect.c trunk/assuan/assuan-socket-server.c trunk/assuan/assuan-socket.c trunk/assuan/assuan-uds.c trunk/assuan/assuan-util.c trunk/assuan/assuan.h trunk/assuan/mkerrors trunk/src/debug.c trunk/src/version.c Log: assuan/ 2009-03-06 Marcus Brinkmann * assuan/: Update to libassuan SVN 2009-03-06. src/ 2009-03-06 Marcus Brinkmann * version.c (do_subsystem_inits): Do not set assuan log level. * debug.c (debug_init): Likewise. [The diff below has been truncated] Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/ChangeLog 2009-03-06 22:29:49 UTC (rev 1358) @@ -1,3 +1,7 @@ +2009-03-06 Marcus Brinkmann + + * assuan/: Update to libassuan SVN 2009-03-06. + 2009-01-26 Werner Koch * configure.ac (AC_CONFIG_FILES): Add tests/opassuan/Makefile. Modified: trunk/assuan/ChangeLog =================================================================== --- trunk/assuan/ChangeLog 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/ChangeLog 2009-03-06 22:29:49 UTC (rev 1358) @@ -3,68 +3,262 @@ * assuan-buffer.c (assuan_send_data): Add hack to optionally send a final "CAN". -2008-11-03 Marcus Brinkmann +2008-11-03 Marcus Brinkmann - * Makefile.am (INCLUDES): Replace gpgme path with src. + * assuan-handler.c (std_handler_help): Make I unsigned to silence + gcc -W warning. + * assuan-logging.c (_assuan_log_print_buffer): Likewise for N. + * funopen.c (_assuan_funopen): Remove initializer to silence gcc + -W warning. + * assuan-handler.c (std_cmd_table): Add missing initializer to + silence gcc -W warning. + * assuan-socket-server.c (io): Likewise. + * assuan-socket-connect.c (assuan_socket_connect_ext): Likewise. -2008-10-30 Marcus Brinkmann +2008-10-29 Marcus Brinkmann - * assuan-pipe-connect.c: Fix prototype for _gpgme_io_spawn. Cast - second argument in its invocation to silence gcc warning. + * assuan.h (assuan_error_t) (_ASSUAN_ONLY_GPG_ERRORS): Make + unsigned int. + (assuan_transact): Change return type of callback handlers to + assuan_error_t. -2008-06-25 Marcus Brinkmann +2008-10-15 Werner Koch - * assuan-pipe-connect.c (struct spawn_fd_item_s): Add new members. - (HANDLE_TRANSLATION): New macro. - (pipe_connect_gpgme): Adjust caller of _gpgme_io_spawn. - [HANDLE_TRANSLATION]: Return translated handles. + * assuan-logging.c (_assuan_log_printf): Flush if the format + string ends with a LF. -2008-02-14 Werner Koch +2008-09-01 Werner Koch - * assuan-pipe-connect.c (_gpgme_io_spawn): Adjust prototype. - (pipe_connect_gpgme, pipe_connect_gpgme): Adjust call. + * assuan-io.c: Include time.h. Fixes bug#951. + (_assuan_usleep): Use nanosleep only is available. -2008-01-04 Marcus Brinkmann +2008-03-25 Marcus Brinkmann - * assuan-pipe-connect.c (_gpgme_io_pipe) - (_gpgme_io_spawn) [_ASSUAN_IN_GPGME_BUILD_ASSUAN]: Add prototypes - to silence compiler warning. Reported by Alon Bar-Lev. + * assuan-inquire.c (assuan_inquire): Loop over _assuan_read_line + for EAGAIN. +2008-03-21 Marcus Brinkmann + + * assuan-defs.h (_assuan_usleep): New prototype. + * assuan-io.c (_assuan_usleep): New function. + * assuan-io-pth.c (_assuan_usleep): New function. + * mkerrors: Do not incude , but assuan-defs.h. + (_assuan_error_is_eagain): Call _assuan_usleep. + + * mkerrors [HAVE_W32_SYSTEM]: Include + (_assuan_error_is_eagain) [HAVE_W32_SYSTEM]: Wait the tenth of a + second. + +2007-11-23 Marcus Brinkmann + + * assuan-inquire.c (_assuan_inquire_ext_cb): Pass through return + value from callback function. + Suggested by Ben Kibbey . + +2007-11-14 Werner Koch + + * assuan-pipe-connect.c (pipe_connect_unix): Add dummy arg FLAGS. + (pipe_connect_w32): Add arg FLAGS and start process detached if + requested. Changed callers to pass 0. + (assuan_pipe_connect_ext): Pass FLAG. + +2007-11-12 Marcus Brinkmann + + * assuan-inquire.c (_assuan_inquire_ext_cb): Clear + CTX->inquire_membuf after deallocating it. + +2007-10-18 Marcus Brinkmann + + * assuan-handler.c (std_handler_help): New function. + (std_cmd_table): Add new command HELP. + +2007-10-08 Werner Koch + + * assuan-util.c (assuan_set_io_hooks): New. + * assuan.h (struct assuan_io_hooks): New. + (assuan_set_io_hooks, _assuan_io_hooks): Add prefix macros. + * assuan-defs.h (_assuan_io_hooks): New. + * assuan-io.c (do_io_read): Take all code from _assuan_io_read. + (_assuan_io_read, _assuan_simple_read): Add hook feature. + (do_io_write): Take all code from _assuan_io_write. + (_assuan_io_write, _assuan_simple_write): Add hook feature. + * assuan-io-pth.c (_assuan_simple_read, _assuan_simple_write) + (_assuan_io_read, _assuan_io_write): Add hook feature. + +2007-10-05 Marcus Brinkmann + + * assuan.h (_assuan_error_is_eagain): Add prefix macro. + + * assuan-defs.h (_assuan_error_is_eagain): New prototype. + * mkerrors (_assuan_error_is_eagain): New function. + * assuan-handler.c (process_next): Leave on EAGAIN. + * assuan-handler.c (process_request), + assuan-client.c (_assuan_read_from_server), + assuan-buffer.c (assuan_read_line): Busy loop over EAGAIN. + +2007-10-05 Werner Koch + + * assuan-socket.c (_assuan_sock_wsa2errno): Map WSANOTINITIALISED. + (_assuan_sock_new): Use assuan_fd_t. + * assuan.h (_assuan_sock_wsa2errno): Add prefix macro. + +2007-10-05 Marcus Brinkmann + + * assuan-defs.h (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: Add prototype. + * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: Move and rename to ... + * assuan-socket.c (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: ... this. + (_assuan_close, _assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind): + Always set errno on error. + + * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: New function. + (uds_reader, uds_writer) [HAVE_W32_SYSTEM]: Set errno. + +2007-10-04 Werner Koch + + * mkerrors: Map EAGAIN to GPG_ERR_EAGAIN for read and write + errors. + +2007-10-02 Werner Koch + + * assuan-io.c (_assuan_io_read) [W32]: Map WSAEWOULDBLOCK to EAGAIN. + * assuan-socket.c (_assuan_sock_check_nonce): N needs to be signed. + + * assuan-defs.h (struct assuan_context_s): Add LISTEN_NONCE. + * assuan-socket-server.c (assuan_set_sock_nonce): New. + (accept_connection): Check the nonce. + +2007-10-01 Werner Koch + + * assuan.h (ASSUAN_INT2FD, ASSUAN_FD2INT): New. + + * assuan-socket.c: Rewritten. + (assuan_sock_new, assuan_sock_connect, assuan_sock_bind) + (assuan_sock_get_nonce, assuan_sock_check_nonce): New APIs. + + * assuan-io.c (_assuan_simple_read, _assuan_simple_write): + Factored code out to ... + (_assuan_io_read, _assuan_io_write): .. new. + * assuan-io-pth.c (_assuan_io_read, _assuan_io_write): New. + 2007-09-25 Werner Koch * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add - new wrappers. + wrappers for these new internal functions. +2007-09-24 Marcus Brinkmann + + * assuan-uds.c (uds_reader) [HAVE_W32_SYSTEM]: Do not touch the + UDS structure in the context. Reported by Frank Osterfeld. + (uds_writer): Clarify code. + +2007-09-14 Marcus Brinkmann + + * assuan-pipe-connect.c (do_finish) [HAVE_W32_SYSTEM]: Close + ctx->pid as handle. + (pipe_connect_w32): Save the spawned processes handle. + +2007-09-13 Werner Koch + + * assuan-socket.c (_assuan_close): Add inactive debug outputs. + +2007-09-11 Marcus Brinkmann + + * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. + +2007-09-07 Marcus Brinkmann + + * assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still + initialize MEMBUF. + + * assuan-inquire.c (_assuan_inquire_ext_cb): Clear CTX->in_inquire + before invoking callback and returning. + +2007-09-05 Marcus Brinkmann + + * assuan-handler.c (dispatch_command): Return non-critical errors + with PROCESS_DONE (). + 2007-09-03 Marcus Brinkmann * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames with _ASSUAN_PREFIX. -2007-08-02 Werner Koch +2007-09-03 Marcus Brinkmann - * assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. - (pipe_connect_w32): Use DETACHED_PROCESS flag. - * assuan-logging.c (log_level): New. Use this to disable logging. - (assuan_set_assuan_log_level): New. - * assuan.h: Add prototype. + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames + with _ASSUAN_PREFIX. + * assuan.h (assuan_inquire_ext): Move buffer and buffer_length + arguments callback in prototype. + * assuan-defs.h (struct assuan_context_s): Remove members + inquire_r_buffer and inquire_r_buffer_len. Add buffer and buffer + length arguments to inquire_cb. + * assuan-inquire.c (_assuan_inquire_ext_cb): Return buffer and + buffer length via callback. + (assuan_inquire_ext): Move buffer and buffer length arguments to + callback. + +2007-08-24 Werner Koch + + Switched license to back to LGPLv2.1. + +2007-08-09 Marcus Brinkmann + + * assuan.h (assuan_process_done, assuan_inquire_ext): New + prototypes. + * assuan-defs.h (struct assuan_context_s): New members + in_process_next, in_command, inquire_cb, inquire_cb_data, + inquire_r_buffer, inquire_r_buffer_len, inquire_membuf. + (_assuan_inquire_ext_cb, _assuan_inquire_release): New prototypes. + * assuan-handler.c (PROCESS_DONE): New macro. + (dummy_handler, std_handler_nop, std_handler_cancel) + (std_handler_option, std_handler_bye, std_handler_auth) + (std_handler_reset, std_handler_end): Use PROCESS_DONE to + optionally call assuan_process_done if CTX->in_process_next is + true. + (assuan_process_done, process_next): New functions. + (assuan_process_next): Rewritten to support external event + handling. + * mkerrors: Do not clear high bits of -1 for old style EOF. + * assuan-inquire.c (_assuan_inquire_release) + (_assuan_inquire_ext_cb, assuan_inquire_ext): New functions. + * assuan-pipe-server.c (_assuan_release_context): Call + _assuan_inquire_release. + 2007-07-12 Werner Koch - * assuan-handler.c (assuan_get_active_fds): Use get_osfhandle for - the data fp. - * assuan-socket.c (_assuan_close) [W32]: Use CloseHandle and not close. + * assuan.h (assuan_fd_t): New. + (ASSUAN_INVALID_FD): New. Use it everywhere. + * assuan-defs.h (SOCKET2HANDLE, HANDLE2SOCKET) [W32]: New. Use + them to cast descriptors for socket fucntions. + * assuan-pipe-connect.c (fd_to_handle, handle_to_fd): Remove + definition and all uses. + (pid_to_handle, handle_to_pid): Remove as they are ununsed. + * assuan-io.c (_assuan_simple_write, _assuan_simple_read) [W32]: + Make use of HANDLE2SOCKET. + * assuan-socket.c (_assuan_close) [W32]: Use CloseHandle and not + close. + * assuan-handler.c (assuan_get_active_fds) [W32]: Use + _get_osfhandle for the data fp. - * assuan-io.c (_assuan_simple_write, _assuan_simple_read): Map - ERROR_BROKEN_PIPE to EPIPE. - + * assuan-io.c (_assuan_simple_write): Return EPIPE on a closed pipe. + (_assuan_simple_read): Likewise + 2007-07-08 Marcus Brinkmann - * assuan-defs.h (struct assuan_context_s): Have partial peercred - structure even if HAVE_W32_SYSTEM, and have full peercred - structure only if HAVE_SO_PEERCRED. + * assuan-defs.h (struct assuan_context_s): Have full peercred + structure for HAVE_SO_PEERCRED. * assuan-connect.c (assuan_get_peercred) [!HAVE_SO_PEERCRED]: Do not try to set PID, UID and GID. +2007-07-05 Werner Koch + + * assuan-defs.h (struct assuan_context_s): Have peercred.valid + even for Windows. This makes some other code cleaner. + + * assuan.h (ASSUAN_CONFIDENTIAL): New flag. + * assuan-util.c (assuan_set_flag, assuan_get_flag): Support flag. + 2007-07-04 Marcus Brinkmann Change _WIN32 to HAVE_W32_SYSTEM for consistency. @@ -382,28 +576,63 @@ to silence gcc warning. * assuan-inquire.c (assuan_inquire): Likewise. -2005-08-19 Werner Koch +2005-09-08 Marcus Brinkmann - * funopen.c, assuan-socket.c: Copied from libassuan CVS. * assuan-pipe-connect.c (assuan_pipe_connect2): Add missing declaration of PID. 2005-08-09 Werner Koch - * README.1st: Adjusted to cope with changes done in upstream Assuan. + * mkerrors: Include config.h into assuan-errors.c. This is + required so that assuan.h knows about the W32 macro. - Merged changes for W32 support from libassuan. - * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New. * assuan-io.c [_ASSUAN_NO_PTH]: New. * assuan-pipe-connect.c (fix_signals) [_ASSUAN_NO_FIXED_SIGNALS]: New. (assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork. (fix_signals) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait.. - * assuan-logging.c, assuan-io.c: Include config.h - Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because - there is nothing winning in this API. - * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return - error Not Imlemented. + +2005-05-21 Werner Koch + + * assuan-util.c (assuan_set_flag, assuan_get_flag): New. + * assuan-defs.h (struct assuan_context_s): New field flags. + * assuan.h (assuan_flag_t): New with one flag value + ASSUAN_NO_WAITPID for now. + * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid + flag. + +2005-04-04 Werner Koch + + * assuan-util.c (_assuan_calloc): Avoid integer overflow. + +2005-03-22 Werner Koch + + * assuan-defs.h (struct assuan_io): Renamed elements READ and + WRITE to READFNC and WRITEFNC to avoid problems with read defined + as macros. Changed callers. Noted by Ville Skytt?. + +2005-02-24 Werner Koch + + * assuan-client.c (assuan_transact): Handle empty and comment + commands correctly. + +2004-12-20 Werner Koch + + * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for + a drive letter in the path. + +2004-12-19 Werner Koch + + * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file + descriptors using _get_osfhandle. + +2004-12-19 Moritz Schulte + + * assuan-pipe-connect.c (assuan_pipe_connect2): Removed "`" + character at beginning of line 532. + +2004-12-18 Werner Koch + * assuan-logging.c (_assuan_w32_strerror): New. * assuan-defs.h (w32_strerror): new. * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals): @@ -411,58 +640,96 @@ (build_w32_commandline, create_inheritable_pipe): New. Taken from gnupg 1.9. (assuan_pipe_connect2) [W32]: Implemented for W32. - * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file - descriptors using _get_osfhandle. - * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for - a drive letter in the path. - * assuan-client.c (assuan_transact): Handle empty and comment - commands correctly. - * assuan-util.c (_assuan_calloc): Avoid integer overflow. - * assuan-util.c (assuan_set_flag, assuan_get_flag): New. - * assuan-defs.h (struct assuan_context_s): New field flags. - * assuan.h (assuan_flag_t): New with one flag value - ASSUAN_NO_WAITPID for now. - * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid - flag. - * mkerrors: Include config.h into assuan-errors.c. This is - required so that assuan.h knows about the W32 macro. -2005-08-09 Timo Schulz (ported from libassuan by wk) +2004-12-14 Werner Koch + + * assuan-socket-connect.c (assuan_socket_connect): Always allow + NAME to start with a froward slash. + +2004-12-07 Werner Koch + + * assuan-logging.c, assuan-io.c: Include config.h + + Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because + there is nothing winning in this API. + + * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return + error Not Imlemented. + +2004-11-27 Werner Koch + + * assuan-socket.c: Include sys/types.h. Noted by Michael + Nottebrock. + +2004-11-26 Werner Koch + + * assuan-io.c [_WIN32]: Avoid warnings about unknown pragmas. + +2004-11-24 Werner Koch + + * assuan-logging.c (_assuan_log_printf): New. + * assuan-domain-connect.c (LOG): Removed and replaced all callers + by _assuan_log_printf. This is needed for C89 and gcc 2.95 which + both don't have C99 style variable arg macros. + * assuan-pipe-connect.c (LOG): Ditto. + * assuan-socket-connect.c (LOG): Ditto. + + * assuan-socket.c[!_WIN32]: Fixed includes. + +2004-11-23 Timo Schulz + + * assuan-socket.c (_assuan_sock_connect): Get local port from + the sun_path[] file. + (_assuan_sock_bind): Write local port to the sun_path[] file. + * assuan-socket-connect.c (assuan_socket_connect): Use DIRSEP_C + for a better portability. + (assuan-defs.h): Define DIRSEP_C. +2004-11-19 Werner Koch + + * assuan-handler.c (assuan_write_status): Return an error code. + +2004-11-22 Timo Schulz + * assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32 support. * assuan-socket.c (_assuan_close): New. (_assuan_sock_new): New. (_assuan_sock_bind): New. + +2004-11-16 Werner Koch -2005-03-22 Werner Koch + * assuan-socket-connect.c (LOG): Fixed macro to print not only the + prefix. + * assuan-domain-connect.c, assuan-socket-connect.c (LOG): Ditto. - * assuan-defs.h (struct assuan_io): Renamed elements READ and - WRITE to READFNC and WRITEFNC to avoid problems with read defined - as macro. Changed callers. Noted by Ville Skytt?. +2004-10-02 Werner Koch -2004-12-16 Marcus Brinkmann + * assuan-socket-connect.c: Define SUN_LEN, AF_LOCAL and PF_LOCAL + if they are not available. + * assuan-domain-connect.c: Define PF_LOCAL and AF_LOCAL if needed. - * assuan-pipe-connect.c (do_finish): Do not wait for child to finish. - (assuan_pipe_connect): Use double-fork approach. - * assuan-connect.c (assuan_disconnect): Do not write BYE to the - status line. +2004-06-23 Marcus Brinkmann -2004-12-07 Marcus Brinkmann + * assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include . - * README.1st: Add copyright notice. +2004-05-11 Werner Koch -2004-06-23 Marcus Brinkmann + * assuan-listen.c (assuan_set_hello_line, assuan_accept): Allow + for multi line hello strings. - * assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include . + * assuan-buffer.c (_assuan_write_line): New with parts of .. + (assuan_write_line): .. factored out. - * assuan-handler.c: Include . +2004-04-29 Werner Koch -2004-06-08 Marcus Brinkmann + * assuan-socket-connect.c: Include string.h. + * assuan-logging.c: Ditto. - * assuan-buffer.c (assuan_write_line): If the line is longer than - the maximum line length, bail out early. +2004-04-22 Marcus Brinkmann + * libassuan.m4: Quote first argument to AC_DEFUN. + 2004-04-21 Werner Koch * assuan-socket-server.c (accept_connection_bottom): Save the pid @@ -1039,7 +1306,7 @@ * assuan-defs.h: Add space in the context for this. - Copyright 2001, 2002, 2006 Free Software Foundation, Inc. + Copyright 2001, 2002, 2006, 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 Modified: trunk/assuan/assuan-buffer.c =================================================================== --- trunk/assuan/assuan-buffer.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-buffer.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #include @@ -53,9 +51,10 @@ return 0; /* okay */ } -/* Read an entire line. Returns 0 on success or -1 and ERRNo on +/* Read an entire line. Returns 0 on success or -1 and ERRNO on failure. EOF is indictated by setting the integer at address - R_EOF. */ + R_EOF. Note: BUF, R_NREAD and R_EOF contain a valid result even if + an error is returned. */ static int readline (assuan_context_t ctx, char *buf, size_t buflen, int *r_nread, int *r_eof) @@ -94,7 +93,7 @@ } -/* Function returns an Assuan error. */ +/* Function returns an Assuan error. */ assuan_error_t _assuan_read_line (assuan_context_t ctx) { @@ -134,11 +133,23 @@ &nread, &ctx->inbound.eof); if (rc) { + int saved_errno = errno; + if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s (%d)]\n", - assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd, - strerror (errno), errno); + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", + assuan_get_assuan_log_prefix (), + (unsigned int)getpid (), (int)ctx->inbound.fd, + strerror (errno)); + + if (saved_errno == EAGAIN) + { + /* We have to save a partial line. */ + memcpy (ctx->inbound.attic.line, line, atticlen + nread); + ctx->inbound.attic.pending = 0; + ctx->inbound.attic.linelen = atticlen + nread; + } + + errno = saved_errno; return _assuan_error (ASSUAN_Read_Error); } if (!nread) @@ -147,7 +158,7 @@ if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); return _assuan_error (-1); } @@ -191,7 +202,7 @@ { fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else @@ -207,7 +218,7 @@ if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); *line = 0; ctx->inbound.linelen = 0; return _assuan_error (ctx->inbound.eof @@ -234,7 +245,12 @@ if (!ctx) return _assuan_error (ASSUAN_Invalid_Value); - err = _assuan_read_line (ctx); + do + { + err = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (err)); + *line = ctx->inbound.line; *linelen = ctx->inbound.linelen; return err; @@ -265,7 +281,7 @@ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> " "[supplied line too long -truncated]\n", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); if (prefixlen > 5) prefixlen = 5; if (len > ASSUAN_LINELENGTH - prefixlen - 2) @@ -281,7 +297,7 @@ { fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else @@ -333,7 +349,7 @@ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> " "[supplied line contained a LF - truncated]\n", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); return _assuan_write_line (ctx, NULL, line, len); } @@ -398,7 +414,7 @@ { fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); @@ -454,7 +470,7 @@ { fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ", assuan_get_assuan_log_prefix (), - (unsigned int)getpid (), ctx->inbound.fd); + (unsigned int)getpid (), (int)ctx->inbound.fd); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else @@ -524,11 +540,11 @@ } assuan_error_t -assuan_sendfd (assuan_context_t ctx, int fd) +assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd) { /* It is explicitly allowed to use (NULL, -1) as a runtime test to check whether descriptor passing is available. */ - if (!ctx && fd == -1) + if (!ctx && fd == ASSUAN_INVALID_FD) #ifdef USE_DESCRIPTOR_PASSING return 0; #else @@ -543,7 +559,7 @@ } assuan_error_t -assuan_receivefd (assuan_context_t ctx, int *fd) +assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd) { if (! ctx->io->receivefd) return set_error (ctx, Not_Implemented, Modified: trunk/assuan/assuan-client.c =================================================================== --- trunk/assuan/assuan-client.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-client.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #include @@ -44,7 +42,11 @@ *off = 0; do { - rc = _assuan_read_line (ctx); + do + { + rc = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (rc)); if (rc) return rc; line = ctx->inbound.line; Modified: trunk/assuan/assuan-connect.c =================================================================== --- trunk/assuan/assuan-connect.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-connect.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H @@ -60,8 +58,8 @@ #ifndef HAVE_W32_SYSTEM -/* Return user credentials. PID, UID and GID amy be gived as NULL if - you are not interested in this value. For getting the pid of the +/* Return user credentials. PID, UID and GID may be given as NULL if + you are not interested in a value. For getting the pid of the peer the assuan_get_pid is usually better suited. */ assuan_error_t assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid) Modified: trunk/assuan/assuan-defs.h =================================================================== --- trunk/assuan/assuan-defs.h 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-defs.h 2009-03-06 22:29:49 UTC (rev 1358) @@ -1,5 +1,5 @@ /* assuan-defs.c - Internal definitions to Assuan - * Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -40,17 +40,6 @@ #endif #ifdef HAVE_W32_SYSTEM -#define AF_LOCAL AF_UNIX -/* We need to prefix the structure with a sockaddr_in header so we can - use it later for sendto and recvfrom. */ -struct sockaddr_un -{ - short sun_family; - unsigned short sun_port; - struct in_addr sun_addr; - char sun_path[108-2-4]; /* Path name. */ -}; - /* Not needed anymore because the current mingw32 defines this in sys/types.h */ /* typedef int ssize_t; */ @@ -80,12 +69,16 @@ /* Routine to write to output_fd. */ ssize_t (*writefnc) (assuan_context_t, const void *, size_t); /* Send a file descriptor. */ - assuan_error_t (*sendfd) (assuan_context_t, int); + assuan_error_t (*sendfd) (assuan_context_t, assuan_fd_t); /* Receive a file descriptor. */ - assuan_error_t (*receivefd) (assuan_context_t, int *); + assuan_error_t (*receivefd) (assuan_context_t, assuan_fd_t *); }; +/* The global variable with the optional hook fucntions. */ +extern struct assuan_io_hooks _assuan_io_hooks; + + /* The context we use with most functions. */ struct assuan_context_s { @@ -103,6 +96,14 @@ int confidential; int is_server; /* Set if this is context belongs to a server */ int in_inquire; + int in_process_next; + int in_command; + + /* The following members are used by assuan_inquire_ext. */ + int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len); + void *inquire_cb_data; + void *inquire_membuf; + char *hello_line; char *okay_line; /* See assuan_set_okay_line() */ @@ -111,7 +112,7 @@ FILE *log_fp; struct { - int fd; + assuan_fd_t fd; int eof; char line[LINELENGTH]; int linelen; /* w/o CR, LF - might not be the same as @@ -125,7 +126,7 @@ } inbound; struct { - int fd; + assuan_fd_t fd; struct { FILE *fp; char line[LINELENGTH]; @@ -137,8 +138,10 @@ int pipe_mode; /* We are in pipe mode, i.e. we can handle just one connection and must terminate then. */ pid_t pid; /* The pid of the peer. */ - int listen_fd; /* The fd we are listening on (used by socket servers) */ - int connected_fd; /* helper */ + assuan_fd_t listen_fd; /* The fd we are listening on (used by + socket servers) */ + assuan_sock_nonce_t listen_nonce; /* Used with LISTEN_FD. */ + assuan_fd_t connected_fd; /* helper */ struct { int valid; /* Whether this structure has valid information. */ @@ -162,7 +165,7 @@ int bufferoffset; /* Offset of start of buffer. */ int buffersize; /* Bytes buffered. */ - int pendingfds[5]; /* Array to save received descriptors. */ + assuan_fd_t pendingfds[5]; /* Array to save received descriptors. */ int pendingfdscount; /* Number of received descriptors. */ } uds; @@ -188,15 +191,15 @@ /* If set, this is called right before logging an I/O line. With DIRECTION set to 1 it is called for an output oeration; 0 means an input operation. If bit 0 is set in the return value, the - logging of the will be suppressed. With bit 1 set, the entire - line will be ignored. */ + logging of the line will be suppressed. With bit 1 set, the + entire line will be ignored. */ unsigned int (*io_monitor)(assuan_context_t ctx, int direction, const char *line, size_t linelen); - int input_fd; /* set by INPUT command */ - int output_fd; /* set by OUTPUT command */ + assuan_fd_t input_fd; /* Set by the INPUT command. */ + assuan_fd_t output_fd; /* Set by the OUTPUT command. */ /* io routines. */ struct assuan_io *io; @@ -228,17 +231,22 @@ /*-- assuan-error.c --*/ +/*-- assuan-inquire.c --*/ +int _assuan_inquire_ext_cb (assuan_context_t ctx); +void _assuan_inquire_release (assuan_context_t ctx); -/* Map error codes as used in this implementaion to the libgpg-error +/* Map error codes as used in this implementation to the libgpg-error codes. */ assuan_error_t _assuan_error (int oldcode); +/* Check if ERR means EAGAIN. */ +int _assuan_error_is_eagain (assuan_error_t err); -/* Extrac the erro code from A. This works for both the old and the - new style error codes. This needs to be whenever an error code is - compared. */ +/* Extract the error code from A. This works for both the old and the + new style error codes. This needs to be used whenever an error + code is compared. */ #define err_code(a) ((a) & 0x00ffffff) -/* Check whether A is the erro code for EOF. We allow forold and new +/* Check whether A is the erro code for EOF. We allow for old and new style EOF error codes here. */ #define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383) @@ -284,6 +292,8 @@ ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size); ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size); +ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size); +ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size); #ifdef HAVE_W32_SYSTEM int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg); int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg); @@ -292,11 +302,21 @@ ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg); #endif +void _assuan_usleep (unsigned int usec); + + /*-- assuan-socket.c --*/ -int _assuan_close (int fd); -int _assuan_sock_new (int domain, int type, int proto); -int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); -int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); +int _assuan_close (assuan_fd_t fd); +assuan_fd_t _assuan_sock_new (int domain, int type, int proto); +int _assuan_sock_connect (assuan_fd_t sockfd, + struct sockaddr *addr, int addrlen); +int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, + assuan_sock_nonce_t *nonce); +int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); +#ifdef HAVE_W32_SYSTEM +int _assuan_sock_wsa2errno (int err); +#endif #ifdef HAVE_FOPENCOOKIE /* We have to implement funopen in terms of glibc's fopencookie. */ @@ -329,4 +349,13 @@ #define DIMof(type,member) DIM(((type *)0)->member) +#if HAVE_W32_SYSTEM +#define SOCKET2HANDLE(s) ((void *)(s)) +#define HANDLE2SOCKET(h) ((unsigned int)(h)) +#else +#define SOCKET2HANDLE(s) (s) +#define HANDLE2SOCKET(h) (h) +#endif + + #endif /*ASSUAN_DEFS_H*/ Modified: trunk/assuan/assuan-handler.c =================================================================== --- trunk/assuan/assuan-handler.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-handler.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -1,5 +1,5 @@ /* assuan-handler.c - dispatch commands - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #include @@ -35,18 +33,21 @@ static int my_strcasecmp (const char *a, const char *b); +#define PROCESS_DONE(ctx, rc) \ + ((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc)) static int dummy_handler (assuan_context_t ctx, char *line) { - return set_error (ctx, Server_Fault, "no handler registered"); + return + PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered")); } static int std_handler_nop (assuan_context_t ctx, char *line) { - return 0; /* okay */ + return PROCESS_DONE (ctx, 0); /* okay */ } static int @@ -54,7 +55,7 @@ { if (ctx->cancel_notify_fnc) ctx->cancel_notify_fnc (ctx); - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } static int @@ -65,9 +66,12 @@ for (key=line; spacep (key); key++) ; if (!*key) - return set_error (ctx, Syntax_Error, "argument required"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required")); if (*key == '=') - return set_error (ctx, Syntax_Error, "no option name given"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, + "no option name given")); for (value=key; *value && !spacep (value) && *value != '='; value++) ; if (*value) @@ -82,7 +86,9 @@ for (; spacep (value); value++) ; if (!*value) - return set_error (ctx, Syntax_Error, "option argument expected"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, + "option argument expected")); } if (*value) { @@ -96,12 +102,13 @@ if (*key == '-' && key[1] == '-' && key[2]) key += 2; /* the double dashes are optional */ if (*key == '-') - return set_error (ctx, Syntax_Error, - "option should not begin with one dash"); + return PROCESS_DONE (ctx, + set_error (ctx, Syntax_Error, + "option should not begin with one dash")); if (ctx->option_handler_fnc) - return ctx->option_handler_fnc (ctx, key, value); - return 0; + return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value)); + return PROCESS_DONE (ctx, 0); } static int @@ -111,13 +118,13 @@ ctx->bye_notify_fnc (ctx); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); - return -1; /* pretty simple :-) */ + return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */ } static int std_handler_auth (assuan_context_t ctx, char *line) { - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } static int @@ -128,17 +135,35 @@ assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); _assuan_uds_close_fds (ctx); - return 0; + return PROCESS_DONE (ctx, 0); } static int +std_handler_help (assuan_context_t ctx, char *line) +{ + unsigned int i; + char buf[ASSUAN_LINELENGTH]; + + for (i = 0; i < ctx->cmdtbl_used; i++) + { + snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name); + buf[ASSUAN_LINELENGTH - 1] = '\0'; + assuan_write_line (ctx, buf); + } + + return PROCESS_DONE (ctx, 0); +} + + +static int std_handler_end (assuan_context_t ctx, char *line) { - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } + assuan_error_t -assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd) +assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd) { char *endp; @@ -151,7 +176,13 @@ line ++; if (!digitp (*line)) return set_error (ctx, Syntax_Error, "number required"); +#ifdef HAVE_W32_SYSTEM + /* Fixme: For a W32/64bit system we will need to change the cast + and the conversion fucntion. */ + *rfd = (void*)strtoul (line, &endp, 10); +#else *rfd = strtoul (line, &endp, 10); +#endif /* Remove that argument so that a notify handler won't see it. */ memset (line, ' ', endp? (endp-line):strlen(line)); @@ -166,34 +197,37 @@ return assuan_receivefd (ctx, rfd); } + /* Format is INPUT FD= */ static int std_handler_input (assuan_context_t ctx, char *line) { - int rc, fd; + int rc; + assuan_fd_t fd; rc = assuan_command_parse_fd (ctx, line, &fd); if (rc) - return rc; + return PROCESS_DONE (ctx, rc); ctx->input_fd = fd; if (ctx->input_notify_fnc) ctx->input_notify_fnc (ctx, line); - return 0; + return PROCESS_DONE (ctx, 0); } /* Format is OUTPUT FD= */ static int std_handler_output (assuan_context_t ctx, char *line) { - int rc, fd; + int rc; + assuan_fd_t fd; rc = assuan_command_parse_fd (ctx, line, &fd); if (rc) - return rc; + return PROCESS_DONE (ctx, rc); ctx->output_fd = fd; if (ctx->output_notify_fnc) ctx->output_notify_fnc (ctx, line); - return 0; + return PROCESS_DONE (ctx, 0); } @@ -215,11 +249,12 @@ { "AUTH", std_handler_auth, 1 }, { "RESET", std_handler_reset, 1 }, { "END", std_handler_end, 1 }, + { "HELP", std_handler_help, 1 }, - { "INPUT", std_handler_input }, - { "OUTPUT", std_handler_output }, + { "INPUT", std_handler_input, 0 }, + { "OUTPUT", std_handler_output, 0 }, { "OPTION", std_handler_option, 1 }, - { NULL } + { NULL, NULL, 0 } }; @@ -406,9 +441,10 @@ return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b); } + /* Parse the line, break out the command, find it in the command table, remove leading and white spaces from the arguments, call the - handler with the argument line and return the error */ + handler with the argument line and return the error. */ static int dispatch_command (assuan_context_t ctx, char *line, int linelen) { @@ -416,13 +452,21 @@ const char *s; int shift, i; + /* Note that as this function is invoked by assuan_process_next as + well, we need to hide non-critical errors with PROCESS_DONE. */ + if (*line == 'D' && line[1] == ' ') /* divert to special handler */ - return handle_data_line (ctx, line+2, linelen-2); + /* FIXME: Depending on the final implementation of + handle_data_line, this may be wrong here. For example, if a + user callback is invoked, and that callback is responsible for + calling assuan_process_done, then this is wrong. */ + return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2)); for (p=line; *p && *p != ' ' && *p != '\t'; p++) ; if (p==line) - return set_error (ctx, Syntax_Error, "leading white-space"); + return PROCESS_DONE + (ctx, set_error (ctx, Syntax_Error, "leading white-space")); if (*p) { /* Skip over leading WS after the keyword */ *p++ = 0; @@ -445,7 +489,7 @@ } } if (!s) - return set_error (ctx, Unknown_Command, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL)); line += shift; linelen -= shift; @@ -453,42 +497,34 @@ return ctx->cmdtbl[i].handler (ctx, line); } - - -static int -process_request (assuan_context_t ctx) +/* Call this to acknowledge the current command. */ +int +assuan_process_done (assuan_context_t ctx, int rc) { - int rc; + if (!ctx->in_command) + return _assuan_error (ASSUAN_General_Error); - if (ctx->in_inquire) - return _assuan_error (ASSUAN_Nested_Commands); + ctx->in_command = 0; - rc = _assuan_read_line (ctx); - if (rc) - return rc; - if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) - return 0; /* comment line - ignore */ - - ctx->outbound.data.error = 0; - ctx->outbound.data.linelen = 0; - /* dispatch command and return reply */ - rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); - /* check from data write errors */ + /* Check for data write errors. */ if (ctx->outbound.data.fp) - { /* Flush the data lines */ + { + /* Flush the data lines. */ fclose (ctx->outbound.data.fp); ctx->outbound.data.fp = NULL; if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; + rc = ctx->outbound.data.error; } - else /* flush any data send w/o using the data fp */ + else { + /* Flush any data send without using the data FP. */ assuan_send_data (ctx, NULL, 0); if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; + rc = ctx->outbound.data.error; } - /* Error handling */ + + /* Error handling. */ if (!rc) { rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); @@ -501,26 +537,26 @@ else { char errline[300]; - + if (rc < 100) sprintf (errline, "ERR %d server fault (%.50s)", _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc)); else { const char *text = ctx->err_no == rc? ctx->err_str:NULL; - + #if defined(HAVE_W32_SYSTEM) unsigned int source, code; char ebuf[50]; const char *esrc; - + source = ((rc >> 24) & 0xff); code = (rc & 0x00ffffff); if (source && !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf) && (esrc=_assuan_gpg_strsource (rc))) { - /* Assume this is an libgpg-error. */ + /* Assume this is an libgpg-error. */ sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", rc, ebuf, esrc, text? " - ":"", text?text:""); @@ -554,7 +590,7 @@ { /* Assume this is an libgpg-error. */ char ebuf[50]; - + gpg_strerror_r (rc, ebuf, sizeof ebuf ); sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", rc, @@ -569,19 +605,123 @@ } rc = assuan_write_line (ctx, errline); } - + if (ctx->post_cmd_notify_fnc) ctx->post_cmd_notify_fnc (ctx, rc); - + ctx->confidential = 0; if (ctx->okay_line) { xfree (ctx->okay_line); ctx->okay_line = NULL; } + return rc; } + +static int +process_next (assuan_context_t ctx) +{ + int rc; + + /* What the next thing to do is depends on the current state. + However, we will always first read the next line. The client is + required to write full lines without blocking long after starting + a partial line. */ + rc = _assuan_read_line (ctx); + if (_assuan_error_is_eagain (rc)) + return 0; + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + /* Comment lines are ignored. */ + return 0; + + /* Now we have a line that really means something. It could be one + of the following things: First, if we are not in a command + already, it is the next command to dispatch. Second, if we are + in a command, it can only be the response to an INQUIRE + reply. */ + + if (!ctx->in_command) + { + ctx->in_command = 1; + + ctx->outbound.data.error = 0; + ctx->outbound.data.linelen = 0; + /* Dispatch command and return reply. */ + ctx->in_process_next = 1; + rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + ctx->in_process_next = 0; + } + else if (ctx->in_inquire) + { + /* FIXME: Pick up the continuation. */ + rc = _assuan_inquire_ext_cb (ctx); + } + else + { + /* Should not happen. The client is sending data while we are + in a command and not waiting for an inquire. We log an error + and discard it. */ + _assuan_log_printf ("unexpected client data\n"); + rc = 0; + } + + return rc; +} + + +/* This function should be invoked when the assuan connected FD is + ready for reading. If the equivalent to EWOULDBLOCK is returned + (this should be done by the command handler), assuan_process_next + should be invoked the next time the connected FD is readable. + Eventually, the caller will finish by invoking + assuan_process_done. */ +int +assuan_process_next (assuan_context_t ctx) +{ + int rc; + + do + { + rc = process_next (ctx); + } + while (!rc && assuan_pending_line (ctx)); + + return rc; +} + + + +static int +process_request (assuan_context_t ctx) +{ + int rc; + + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + do + { + rc = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (rc)); + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + return 0; /* comment line - ignore */ + + ctx->in_command = 1; + ctx->outbound.data.error = 0; + ctx->outbound.data.linelen = 0; + /* dispatch command and return reply */ + rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + + return assuan_process_done (ctx, rc); +} + /** * assuan_process: * @ctx: assuan context @@ -610,24 +750,6 @@ /** - * assuan_process_next: - * @ctx: Assuan context - * - * Same as assuan_process() but the user has to provide the outer - * loop. He should loop as long as the return code is zero and stop - * otherwise; -1 is regular end. - * - * See also: assuan_get_active_fds() - * Return value: -1 for end of server, 0 on success or an error code - **/ -int -assuan_process_next (assuan_context_t ctx) -{ - return process_request (ctx); -} - - -/** * assuan_get_active_fds: * @ctx: Assuan context * @what: 0 for read fds, 1 for write fds @@ -646,7 +768,7 @@ **/ int assuan_get_active_fds (assuan_context_t ctx, int what, - int *fdarray, int fdarraysize) + assuan_fd_t *fdarray, int fdarraysize) { int n = 0; @@ -655,16 +777,16 @@ if (!what) { - if (ctx->inbound.fd != -1) + if (ctx->inbound.fd != ASSUAN_INVALID_FD) fdarray[n++] = ctx->inbound.fd; } else { - if (ctx->outbound.fd != -1) + if (ctx->outbound.fd != ASSUAN_INVALID_FD) fdarray[n++] = ctx->outbound.fd; if (ctx->outbound.data.fp) #ifdef HAVE_W32_SYSTEM - fdarray[n++] = _get_osfhandle (fileno (ctx->outbound.data.fp)); + fdarray[n++] = (void*)_get_osfhandle (fileno (ctx->outbound.data.fp)); #else fdarray[n++] = fileno (ctx->outbound.data.fp); #endif Modified: trunk/assuan/assuan-inquire.c =================================================================== --- trunk/assuan/assuan-inquire.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-inquire.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -1,5 +1,5 @@ /* assuan-inquire.c - handle inquire stuff - * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #include @@ -44,7 +42,7 @@ -/* A simple implemnation of a dynamic buffer. Use init_membuf() to +/* A simple implementation of a dynamic buffer. Use init_membuf() to create a buffer, put_membuf to append bytes and get_membuf to release and return the buffer. Allocation errors are detected but only returned at the final get_membuf(), this helps not to clutter @@ -171,7 +169,9 @@ { do { - rc = _assuan_read_line (ctx); + do + rc = _assuan_read_line (ctx); + while (_assuan_error_is_eagain (rc)); if (rc) goto leave; line = (unsigned char *) ctx->inbound.line; @@ -234,8 +234,154 @@ return rc; } + +void +_assuan_inquire_release (assuan_context_t ctx) +{ + if (ctx->in_inquire) + { + if (ctx->inquire_membuf) + { + free_membuf (ctx->inquire_membuf); + free (ctx->inquire_membuf); + } + ctx->in_inquire = 0; + } +} +int +_assuan_inquire_ext_cb (assuan_context_t ctx) +{ + int rc; + unsigned char *line; + int linelen; + struct membuf *mb; + unsigned char *p; + line = (unsigned char *) ctx->inbound.line; + linelen = ctx->inbound.linelen; + mb = ctx->inquire_membuf; + if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') + { + rc = _assuan_error (ASSUAN_Canceled); + goto leave; + } + if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (!line[3] || line[3] == ' ')) + { + rc = 0; + goto leave; + } + if (line[0] != 'D' || line[1] != ' ' || mb == NULL) + { + rc = _assuan_error (ASSUAN_Unexpected_Command); + goto leave; + } + + if (linelen < 3) + return 0; + line += 2; + linelen -= 2; + + p = line; + while (linelen) + { + for (;linelen && *p != '%'; linelen--, p++) + ; + put_membuf (mb, line, p-line); + if (linelen > 2) + { /* handle escaping */ + unsigned char tmp[1]; + p++; + *tmp = xtoi_2 (p); + p += 2; + linelen -= 3; + put_membuf (mb, tmp, 1); + } + line = p; + } + if (mb->too_large) + { + rc = _assuan_error (ASSUAN_Too_Much_Data); + goto leave; + } + + return 0; + + leave: + { + size_t buf_len = 0; + unsigned char *buf = NULL; + + if (mb) + { + buf = get_membuf (mb, &buf_len); + if (!buf) + rc = _assuan_error (ASSUAN_Out_Of_Core); + free_membuf (mb); + free (mb); + ctx->inquire_membuf = NULL; + } + ctx->in_inquire = 0; + rc = (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len); + } + return rc; +} + +/** + * assuan_inquire_ext: + * @ctx: An assuan context + * @keyword: The keyword used for the inquire + * @maxlen: If not 0, the size limit of the inquired data. + * @cb: A callback handler which is invoked after the operation completed. + * @cb_data: A user-provided value passed to the callback handler. + * + * A Server may use this to Send an inquire. r_buffer, r_length and + * maxlen may all be NULL/0 to indicate that no real data is expected. + * When this function returns, + * + * Return value: 0 on success or an ASSUAN error code + **/ +assuan_error_t +assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen, + int (*cb) (void *cb_data, int rc, unsigned char *buf, + size_t len), + void *cb_data) +{ + assuan_error_t rc; + struct membuf *mb = NULL; + char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ + + if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) + return _assuan_error (ASSUAN_Invalid_Value); + if (!ctx->is_server) + return _assuan_error (ASSUAN_Not_A_Server); + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + mb = malloc (sizeof (struct membuf)); + if (!mb) + return _assuan_error (ASSUAN_Out_Of_Core); + init_membuf (mb, maxlen ? maxlen : 1024, maxlen); + + strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); + rc = assuan_write_line (ctx, cmdbuf); + if (rc) + { + free_membuf (mb); + free (mb); + return rc; + } + + ctx->in_inquire = 1; + + /* Set up the continuation. */ + ctx->inquire_cb = cb; + ctx->inquire_cb_data = cb_data; + ctx->inquire_membuf = mb; + + return 0; +} Modified: trunk/assuan/assuan-io.c =================================================================== --- trunk/assuan/assuan-io.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-io.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -1,5 +1,5 @@ /* assuan-io.c - Wraps the read and write functions. - * Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -14,15 +14,14 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include #ifdef HAVE_SYS_SOCKET_H @@ -48,8 +47,8 @@ #endif -ssize_t -_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +static ssize_t +do_io_read (assuan_fd_t fd, void *buffer, size_t size) { #if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) /* Due to the peculiarities of the W32 API we can't use read for a @@ -57,45 +56,84 @@ read if recv detects that it is not a network socket. */ int n; - n = recv (ctx->inbound.fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + n = recv (HANDLE2SOCKET(fd), buffer, size, 0); + if (n == -1) { - DWORD nread = 0; - - n = ReadFile ((HANDLE)ctx->inbound.fd, buffer, size, &nread, NULL); - if (!n) + switch (WSAGetLastError ()) { - switch (GetLastError()) - { - case ERROR_BROKEN_PIPE: errno = EPIPE; break; - default: errno = EIO; - } - n = -1; + case WSAENOTSOCK: + { + DWORD nread = 0; + + n = ReadFile (fd, buffer, size, &nread, NULL); + if (!n) + { + switch (GetLastError()) + { + case ERROR_BROKEN_PIPE: errno = EPIPE; break; + default: errno = EIO; + } + n = -1; + } + else + n = (int)nread; + } + break; + + case WSAEWOULDBLOCK: errno = EAGAIN; break; + case ERROR_BROKEN_PIPE: errno = EPIPE; break; + default: errno = EIO; break; } - else - n = (int)nread; } return n; #else /*!HAVE_W32_SYSTEM*/ - return read (ctx->inbound.fd, buffer, size); + return read (fd, buffer, size); #endif /*!HAVE_W32_SYSTEM*/ } + ssize_t -_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) { + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; + + return do_io_read (fd, buffer, size); +} + +ssize_t +_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +{ + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd, + buffer, size, &retval) == 1) + return retval; + + return do_io_read (ctx->inbound.fd, buffer, size); +} + + + +static ssize_t +do_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ #if defined(HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN) /* Due to the peculiarities of the W32 API we can't use write for a network socket and thus we try to use send first and fallback to write if send detects that it is not a network socket. */ int n; - n = send (ctx->outbound.fd, buffer, size, 0); + n = send (HANDLE2SOCKET(fd), buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nwrite; - n = WriteFile ((HANDLE)ctx->outbound.fd, buffer, size, &nwrite, NULL); + n = WriteFile (fd, buffer, size, &nwrite, NULL); if (!n) { switch (GetLastError ()) @@ -111,11 +149,35 @@ } return n; #else /*!HAVE_W32_SYSTEM*/ - return write (ctx->outbound.fd, buffer, size); + return write (fd, buffer, size); #endif /*!HAVE_W32_SYSTEM*/ } +ssize_t +_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; + return do_io_write (fd, buffer, size); +} +ssize_t +_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +{ + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd, + buffer, size, &retval) == 1) + return retval; + + return do_io_write (ctx->outbound.fd, buffer, size); +} + + #ifdef HAVE_W32_SYSTEM int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg) @@ -152,3 +214,32 @@ return ret; #endif } + + +void +_assuan_usleep (unsigned int usec) +{ + if (usec) + { +#ifdef HAVE_NANOSLEEP + struct timespec req; + struct timespec rem; + + req.tv_sec = 0; + req.tv_nsec = usec * 1000; + + while (nanosleep (&req, &rem) < 0 && errno == EINTR) + req = rem; + +#elif defined(HAVE_W32_SYSTEM) + Sleep (usec / 1000); +#else + struct timeval tv; + + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + select (0, NULL, NULL, NULL, &tv); +#endif + } +} + Modified: trunk/assuan/assuan-listen.c =================================================================== --- trunk/assuan/assuan-listen.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-listen.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #include @@ -116,17 +114,17 @@ -int +assuan_fd_t assuan_get_input_fd (assuan_context_t ctx) { - return ctx? ctx->input_fd : -1; + return ctx? ctx->input_fd : ASSUAN_INVALID_FD; } -int +assuan_fd_t assuan_get_output_fd (assuan_context_t ctx) { - return ctx? ctx->output_fd : -1; + return ctx? ctx->output_fd : ASSUAN_INVALID_FD; } @@ -135,10 +133,10 @@ assuan_error_t assuan_close_input_fd (assuan_context_t ctx) { - if (!ctx || ctx->input_fd == -1) + if (!ctx || ctx->input_fd == ASSUAN_INVALID_FD) return _assuan_error (ASSUAN_Invalid_Value); _assuan_close (ctx->input_fd); - ctx->input_fd = -1; + ctx->input_fd = ASSUAN_INVALID_FD; return 0; } @@ -147,11 +145,11 @@ assuan_error_t assuan_close_output_fd (assuan_context_t ctx) { - if (!ctx || ctx->output_fd == -1) + if (!ctx || ctx->output_fd == ASSUAN_INVALID_FD) return _assuan_error (ASSUAN_Invalid_Value); _assuan_close (ctx->output_fd); - ctx->output_fd = -1; + ctx->output_fd = ASSUAN_INVALID_FD; return 0; } Modified: trunk/assuan/assuan-logging.c =================================================================== --- trunk/assuan/assuan-logging.c 2009-02-24 15:13:01 UTC (rev 1357) +++ trunk/assuan/assuan-logging.c 2009-03-06 22:29:49 UTC (rev 1358) @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H @@ -37,24 +35,7 @@ static char prefix_buffer[80]; static FILE *_assuan_log; static int full_logging; -static int log_level = 1; /* Defaults to logging enabled. */ - -/* Set the log level for general assuan commands. 0 is no logging at - all, 1 is the standard logging and the default. Higher leveles may - be defined in the future. Passing a level of -1 will not change - the current log level. Returns previosu log level. */ -int -assuan_set_assuan_log_level (int level) -{ - int old = log_level; - - if (level != -1) - log_level = level; - return old; -} - - void _assuan_set_default_log_stream (FILE *fp) From cvs at cvs.gnupg.org Tue Mar 10 17:10:36 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 10 Mar 2009 17:10:36 +0100 Subject: [svn] GnuPG - r4946 - trunk/scd Message-ID: Author: wk Date: 2009-03-10 17:10:35 +0100 (Tue, 10 Mar 2009) New Revision: 4946 Modified: trunk/scd/ChangeLog trunk/scd/app-openpgp.c trunk/scd/command.c trunk/scd/scdaemon.h Log: Add new attribute KEY-ATTR. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-06 17:31:27 UTC (rev 4945) +++ trunk/scd/ChangeLog 2009-03-10 16:10:35 UTC (rev 4946) @@ -1,3 +1,9 @@ +2009-03-10 Werner Koch + + * app-openpgp.c (send_key_attr): New. + (do_getattr): New attribute KEY_ATTR. + * command.c (send_status_direct): New. + 2009-03-06 Werner Koch * app-nks.c (do_learn_status): Factor code out to.. Modified: trunk/scd/app-openpgp.c =================================================================== --- trunk/scd/app-openpgp.c 2009-03-06 17:31:27 UTC (rev 4945) +++ trunk/scd/app-openpgp.c 2009-03-10 16:10:35 UTC (rev 4946) @@ -151,7 +151,7 @@ key. Might be NULL if key is not available. */ size_t keylen; /* The length of the above S-expression. This - is usullay only required for cross checks + is usually only required for cross checks because the length of an S-expression is implicitly available. */ } pk[3]; @@ -746,6 +746,24 @@ xfree (buf); } + +static void +send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number) +{ + char buffer[200]; + + assert (number >=0 && number < DIM(app->app_local->keyattr)); + + /* We only support RSA thus the algo identifier is fixed to 1. */ + snprintf (buffer, sizeof buffer, "%d 1 %u %u %d", + number+1, + app->app_local->keyattr[number].n_bits, + app->app_local->keyattr[number].e_bits, + app->app_local->keyattr[number].format); + send_status_direct (ctrl, keyword, buffer); +} + + /* Implement the GETATTR command. This is similar to the LEARN command but returns just one value via the status interface. */ static gpg_error_t @@ -763,6 +781,7 @@ { "PUBKEY-URL", 0x5F50 }, { "KEY-FPR", 0x00C5, 3 }, { "KEY-TIME", 0x00CD, 4 }, + { "KEY-ATTR", 0x0000, -5 }, { "CA-FPR", 0x00C6, 3 }, { "CHV-STATUS", 0x00C4, 1 }, { "SIG-COUNTER", 0x0093, 2 }, @@ -811,14 +830,16 @@ } if (table[idx].special == -2) { - char tmp[50]; + char tmp[100]; - sprintf (tmp, "gc=%d ki=%d fc=%d pd=%d mcl3=%u", - app->app_local->extcap.get_challenge, - app->app_local->extcap.key_import, - app->app_local->extcap.change_force_chv, - app->app_local->extcap.private_dos, - app->app_local->extcap.max_certlen_3); + snprintf (tmp, sizeof tmp, + "gc=%d ki=%d fc=%d pd=%d mcl3=%u aac=%d", + app->app_local->extcap.get_challenge, + app->app_local->extcap.key_import, + app->app_local->extcap.change_force_chv, + app->app_local->extcap.private_dos, + app->app_local->extcap.max_certlen_3, + app->app_local->extcap.algo_attr_change); send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); return 0; } @@ -845,6 +866,12 @@ } return gpg_error (GPG_ERR_INV_NAME); } + if (table[idx].special == -5) + { + for (i=0; i < 3; i++) + send_key_attr (ctrl, app, table[idx].name, i); + return 0; + } relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &rc); if (relptr) Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-06 17:31:27 UTC (rev 4945) +++ trunk/scd/command.c 2009-03-10 16:10:35 UTC (rev 4946) @@ -2018,7 +2018,19 @@ } +/* Send a ready formatted status line via assuan. */ +void +send_status_direct (ctrl_t ctrl, const char *keyword, const char *args) +{ + assuan_context_t ctx = ctrl->server_local->assuan_ctx; + if (strchr (args, '\n')) + log_error ("error: LF detected in status line - not sending\n"); + else + assuan_write_status (ctx, keyword, args); +} + + /* Helper to send the clients a status change notification. */ static void send_client_notifications (void) Modified: trunk/scd/scdaemon.h =================================================================== --- trunk/scd/scdaemon.h 2009-03-06 17:31:27 UTC (rev 4945) +++ trunk/scd/scdaemon.h 2009-03-10 16:10:35 UTC (rev 4946) @@ -125,6 +125,7 @@ int scd_command_handler (ctrl_t, int); void send_status_info (ctrl_t ctrl, const char *keyword, ...) GNUPG_GCC_A_SENTINEL(1); +void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args); void scd_update_reader_status_file (void); From cvs at cvs.gnupg.org Tue Mar 10 17:35:36 2009 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 10 Mar 2009 17:35:36 +0100 Subject: [svn] GpgEX - r65 - in trunk: . po src Message-ID: Author: marcus Date: 2009-03-10 17:35:35 +0100 (Tue, 10 Mar 2009) New Revision: 65 Modified: trunk/ChangeLog trunk/po/ar.po trunk/po/de.po trunk/po/es.po trunk/po/ru.po trunk/src/ChangeLog trunk/src/client.cc trunk/src/client.h trunk/src/gpgex.cc Log: src/ 2009-03-10 Marcus Brinkmann * client.h, client.cc, gpgex.cc: Change encrypt&sign to sign&encrypt everywhere (except in the protocol, of course). po/ 2009-03-10 Marcus Brinkmann * po/de.po, po/es.po, po/ru.po, po/ar.po: Change encrypt&sign to sign&encrypt everywhere. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-02-11 22:15:29 UTC (rev 64) +++ trunk/ChangeLog 2009-03-10 16:35:35 UTC (rev 65) @@ -1,3 +1,8 @@ +2009-03-10 Marcus Brinkmann + + * po/de.po, po/es.po, po/ru.po, po/ar.po: Change encrypt&sign to + sign&encrypt everywhere. + 2009-01-28 Werner Koch Release 0.9.2. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2009-02-11 22:15:29 UTC (rev 64) +++ trunk/src/ChangeLog 2009-03-10 16:35:35 UTC (rev 65) @@ -1,3 +1,8 @@ +2009-03-10 Marcus Brinkmann + + * client.h, client.cc, gpgex.cc: Change encrypt&sign to + sign&encrypt everywhere (except in the protocol, of course). + 2009-02-11 Marcus Brinkmann * bitmaps.cc (load_bitmap): Change minus to underscore. Modified: trunk/po/ar.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/ru.po [not shown] Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2009-02-11 22:15:29 UTC (rev 64) +++ trunk/src/client.cc 2009-03-10 16:35:35 UTC (rev 65) @@ -378,7 +378,7 @@ void -client_t::encrypt_sign (vector &filenames) +client_t::sign_encrypt (vector &filenames) { this->call_assuan ("ENCRYPT_SIGN_FILES", filenames); } Modified: trunk/src/client.h =================================================================== --- trunk/src/client.h 2009-02-11 22:15:29 UTC (rev 64) +++ trunk/src/client.h 2009-03-10 16:35:35 UTC (rev 65) @@ -45,7 +45,7 @@ void decrypt_verify (vector &filenames); void decrypt (vector &filenames); void verify (vector &filenames); - void encrypt_sign (vector &filenames); + void sign_encrypt (vector &filenames); void encrypt (vector &filenames); void sign (vector &filenames); void import (vector &filenames); Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2009-02-11 22:15:29 UTC (rev 64) +++ trunk/src/gpgex.cc 2009-03-10 16:35:35 UTC (rev 65) @@ -46,7 +46,7 @@ #define ID_CMD_DECRYPT_VERIFY 1 #define ID_CMD_DECRYPT 2 #define ID_CMD_VERIFY 3 -#define ID_CMD_ENCRYPT_SIGN 4 +#define ID_CMD_SIGN_ENCRYPT 4 #define ID_CMD_ENCRYPT 5 #define ID_CMD_SIGN 6 #define ID_CMD_IMPORT 7 @@ -59,7 +59,7 @@ #define ID_CMD_STR_DECRYPT_VERIFY _("Decrypt and verify") #define ID_CMD_STR_DECRYPT _("Decrypt") #define ID_CMD_STR_VERIFY _("Verify") -#define ID_CMD_STR_ENCRYPT_SIGN _("Encrypt and sign") +#define ID_CMD_STR_SIGN_ENCRYPT _("Sign and encrypt") #define ID_CMD_STR_ENCRYPT _("Encrypt") #define ID_CMD_STR_SIGN _("Sign") #define ID_CMD_STR_IMPORT _("Import keys") @@ -289,8 +289,8 @@ { /* FIXME: Check error. */ res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_ENCRYPT_SIGN, - ID_CMD_STR_ENCRYPT_SIGN); + idCmdFirst + ID_CMD_SIGN_ENCRYPT, + ID_CMD_STR_SIGN_ENCRYPT); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); } @@ -351,8 +351,8 @@ ID_CMD_STR_SIGN); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_ENCRYPT_SIGN, - ID_CMD_STR_ENCRYPT_SIGN); + idCmdFirst + ID_CMD_SIGN_ENCRYPT, + ID_CMD_STR_SIGN_ENCRYPT); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_IMPORT, ID_CMD_STR_IMPORT); @@ -419,8 +419,8 @@ txt = _("Verify the marked files."); break; - case ID_CMD_ENCRYPT_SIGN: - txt = _("Encrypt and sign the marked files."); + case ID_CMD_SIGN_ENCRYPT: + txt = _("Sign and encrypt the marked files."); break; case ID_CMD_ENCRYPT: @@ -584,8 +584,8 @@ client.verify (this->filenames); break; - case ID_CMD_ENCRYPT_SIGN: - client.encrypt_sign (this->filenames); + case ID_CMD_SIGN_ENCRYPT: + client.sign_encrypt (this->filenames); break; case ID_CMD_ENCRYPT: From cvs at cvs.gnupg.org Fri Mar 13 15:19:56 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 13 Mar 2009 15:19:56 +0100 Subject: [svn] gpgme - r1359 - trunk/src Message-ID: Author: wk Date: 2009-03-13 15:19:55 +0100 (Fri, 13 Mar 2009) New Revision: 1359 Modified: trunk/src/ChangeLog trunk/src/gpgme-config.in Log: Fix locale problem, e.g. for et_ET. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2009-03-06 22:29:49 UTC (rev 1358) +++ trunk/src/ChangeLog 2009-03-13 14:19:55 UTC (rev 1359) @@ -1,3 +1,7 @@ +2009-03-13 Werner Koch + + * gpgme-config.in: Make sure locale is set to C. + 2009-02-24 Werner Koch * gpgme.h.in (struct _gpgme_op_assuan_result): New. Modified: trunk/src/gpgme-config.in =================================================================== --- trunk/src/gpgme-config.in 2009-03-06 22:29:49 UTC (rev 1358) +++ trunk/src/gpgme-config.in 2009-03-13 14:19:55 UTC (rev 1359) @@ -14,6 +14,11 @@ includedir=@includedir@ libdir=@libdir@ +# Make sure that no weird locale setting messes up our sed regexps etc. +LC_COLLATE=C +LC_ALL=C +LANG=C + # Network libraries. netlibs="@NETLIBS@" From cvs at cvs.gnupg.org Fri Mar 13 18:27:35 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Fri, 13 Mar 2009 18:27:35 +0100 Subject: [svn] GnuPG - r4947 - branches/STABLE-BRANCH-1-4/util Message-ID: Author: dshaw Date: 2009-03-13 18:27:35 +0100 (Fri, 13 Mar 2009) New Revision: 4947 Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog branches/STABLE-BRANCH-1-4/util/Makefile.am branches/STABLE-BRANCH-1-4/util/http.c Log: * Makefile.am, http.c (start_server): Minor tweaks to get http-test compiling again. Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-10 16:10:35 UTC (rev 4946) +++ branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-13 17:27:35 UTC (rev 4947) @@ -1,3 +1,8 @@ +2009-03-13 David Shaw + + * Makefile.am, http.c (start_server): Minor tweaks to get + http-test compiling again. + 2008-09-05 David Shaw * Makefile.am: Use $(CC) instead of "cc" to compile, as the user Modified: branches/STABLE-BRANCH-1-4/util/Makefile.am =================================================================== --- branches/STABLE-BRANCH-1-4/util/Makefile.am 2009-03-10 16:10:35 UTC (rev 4946) +++ branches/STABLE-BRANCH-1-4/util/Makefile.am 2009-03-13 17:27:35 UTC (rev 4947) @@ -1,4 +1,5 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc. +# Copyright (C) 1998, 1999, 2000, 2001, 2005, 2006, 2008 +# 2009 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -64,17 +65,17 @@ libcompat_a_LIBADD = @LIBOBJS@ http-test: http.c - $(CC) -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \ + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -I. $(INCLUDES) $(LDFLAGS) -g -Wall \ -DTEST -o http-test http.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@ srv-test: srv.c - $(CC) -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \ + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -I. $(INCLUDES) $(LDFLAGS) -g -Wall \ -DTEST -o srv-test srv.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@ pka-test: pka.c - $(CC) -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \ + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -I. $(INCLUDES) $(LDFLAGS) -g -Wall \ -DTEST -o pka-test pka.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@ cert-test: cert.c - $(CC) -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \ + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -I. $(INCLUDES) $(LDFLAGS) -g -Wall \ -DTEST -o cert-test cert.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@ Modified: branches/STABLE-BRANCH-1-4/util/http.c =================================================================== --- branches/STABLE-BRANCH-1-4/util/http.c 2009-03-10 16:10:35 UTC (rev 4946) +++ branches/STABLE-BRANCH-1-4/util/http.c 2009-03-13 17:27:35 UTC (rev 4947) @@ -1,6 +1,6 @@ /* http.c - HTTP protocol handler * Copyright (C) 1999, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * 2005, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -713,7 +713,7 @@ #ifdef TEST static int -start_server() +start_server(void) { struct sockaddr_in mya; struct sockaddr_in peer; @@ -1062,7 +1062,7 @@ } release_parsed_uri( uri ); uri = NULL; - rc = http_open_document( &hd, *argv, 0, NULL ); + rc = http_open_document( &hd, *argv, NULL, 0, NULL ); if( rc ) { log_error("can't get `%s': %s\n", *argv, g10_errstr(rc)); return 1; From cvs at cvs.gnupg.org Fri Mar 13 18:51:05 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Fri, 13 Mar 2009 18:51:05 +0100 Subject: [svn] GnuPG - r4948 - branches/STABLE-BRANCH-1-4/util Message-ID: Author: dshaw Date: 2009-03-13 18:51:05 +0100 (Fri, 13 Mar 2009) New Revision: 4948 Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog branches/STABLE-BRANCH-1-4/util/http.c Log: * http.c (do_parse_uri): Properly handle IPv6 literal addresses as per RFC-2732. Adapted from patch by Phil Pennock. Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-13 17:27:35 UTC (rev 4947) +++ branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-13 17:51:05 UTC (rev 4948) @@ -1,5 +1,8 @@ 2009-03-13 David Shaw + * http.c (do_parse_uri): Properly handle IPv6 literal addresses as + per RFC-2732. Adapted from patch by Phil Pennock. + * Makefile.am, http.c (start_server): Minor tweaks to get http-test compiling again. Modified: branches/STABLE-BRANCH-1-4/util/http.c =================================================================== --- branches/STABLE-BRANCH-1-4/util/http.c 2009-03-13 17:27:35 UTC (rev 4947) +++ branches/STABLE-BRANCH-1-4/util/http.c 2009-03-13 17:51:05 UTC (rev 4948) @@ -343,16 +343,27 @@ } strlwr( p ); - uri->host = p; - if( (p3=strchr( p, ':' )) ) { - *p3++ = 0; + + /* Handle a host of [IP] so that [IP:V6]:port works */ + if( *p == '[' && (p3=strchr( p, ']' )) ) + { + *p3++ = '\0'; + /* worst case, uri->host should have length 0, points to \0 */ + uri->host = p + 1; + p = p3; + } + else + uri->host = p; + + if( (p3=strchr( p, ':' )) ) + { + *p3++ = '\0'; uri->port = atoi( p3 ); - } + } - uri->host = p; if( (n = remove_escapes( uri->host )) < 0 ) return G10ERR_BAD_URI; - if( n != strlen( p ) ) + if( n != strlen( uri->host ) ) return G10ERR_BAD_URI; /* hostname with a Nul in it */ p = p2 ? p2 : NULL; } From cvs at cvs.gnupg.org Fri Mar 13 19:59:07 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Fri, 13 Mar 2009 19:59:07 +0100 Subject: [svn] GnuPG - r4949 - trunk/common Message-ID: Author: dshaw Date: 2009-03-13 19:59:07 +0100 (Fri, 13 Mar 2009) New Revision: 4949 Modified: trunk/common/ChangeLog trunk/common/http.c Log: * http.c (do_parse_uri): Properly handle IPv6 literal addresses as per RFC-2732. Adapted from patch by Phil Pennock. Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2009-03-13 17:51:05 UTC (rev 4948) +++ trunk/common/ChangeLog 2009-03-13 18:59:07 UTC (rev 4949) @@ -1,3 +1,8 @@ +2009-03-13 David Shaw + + * http.c (do_parse_uri): Properly handle IPv6 literal addresses as + per RFC-2732. Adapted from patch by Phil Pennock. + 2009-03-06 Werner Koch * sexputil.c (make_canon_sexp): New. Modified: trunk/common/http.c =================================================================== --- trunk/common/http.c 2009-03-13 17:51:05 UTC (rev 4948) +++ trunk/common/http.c 2009-03-13 18:59:07 UTC (rev 4949) @@ -1,6 +1,6 @@ /* http.c - HTTP protocol handler - * Copyright (C) 1999, 2001, 2002, 2003, 2004, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, + * 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -623,17 +623,27 @@ for (pp=p; *pp; pp++) *pp = tolower (*(unsigned char*)pp); - uri->host = p; + + /* Handle an IPv6 literal */ + if( *p == '[' && (p3=strchr( p, ']' )) ) + { + *p3++ = '\0'; + /* worst case, uri->host should have length 0, points to \0 */ + uri->host = p + 1; + p = p3; + } + else + uri->host = p; + if ((p3 = strchr (p, ':'))) { - *p3++ = 0; + *p3++ = '\0'; uri->port = atoi (p3); } - uri->host = p; if ((n = remove_escapes (uri->host)) < 0) return gpg_error (GPG_ERR_BAD_URI); - if (n != strlen (p)) + if (n != strlen (uri->host)) return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */ p = p2 ? p2 : NULL; } From cvs at cvs.gnupg.org Sun Mar 15 04:10:05 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Sun, 15 Mar 2009 04:10:05 +0100 Subject: [svn] GnuPG - r4950 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2009-03-15 04:10:04 +0100 (Sun, 15 Mar 2009) New Revision: 4950 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/gpgv.c Log: * gpgv.c (strusage): Fix name of program in "Syntax" line. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2009-03-13 18:59:07 UTC (rev 4949) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2009-03-15 03:10:04 UTC (rev 4950) @@ -1,3 +1,7 @@ +2009-03-14 David Shaw + + * gpgv.c (strusage): Fix name of program in "Syntax" line. + 2009-02-09 Werner Koch * keylist.c (print_capabilities): Take care of cert-only keys. Modified: branches/STABLE-BRANCH-1-4/g10/gpgv.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/gpgv.c 2009-03-13 18:59:07 UTC (rev 4949) +++ branches/STABLE-BRANCH-1-4/g10/gpgv.c 2009-03-15 03:10:04 UTC (rev 4950) @@ -1,6 +1,6 @@ /* gpgv.c - The GnuPG signature verify utility - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, + * 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -99,7 +99,7 @@ _("Usage: gpgv [options] [files] (-h for help)"); break; case 41: p = - _("Syntax: gpg [options] [files]\n" + _("Syntax: gpgv [options] [files]\n" "Check signatures against known trusted keys\n"); break; From cvs at cvs.gnupg.org Sun Mar 15 04:39:51 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Sun, 15 Mar 2009 04:39:51 +0100 Subject: [svn] GnuPG - r4951 - trunk/g10 Message-ID: Author: dshaw Date: 2009-03-15 04:39:50 +0100 (Sun, 15 Mar 2009) New Revision: 4951 Modified: trunk/g10/ChangeLog trunk/g10/gpgv.c Log: * gpgv.c (my_strusage): Fix name of program in "Syntax" line. Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2009-03-15 03:10:04 UTC (rev 4950) +++ trunk/g10/ChangeLog 2009-03-15 03:39:50 UTC (rev 4951) @@ -1,3 +1,7 @@ +2009-03-14 David Shaw + + * gpgv.c (my_strusage): Fix name of program in "Syntax" line. + 2009-02-27 Werner Koch * call-agent.c (agent_scd_pksign, agent_scd_pkdecrypt): First send Modified: trunk/g10/gpgv.c =================================================================== --- trunk/g10/gpgv.c 2009-03-15 03:10:04 UTC (rev 4950) +++ trunk/g10/gpgv.c 2009-03-15 03:39:50 UTC (rev 4951) @@ -116,7 +116,7 @@ case 1: case 40: p = _("Usage: gpgv [options] [files] (-h for help)"); break; - case 41: p = _("Syntax: gpg [options] [files]\n" + case 41: p = _("Syntax: gpgv [options] [files]\n" "Check signatures against known trusted keys\n"); break; From cvs at cvs.gnupg.org Sun Mar 15 04:58:39 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Sun, 15 Mar 2009 04:58:39 +0100 Subject: [svn] GnuPG - r4952 - trunk/g10 Message-ID: Author: dshaw Date: 2009-03-15 04:58:38 +0100 (Sun, 15 Mar 2009) New Revision: 4952 Modified: trunk/g10/ChangeLog trunk/g10/gpg.c trunk/g10/gpgv.c Log: * gpg.c (my_strusage): gpg2 and gpgv2 (not gpg and gpgv). * gpgv.c (my_strusage): Same. Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2009-03-15 03:39:50 UTC (rev 4951) +++ trunk/g10/ChangeLog 2009-03-15 03:58:38 UTC (rev 4952) @@ -1,5 +1,8 @@ 2009-03-14 David Shaw + * gpg.c (my_strusage): gpg2 and gpgv2 (not gpg and gpgv). + * gpgv.c (my_strusage): Same. + * gpgv.c (my_strusage): Fix name of program in "Syntax" line. 2009-02-27 Werner Koch Modified: trunk/g10/gpg.c =================================================================== --- trunk/g10/gpg.c 2009-03-15 03:39:50 UTC (rev 4951) +++ trunk/g10/gpg.c 2009-03-15 03:58:38 UTC (rev 4952) @@ -800,7 +800,7 @@ const char *p; switch( level ) { - case 11: p = "gpg (GnuPG)"; + case 11: p = "gpg2 (GnuPG)"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; @@ -828,10 +828,10 @@ case 1: case 40: p = - _("Usage: gpg [options] [files] (-h for help)"); + _("Usage: gpg2 [options] [files] (-h for help)"); break; case 41: p = - _("Syntax: gpg [options] [files]\n" + _("Syntax: gpg2 [options] [files]\n" "sign, check, encrypt or decrypt\n" "default operation depends on the input data\n"); break; Modified: trunk/g10/gpgv.c =================================================================== --- trunk/g10/gpgv.c 2009-03-15 03:39:50 UTC (rev 4951) +++ trunk/g10/gpgv.c 2009-03-15 03:58:38 UTC (rev 4952) @@ -107,16 +107,16 @@ switch (level) { - case 11: p = "gpgv (GnuPG)"; + case 11: p = "gpgv2 (GnuPG)"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = _("Please report bugs to .\n"); break; case 1: - case 40: p = _("Usage: gpgv [options] [files] (-h for help)"); + case 40: p = _("Usage: gpgv2 [options] [files] (-h for help)"); break; - case 41: p = _("Syntax: gpgv [options] [files]\n" + case 41: p = _("Syntax: gpgv2 [options] [files]\n" "Check signatures against known trusted keys\n"); break; From cvs at cvs.gnupg.org Mon Mar 16 10:44:45 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 16 Mar 2009 10:44:45 +0100 Subject: [svn] GnuPG - r4953 - in trunk: common sm Message-ID: Author: wk Date: 2009-03-16 10:44:44 +0100 (Mon, 16 Mar 2009) New Revision: 4953 Modified: trunk/common/ChangeLog trunk/common/gettime.c trunk/common/util.h trunk/sm/ChangeLog trunk/sm/certchain.c trunk/sm/certdump.c trunk/sm/gpgsm.c trunk/sm/verify.c Log: Remove duplicated code. Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/common/ChangeLog 2009-03-16 09:44:44 UTC (rev 4953) @@ -3,6 +3,11 @@ * http.c (do_parse_uri): Properly handle IPv6 literal addresses as per RFC-2732. Adapted from patch by Phil Pennock. +2009-03-12 Werner Koch + + * gettime.c: Include i18n.h. + (dump_isotime): New. + 2009-03-06 Werner Koch * sexputil.c (make_canon_sexp): New. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/sm/ChangeLog 2009-03-16 09:44:44 UTC (rev 4953) @@ -1,3 +1,9 @@ +2009-03-12 Werner Koch + + * certdump.c (gpgsm_dump_time): Remove. + * certdump.c, verify.c, certchain.c + * gpgsm.c: s/gpgsm_dump_time/dump_isotime/. + 2009-03-06 Werner Koch * call-agent.c (gpgsm_agent_keyinfo, keyinfo_status_cb): New. Modified: trunk/common/gettime.c =================================================================== --- trunk/common/gettime.c 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/common/gettime.c 2009-03-16 09:44:44 UTC (rev 4953) @@ -26,6 +26,7 @@ #endif #include "util.h" +#include "i18n.h" static unsigned long timewarp; static enum { NORMAL = 0, FROZEN, FUTURE, PAST } timemode; @@ -495,7 +496,17 @@ } +void +dump_isotime (const gnupg_isotime_t t) +{ + if (!t || !*t) + log_printf (_("[none]")); + else + log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s", + t, t+4, t+6, t+9, t+11, t+13); +} + /* Add SECONDS to ATIME. SECONDS may not be negative and is limited to about the equivalent of 62 years which should be more then enough for our purposes. */ Modified: trunk/common/util.h =================================================================== --- trunk/common/util.h 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/common/util.h 2009-03-16 09:44:44 UTC (rev 4953) @@ -119,6 +119,7 @@ gpg_error_t add_seconds_to_isotime (gnupg_isotime_t atime, int nseconds); gpg_error_t add_days_to_isotime (gnupg_isotime_t atime, int ndays); gpg_error_t check_isotime (const gnupg_isotime_t atime); +void dump_isotime (const gnupg_isotime_t atime); /* Copy one ISO date to another, this is inline so that we can do a minimal sanity check. A null date (empty string) is allowed. */ Modified: trunk/sm/certchain.c =================================================================== --- trunk/sm/certchain.c 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/sm/certchain.c 2009-03-16 09:44:44 UTC (rev 4953) @@ -979,7 +979,7 @@ if (!listmode) { log_info (" (valid from "); - gpgsm_dump_time (not_before); + dump_isotime (not_before); log_printf (")\n"); } return gpg_error (GPG_ERR_CERT_TOO_YOUNG); @@ -994,7 +994,7 @@ if (!listmode) { log_info (" (expired at "); - gpgsm_dump_time (not_after); + dump_isotime (not_after); log_printf (")\n"); } if (opt.ignore_expiration) @@ -1043,9 +1043,9 @@ do_list (1, listmode, listfp, _("certificate with invalid validity")); log_info (" (valid from "); - gpgsm_dump_time (not_before); + dump_isotime (not_before); log_printf (" expired at "); - gpgsm_dump_time (not_after); + dump_isotime (not_after); log_printf (")\n"); return gpg_error (GPG_ERR_BAD_CERT); } @@ -1064,7 +1064,7 @@ if (!listmode) { log_info (" (valid from "); - gpgsm_dump_time (not_before); + dump_isotime (not_before); log_printf (")\n"); } return gpg_error (GPG_ERR_CERT_TOO_YOUNG); @@ -1087,13 +1087,13 @@ { log_info (depth== 0? _(" ( signature created at ") : /* */ _(" (certificate created at ") ); - gpgsm_dump_time (check_time); + dump_isotime (check_time); log_printf (")\n"); log_info (depth==0? _(" (certificate valid from ") : /* */ _(" ( issuer valid from ") ); - gpgsm_dump_time (not_before); + dump_isotime (not_before); log_info (" to "); - gpgsm_dump_time (not_after); + dump_isotime (not_after); log_printf (")\n"); } if (opt.ignore_expiration) Modified: trunk/sm/certdump.c =================================================================== --- trunk/sm/certdump.c 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/sm/certdump.c 2009-03-16 09:44:44 UTC (rev 4953) @@ -148,19 +148,6 @@ void -gpgsm_dump_time (ksba_isotime_t t) -{ - if (!t || !*t) - log_printf (_("[none]")); - else - log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s", - t, t+4, t+6, t+9, t+11, t+13); -} - - - - -void gpgsm_dump_string (const char *string) { @@ -207,11 +194,11 @@ ksba_cert_get_validity (cert, 0, t); log_debug (" notBefore: "); - gpgsm_dump_time (t); + dump_isotime (t); log_printf ("\n"); ksba_cert_get_validity (cert, 1, t); log_debug (" notAfter: "); - gpgsm_dump_time (t); + dump_isotime (t); log_printf ("\n"); dn = ksba_cert_get_issuer (cert, 0); Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/sm/gpgsm.c 2009-03-16 09:44:44 UTC (rev 4953) @@ -1405,7 +1405,7 @@ log_info (_("WARNING: running with faked system time: ")); gnupg_get_isotime (tbuf); - gpgsm_dump_time (tbuf); + dump_isotime (tbuf); log_printf ("\n"); } Modified: trunk/sm/verify.c =================================================================== --- trunk/sm/verify.c 2009-03-15 03:58:38 UTC (rev 4952) +++ trunk/sm/verify.c 2009-03-16 09:44:44 UTC (rev 4953) @@ -446,7 +446,7 @@ log_info (_("Signature made ")); if (*sigtime) - gpgsm_dump_time (sigtime); + dump_isotime (sigtime); else log_printf (_("[date not given]")); log_printf (_(" using certificate ID 0x%08lX\n"), From cvs at cvs.gnupg.org Mon Mar 16 19:45:47 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Mon, 16 Mar 2009 19:45:47 +0100 Subject: [svn] GnuPG - r4954 - trunk/doc Message-ID: Author: dshaw Date: 2009-03-16 19:45:46 +0100 (Mon, 16 Mar 2009) New Revision: 4954 Modified: trunk/doc/ChangeLog trunk/doc/gpg.texi Log: * gpg.texi (GPG Configuration Options): Document keyserver-options debug. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2009-03-16 09:44:44 UTC (rev 4953) +++ trunk/doc/ChangeLog 2009-03-16 18:45:46 UTC (rev 4954) @@ -1,3 +1,8 @@ +2009-03-16 David Shaw + + * gpg.texi (GPG Configuration Options): Document keyserver-options + debug. + 2009-03-04 Werner Koch * help.txt (gpg.keygen.size): Add a link to web page. Modified: trunk/doc/gpg.texi =================================================================== --- trunk/doc/gpg.texi 2009-03-16 09:44:44 UTC (rev 4953) +++ trunk/doc/gpg.texi 2009-03-16 18:45:46 UTC (rev 4954) @@ -1,5 +1,5 @@ - at c Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - at c 2007 Free Software Foundation, Inc. + at c Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + at c 2008, 2009 Free Software Foundation, Inc. @c This is part of the GnuPG manual. @c For copying conditions, see the file gnupg.texi. @@ -1490,6 +1490,12 @@ @item max-cert-size When retrieving a key via DNS CERT, only accept keys up to this size. Defaults to 16384 bytes. + + at item debug +Turn on debug output in the keyserver helper program. Note that the +details of debug output depends on which keyserver helper program is +being used, and in turn, on any libraries that the keyserver helper +program uses internally (libcurl, openldap, etc). @end table @item --completes-needed @code{n} From cvs at cvs.gnupg.org Tue Mar 17 13:13:33 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 17 Mar 2009 13:13:33 +0100 Subject: [svn] GnuPG - r4955 - in trunk: agent g10 Message-ID: Author: wk Date: 2009-03-17 13:13:32 +0100 (Tue, 17 Mar 2009) New Revision: 4955 Modified: trunk/agent/ChangeLog trunk/agent/command.c trunk/g10/ChangeLog trunk/g10/call-agent.c trunk/g10/call-agent.h trunk/g10/gpg.c trunk/g10/gpgv.c trunk/g10/passphrase.c Log: Move password repetition from gpg to gpg-agent. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/agent/ChangeLog 2009-03-17 12:13:32 UTC (rev 4955) @@ -1,3 +1,13 @@ +2009-03-17 Werner Koch + + * command.c (cmd_get_passphrase): Break repeat loop on error. + +2009-03-17 Daiki Ueno + + * command.c (option_value): New function. + (cmd_get_passphrase): Accept new option --repeat, which makes + gpg-agent to ask passphrase several times. + 2009-03-06 Werner Koch * command.c (cmd_keyinfo): New command. Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/ChangeLog 2009-03-17 12:13:32 UTC (rev 4955) @@ -1,3 +1,19 @@ +2009-03-17 Daiki Ueno + + * passphrase.c (passphrase_get): Add extra arg REPEAT and adjust + callers; remove special treatment for MODE==2. + (passphrase_to_dek): Move --passphrase-repeat handling to + gpg-agent. + + * call-agent.c (agent_get_passphrase): Add extra arg REPEAT. + * call-agent.h: Ditto. + +2009-03-16 Werner Koch + + * gpg.c (my_strusage): Revert last change. Systems w/o a gpg1 may, + and actually do, install gpg2 as gpg. + * gpgv.c (my_strusage): Ditto. + 2009-03-14 David Shaw * gpg.c (my_strusage): gpg2 and gpgv2 (not gpg and gpgv). Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/agent/command.c 2009-03-17 12:13:32 UTC (rev 4955) @@ -36,6 +36,7 @@ #include +#include "i18n.h" #include "agent.h" /* maximum allowed size of the inquired ciphertext */ @@ -181,7 +182,27 @@ && (!s[n] || spacep (s+n) || s[n] == '=')); } +/* Return a pointer to the argument of the option with NAME. If such + an option is not given, it returns NULL. */ +static char * +option_value (const char *line, const char *name) +{ + char *s; + int n = strlen (name); + s = strstr (line, name); + if (s && (s == line || spacep (s-1)) + && s[n] && (spacep (s+n) || s[n] == '=')) + { + s += n + 1; + s += strspn (s, " "); + if (*s && !spacep(s)) + return s; + } + return NULL; +} + + /* Skip over options. It is assumed that leading spaces have been removed (this is the case for lines passed to a handler from assuan). Blanks after the options are also removed. */ @@ -990,7 +1011,7 @@ } -/* GET_PASSPHRASE [--data] [--check] [--no-ask] +/* GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]] [ ] This function is usually used to ask for a passphrase to be used @@ -1021,13 +1042,22 @@ const char *pw; char *response; char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL; + const char *desc2 = _("Please re-enter this passphrase"); char *p; void *cache_marker; - int opt_data, opt_check, opt_no_ask; + int opt_data, opt_check, opt_no_ask, opt_repeat = 0; opt_data = has_option (line, "--data"); opt_check = has_option (line, "--check"); opt_no_ask = has_option (line, "--no-ask"); + if (has_option_name (line, "--repeat")) + { + p = option_value (line, "--repeat"); + if (p) + opt_repeat = atoi (p); + else + opt_repeat = 1; + } line = skip_options (line); cacheid = line; @@ -1094,21 +1124,39 @@ if (desc) plus_to_blank (desc); - response = NULL; - do + next_try: + rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + if (!rc) { - xfree (response); - rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); - } - while (!rc - && opt_check - && check_passphrase_constraints (ctrl, response, 0)); + int i; - if (!rc) - { - if (cacheid) - agent_put_cache (cacheid, CACHE_MODE_USER, response, 0); - rc = send_back_passphrase (ctx, opt_data, response); + if (opt_check && check_passphrase_constraints (ctrl, response, 0)) + { + xfree (response); + goto next_try; + } + for (i = 0; i < opt_repeat; i++) + { + char *response2; + + rc = agent_get_passphrase (ctrl, &response2, desc2, prompt, + errtext); + if (rc) + break; + if (strcmp (response2, response)) + { + xfree (response2); + xfree (response); + goto next_try; + } + xfree (response2); + } + if (!rc) + { + if (cacheid) + agent_put_cache (cacheid, CACHE_MODE_USER, response, 0); + rc = send_back_passphrase (ctx, opt_data, response); + } xfree (response); } } Modified: trunk/g10/call-agent.c =================================================================== --- trunk/g10/call-agent.c 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/call-agent.c 2009-03-17 12:13:32 UTC (rev 4955) @@ -874,11 +874,12 @@ const char *err_msg, const char *prompt, const char *desc_msg, + int repeat, char **r_passphrase) { int rc; char *line, *p; - char cmd[] = "GET_PASSPHRASE --data -- "; + char cmd[] = "GET_PASSPHRASE --data --repeat=%d -- "; membuf_t data; *r_passphrase = NULL; @@ -889,7 +890,7 @@ /* We allocate 3 times the needed space for the texts so that there is enough space for escaping. */ - line = xtrymalloc ( strlen (cmd) + 1 + line = xtrymalloc ( strlen (cmd) + sizeof(repeat) + 1 + (cache_id? 3*strlen (cache_id): 1) + 1 + (err_msg? 3*strlen (err_msg): 1) + 1 + (prompt? 3*strlen (prompt): 1) + 1 @@ -898,7 +899,7 @@ if (!line) return gpg_error_from_syserror (); - p = stpcpy (line, cmd); + p = line + sprintf (line, cmd, repeat); if (cache_id && *cache_id) p = my_percent_plus_escape (p, cache_id); else Modified: trunk/g10/call-agent.h =================================================================== --- trunk/g10/call-agent.h 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/call-agent.h 2009-03-17 12:13:32 UTC (rev 4955) @@ -115,6 +115,7 @@ const char *err_msg, const char *prompt, const char *desc_msg, + int repeat, char **r_passphrase); /* Send the CLEAR_PASSPHRASE command to the agent. */ Modified: trunk/g10/gpg.c =================================================================== --- trunk/g10/gpg.c 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/gpg.c 2009-03-17 12:13:32 UTC (rev 4955) @@ -800,7 +800,7 @@ const char *p; switch( level ) { - case 11: p = "gpg2 (GnuPG)"; + case 11: p = "gpg (GnuPG)"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; @@ -828,10 +828,10 @@ case 1: case 40: p = - _("Usage: gpg2 [options] [files] (-h for help)"); + _("Usage: gpg [options] [files] (-h for help)"); break; case 41: p = - _("Syntax: gpg2 [options] [files]\n" + _("Syntax: gpg [options] [files]\n" "sign, check, encrypt or decrypt\n" "default operation depends on the input data\n"); break; Modified: trunk/g10/gpgv.c =================================================================== --- trunk/g10/gpgv.c 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/gpgv.c 2009-03-17 12:13:32 UTC (rev 4955) @@ -107,16 +107,16 @@ switch (level) { - case 11: p = "gpgv2 (GnuPG)"; + case 11: p = "gpgv (GnuPG)"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = _("Please report bugs to .\n"); break; case 1: - case 40: p = _("Usage: gpgv2 [options] [files] (-h for help)"); + case 40: p = _("Usage: gpgv [options] [files] (-h for help)"); break; - case 41: p = _("Syntax: gpgv2 [options] [files]\n" + case 41: p = _("Syntax: gpgv [options] [files]\n" "Check signatures against known trusted keys\n"); break; Modified: trunk/g10/passphrase.c =================================================================== --- trunk/g10/passphrase.c 2009-03-16 18:45:46 UTC (rev 4954) +++ trunk/g10/passphrase.c 2009-03-17 12:13:32 UTC (rev 4955) @@ -237,7 +237,6 @@ * Ask the GPG Agent for the passphrase. * Mode 0: Allow cached passphrase * 1: No cached passphrase FIXME: Not really implemented - * 2: Ditto, but change the text to "repeat entry" * * Note that TRYAGAIN_TEXT must not be translated. If CANCELED is not * NULL, the function does set it to 1 if the user canceled the @@ -246,7 +245,7 @@ * computed, this will be used as the cacheid. */ static char * -passphrase_get ( u32 *keyid, int mode, const char *cacheid, +passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat, const char *tryagain_text, const char *custom_description, const char *custom_prompt, int *canceled) @@ -331,8 +330,6 @@ } } - else if (mode == 2 ) - atext = xstrdup ( _("Repeat passphrase\n") ); else atext = xstrdup ( _("Enter passphrase\n") ); @@ -349,7 +346,8 @@ my_prompt = custom_prompt ? native_to_utf8 (custom_prompt): NULL; - rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext, &pw); + rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext, + repeat, &pw); xfree (my_prompt); xfree (atext); atext = NULL; @@ -470,7 +468,7 @@ strcpy (pw, fd_passwd); } else - pw = passphrase_get (NULL, 0, cacheid, + pw = passphrase_get (NULL, 0, cacheid, 0, tryagain_text, description, prompt, canceled ); @@ -611,7 +609,8 @@ else { /* Divert to the gpg-agent. */ - pw = passphrase_get ( keyid, mode == 2? 1: 0, NULL, + pw = passphrase_get ( keyid, mode == 2, NULL, + mode == 2? opt.passwd_repeat: 0, tryagain_text, NULL, NULL, canceled ); if (*canceled) { @@ -619,33 +618,6 @@ write_status( STATUS_MISSING_PASSPHRASE ); return NULL; } - if (!pw) - pw = xstrdup (""); - if ( *pw && mode == 2 ) - { - int i; - for(i=0;i Author: wk Date: 2009-03-17 18:59:36 +0100 (Tue, 17 Mar 2009) New Revision: 4956 Modified: trunk/agent/ChangeLog trunk/agent/command.c trunk/g10/ChangeLog trunk/g10/call-agent.c Log: Enhanced last patch. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-17 12:13:32 UTC (rev 4955) +++ trunk/agent/ChangeLog 2009-03-17 17:59:36 UTC (rev 4956) @@ -1,6 +1,9 @@ 2009-03-17 Werner Koch * command.c (cmd_get_passphrase): Break repeat loop on error. + Show error message. + (cmd_getinfo): Add subcommand "cmd_has_option". + (command_has_option): New. 2009-03-17 Daiki Ueno Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2009-03-17 12:13:32 UTC (rev 4955) +++ trunk/g10/ChangeLog 2009-03-17 17:59:36 UTC (rev 4956) @@ -1,3 +1,8 @@ +2009-03-17 Werner Koch + + * call-agent.c (my_percent_plus_escape): Remove. + (agent_get_passphrase): Rewrite using percent_plus_escape. + 2009-03-17 Daiki Ueno * passphrase.c (passphrase_get): Add extra arg REPEAT and adjust Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-17 12:13:32 UTC (rev 4955) +++ trunk/agent/command.c 2009-03-17 17:59:36 UTC (rev 4956) @@ -105,8 +105,12 @@ } eventcounter; + +/* Local prototypes. */ +static int command_has_option (const char *cmd, const char *cmdopt); + /* Release the memory buffer MB but first wipe out the used memory. */ static void @@ -1046,6 +1050,7 @@ char *p; void *cache_marker; int opt_data, opt_check, opt_no_ask, opt_repeat = 0; + char *repeat_errtext = NULL; opt_data = has_option (line, "--data"); opt_check = has_option (line, "--check"); @@ -1125,7 +1130,10 @@ plus_to_blank (desc); next_try: - rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + rc = agent_get_passphrase (ctrl, &response, desc, prompt, + repeat_errtext? repeat_errtext:errtext); + xfree (repeat_errtext); + repeat_errtext = NULL; if (!rc) { int i; @@ -1147,6 +1155,13 @@ { xfree (response2); xfree (response); + repeat_errtext = try_percent_escape + (_("does not match - try again"), NULL); + if (!repeat_errtext) + { + rc = gpg_error_from_syserror (); + break; + } goto next_try; } xfree (response2); @@ -1599,6 +1614,9 @@ socket_name - Return the name of the socket. ssh_socket_name - Return the name of the ssh socket. scd_running - Return OK if the SCdaemon is already running. + + cmd_has_option CMD OPT + - Returns OK if the command CMD implements the option OPT. */ static int cmd_getinfo (assuan_context_t ctx, char *line) @@ -1639,6 +1657,38 @@ { rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL); } + else if (!strncmp (line, "cmd_has_option", 14) + && (line[14] == ' ' || line[14] == '\t' || !line[14])) + { + char *cmd, *cmdopt; + line += 14; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmd = line; + while (*line && (*line != ' ' && *line != '\t')) + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + *line++ = 0; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmdopt = line; + if (!command_has_option (cmd, cmdopt)) + rc = gpg_error (GPG_ERR_GENERAL); + } + } + } + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); return rc; @@ -1765,6 +1815,20 @@ } +/* Return true if the commznd CMD implements the option OPT. */ +static int +command_has_option (const char *cmd, const char *cmdopt) +{ + if (!strcmp (cmd, "GET_PASSPHRASE")) + { + if (!strcmp (cmdopt, "repeat")) + return 1; + } + + return 0; +} + + /* Tell the assuan library about our commands */ static int register_commands (assuan_context_t ctx) Modified: trunk/g10/call-agent.c =================================================================== --- trunk/g10/call-agent.c 2009-03-17 12:13:32 UTC (rev 4955) +++ trunk/g10/call-agent.c 2009-03-17 17:59:36 UTC (rev 4956) @@ -144,30 +144,7 @@ return buffer; } -/* Copy the text ATEXT into the buffer P and do plus '+' and percent - escaping. Note that the provided buffer needs to be 3 times the - size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */ -static char * -my_percent_plus_escape (char *p, const char *atext) -{ - const unsigned char *s; - for (s=atext; *s; s++) - { - if (*s < ' ' || *s == '+' || *s == '%') - { - snprintf (p, 4, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } - *p = 0; - return p; -} - /* Take a 20 byte hexencoded string and put it into the the provided 20 byte buffer FPR in binary format. */ static int @@ -878,8 +855,11 @@ char **r_passphrase) { int rc; - char *line, *p; - char cmd[] = "GET_PASSPHRASE --data --repeat=%d -- "; + char line[ASSUAN_LINELENGTH]; + char *arg1 = NULL; + char *arg2 = NULL; + char *arg3 = NULL; + char *arg4 = NULL; membuf_t data; *r_passphrase = NULL; @@ -888,42 +868,38 @@ if (rc) return rc; - /* We allocate 3 times the needed space for the texts so that - there is enough space for escaping. */ - line = xtrymalloc ( strlen (cmd) + sizeof(repeat) + 1 - + (cache_id? 3*strlen (cache_id): 1) + 1 - + (err_msg? 3*strlen (err_msg): 1) + 1 - + (prompt? 3*strlen (prompt): 1) + 1 - + (desc_msg? 3*strlen (desc_msg): 1) + 1 - + 1); - if (!line) - return gpg_error_from_syserror (); + /* Check that the gpg-agent understands the repeat option. */ + if (assuan_transact (agent_ctx, + "GETINFO cmd_has_option GET_PASSPHRASE repeat", + NULL, NULL, NULL, NULL, NULL, NULL)) + return gpg_error (GPG_ERR_NOT_SUPPORTED); - p = line + sprintf (line, cmd, repeat); if (cache_id && *cache_id) - p = my_percent_plus_escape (p, cache_id); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg1 = percent_plus_escape (cache_id))) + goto no_mem; if (err_msg && *err_msg) - p = my_percent_plus_escape (p, err_msg); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg2 = percent_plus_escape (err_msg))) + goto no_mem; if (prompt && *prompt) - p = my_percent_plus_escape (p, prompt); - else - *p++ = 'X'; - *p++ = ' '; - + if (!(arg3 = percent_plus_escape (prompt))) + goto no_mem; if (desc_msg && *desc_msg) - p = my_percent_plus_escape (p, desc_msg); - else - *p++ = 'X'; - *p = 0; + if (!(arg4 = percent_plus_escape (desc_msg))) + goto no_mem; + snprintf (line, DIM(line)-1, + "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s", + repeat, + arg1? arg1:"X", + arg2? arg2:"X", + arg3? arg3:"X", + arg4? arg4:"X"); + line[DIM(line)-1] = 0; + xfree (arg1); + xfree (arg2); + xfree (arg3); + xfree (arg4); + init_membuf_secure (&data, 64); rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, @@ -938,8 +914,14 @@ if (!*r_passphrase) rc = gpg_error_from_syserror (); } - xfree (line); return rc; + no_mem: + rc = gpg_error_from_syserror (); + xfree (arg1); + xfree (arg2); + xfree (arg3); + xfree (arg4); + return rc; } From cvs at cvs.gnupg.org Wed Mar 18 12:18:57 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 18 Mar 2009 12:18:57 +0100 Subject: [svn] GnuPG - r4957 - in trunk: scd sm Message-ID: Author: wk Date: 2009-03-18 12:18:56 +0100 (Wed, 18 Mar 2009) New Revision: 4957 Modified: trunk/scd/ChangeLog trunk/scd/app-common.h trunk/scd/app-dinsig.c trunk/scd/app-geldkarte.c trunk/scd/app-nks.c trunk/scd/app-openpgp.c trunk/scd/app-p15.c trunk/scd/app.c trunk/scd/command.c trunk/sm/ChangeLog trunk/sm/gpgsm.c trunk/sm/gpgsm.h trunk/sm/keylist.c trunk/sm/server.c Log: Add server option with-ephemeral-keys. Extend SCD LEARN command. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) @@ -1,3 +1,12 @@ +2009-03-18 Werner Koch + + * command.c (cmd_learn): Add option --keypairinfo. + * app.c (app_write_learn_status): Add arg FLAGS. + * app-common.h (struct app_ctx_s): Add arg FLAGS to LEARN_STATUS. + Change all implementors. + * app-p15.c (do_learn_status): Take care of flag bit 0. + * app-nks.c (do_learn_status, do_learn_status_core): Ditto. + 2009-03-10 Werner Koch * app-openpgp.c (send_key_attr): New. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/sm/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) @@ -1,3 +1,11 @@ +2009-03-18 Werner Koch + + * gpgsm.h (struct opt): Move field WITH_EPHEMERAL_KEYS to struct + server_control_s. + * gpgsm.c (main): Change accordingly. + * keylist.c (list_internal_keys): Ditto. + * server.c (option_handler): Add "with-ephemeral-keys". + 2009-03-12 Werner Koch * certdump.c (gpgsm_dump_time): Remove. Modified: trunk/scd/app-common.h =================================================================== --- trunk/scd/app-common.h 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-common.h 2009-03-18 11:18:56 UTC (rev 4957) @@ -67,7 +67,7 @@ struct app_local_s *app_local; /* Local to the application. */ struct { void (*deinit) (app_t app); - gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl); + gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags); gpg_error_t (*readcert) (app_t app, const char *certid, unsigned char **cert, size_t *certlen); gpg_error_t (*readkey) (app_t app, const char *certid, @@ -145,7 +145,8 @@ void release_application (app_t app); gpg_error_t app_munge_serialno (app_t app); gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); -gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl); +gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl, + unsigned int flags); gpg_error_t app_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen); gpg_error_t app_readkey (app_t app, const char *keyid, Modified: trunk/scd/app-dinsig.c =================================================================== --- trunk/scd/app-dinsig.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-dinsig.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -86,7 +86,7 @@ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; char ct_buf[100], id_buf[100]; @@ -97,6 +97,8 @@ ksba_cert_t cert; int fid; + (void)flags; + /* Return the certificate of the card holder. */ fid = 0xC000; len = app_help_read_length_of_cert (app->slot, fid, &certoff); Modified: trunk/scd/app-geldkarte.c =================================================================== --- trunk/scd/app-geldkarte.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-geldkarte.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -147,7 +147,7 @@ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { static const char *names[] = { "X-KBLZ", @@ -167,6 +167,8 @@ gpg_error_t err = 0; int idx; + (void)flags; + for (idx=0; names[idx] && !err; idx++) err = do_getattr (app, ctrl, names[idx]); return err; Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-nks.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -309,7 +309,7 @@ static void -do_learn_status_core (app_t app, ctrl_t ctrl, int is_sigg) +do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags, int is_sigg) { gpg_error_t err; char ct_buf[100], id_buf[100]; @@ -332,7 +332,7 @@ if (!!filelist[i].is_sigg != !!is_sigg) continue; - if (filelist[i].certtype) + if (filelist[i].certtype && !(flags &1)) { size_t len; @@ -377,7 +377,7 @@ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; @@ -385,13 +385,13 @@ if (err) return err; - do_learn_status_core (app, ctrl, 0); + do_learn_status_core (app, ctrl, flags, 0); err = switch_application (app, 1); if (err) return 0; /* Silently ignore if we can't switch to SigG. */ - do_learn_status_core (app, ctrl, 1); + do_learn_status_core (app, ctrl, flags, 1); return 0; } Modified: trunk/scd/app-openpgp.c =================================================================== --- trunk/scd/app-openpgp.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-openpgp.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -1295,8 +1295,10 @@ /* Handle the LEARN command for OpenPGP. */ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { + (void)flags; + do_getattr (app, ctrl, "EXTCAP"); do_getattr (app, ctrl, "DISP-NAME"); do_getattr (app, ctrl, "DISP-LANG"); Modified: trunk/scd/app-p15.c =================================================================== --- trunk/scd/app-p15.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app-p15.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -2492,18 +2492,24 @@ /* This is the handler for the LEARN command. */ static gpg_error_t -do_learn_status (app_t app, ctrl_t ctrl) +do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; - err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info); + if ((flags & 1)) + err = 0; + else + { + err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "101", + app->app_local->trusted_certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "102", + app->app_local->useful_certificate_info); + } + if (!err) - err = send_certinfo (app, ctrl, "101", - app->app_local->trusted_certificate_info); - if (!err) - err = send_certinfo (app, ctrl, "102", - app->app_local->useful_certificate_info); - if (!err) err = send_keypairinfo (app, ctrl, app->app_local->private_key_info); return err; Modified: trunk/scd/app.c =================================================================== --- trunk/scd/app.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/app.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -542,7 +542,7 @@ /* Write out the application specifig status lines for the LEARN command. */ gpg_error_t -app_write_learn_status (app_t app, ctrl_t ctrl) +app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags) { gpg_error_t err; @@ -553,13 +553,14 @@ if (!app->fnc.learn_status) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - if (app->apptype) + /* We do not send APPTYPE if only keypairinfo is requested. */ + if (app->apptype && !(flags & 1)) send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); err = lock_reader (app->slot); if (err) return err; - err = app->fnc.learn_status (app, ctrl); + err = app->fnc.learn_status (app, ctrl, flags); unlock_reader (app->slot); return err; } Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/scd/command.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -1,6 +1,6 @@ /* command.c - SCdaemon command handler * Copyright (C) 2001, 2002, 2003, 2004, 2005, - * 2007, 2008 Free Software Foundation, Inc. + * 2007, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -184,7 +184,7 @@ -/* Check whether the option NAME appears in LINE */ +/* Check whether the option NAME appears in LINE. Returns 1 or 0. */ static int has_option (const char *line, const char *name) { @@ -528,7 +528,7 @@ -/* LEARN [--force] +/* LEARN [--force] [--keypairinfo] Learn all useful information of the currently inserted card. When used without the force options, the command might do an INQUIRE @@ -538,9 +538,14 @@ The client should just send an "END" if the processing should go on or a "CANCEL" to force the function to terminate with a Cancel - error message. The response of this command is a list of status - lines formatted as this: + error message. + With the option --keypairinfo only KEYPARIINFO lstatus lines are + returned. + + The response of this command is a list of status lines formatted as + this: + S APPTYPE This returns the type of the application, currently the strings: @@ -589,13 +594,14 @@ The URL to be used for locating the entire public key. - Note, that this function may be even be used on a locked card. + Note, that this function may even be used on a locked card. */ static int cmd_learn (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; + int only_keypairinfo = has_option (line, "--keypairinfo"); if ((rc = open_card (ctrl, NULL))) return rc; @@ -604,51 +610,53 @@ the card using a serial number and inquiring the client with that. The client may choose to cancel the operation if he already knows about this card */ - { - char *serial_and_stamp; - char *serial; - time_t stamp; - - rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); - if (rc) - return rc; - rc = estream_asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); - xfree (serial); - if (rc < 0) - return out_of_core (); - rc = 0; - assuan_write_status (ctx, "SERIALNO", serial_and_stamp); - - if (!has_option (line, "--force")) - { - char *command; - - rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); - if (rc < 0) - { - xfree (serial_and_stamp); - return out_of_core (); - } - rc = 0; - rc = assuan_inquire (ctx, command, NULL, NULL, 0); - xfree (command); - if (rc) - { - if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED) - log_error ("inquire KNOWNCARDP failed: %s\n", - gpg_strerror (rc)); - xfree (serial_and_stamp); - return rc; - } - /* not canceled, so we have to proceeed */ - } - xfree (serial_and_stamp); - } - + if (!only_keypairinfo) + { + char *serial_and_stamp; + char *serial; + time_t stamp; + + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); + if (rc) + return rc; + rc = estream_asprintf (&serial_and_stamp, "%s %lu", + serial, (unsigned long)stamp); + xfree (serial); + if (rc < 0) + return out_of_core (); + rc = 0; + assuan_write_status (ctx, "SERIALNO", serial_and_stamp); + + if (!has_option (line, "--force")) + { + char *command; + + rc = estream_asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); + if (rc < 0) + { + xfree (serial_and_stamp); + return out_of_core (); + } + rc = 0; + rc = assuan_inquire (ctx, command, NULL, NULL, 0); + xfree (command); + if (rc) + { + if (gpg_err_code (rc) != GPG_ERR_ASS_CANCELED) + log_error ("inquire KNOWNCARDP failed: %s\n", + gpg_strerror (rc)); + xfree (serial_and_stamp); + return rc; + } + /* Not canceled, so we have to proceeed. */ + } + xfree (serial_and_stamp); + } + /* Let the application print out its collection of useful status information. */ if (!rc) - rc = app_write_learn_status (ctrl->app_ctx, ctrl); + rc = app_write_learn_status (ctrl->app_ctx, ctrl, only_keypairinfo); TEST_CARD_REMOVAL (ctrl, rc); return rc; Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/sm/gpgsm.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -1259,7 +1259,7 @@ case oWithKeyData: opt.with_key_data=1; /* fall thru */ case oWithColons: ctrl.with_colons = 1; break; case oWithValidation: ctrl.with_validation=1; break; - case oWithEphemeralKeys: opt.with_ephemeral_keys=1; break; + case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break; case oSkipVerify: opt.skip_verify=1; break; Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/sm/gpgsm.h 2009-03-18 11:18:56 UTC (rev 4957) @@ -82,9 +82,6 @@ int with_md5_fingerprint; /* Also print an MD5 fingerprint for standard key listings. */ - int with_ephemeral_keys; /* Include ephemeral flagged keys in the - keylisting. */ - int armor; /* force base64 armoring (see also ctrl.with_base64) */ int no_armor; /* don't try to figure out whether data is base64 armored*/ @@ -176,6 +173,8 @@ int with_colons; /* Use column delimited output format */ int with_chain; /* Include the certifying certs in a listing */ int with_validation;/* Validate each key while listing. */ + int with_ephemeral_keys; /* Include ephemeral flagged keys in the + keylisting. */ int autodetect_encoding; /* Try to detect the input encoding */ int is_pem; /* Is in PEM format */ Modified: trunk/sm/keylist.c =================================================================== --- trunk/sm/keylist.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/sm/keylist.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -1292,7 +1292,7 @@ gpg_error_t rc = 0; const char *lastresname, *resname; int have_secret; - int want_ephemeral = opt.with_ephemeral_keys; + int want_ephemeral = ctrl->with_ephemeral_keys; hd = keydb_new (0); if (!hd) Modified: trunk/sm/server.c =================================================================== --- trunk/sm/server.c 2009-03-17 17:59:36 UTC (rev 4956) +++ trunk/sm/server.c 2009-03-18 11:18:56 UTC (rev 4957) @@ -296,6 +296,11 @@ } else if (!strcmp (key, "allow-pinentry-notify")) ctrl->server_local->allow_pinentry_notify = 1; + else if (!strcmp (key, "with-ephemeral-keys")) + { + int i = *value? atoi (value) : 0; + ctrl->with_ephemeral_keys = i; + } else return gpg_error (GPG_ERR_UNKNOWN_OPTION); From cvs at cvs.gnupg.org Wed Mar 18 12:19:29 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 18 Mar 2009 12:19:29 +0100 Subject: [svn] gpgme - r1360 - in trunk: . doc src Message-ID: Author: wk Date: 2009-03-18 12:19:29 +0100 (Wed, 18 Mar 2009) New Revision: 1360 Modified: trunk/NEWS trunk/doc/gpgme.texi trunk/src/ChangeLog trunk/src/engine-gpgsm.c trunk/src/gpgme.h.in Log: Add GPGME_KEYLIST_MODE_EPHEMERAL. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2009-03-13 14:19:55 UTC (rev 1359) +++ trunk/src/ChangeLog 2009-03-18 11:19:29 UTC (rev 1360) @@ -1,3 +1,8 @@ +2009-03-18 Werner Koch + + * gpgme.h.in (GPGME_KEYLIST_MODE_EPHEMERAL): New. + * engine-gpgsm.c (gpgsm_keylist): Send new option. + 2009-03-13 Werner Koch * gpgme-config.in: Make sure locale is set to C. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-13 14:19:55 UTC (rev 1359) +++ trunk/NEWS 2009-03-18 11:19:29 UTC (rev 1360) @@ -3,6 +3,7 @@ * Interface changes relative to the 1.1.7 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GPGME_KEYLIST_MODE_EPHEMERAL NEW. GPGME_PROTOCOL_ASSUAN NEW. gpgme_assuan_data_cb_t NEW. gpgme_assuan_inquire_cb_t NEW. Modified: trunk/doc/gpgme.texi =================================================================== --- trunk/doc/gpgme.texi 2009-03-13 14:19:55 UTC (rev 1359) +++ trunk/doc/gpgme.texi 2009-03-18 11:19:29 UTC (rev 1360) @@ -2208,6 +2208,10 @@ keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also enabled. + at item GPGME_KEYLIST_MODE_EPHEMERAL +The @code{GPGME_KEYLIST_MODE_EPHEMERAL} symbol specifies that keys +flagged as ephemeral are included in the listing. + @item GPGME_KEYLIST_MODE_VALIDATE The @code{GPGME_KEYLIST_MODE_VALIDATE} symbol specifies that the backend should do key or certificate validation and not just get the Modified: trunk/src/engine-gpgsm.c =================================================================== --- trunk/src/engine-gpgsm.c 2009-03-13 14:19:55 UTC (rev 1359) +++ trunk/src/engine-gpgsm.c 2009-03-18 11:19:29 UTC (rev 1360) @@ -1,6 +1,6 @@ /* engine-gpgsm.c - GpgSM engine. Copyright (C) 2000 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH This file is part of GPGME. @@ -1575,13 +1575,20 @@ /* Always send key validation because RESET does not reset it. */ - /* Use the validation mode if required. We don't check for an error + /* Use the validation mode if requested. We don't check for an error yet because this is a pretty fresh gpgsm features. */ gpgsm_assuan_simple_command (gpgsm->assuan_ctx, (mode & GPGME_KEYLIST_MODE_VALIDATE)? "OPTION with-validation=1": "OPTION with-validation=0" , NULL, NULL); + /* Include the ephemeral keys if requested. We don't check for an error + yet because this is a pretty fresh gpgsm features. */ + gpgsm_assuan_simple_command (gpgsm->assuan_ctx, + (mode & GPGME_KEYLIST_MODE_EPHEMERAL)? + "OPTION with-ephemeral-keys=1": + "OPTION with-ephemeral-keys=0" , + NULL, NULL); /* Length is "LISTSECRETKEYS " + p + '\0'. */ Modified: trunk/src/gpgme.h.in =================================================================== --- trunk/src/gpgme.h.in 2009-03-13 14:19:55 UTC (rev 1359) +++ trunk/src/gpgme.h.in 2009-03-18 11:19:29 UTC (rev 1360) @@ -312,6 +312,7 @@ #define GPGME_KEYLIST_MODE_EXTERN 2 #define GPGME_KEYLIST_MODE_SIGS 4 #define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8 +#define GPGME_KEYLIST_MODE_EPHEMERAL 128 #define GPGME_KEYLIST_MODE_VALIDATE 256 typedef unsigned int gpgme_keylist_mode_t; From cvs at cvs.gnupg.org Thu Mar 19 08:09:31 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 19 Mar 2009 08:09:31 +0100 Subject: [svn] GnuPG - r4958 - in trunk: . agent common scd Message-ID: Author: wk Date: 2009-03-19 08:09:31 +0100 (Thu, 19 Mar 2009) New Revision: 4958 Modified: trunk/ChangeLog trunk/NEWS trunk/agent/ChangeLog trunk/agent/gpg-agent.c trunk/common/ChangeLog trunk/common/Makefile.am trunk/common/exechelp.c trunk/common/exechelp.h trunk/configure.ac trunk/scd/ChangeLog trunk/scd/apdu.c Log: Make sure not to leak file descriptors if running gpg-agent with a command. Restore the signal mask to solve a problem in Mono. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/ChangeLog 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,3 +1,7 @@ +2009-03-18 Werner Koch + + * configure.ac: Test for getrlimit. + 2009-03-03 Werner Koch Release 2.0.11. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/agent/ChangeLog 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,3 +1,8 @@ +2009-03-19 Werner Koch + + * gpg-agent.c (main): Save signal mask and open fds. Restore mask + and close all fds prior to the exec. Fixes bug#1013. + 2009-03-17 Werner Koch * command.c (cmd_get_passphrase): Break repeat loop on error. Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/common/ChangeLog 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,3 +1,13 @@ +2009-03-18 Werner Koch + + * exechelp.c: Include sys/resource.h and sys/stat.h. + (get_max_open_fds): New. + (do_exec): Use it. + (get_all_open_fds): New. + (close_all_fds): New. + (do_exec): Use close_all_fds. + * t-exechelp.c: New. + 2009-03-13 David Shaw * http.c (do_parse_uri): Properly handle IPv6 literal addresses as Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/scd/ChangeLog 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,5 +1,7 @@ 2009-03-18 Werner Koch + * apdu.c (open_pcsc_reader_wrapped): Use close_all_fds. + * command.c (cmd_learn): Add option --keypairinfo. * app.c (app_write_learn_status): Add arg FLAGS. * app-common.h (struct app_ctx_s): Add arg FLAGS to LEARN_STATUS. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/NEWS 2009-03-19 07:09:31 UTC (rev 4958) @@ -7,7 +7,10 @@ * New command "KEYINFO" for GPG_AGENT. GPGSM now also returns information about smartcards. + * Make sure not to leak file descriptors if running gpg-agent with a + command. Restore the signal mask to solve a problem in Mono. + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/agent/gpg-agent.c 2009-03-19 07:09:31 UTC (rev 4958) @@ -47,6 +47,7 @@ #include "sysutils.h" #include "setenv.h" #include "gc-opt-flags.h" +#include "exechelp.h" enum cmd_and_opt_values @@ -197,6 +198,17 @@ #define TIMERTICK_INTERVAL (2) /* Seconds. */ #endif + +/* The list of open file descriptors at startup. Note that this list + has been allocated using the standard malloc. */ +static int *startup_fd_list; + +/* The signal mask at startup and a flag telling whether it is valid. */ +#ifdef HAVE_SIGPROCMASK +static sigset_t startup_signal_mask; +static int startup_signal_mask_valid; +#endif + /* Flag to indicate that a shutdown was requested. */ static int shutdown_pending; @@ -530,6 +542,16 @@ const char *env_file_name = NULL; + /* Before we do anything else we save the list of currently open + file descriptors and the signal mask. This info is required to + do the exec call properly. */ + startup_fd_list = get_all_open_fds (); +#ifdef HAVE_SIGPROCMASK + if (!sigprocmask (SIG_UNBLOCK, NULL, &startup_signal_mask)) + startup_signal_mask_valid = 1; +#endif /*HAVE_SIGPROCMASK*/ + + /* Set program name etc. */ set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); /* Please note that we may running SUID(ROOT), so be very CAREFUL @@ -961,6 +983,27 @@ close (fd); + /* Note that we used a standard fork so that Pth runs in + both the parent and the child. The pth_fork would + terminate Pth in the child but that is not the way we + want it. Thus we use a plain fork and terminate Pth here + in the parent. The pth_kill may or may not work reliable + but it should not harm to call it. Because Pth fiddles + with the signal mask the signal mask might not be correct + right now and thus we restore it. That is not strictly + necessary but some programs falsely assume a cleared + signal mask. */ +#ifdef HAVE_SIGPROCMASK + if (startup_signal_mask_valid) + { + if (sigprocmask (SIG_SETMASK, &startup_signal_mask, NULL)) + log_error ("error restoring signal mask: %s\n", + strerror (errno)); + } + else + log_info ("no saved signal mask\n"); +#endif /*HAVE_SIGPROCMASK*/ + /* Create the info string: :: */ if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1", socket_name, (ulong)pid ) < 0) @@ -1039,6 +1082,14 @@ kill (pid, SIGTERM ); exit (1); } + + /* Close all the file descriptors except the standard + ones and those open at startup. We explicitly don't + close 0,1,2 in case something went wrong collecting + them at startup. */ + close_all_fds (3, startup_fd_list); + + /* Run the command. */ execvp (argv[0], argv); log_error ("failed to run the command: %s\n", strerror (errno)); kill (pid, SIGTERM); Modified: trunk/common/Makefile.am =================================================================== --- trunk/common/Makefile.am 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/common/Makefile.am 2009-03-19 07:09:31 UTC (rev 4958) @@ -108,7 +108,7 @@ # # Module tests # -module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil +module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil t-exechelp module_maint_tests = t-helpfile t-b64 t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ @@ -121,6 +121,7 @@ t_helpfile_LDADD = $(t_common_ldadd) t_sexputil_LDADD = $(t_common_ldadd) t_b64_LDADD = $(t_common_ldadd) +t_exechelp_LDADD = $(t_common_ldadd) Modified: trunk/common/exechelp.c =================================================================== --- trunk/common/exechelp.c 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/common/exechelp.c 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,5 +1,5 @@ /* exechelp.c - fork and exec helpers - * Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,6 +40,16 @@ #include #endif +#ifdef HAVE_GETRLIMIT +#include +#include +#endif /*HAVE_GETRLIMIT*/ + +#ifdef HAVE_STAT +# include +#endif + + #include "util.h" #include "i18n.h" #include "exechelp.h" @@ -48,12 +58,6 @@ #define DEBUG_W32_SPAWN 1 -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - /* We have the usual problem here: Some modules are linked against pth and some are not. However we want to use pth_fork and pth_waitpid here. Using a weak symbol works but is not portable - we should @@ -85,6 +89,145 @@ #endif +/* Return the maximum number of currently allowed open file + descriptors. Only useful on POSIX systems but returns a value on + other systems too. */ +int +get_max_fds (void) +{ + int max_fds = -1; +#ifdef HAVE_GETRLIMIT + struct rlimit rl; + +# ifdef RLIMIT_NOFILE + if (!getrlimit (RLIMIT_NOFILE, &rl)) + max_fds = rl.rlim_max; +# endif + +# ifdef RLIMIT_OFILE + if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl)) + max_fds = rl.rlim_max; + +# endif +#endif /*HAVE_GETRLIMIT*/ + +#ifdef _SC_OPEN_MAX + if (max_fds == -1) + { + long int scres = sysconf (_SC_OPEN_MAX); + if (scres >= 0) + max_fds = scres; + } +#endif + +#ifdef _POSIX_OPEN_MAX + if (max_fds == -1) + max_fds = _POSIX_OPEN_MAX; +#endif + +#ifdef OPEN_MAX + if (max_fds == -1) + max_fds = OPEN_MAX; +#endif + + if (max_fds == -1) + max_fds = 256; /* Arbitrary limit. */ + + return max_fds; +} + + +/* Close all file descriptors starting with descriptor FIRST. If + EXCEPT is not NULL, it is expected to be a list of file descriptors + which shall not be closed. This list shall be sorted in ascending + order with the end marked by -1. */ +void +close_all_fds (int first, int *except) +{ + int max_fd = get_max_fds (); + int fd, i, except_start; + + if (except) + { + except_start = 0; + for (fd=first; fd < max_fd; fd++) + { + for (i=except_start; except[i] != -1; i++) + { + if (except[i] == fd) + { + /* If we found the descriptor in the exception list + we can start the next compare run at the next + index because the exception list is ordered. */ + except_start = i + 1; + break; + } + } + if (except[i] == -1) + close (fd); + } + } + else + { + for (fd=first; fd < max_fd; fd++) + close (fd); + } + + errno = 0; +} + + +/* Returns an array with all currently open file descriptors. The end + of the array is marked by -1. The caller needs to release this + array using the *standard free* and not with xfree. This allow the + use of this fucntion right at startup even before libgcrypt has + been initialized. Returns NULL on error and sets ERRNO + accordingly. */ +int * +get_all_open_fds (void) +{ + int *array; + size_t narray; + int fd, max_fd, idx; +#ifndef HAVE_STAT + array = calloc (1, sizeof *array); + if (array) + array[0] = -1; +#else /*HAVE_STAT*/ + struct stat statbuf; + + max_fd = get_max_fds (); + narray = 32; /* If you change this change also t-exechelp.c. */ + array = calloc (narray, sizeof *array); + if (!array) + return NULL; + + /* Note: The list we return is ordered. */ + for (idx=0, fd=0; fd < max_fd; fd++) + if (!(fstat (fd, &statbuf) == -1 && errno == EBADF)) + { + if (idx+1 >= narray) + { + int *tmp; + + narray += (narray < 256)? 32:256; + tmp = realloc (array, narray * sizeof *array); + if (!tmp) + { + free (array); + return NULL; + } + array = tmp; + } + array[idx++] = fd; + } + array[idx] = -1; +#endif /*HAVE_STAT*/ + return array; +} + + + #ifdef HAVE_W32_SYSTEM /* Helper function to build_w32_commandline. */ static char * @@ -216,7 +359,7 @@ void (*preexec)(void) ) { char **arg_list; - int n, i, j; + int i, j; int fds[3]; fds[0] = fd_in; @@ -259,12 +402,7 @@ } /* Close all other files. */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=3; i < n; i++) - close(i); - errno = 0; + close_all_fds (3, NULL); if (preexec) preexec (); Modified: trunk/common/exechelp.h =================================================================== --- trunk/common/exechelp.h 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/common/exechelp.h 2009-03-19 07:09:31 UTC (rev 4958) @@ -1,5 +1,5 @@ /* exechelp.h - Definitions for the fork and exec helpers - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -20,7 +20,26 @@ #ifndef GNUPG_COMMON_EXECHELP_H #define GNUPG_COMMON_EXECHELP_H +/* Return the maximum number of currently allowed file descriptors. + Only useful on POSIX systems. */ +int get_max_fds (void); + +/* Close all file descriptors starting with descriptor FIRST. If + EXCEPT is not NULL, it is expected to be a list of file descriptors + which are not to close. This list shall be sorted in ascending + order with its end marked by -1. */ +void close_all_fds (int first, int *except); + + +/* Returns an array with all currently open file descriptors. The end + of the array is marked by -1. The caller needs to release this + array using the *standard free* and not with xfree. This allow the + use of this fucntion right at startup even before libgcrypt has + been initialized. Returns NULL on error and sets ERRNO accordingly. */ +int *get_all_open_fds (void); + + /* Portable function to create a pipe. Under Windows the write end is inheritable. */ gpg_error_t gnupg_create_inbound_pipe (int filedes[2]); Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/configure.ac 2009-03-19 07:09:31 UTC (rev 4958) @@ -1059,7 +1059,7 @@ AC_CHECK_FUNCS([strerror strlwr tcgetattr mmap]) AC_CHECK_FUNCS([strcasecmp strncasecmp ctermid times gmtime_r]) AC_CHECK_FUNCS([unsetenv getpwnam getpwuid fcntl ftruncate]) -AC_CHECK_FUNCS([gettimeofday getrusage setrlimit clock_gettime]) +AC_CHECK_FUNCS([gettimeofday getrusage getrlimit setrlimit clock_gettime]) AC_CHECK_FUNCS([atexit raise getpagesize strftime nl_langinfo setlocale]) AC_CHECK_FUNCS([waitpid wait4 sigaction sigprocmask pipe stat getaddrinfo]) AC_CHECK_FUNCS([ttyname rand ftello]) Modified: trunk/scd/apdu.c =================================================================== --- trunk/scd/apdu.c 2009-03-18 11:18:56 UTC (rev 4957) +++ trunk/scd/apdu.c 2009-03-19 07:09:31 UTC (rev 4958) @@ -57,6 +57,7 @@ #include "cardglue.h" #else /* GNUPG_MAJOR_VERSION != 1 */ #include "scdaemon.h" +#include "exechelp.h" #endif /* GNUPG_MAJOR_VERSION != 1 */ #include "apdu.h" @@ -81,11 +82,6 @@ #define DLSTDCALL #endif -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif /* Helper to pass parameters related to keypad based operations. */ struct pininfo_s @@ -1653,12 +1649,7 @@ log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); /* Close all other files. */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=3; i < n; i++) - close(i); - errno = 0; + close_all_fds (3, NULL); execl (wrapperpgm, "pcsc-wrapper", From cvs at cvs.gnupg.org Thu Mar 19 10:48:11 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 19 Mar 2009 10:48:11 +0100 Subject: [svn] pinentry - r193 - in trunk: . gtk+-2 pinentry Message-ID: Author: wk Date: 2009-03-19 10:48:11 +0100 (Thu, 19 Mar 2009) New Revision: 193 Modified: trunk/ChangeLog trunk/NEWS trunk/gtk+-2/pinentry-gtk-2.c trunk/pinentry/pinentry.c trunk/pinentry/pinentry.h Log: Return GPG_ERR_CANCELED if during a "CONFIRM" command the user closed the window. Only Gtk+-2 for now. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-02-20 15:41:11 UTC (rev 192) +++ trunk/ChangeLog 2009-03-19 09:48:11 UTC (rev 193) @@ -1,3 +1,12 @@ +2009-03-19 Werner Koch + + * pinentry/pinentry.h (struct pinentry): Add field user_closed. + * pinentry/pinentry.c (cmd_getpin, cmd_confirm, cmd_message): + Reset this field. + (cmd_confirm): Return cancel if the user closed the window. + * gtk+-2/pinentry-gtk-2.c (window_closed): New. + (gtk_cmd_handler, delete_event): Set it. + 2009-02-19 Marcus Brinkmann * secmem/secmem++.h: New file. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-02-20 15:41:11 UTC (rev 192) +++ trunk/NEWS 2009-03-19 09:48:11 UTC (rev 193) @@ -7,7 +7,10 @@ * Fix utf-8 problem in Qt pinentries. + * Return GPG_ERR_CANCELED if during a "CONFIRM" command the user + closed the window. + Noteworthy changes in version 0.7.5 (2008-02-15) ------------------------------------------------ Modified: trunk/gtk+-2/pinentry-gtk-2.c =================================================================== --- trunk/gtk+-2/pinentry-gtk-2.c 2009-02-20 15:41:11 UTC (rev 192) +++ trunk/gtk+-2/pinentry-gtk-2.c 2009-03-19 09:48:11 UTC (rev 193) @@ -54,6 +54,7 @@ static pinentry_t pinentry; static int passphrase_ok; static int confirm_yes; +static int window_closed; static GtkWidget *entry; static GtkWidget *qualitybar; @@ -149,6 +150,7 @@ static int delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) { + window_closed = 1; gtk_main_quit (); return TRUE; } @@ -489,6 +491,7 @@ pinentry = pe; confirm_yes = 0; + window_closed = 0; passphrase_ok = 0; w = create_window (want_pass ? 0 : 1); gtk_main (); @@ -496,6 +499,9 @@ while (gtk_events_pending ()) gtk_main_iteration (); + if (window_closed) + pe->user_closed = 1; + pinentry = NULL; if (want_pass) { Modified: trunk/pinentry/pinentry.c =================================================================== --- trunk/pinentry/pinentry.c 2009-02-20 15:41:11 UTC (rev 192) +++ trunk/pinentry/pinentry.c 2009-03-19 09:48:11 UTC (rev 193) @@ -819,6 +819,7 @@ set_prompt = 1; } pinentry.locale_err = 0; + pinentry.user_closed = 0; pinentry.one_button = 0; pinentry.ctx_assuan = ctx; result = (*pinentry_cmd_handler) (&pinentry); @@ -875,6 +876,7 @@ pinentry.one_button = !!strstr (line, "--one-button"); pinentry.quality_bar = 0; pinentry.locale_err = 0; + pinentry.user_closed = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) { @@ -886,7 +888,9 @@ : (pinentry.locale_err? ASSUAN_Locale_Problem : (pinentry.one_button ? 0 - : ASSUAN_Not_Confirmed)); + : (pinentry.user_closed + ? ASSUAN_Canceled + : ASSUAN_Not_Confirmed))); } @@ -898,6 +902,7 @@ pinentry.one_button = 1; pinentry.quality_bar = 0; pinentry.locale_err = 0; + pinentry.user_closed = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) { Modified: trunk/pinentry/pinentry.h =================================================================== --- trunk/pinentry/pinentry.h 2009-02-20 15:41:11 UTC (rev 192) +++ trunk/pinentry/pinentry.h 2009-03-19 09:48:11 UTC (rev 193) @@ -84,6 +84,10 @@ and to the length of the PIN stored in pin otherwise. */ int result; + /* The user should set this is the pinentry window was closed by the + user without using a button. */ + int user_closed; + /* The user should set this to true if an error with the local conversion occured. */ int locale_err; From cvs at cvs.gnupg.org Thu Mar 19 11:21:52 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 19 Mar 2009 11:21:52 +0100 Subject: [svn] GnuPG - r4959 - in trunk: . agent doc Message-ID: Author: wk Date: 2009-03-19 11:21:51 +0100 (Thu, 19 Mar 2009) New Revision: 4959 Modified: trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/command.c trunk/agent/trustlist.c trunk/doc/gpg-agent.texi Log: Changed order of the confirmation questions for root certificates and stores negative answers in trustlist.txt. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/agent/ChangeLog 2009-03-19 10:21:51 UTC (rev 4959) @@ -1,5 +1,12 @@ 2009-03-19 Werner Koch + * trustlist.c (struct trustitem_s): Add field DISABLED. + (read_one_trustfile): Parse the '!' flag. + (agent_istrusted, agent_listtrusted): Check flag. + (agent_istrusted): Add arg R_DISABLED. Change all callers. + (agent_marktrusted): Do not ask if flagged as disabled. Reverse + the order of the questions. Store the disabled flag. + * gpg-agent.c (main): Save signal mask and open fds. Restore mask and close all fds prior to the exec. Fixes bug#1013. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/NEWS 2009-03-19 10:21:51 UTC (rev 4959) @@ -7,10 +7,13 @@ * New command "KEYINFO" for GPG_AGENT. GPGSM now also returns information about smartcards. - * Make sure not to leak file descriptors if running gpg-agent with a - command. Restore the signal mask to solve a problem in Mono. + * Made sure not to leak file descriptors if running gpg-agent with a + command. Restores the signal mask to solve a problem in Mono. + * Changed order of the confirmation questions for root certificates + and stores negative answers in trustlist.txt. + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/agent/agent.h 2009-03-19 10:21:51 UTC (rev 4959) @@ -303,7 +303,7 @@ /*-- trustlist.c --*/ void initialize_module_trustlist (void); -gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr); +gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled); gpg_error_t agent_listtrusted (void *assuan_context); gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag); Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/agent/command.c 2009-03-19 10:21:51 UTC (rev 4959) @@ -461,7 +461,7 @@ for (p=line; i < 40; p++, i++) fpr[i] = *p >= 'a'? (*p & 0xdf): *p; fpr[i] = 0; - rc = agent_istrusted (ctrl, fpr); + rc = agent_istrusted (ctrl, fpr, NULL); if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) return rc; else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF ) Modified: trunk/agent/trustlist.c =================================================================== --- trunk/agent/trustlist.c 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/agent/trustlist.c 2009-03-19 10:21:51 UTC (rev 4959) @@ -1,5 +1,5 @@ /* trustlist.c - Maintain the list of trusted keys - * Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2006, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -38,6 +38,7 @@ { struct { + int disabled:1; /* This entry is disabled. */ int for_pgp:1; /* Set by '*' or 'P' as first flag. */ int for_smime:1; /* Set by '*' or 'S' as first flag. */ int relax:1; /* Relax checking of root certificate @@ -59,11 +60,13 @@ static const char headerblurb[] = "# This is the list of trusted keys. Comment lines, like this one, as\n" "# well as empty lines are ignored. Lines have a length limit but this\n" -"# is not serious limitation as the format of the entries is fixed and\n" +"# is not a serious limitation as the format of the entries is fixed and\n" "# checked by gpg-agent. A non-comment line starts with optional white\n" -"# space, followed by the SHA-1 fingerpint in hex, optionally followed\n" -"# by a flag character which my either be 'P', 'S' or '*'. You should\n" -"# give the gpg-agent a HUP after editing this file.\n" +"# space, followed by the SHA-1 fingerpint in hex, followed by a flag\n" +"# which may be one of 'P', 'S' or '*' and optionally followed by a list of\n" +"# other flags. The fingerprint may be prefixed with a '!' to mark the\n" +"# key as not trusted. You should give the gpg-agent a HUP or run the\n" +"# command \"gpgconf --reload gpg-agent\" after changing this file.\n" "\n\n" "# Include the default trust list\n" "include-default\n" @@ -120,7 +123,7 @@ int tableidx; size_t tablesize; int lnr = 0; - + table = *addr_of_table; tablesize = *addr_of_tablesize; tableidx = *addr_of_tableidx; @@ -210,6 +213,15 @@ ti = table + tableidx; + memset (&ti->flags, 0, sizeof ti->flags); + if (*p == '!') + { + ti->flags.disabled = 1; + p++; + while (spacep (p)) + p++; + } + n = hexcolon2bin (p, ti->fpr, 20); if (n < 0) { @@ -221,7 +233,6 @@ for (; spacep (p); p++) ; - memset (&ti->flags, 0, sizeof ti->flags); /* Process the first flag which needs to be the first for backward compatibility. */ if (!*p || *p == '*' ) @@ -366,13 +377,16 @@ /* Check whether the given fpr is in our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. */ gpg_error_t -agent_istrusted (ctrl_t ctrl, const char *fpr) +agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled) { gpg_error_t err; trustitem_t *ti; size_t len; unsigned char fprbin[20]; + if (r_disabled) + *r_disabled = 0; + if ( hexcolon2bin (fpr, fprbin, 20) < 0 ) return gpg_error (GPG_ERR_INV_VALUE); @@ -407,7 +421,13 @@ if (err) return err; } - return 0; /* Trusted. */ + if (ti->flags.disabled) + { + if (r_disabled) + *r_disabled = 1; + return gpg_error (GPG_ERR_NOT_TRUSTED); + } + return 0; /* Trusted. */ } } return gpg_error (GPG_ERR_NOT_TRUSTED); @@ -440,6 +460,8 @@ lock_trusttable (); for (ti=trusttable, len = trusttablesize; len; ti++, len--) { + if (ti->flags.disabled) + continue; bin2hex (ti->fpr, 20, key); key[40] = ' '; key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*' @@ -490,7 +512,7 @@ This function does first check whether that key has already been put into the trustdb and returns success in this case. Before a FPR actually gets inserted, the user is asked by means of the Pinentry - whether this is actual wants he want to do. */ + whether this is actual want he wants to do. */ gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag) { @@ -499,8 +521,9 @@ char *fname; FILE *fp; char *fprformatted; + int is_disabled; + int yes_i_trust; - /* Check whether we are at all allowed to modify the trustlist. This is useful so that the trustlist may be a symlink to a global trustlist with only admin priviliges to modify it. Of course @@ -514,57 +537,29 @@ } xfree (fname); - if (!agent_istrusted (ctrl, fpr)) + if (!agent_istrusted (ctrl, fpr, &is_disabled)) { return 0; /* We already got this fingerprint. Silently return success. */ } - + /* This feature must explicitly been enabled. */ if (!opt.allow_mark_trusted) return gpg_error (GPG_ERR_NOT_SUPPORTED); - /* Insert a new one. */ - fprformatted = insert_colons (fpr); - if (!fprformatted) - return out_of_core (); - desc = xtryasprintf ( - /* TRANSLATORS: This prompt is shown by the Pinentry - and has one special property: A "%%0A" is used by - Pinentry to insert a line break. The double - percent sign is actually needed because it is also - a printf format string. If you need to insert a - plain % sign, you need to encode it as "%%25". The - second "%s" gets replaced by a hexdecimal - fingerprint string whereas the first one receives - the name as stored in the certificate. */ - _("Please verify that the certificate identified as:%%0A" - " \"%s\"%%0A" - "has the fingerprint:%%0A" - " %s"), name, fprformatted); - if (!desc) + if (is_disabled) { - xfree (fprformatted); - return out_of_core (); + /* There is an disabled entry in the trustlist. Return an error + so that the user won't be asked again for that one. Changing + this flag with the integrated marktrusted feature is and will + not be made possible. */ + return gpg_error (GPG_ERR_NOT_TRUSTED); } - /* TRANSLATORS: "Correct" is the label of a button and intended to - be hit if the fingerprint matches the one of the CA. The other - button is "the default "Cancel" of the Pinentry. */ - err = agent_get_confirmation (ctrl, desc, _("Correct"), NULL); - xfree (desc); - /* If the user did not confirmed this, we return cancel here so that - gpgsm may stop asking further questions. We won't do this for - the second question of course. */ - if (err) - { - xfree (fprformatted); - return (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED ? - gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED) : err); - } + /* Insert a new one. */ - + /* First a general question whether this is trusted. */ desc = xtryasprintf ( /* TRANSLATORS: This prompt is shown by the Pinentry and has one special property: A "%%0A" is used by @@ -579,32 +574,77 @@ "to correctly certify user certificates?"), name); if (!desc) - { - xfree (fprformatted); - return out_of_core (); - } - + return out_of_core (); err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No")); xfree (desc); - if (err) + if (!err) + yes_i_trust = 1; + else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED) + yes_i_trust = 0; + else + return err; + + + fprformatted = insert_colons (fpr); + if (!fprformatted) + return out_of_core (); + + /* If the user trusts this certificate he has to verify the + fingerprint of course. */ + if (yes_i_trust) { - xfree (fprformatted); - return err; + desc = xtryasprintf + ( + /* TRANSLATORS: This prompt is shown by the Pinentry and has + one special property: A "%%0A" is used by Pinentry to + insert a line break. The double percent sign is actually + needed because it is also a printf format string. If you + need to insert a plain % sign, you need to encode it as + "%%25". The second "%s" gets replaced by a hexdecimal + fingerprint string whereas the first one receives the name + as stored in the certificate. */ + _("Please verify that the certificate identified as:%%0A" + " \"%s\"%%0A" + "has the fingerprint:%%0A" + " %s"), name, fprformatted); + if (!desc) + { + xfree (fprformatted); + return out_of_core (); + } + + /* TRANSLATORS: "Correct" is the label of a button and intended + to be hit if the fingerprint matches the one of the CA. The + other button is "the default "Cancel" of the Pinentry. */ + err = agent_get_confirmation (ctrl, desc, _("Correct"), _("Wrong")); + xfree (desc); + if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED) + yes_i_trust = 0; + else if (err) + { + xfree (fprformatted); + return err; + } } + /* Now check again to avoid duplicates. We take the lock to make sure that nobody else plays with our file. Frankly we don't work with the trusttable but using this lock is just fine for our purpose. */ lock_trusttable (); - if (!agent_istrusted (ctrl, fpr)) - { - unlock_trusttable (); - xfree (fprformatted); - return 0; - } + { + int now_disabled; + if (!agent_istrusted (ctrl, fpr, &now_disabled) || now_disabled) + { + unlock_trusttable (); + xfree (fprformatted); + return now_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0; + } + } + fname = make_filename (opt.homedir, "trustlist.txt", NULL); if ( access (fname, F_OK) && errno == ENOENT) { @@ -635,7 +675,7 @@ /* Append the key. */ fputs ("\n# ", fp); print_sanitized_string (fp, name, 0); - fprintf (fp, "\n%s %c\n", fprformatted, flag); + fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag); if (ferror (fp)) err = gpg_error_from_syserror (); Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2009-03-19 07:09:31 UTC (rev 4958) +++ trunk/doc/gpg-agent.texi 2009-03-19 10:21:51 UTC (rev 4959) @@ -520,9 +520,11 @@ you need to enter its fingerprint followed by a space and a capital letter @code{S}. Colons may optionally be used to separate the bytes of a fingerprint; this allows to cut and paste the fingerprint from a key - listing output. + listing output. If the line is prefixed with a @code{!} the key is + explicitly marked as not trusted. - Here is an example where two keys are marked as ultimately trusted: + Here is an example where two keys are marked as ultimately trusted + and one as not trusted: @example # CN=Wurzel ZS 3,O=Intevation GmbH,C=DE @@ -530,6 +532,9 @@ # CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S + + # CN=Root-CA/O=Schlapphuete/L=Pullach/C=DE + !14:56:98:D3:FE:9C:CA:5A:31:6E:BC:81:D3:11:4E:00:90:A3:44:C2 S @end example Before entering a key into this file, you need to ensure its From cvs at cvs.gnupg.org Thu Mar 19 12:19:48 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 19 Mar 2009 12:19:48 +0100 Subject: [svn] GnuPG - r4960 - trunk/common Message-ID: Author: wk Date: 2009-03-19 12:19:48 +0100 (Thu, 19 Mar 2009) New Revision: 4960 Added: trunk/common/t-exechelp.c Log: Add missing file. From cvs at cvs.gnupg.org Fri Mar 20 20:04:48 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 20 Mar 2009 20:04:48 +0100 Subject: [svn] GnuPG - r4961 - in trunk: agent doc scd sm Message-ID: Author: wk Date: 2009-03-20 20:04:47 +0100 (Fri, 20 Mar 2009) New Revision: 4961 Modified: trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/learncard.c trunk/doc/DETAILS trunk/scd/ChangeLog trunk/scd/app-nks.c trunk/sm/ChangeLog trunk/sm/call-agent.c trunk/sm/keylist.c Log: Fix keygrip computation for TCOS 3 cards. Emit PROGRESS status lines during --learn-card. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/agent/ChangeLog 2009-03-20 19:04:47 UTC (rev 4961) @@ -1,3 +1,12 @@ +2009-03-20 Werner Koch + + * learncard.c (struct kpinfo_cp_parm_s): Add field CTRL. + (struct certinfo_cb_parm_s): Ditto. + (agent_handle_learn): Set CTRL field. + (kpinfo_cb, certinfo_cb): Send progress status. + + * agent.h (agent_write_status): Flag with GNUPG_GCC_A_SENTINEL. + 2009-03-19 Werner Koch * trustlist.c (struct trustitem_s): Add field DISABLED. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/scd/ChangeLog 2009-03-20 19:04:47 UTC (rev 4961) @@ -1,3 +1,7 @@ +2009-03-20 Werner Koch + + * app-nks.c (keygripstr_from_pk_file): Fix for TCOS 3 cards. + 2009-03-18 Werner Koch * apdu.c (open_pcsc_reader_wrapped): Use close_all_fds. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/sm/ChangeLog 2009-03-20 19:04:47 UTC (rev 4961) @@ -1,3 +1,11 @@ +2009-03-20 Werner Koch + + * keylist.c (list_internal_keys): Set released cert to NULL. + + * call-agent.c (learn_status_cb): New. + (gpgsm_agent_learn): Use it. + (learn_cb): Send a progress for every certificate. + 2009-03-18 Werner Koch * gpgsm.h (struct opt): Move field WITH_EPHEMERAL_KEYS to struct Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/agent/agent.h 2009-03-20 19:04:47 UTC (rev 4961) @@ -212,7 +212,8 @@ /*-- command.c --*/ gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid); -gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...); +gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...) + GNUPG_GCC_A_SENTINEL(0); void bump_key_eventcounter (void); void bump_card_eventcounter (void); void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t); Modified: trunk/agent/learncard.c =================================================================== --- trunk/agent/learncard.c 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/agent/learncard.c 2009-03-20 19:04:47 UTC (rev 4961) @@ -1,5 +1,5 @@ /* learncard.c - Handle the LEARN command - * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -32,7 +32,8 @@ /* Structures used by the callback mechanism to convey information pertaining to key pairs. */ -struct keypair_info_s { +struct keypair_info_s +{ struct keypair_info_s *next; int no_cert; char *id; /* points into grip */ @@ -43,13 +44,14 @@ }; typedef struct keypair_info_s *KEYPAIR_INFO; -struct kpinfo_cb_parm_s { +struct kpinfo_cb_parm_s +{ + ctrl_t ctrl; int error; KEYPAIR_INFO info; }; - /* Structures used by the callback mechanism to convey information pertaining to certificates. */ struct certinfo_s { @@ -60,7 +62,9 @@ }; typedef struct certinfo_s *CERTINFO; -struct certinfo_cb_parm_s { +struct certinfo_cb_parm_s +{ + ctrl_t ctrl; int error; CERTINFO info; }; @@ -130,6 +134,11 @@ if (parm->error) return; /* no need to gather data after an error coccured */ + + if ((parm->error = agent_write_status (parm->ctrl, "PROGRESS", + "learncard", "k", "0", "0", NULL))) + return; + item = xtrycalloc (1, sizeof *item + strlen (line)); if (!item) { @@ -183,6 +192,10 @@ if (parm->error) return; /* no need to gather data after an error coccured */ + if ((parm->error = agent_write_status (parm->ctrl, "PROGRESS", + "learncard", "c", "0", "0", NULL))) + return; + type = strtol (line, &p, 10); while (spacep (p)) p++; @@ -296,6 +309,8 @@ memset (&parm, 0, sizeof parm); memset (&cparm, 0, sizeof cparm); memset (&sparm, 0, sizeof sparm); + parm.ctrl = ctrl; + cparm.ctrl = ctrl; /* Check whether a card is present and get the serial number */ rc = agent_card_serialno (ctrl, &serialno); Modified: trunk/doc/DETAILS =================================================================== --- trunk/doc/DETAILS 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/doc/DETAILS 2009-03-20 19:04:47 UTC (rev 4961) @@ -518,7 +518,8 @@ still working. "starting_agent" - A gpg-agent was started because it is not running as a daemon. - + "learncard" Send by the agent and gpgsm while learing + the data of a smartcard. SIG_CREATED A signature has been created using these parameters. Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/scd/app-nks.c 2009-03-20 19:04:47 UTC (rev 4961) @@ -124,7 +124,8 @@ size_t buflen[2]; gcry_sexp_t sexp; int i; - + int offset[2] = { 0, 0 }; + err = iso7816_select_file (app->slot, fid, 0, NULL, NULL); if (err) return err; @@ -137,7 +138,7 @@ xfree (buffer[0]); return err; } - + if (app->app_local->nks_version < 3) { /* Old versions of NKS store the values in a TLV encoded format. @@ -152,14 +153,55 @@ err = gpg_error (GPG_ERR_TOO_SHORT); else if (buffer[i][1] != buflen[i]-2 ) err = gpg_error (GPG_ERR_INV_OBJ); + else + offset[i] = 2; } } + else + { + /* Remove leading zeroes to get a correct keygrip. Take care of + negative numbers. We should also fix it the same way in + libgcrypt but we can't yet rely on it yet. */ + for (i=0; i < 2; i++) + { + while (buflen[i]-offset[i] > 1 + && !buffer[i][offset[i]] + && !(buffer[i][offset[i]+1] & 0x80)) + offset[i]++; + } + } + /* Check whether negative values are not prefixed with a zero and + fix that. */ + for (i=0; i < 2; i++) + { + if ((buflen[i]-offset[i]) && (buffer[i][offset[i]] & 0x80)) + { + unsigned char *newbuf; + size_t newlen; + + newlen = 1 + buflen[i] - offset[i]; + newbuf = xtrymalloc (newlen); + if (!newlen) + { + xfree (buffer[0]); + xfree (buffer[1]); + return gpg_error_from_syserror (); + } + newbuf[0] = 0; + memcpy (newbuf+1, buffer[i]+offset[i], buflen[i] - offset[i]); + xfree (buffer[i]); + buffer[i] = newbuf; + buflen[i] = newlen; + offset[i] = 0; + } + } + if (!err) err = gcry_sexp_build (&sexp, NULL, "(public-key (rsa (n %b) (e %b)))", - (int)buflen[0]-2, buffer[0]+2, - (int)buflen[1]-2, buffer[1]+2); + (int)buflen[0]-offset[0], buffer[0]+offset[0], + (int)buflen[1]-offset[1], buffer[1]+offset[1]); xfree (buffer[0]); xfree (buffer[1]); Modified: trunk/sm/call-agent.c =================================================================== --- trunk/sm/call-agent.c 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/sm/call-agent.c 2009-03-20 19:04:47 UTC (rev 4961) @@ -668,6 +668,25 @@ static int +learn_status_cb (void *opaque, const char *line) +{ + struct learn_parm_s *parm = opaque; + + /* Pass progress data to the caller. */ + if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) + { + if (parm->ctrl) + { + for (line += 8; *line == ' '; line++) + ; + if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) + return gpg_error (GPG_ERR_ASS_CANCELED); + } + } + return 0; +} + +static int learn_cb (void *opaque, const void *buffer, size_t length) { struct learn_parm_s *parm = opaque; @@ -692,6 +711,8 @@ return 0; } + if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, "learncard C 0 0")) + return gpg_error (GPG_ERR_ASS_CANCELED); /* FIXME: this should go into import.c */ rc = ksba_cert_new (&cert); @@ -755,7 +776,8 @@ learn_parm.data = &data; rc = assuan_transact (agent_ctx, "LEARN --send", learn_cb, &learn_parm, - NULL, NULL, NULL, NULL); + NULL, NULL, + learn_status_cb, &learn_parm); xfree (get_membuf (&data, &len)); if (rc) return rc; Modified: trunk/sm/keylist.c =================================================================== --- trunk/sm/keylist.c 2009-03-19 11:19:48 UTC (rev 4960) +++ trunk/sm/keylist.c 2009-03-20 19:04:47 UTC (rev 4961) @@ -1391,6 +1391,7 @@ if (gpgsm_certs_identical_p (cert, lastcert)) { ksba_cert_release (cert); + cert = NULL; continue; } From cvs at cvs.gnupg.org Fri Mar 20 21:33:15 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Fri, 20 Mar 2009 21:33:15 +0100 Subject: [svn] GnuPG - r4962 - branches/STABLE-BRANCH-1-4/util Message-ID: Author: dshaw Date: 2009-03-20 21:33:14 +0100 (Fri, 20 Mar 2009) New Revision: 4962 Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog branches/STABLE-BRANCH-1-4/util/iobuf.c Log: * iobuf.c (fd_cache_synchronize): New. fsync() a file in cache. (iobuf_ioctl): Called here, for ioctl 4. (fd_cache_invalidate): Pass return code from close() back to iobuf_ioctl(). Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-20 19:04:47 UTC (rev 4961) +++ branches/STABLE-BRANCH-1-4/util/ChangeLog 2009-03-20 20:33:14 UTC (rev 4962) @@ -1,3 +1,10 @@ +2009-03-20 David Shaw + + * iobuf.c (fd_cache_synchronize): New. fsync() a file in cache. + (iobuf_ioctl): Called here, for ioctl 4. + (fd_cache_invalidate): Pass return code from close() back to + iobuf_ioctl(). + 2009-03-13 David Shaw * http.c (do_parse_uri): Properly handle IPv6 literal addresses as Modified: branches/STABLE-BRANCH-1-4/util/iobuf.c =================================================================== --- branches/STABLE-BRANCH-1-4/util/iobuf.c 2009-03-20 19:04:47 UTC (rev 4961) +++ branches/STABLE-BRANCH-1-4/util/iobuf.c 2009-03-20 20:33:14 UTC (rev 4962) @@ -1,6 +1,6 @@ /* iobuf.c - file handling - * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004, 2008 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2008, + * 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -162,10 +162,11 @@ * Invalidate (i.e. close) a cached iobuf or all iobufs if NULL is * used for FNAME. */ -static void +static int fd_cache_invalidate (const char *fname) { CLOSE_CACHE cc; + int err=0; if (!fname) { if( DBG_IOBUF ) @@ -181,7 +182,7 @@ cc->fp = INVALID_FP; } } - return; + return err; } if( DBG_IOBUF ) @@ -192,17 +193,44 @@ if( DBG_IOBUF ) log_debug (" did (%s)\n", cc->fname); #ifdef HAVE_DOSISH_SYSTEM - CloseHandle (cc->fp); + if(CloseHandle (cc->fp)==0) + err=-1; #else - close(cc->fp); + err=close(cc->fp); #endif cc->fp = INVALID_FP; } } + + return err; } +static int +fd_cache_synchronize(const char *fname) +{ + int err=0; +#ifndef HAVE_DOSISH_SYSTEM + CLOSE_CACHE cc; + if( DBG_IOBUF ) + log_debug ("fd_cache_synchronize (%s)\n", fname); + + for (cc=close_cache; cc; cc = cc->next ) + { + if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) + { + if( DBG_IOBUF ) + log_debug (" did (%s)\n", cc->fname); + + err=fsync(cc->fp); + } + } +#endif + + return err; +} + static FILEP_OR_FD direct_open (const char *fname, const char *mode) { @@ -1298,10 +1326,10 @@ ptrval? (char*)ptrval:"[all]"); if ( !a && !intval ) { #ifndef FILE_FILTER_USES_STDIO - fd_cache_invalidate (ptrval); + return fd_cache_invalidate (ptrval); #endif return 0; - } + } } else if ( cmd == 3 ) { /* disallow/allow caching */ if( DBG_IOBUF ) @@ -1322,7 +1350,24 @@ } #endif } + else if(cmd==4) + { + /* Do a fsync on the open fd and return any errors to the + caller of iobuf_ioctl */ + if( DBG_IOBUF ) + log_debug("iobuf-*.*: ioctl `%s' fsync\n", + ptrval? (char*)ptrval:""); + if(!a && !intval && ptrval) + { +#ifndef FILE_FILTER_USES_STDIO + return fd_cache_synchronize (ptrval); +#else + return 0; +#endif + } + } + return -1; } From cvs at cvs.gnupg.org Fri Mar 20 21:55:47 2009 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Fri, 20 Mar 2009 21:55:47 +0100 Subject: [svn] GnuPG - r4963 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2009-03-20 21:55:47 +0100 (Fri, 20 Mar 2009) New Revision: 4963 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/keyring.c Log: * keyring.c (rename_tmp_file): Force a fsync (via iobuf_ioctl) on secret keyring files to be extra safe on filesystems that may not sync data and metadata together (ext4). Also check return code from the cache invalidation to make sure we're safe over NFS and similar. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2009-03-20 20:33:14 UTC (rev 4962) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2009-03-20 20:55:47 UTC (rev 4963) @@ -1,3 +1,11 @@ +2009-03-20 David Shaw + + * keyring.c (rename_tmp_file): Force a fsync (via iobuf_ioctl) on + secret keyring files to be extra safe on filesystems that may not + sync data and metadata together (ext4). Also check return code + from the cache invalidation to make sure we're safe over NFS and + similar. + 2009-03-14 David Shaw * gpgv.c (strusage): Fix name of program in "Syntax" line. Modified: branches/STABLE-BRANCH-1-4/g10/keyring.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/keyring.c 2009-03-20 20:33:14 UTC (rev 4962) +++ branches/STABLE-BRANCH-1-4/g10/keyring.c 2009-03-20 20:55:47 UTC (rev 4963) @@ -1,5 +1,5 @@ /* keyring.c - keyring file handling - * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2004, 2007, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1212,10 +1212,17 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, const char *fname, int secret ) { - int rc=0; + int rc=G10ERR_GENERAL; + /* It's a secret keyring, so let's force a fsync just to be safe on + filesystems that may not sync data and metadata together + (ext4). */ + if(secret && iobuf_ioctl(NULL,4,0,(char*)tmpfname)!=0) + goto fail; + /* invalidate close caches*/ - iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); + if(iobuf_ioctl (NULL, 2, 0, (char*)tmpfname )!=0) + goto fail; iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); iobuf_ioctl (NULL, 2, 0, (char*)fname ); @@ -1245,15 +1252,7 @@ tmpfname, fname, strerror(errno) ); register_secured_file (fname); rc = G10ERR_RENAME_FILE; - if (secret) - { - log_info(_("WARNING: 2 files with confidential" - " information exists.\n")); - log_info(_("%s is the unchanged one\n"), fname ); - log_info(_("%s is the new one\n"), tmpfname ); - log_info(_("Please fix this possible security flaw\n")); - } - return rc; + goto fail; } /* Now make sure the file has the same permissions as the original */ @@ -1275,6 +1274,17 @@ #endif return 0; + + fail: + if(secret) + { + log_info(_("WARNING: 2 files with confidential information exists.\n")); + log_info(_("%s is the unchanged one\n"), fname ); + log_info(_("%s is the new one\n"), tmpfname ); + log_info(_("Please fix this possible security flaw\n")); + } + + return rc; } From cvs at cvs.gnupg.org Mon Mar 23 17:17:49 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 23 Mar 2009 17:17:49 +0100 Subject: [svn] GnuPG - r4964 - trunk/sm Message-ID: Author: wk Date: 2009-03-23 17:17:49 +0100 (Mon, 23 Mar 2009) New Revision: 4964 Modified: trunk/sm/ChangeLog trunk/sm/delete.c Log: Allow deletion of ephemeral keys. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-20 20:55:47 UTC (rev 4963) +++ trunk/sm/ChangeLog 2009-03-23 16:17:49 UTC (rev 4964) @@ -1,3 +1,8 @@ +2009-03-23 Werner Koch + + * delete.c (delete_one): Also delete ephemeral certificates if + specified uniquely. + 2009-03-20 Werner Koch * keylist.c (list_internal_keys): Set released cert to NULL. Modified: trunk/sm/delete.c =================================================================== --- trunk/sm/delete.c 2009-03-20 20:55:47 UTC (rev 4963) +++ trunk/sm/delete.c 2009-03-23 16:17:49 UTC (rev 4964) @@ -1,5 +1,5 @@ -/* delete.c - * Copyright (C) 2002 Free Software Foundation, Inc. +/* delete.c - Delete certificates from the keybox. + * Copyright (C) 2002, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -43,6 +43,7 @@ KEYDB_HANDLE kh = NULL; ksba_cert_t cert = NULL; int duplicates = 0; + int is_ephem = 0; rc = keydb_classify_name (username, &desc); if (rc) @@ -60,11 +61,21 @@ goto leave; } - + /* If the key is specified in a unique way, include ephemeral keys + in the search. */ + if ( desc.mode == KEYDB_SEARCH_MODE_FPR + || desc.mode == KEYDB_SEARCH_MODE_FPR20 + || desc.mode == KEYDB_SEARCH_MODE_FPR16 + || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP ) + { + is_ephem = 1; + keydb_set_ephemeral (kh, 1); + } + rc = keydb_search (kh, &desc, 1); if (!rc) rc = keydb_get_cert (kh, &cert); - if (!rc) + if (!rc && !is_ephem) { unsigned char fpr[20]; From cvs at cvs.gnupg.org Mon Mar 23 23:23:26 2009 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 23 Mar 2009 23:23:26 +0100 Subject: [svn] gpgme - r1361 - trunk/assuan Message-ID: Author: marcus Date: 2009-03-23 23:23:25 +0100 (Mon, 23 Mar 2009) New Revision: 1361 Modified: trunk/assuan/ChangeLog trunk/assuan/assuan.h Log: 2009-03-23 Marcus Brinkmann * assuan.h: Add prefix macros for _assuan_close and _assuan_usleep. Modified: trunk/assuan/ChangeLog =================================================================== --- trunk/assuan/ChangeLog 2009-03-18 11:19:29 UTC (rev 1360) +++ trunk/assuan/ChangeLog 2009-03-23 22:23:25 UTC (rev 1361) @@ -1,3 +1,7 @@ +2009-03-23 Marcus Brinkmann + + * assuan.h: Add prefix macros for _assuan_close and _assuan_usleep. + 2009-02-24 Werner Koch * assuan-buffer.c (assuan_send_data): Add hack to optionally send Modified: trunk/assuan/assuan.h =================================================================== --- trunk/assuan/assuan.h 2009-03-18 11:19:29 UTC (rev 1360) +++ trunk/assuan/assuan.h 2009-03-23 22:23:25 UTC (rev 1361) @@ -224,6 +224,8 @@ #define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) #define _assuan_sock_get_nonce _ASSUAN_PREFIX(_assuan_sock_get_nonce) #define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce) +#define _assuan_close _ASSUAN_PREFIX(_assuan_close) +#define _assuan_usleep _ASSUAN_PREFIX(_assuan_usleep) #endif /*_ASSUAN_EXT_SYM_PREFIX*/ From cvs at cvs.gnupg.org Tue Mar 24 12:40:57 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 24 Mar 2009 12:40:57 +0100 Subject: [svn] GnuPG - r4965 - in trunk: . scd Message-ID: Author: wk Date: 2009-03-24 12:40:57 +0100 (Tue, 24 Mar 2009) New Revision: 4965 Modified: trunk/NEWS trunk/scd/ChangeLog trunk/scd/app-common.h trunk/scd/app.c trunk/scd/command.c Log: Better syncronization of several smartcard sessions. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-23 16:17:49 UTC (rev 4964) +++ trunk/scd/ChangeLog 2009-03-24 11:40:57 UTC (rev 4965) @@ -1,3 +1,14 @@ +2009-03-24 Werner Koch + + * command.c (struct server_local_s): Add flag + APP_CTX_MARKED_FOR_RELEASE. + (do_reset): Set the flag. + (open_card): Act on this flag. + * app-common.h (struct app_ctx_s): Add flag NO_REUSE. + (application_notify_card_reset): Set the flag. + * app.c (select_application, release_application): Take care of + that flag. + 2009-03-20 Werner Koch * app-nks.c (keygripstr_from_pk_file): Fix for TCOS 3 cards. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-23 16:17:49 UTC (rev 4964) +++ trunk/NEWS 2009-03-24 11:40:57 UTC (rev 4965) @@ -13,7 +13,9 @@ * Changed order of the confirmation questions for root certificates and stores negative answers in trustlist.txt. + * Better synchronization of several smartcard sessions. + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/scd/app-common.h =================================================================== --- trunk/scd/app-common.h 2009-03-23 16:17:49 UTC (rev 4964) +++ trunk/scd/app-common.h 2009-03-24 11:40:57 UTC (rev 4965) @@ -38,16 +38,20 @@ struct app_local_s; /* Defined by all app-*.c. */ struct app_ctx_s { - unsigned int ref_count; /* Number of connections currently using - this application context. If this is - not 0 the application has been - initialized and the function pointers - may be used. Note that for unsupported - operations the particular function - pointer is set to NULL */ + /* Number of connections currently using this application context. + If this is not 0 the application has been initialized and the + function pointers may be used. Note that for unsupported + operations the particular function pointer is set to NULL */ + unsigned int ref_count; - int slot; /* Used reader. */ + /* Flag indicating that a reset has been done for that application + and that this context is merely lingering and just should not be + reused. */ + int no_reuse; + /* Used reader slot. */ + int slot; + /* If this is used by GnuPG 1.4 we need to know the assuan context in case we need to divert the operation to an already running agent. This if ASSUAN_CTX is not NULL we take this as indication Modified: trunk/scd/app.c =================================================================== --- trunk/scd/app.c 2009-03-23 16:17:49 UTC (rev 4964) +++ trunk/scd/app.c 2009-03-24 11:40:57 UTC (rev 4965) @@ -173,6 +173,10 @@ /* FIXME: We are ignoring any error value here. */ lock_reader (slot); + /* Mark application as non-reusable. */ + if (lock_table[slot].app) + lock_table[slot].app->no_reuse = 1; + /* Deallocate a saved application for that slot, so that we won't try to reuse it. If there is no saved application, set a flag so that we won't save the current state. */ @@ -241,6 +245,16 @@ return gpg_error (GPG_ERR_CONFLICT); } + /* Don't use a non-reusable marked application. */ + if (app && app->no_reuse) + { + unlock_reader (slot); + log_info ("lingering application `%s' in use by reader %d" + " - can't switch\n", + app->apptype? app->apptype:"?", slot); + return gpg_error (GPG_ERR_CONFLICT); + } + /* If we don't have an app, check whether we have a saved application for that slot. This is useful so that a card does not get reset even if only one session is using the card - this @@ -278,7 +292,7 @@ unlock_reader (slot); return 0; /* Okay: We share that one. */ } - + /* Need to allocate a new one. */ app = xtrycalloc (1, sizeof *app); if (!app) @@ -458,7 +472,15 @@ if (lock_table[slot].last_app) deallocate_app (lock_table[slot].last_app); - lock_table[slot].last_app = lock_table[slot].app; + if (app->no_reuse) + { + /* If we shall not re-use the application we can't save it for + later use. */ + deallocate_app (app); + lock_table[slot].last_app = NULL; + } + else + lock_table[slot].last_app = lock_table[slot].app; lock_table[slot].app = NULL; unlock_reader (slot); } Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-23 16:17:49 UTC (rev 4964) +++ trunk/scd/command.c 2009-03-24 11:40:57 UTC (rev 4965) @@ -112,6 +112,10 @@ continue operation. */ int card_removed; + /* Flag indicating that the application context needs to be released + at the next opportunity. */ + int app_ctx_marked_for_release; + /* A disconnect command has been sent. */ int disconnect_allowed; @@ -165,7 +169,7 @@ /* Update the CARD_REMOVED element of all sessions using the reader - given by SLOT to VALUE */ + given by SLOT to VALUE. */ static void update_card_removed (int slot, int value) { @@ -274,11 +278,24 @@ if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table)))) BUG (); - /* If there is an active application, release it. */ + /* If there is an active application, release it. Tell all other + sessions using the same application to release the + application. */ if (ctrl->app_ctx) { release_application (ctrl->app_ctx); ctrl->app_ctx = NULL; + if (send_reset) + { + struct server_local_s *sl; + + for (sl=session_list; sl; sl = sl->next_session) + if (sl->ctrl_backlink + && sl->ctrl_backlink->reader_slot == slot) + { + sl->app_ctx_marked_for_release = 1; + } + } } /* If we want a real reset for the card, send the reset APDU and @@ -397,14 +414,23 @@ if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); - if (ctrl->app_ctx) + /* If the application has been marked for release do it now. We + can't do it immediately in do_reset because the application may + still be in use. */ + if (ctrl->server_local->app_ctx_marked_for_release) { - /* Already initialized for one specific application. Need to - check that the client didn't requested a specific application - different from the one in use. */ - return check_application_conflict (ctrl, apptype); + ctrl->server_local->app_ctx_marked_for_release = 0; + release_application (ctrl->app_ctx); + ctrl->app_ctx = NULL; } + /* If we are already initialized for one specific application we + need to check that the client didn't requested a specific + application different from the one in use before we continue. */ + if (ctrl->app_ctx) + return check_application_conflict (ctrl, apptype); + + /* Setup the slot and select the application. */ if (ctrl->reader_slot != -1) slot = ctrl->reader_slot; else From cvs at cvs.gnupg.org Tue Mar 24 19:52:28 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 24 Mar 2009 19:52:28 +0100 Subject: [svn] GnuPG - r4966 - in trunk: . po Message-ID: Author: wk Date: 2009-03-24 19:52:24 +0100 (Tue, 24 Mar 2009) New Revision: 4966 Modified: trunk/NEWS trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.po trunk/po/de.po trunk/po/el.po trunk/po/eo.po trunk/po/es.po trunk/po/et.po trunk/po/fi.po trunk/po/fr.po trunk/po/gl.po trunk/po/hu.po trunk/po/id.po trunk/po/it.po trunk/po/ja.po trunk/po/nb.po trunk/po/pl.po trunk/po/pt.po trunk/po/pt_BR.po trunk/po/ro.po trunk/po/ru.po trunk/po/sk.po trunk/po/sv.po trunk/po/tr.po trunk/po/zh_CN.po trunk/po/zh_TW.po Log: Preparing a snapshot. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-24 11:40:57 UTC (rev 4965) +++ trunk/NEWS 2009-03-24 18:52:24 UTC (rev 4966) @@ -1,6 +1,8 @@ -Noteworthy changes in version 2.0.12 +Noteworthy changes in version 2.0.12 (not released) ------------------------------------------------- + This is a BETA version! + * GPGSM now always lists ephemeral certificates if specified by fingerprint or keygrip. Modified: trunk/po/be.po [not shown] Modified: trunk/po/ca.po [not shown] Modified: trunk/po/cs.po [not shown] Modified: trunk/po/da.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/el.po [not shown] Modified: trunk/po/eo.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/et.po [not shown] Modified: trunk/po/fi.po [not shown] Modified: trunk/po/fr.po [not shown] Modified: trunk/po/gl.po [not shown] Modified: trunk/po/hu.po [not shown] Modified: trunk/po/id.po [not shown] Modified: trunk/po/it.po [not shown] Modified: trunk/po/ja.po [not shown] Modified: trunk/po/nb.po [not shown] Modified: trunk/po/pl.po [not shown] Modified: trunk/po/pt.po [not shown] Modified: trunk/po/pt_BR.po [not shown] Modified: trunk/po/ro.po [not shown] Modified: trunk/po/ru.po [not shown] Modified: trunk/po/sk.po [not shown] Modified: trunk/po/sv.po [not shown] Modified: trunk/po/tr.po [not shown] Modified: trunk/po/zh_CN.po [not shown] Modified: trunk/po/zh_TW.po [not shown] From cvs at cvs.gnupg.org Tue Mar 24 21:03:06 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 24 Mar 2009 21:03:06 +0100 Subject: [svn] GpgEX - r66 - trunk Message-ID: Author: wk Date: 2009-03-24 21:03:06 +0100 (Tue, 24 Mar 2009) New Revision: 66 Modified: trunk/NEWS trunk/configure.ac Log: Release preparation. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-10 16:35:35 UTC (rev 65) +++ trunk/NEWS 2009-03-24 20:03:06 UTC (rev 66) @@ -1,3 +1,9 @@ +Noteworthy changes for version 0.9.3 (2009-03-24) +------------------------------------------------- + +* Fixed build problems with newer WINDRES. + + Noteworthy changes for version 0.9.2 (2009-01-28) ------------------------------------------------- Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-03-10 16:35:35 UTC (rev 65) +++ trunk/configure.ac 2009-03-24 20:03:06 UTC (rev 66) @@ -16,7 +16,7 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [0.9.2]) +m4_define([my_version], [0.9.3]) m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ From cvs at cvs.gnupg.org Tue Mar 24 21:06:52 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 24 Mar 2009 21:06:52 +0100 Subject: [svn] GpgEX - r67 - tags Message-ID: Author: wk Date: 2009-03-24 21:06:52 +0100 (Tue, 24 Mar 2009) New Revision: 67 Added: tags/gpgex-0.9.3/ Log: release! From cvs at cvs.gnupg.org Tue Mar 24 21:10:00 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 24 Mar 2009 21:10:00 +0100 Subject: [svn] GpgEX - r68 - in trunk: . po Message-ID: Author: wk Date: 2009-03-24 21:10:00 +0100 (Tue, 24 Mar 2009) New Revision: 68 Modified: trunk/ChangeLog trunk/NEWS trunk/configure.ac trunk/po/ar.po trunk/po/de.po trunk/po/es.po trunk/po/ru.po Log: Post release updates Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-03-24 20:06:52 UTC (rev 67) +++ trunk/ChangeLog 2009-03-24 20:10:00 UTC (rev 68) @@ -1,3 +1,7 @@ +2009-03-24 Werner Koch + + Release 0.9.3. + 2009-03-10 Marcus Brinkmann * po/de.po, po/es.po, po/ru.po, po/ar.po: Change encrypt&sign to Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-24 20:06:52 UTC (rev 67) +++ trunk/NEWS 2009-03-24 20:10:00 UTC (rev 68) @@ -1,3 +1,7 @@ +Noteworthy changes for version 0.9.4 +------------------------------------------------- + + Noteworthy changes for version 0.9.3 (2009-03-24) ------------------------------------------------- Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-03-24 20:06:52 UTC (rev 67) +++ trunk/configure.ac 2009-03-24 20:10:00 UTC (rev 68) @@ -16,8 +16,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [0.9.3]) -m4_define([my_issvn], [no]) +m4_define([my_version], [0.9.4]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) Modified: trunk/po/ar.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/ru.po [not shown] From cvs at cvs.gnupg.org Wed Mar 25 15:58:36 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 25 Mar 2009 15:58:36 +0100 Subject: [svn] GnuPG - r4967 - in trunk: agent jnlib po Message-ID: Author: wk Date: 2009-03-25 15:58:31 +0100 (Wed, 25 Mar 2009) New Revision: 4967 Modified: trunk/agent/ChangeLog trunk/agent/gpg-agent.c trunk/jnlib/ChangeLog trunk/jnlib/logging.c trunk/jnlib/t-support.c trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.po trunk/po/de.po trunk/po/el.po trunk/po/eo.po trunk/po/es.po trunk/po/et.po trunk/po/fi.po trunk/po/fr.po trunk/po/gl.po trunk/po/hu.po trunk/po/id.po trunk/po/it.po trunk/po/ja.po trunk/po/nb.po trunk/po/pl.po trunk/po/pt.po trunk/po/pt_BR.po trunk/po/ro.po trunk/po/ru.po trunk/po/sk.po trunk/po/sv.po trunk/po/tr.po trunk/po/zh_CN.po trunk/po/zh_TW.po Log: log file fixes. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-24 18:52:24 UTC (rev 4966) +++ trunk/agent/ChangeLog 2009-03-25 14:58:31 UTC (rev 4967) @@ -1,3 +1,7 @@ +2009-03-25 Werner Koch + + * gpg-agent.c (main): Print a started message to show the real pid. + 2009-03-20 Werner Koch * learncard.c (struct kpinfo_cp_parm_s): Add field CTRL. Modified: trunk/jnlib/ChangeLog =================================================================== --- trunk/jnlib/ChangeLog 2009-03-24 18:52:24 UTC (rev 4966) +++ trunk/jnlib/ChangeLog 2009-03-25 14:58:31 UTC (rev 4967) @@ -1,3 +1,8 @@ +2009-03-25 Werner Koch + + * logging.c (fun_closer): Never close fd 2. + (set_file_fd): Close logstream early. + 2009-02-25 Werner Koch * logging.c (get_tid_callback): New. Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2009-03-24 18:52:24 UTC (rev 4966) +++ trunk/agent/gpg-agent.c 2009-03-25 14:58:31 UTC (rev 4967) @@ -467,6 +467,7 @@ || strcmp (current_logfile, pargs->r.ret_str)) { log_set_file (pargs->r.ret_str); + assuan_set_assuan_log_stream (log_get_stream ()); xfree (current_logfile); current_logfile = xtrystrdup (pargs->r.ret_str); } @@ -980,9 +981,10 @@ else if (pid) { /* We are the parent */ char *infostr, *infostr_ssh_sock, *infostr_ssh_pid; - + + /* Close the socket FD. */ close (fd); - + /* Note that we used a standard fork so that Pth runs in both the parent and the child. The pth_fork would terminate Pth in the child but that is not the way we @@ -1184,6 +1186,7 @@ } #endif /*!HAVE_W32_SYSTEM*/ + log_info ("%s %s started\n", strusage(11), strusage(13) ); handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); assuan_sock_close (fd); } Modified: trunk/jnlib/logging.c =================================================================== --- trunk/jnlib/logging.c 2009-03-24 18:52:24 UTC (rev 4966) +++ trunk/jnlib/logging.c 2009-03-25 14:58:31 UTC (rev 4967) @@ -218,7 +218,7 @@ { struct fun_cookie_s *cookie = cookie_arg; - if (cookie->fd != -1) + if (cookie->fd != -1 && cookie->fd != 2) close (cookie->fd); jnlib_free (cookie); log_socket = -1; @@ -239,6 +239,15 @@ struct fun_cookie_s *cookie; #endif + /* Close an open log stream. */ + if (logstream) + { + if (logstream != stderr && logstream != stdout) + fclose (logstream); + logstream = NULL; + } + + /* Figure out what kind of logging we want. */ if (name && !strcmp (name, "-")) { name = NULL; @@ -256,6 +265,7 @@ want_socket = 0; } + /* Setup a new stream. */ #ifdef USE_FUNWRITER cookie = jnlib_xmalloc (sizeof *cookie + (name? strlen (name):0)); strcpy (cookie->name, name? name:""); @@ -310,15 +320,7 @@ #endif /*!USE_FUNWRITER*/ - /* On success close the old logstream right now, so that we are - really sure it has been closed. */ - if (fp && logstream) - { - if (logstream != stderr && logstream != stdout) - fclose (logstream); - logstream = NULL; - } - + /* On error default to stderr. */ if (!fp) { if (name) @@ -333,8 +335,6 @@ else setvbuf (fp, NULL, _IOLBF, 0); - if (logstream && logstream != stderr && logstream != stdout) - fclose (logstream); logstream = fp; /* We always need to print the prefix and the pid for socket mode, Modified: trunk/jnlib/t-support.c =================================================================== --- trunk/jnlib/t-support.c 2009-03-24 18:52:24 UTC (rev 4966) +++ trunk/jnlib/t-support.c 2009-03-25 14:58:31 UTC (rev 4967) @@ -120,6 +120,7 @@ int gpg_err_code_from_errno (int err) { + (void)err; assert (!"stub function"); return -1; } Modified: trunk/po/be.po [not shown] Modified: trunk/po/ca.po [not shown] Modified: trunk/po/cs.po [not shown] Modified: trunk/po/da.po [not shown] Modified: trunk/po/de.po [not shown] Modified: trunk/po/el.po [not shown] Modified: trunk/po/eo.po [not shown] Modified: trunk/po/es.po [not shown] Modified: trunk/po/et.po [not shown] Modified: trunk/po/fi.po [not shown] Modified: trunk/po/fr.po [not shown] Modified: trunk/po/gl.po [not shown] Modified: trunk/po/hu.po [not shown] Modified: trunk/po/id.po [not shown] Modified: trunk/po/it.po [not shown] Modified: trunk/po/ja.po [not shown] Modified: trunk/po/nb.po [not shown] Modified: trunk/po/pl.po [not shown] Modified: trunk/po/pt.po [not shown] Modified: trunk/po/pt_BR.po [not shown] Modified: trunk/po/ro.po [not shown] Modified: trunk/po/ru.po [not shown] Modified: trunk/po/sk.po [not shown] Modified: trunk/po/sv.po [not shown] Modified: trunk/po/tr.po [not shown] Modified: trunk/po/zh_CN.po [not shown] Modified: trunk/po/zh_TW.po [not shown] From cvs at cvs.gnupg.org Wed Mar 25 17:05:17 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 25 Mar 2009 17:05:17 +0100 Subject: [svn] GnuPG - r4968 - in trunk: agent doc g10 sm Message-ID: Author: wk Date: 2009-03-25 17:05:16 +0100 (Wed, 25 Mar 2009) New Revision: 4968 Modified: trunk/agent/ChangeLog trunk/agent/pkdecrypt.c trunk/doc/DETAILS trunk/g10/ChangeLog trunk/g10/mainproc.c trunk/sm/ChangeLog trunk/sm/certdump.c trunk/sm/decrypt.c trunk/sm/fingerprint.c trunk/sm/gpgsm.h trunk/sm/keylist.c trunk/sm/verify.c Log: Print NO_SECKEY status line in gpgsm. This fixes bug#1020. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/agent/ChangeLog 2009-03-25 16:05:16 UTC (rev 4968) @@ -1,5 +1,8 @@ 2009-03-25 Werner Koch + * pkdecrypt.c (agent_pkdecrypt): Return a specific error message + if the key is not available. + * gpg-agent.c (main): Print a started message to show the real pid. 2009-03-20 Werner Koch Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/g10/ChangeLog 2009-03-25 16:05:16 UTC (rev 4968) @@ -1,3 +1,7 @@ +2009-03-25 Werner Koch + + * mainproc.c (print_pkenc_list): Use snprintf. + 2009-03-17 Werner Koch * call-agent.c (my_percent_plus_escape): Remove. Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/ChangeLog 2009-03-25 16:05:16 UTC (rev 4968) @@ -1,3 +1,10 @@ +2009-03-25 Werner Koch + + * decrypt.c (gpgsm_decrypt): Print ENC_TO and NO_SECKEY + stati. Fixes bug#1020. + * fingerprint.c (gpgsm_get_short_fingerprint): Add arg R_HIGH and + change all callers. + 2009-03-23 Werner Koch * delete.c (delete_one): Also delete ephemeral certificates if Modified: trunk/agent/pkdecrypt.c =================================================================== --- trunk/agent/pkdecrypt.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/agent/pkdecrypt.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -69,7 +69,10 @@ CACHE_MODE_NORMAL, &s_skey); if (rc) { - log_error ("failed to read the secret key\n"); + if (gpg_err_code (rc) == GPG_ERR_ENOENT) + rc = gpg_error (GPG_ERR_NO_SECKEY); + else + log_error ("failed to read the secret key\n"); goto leave; } Modified: trunk/doc/DETAILS =================================================================== --- trunk/doc/DETAILS 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/doc/DETAILS 2009-03-25 16:05:16 UTC (rev 4968) @@ -309,13 +309,13 @@ since epoch or an ISO 8601 string which can be detected by the presence of the letter 'T' inside. + ENC_TO + The message is encrypted to this LONG_KEYID. KEYTYPE is the + numerical value of the public key algorithm or 0 if it is not + known, KEYLENGTH is the length of the key or 0 if it is not + known (which is currently always the case). Gpg prints this + line always; Gpgsm only if it knows the certificate. - ENC_TO - The message is encrypted to this keyid. - keytype is the numerical value of the public key algorithm, - keylength is the length of the key or 0 if it is not known - (which is currently always the case). - NODATA No data has been found. Codes for what are: 1 - No armored data. Modified: trunk/g10/mainproc.c =================================================================== --- trunk/g10/mainproc.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/g10/mainproc.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -469,8 +469,8 @@ if( list->reason == G10ERR_NO_SECKEY ) { if( is_status_enabled() ) { char buf[20]; - sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], - (ulong)list->kid[1] ); + snprintf (buf, sizeof buf, "%08lX%08lX", + (ulong)list->kid[0], (ulong)list->kid[1]); write_status_text( STATUS_NO_SECKEY, buf ); } } Modified: trunk/sm/certdump.c =================================================================== --- trunk/sm/certdump.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/certdump.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -952,7 +952,7 @@ "created %s, expires %s.\n" ), subject? subject:"?", sn? sn: "?", - gpgsm_get_short_fingerprint (cert), + gpgsm_get_short_fingerprint (cert, NULL), created, expires); i18n_switchback (orig_codeset); Modified: trunk/sm/decrypt.c =================================================================== --- trunk/sm/decrypt.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/decrypt.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -362,7 +362,10 @@ ksba_sexp_t enc_val; char *hexkeygrip = NULL; char *desc = NULL; + char kidbuf[16+1]; + *kidbuf = 0; + rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); if (rc == -1 && recp) break; /* no more recipients */ @@ -394,6 +397,25 @@ log_error ("failed to get cert: %s\n", gpg_strerror (rc)); goto oops; } + + /* Print the ENC_TO status line. Note that we can + do so only if we have the certificate. This is + in contrast to gpg where the keyID is commonly + included in the encrypted messages. It is too + cumbersome to retrieve the used algorithm, thus + we don't print it for now. We also record the + keyid for later use. */ + { + unsigned long kid[2]; + + kid[0] = gpgsm_get_short_fingerprint (cert, kid+1); + snprintf (kidbuf, sizeof kidbuf, "%08lX%08lX", + kid[1], kid[0]); + gpgsm_status2 (ctrl, STATUS_ENC_TO, + kidbuf, "0", "0", NULL); + } + + /* Just in case there is a problem with the own certificate we print this message - should never happen of course */ @@ -430,6 +452,8 @@ { log_info ("decrypting session key failed: %s\n", gpg_strerror (rc)); + if (gpg_err_code (rc) == GPG_ERR_NO_SECKEY && *kidbuf) + gpgsm_status2 (ctrl, STATUS_NO_SECKEY, kidbuf, NULL); } else { /* setup the bulk decrypter */ Modified: trunk/sm/fingerprint.c =================================================================== --- trunk/sm/fingerprint.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/fingerprint.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -140,13 +140,16 @@ } /* Return a certificate ID. These are the last 4 bytes of the SHA-1 - fingerprint. */ + fingerprint. If R_HIGH is not NULL the next 4 bytes are stored + there. */ unsigned long -gpgsm_get_short_fingerprint (ksba_cert_t cert) +gpgsm_get_short_fingerprint (ksba_cert_t cert, unsigned long *r_high) { unsigned char digest[20]; gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); + if (r_high) + *r_high = ((digest[12]<<24)|(digest[13]<<16)|(digest[14]<< 8)|digest[15]); return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]); } Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/gpgsm.h 2009-03-25 16:05:16 UTC (rev 4968) @@ -229,7 +229,7 @@ /*-- server.c --*/ void gpgsm_server (certlist_t default_recplist); gpg_error_t gpgsm_status (ctrl_t ctrl, int no, const char *text); -gpg_error_t gpgsm_status2 (ctrl_t ctrl, int no, ...); +gpg_error_t gpgsm_status2 (ctrl_t ctrl, int no, ...) GNUPG_GCC_A_SENTINEL(0); gpg_error_t gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text, gpg_err_code_t ec); gpg_error_t gpgsm_proxy_pinentry_notify (ctrl_t ctrl, @@ -240,7 +240,8 @@ unsigned char *array, int *r_len); char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo); char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo); -unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert); +unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert, + unsigned long *r_high); unsigned char *gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array); char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert); int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits); Modified: trunk/sm/keylist.c =================================================================== --- trunk/sm/keylist.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/keylist.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -672,7 +672,7 @@ (void)have_secret; es_fprintf (fp, " ID: 0x%08lX\n", - gpgsm_get_short_fingerprint (cert)); + gpgsm_get_short_fingerprint (cert, NULL)); sexp = ksba_cert_get_serial (cert); es_fputs (" S/N: ", fp); @@ -1042,7 +1042,7 @@ (void)have_secret; es_fprintf (fp, " ID: 0x%08lX\n", - gpgsm_get_short_fingerprint (cert)); + gpgsm_get_short_fingerprint (cert, NULL)); sexp = ksba_cert_get_serial (cert); es_fputs (" S/N: ", fp); Modified: trunk/sm/verify.c =================================================================== --- trunk/sm/verify.c 2009-03-25 14:58:31 UTC (rev 4967) +++ trunk/sm/verify.c 2009-03-25 16:05:16 UTC (rev 4968) @@ -450,7 +450,7 @@ else log_printf (_("[date not given]")); log_printf (_(" using certificate ID 0x%08lX\n"), - gpgsm_get_short_fingerprint (cert)); + gpgsm_get_short_fingerprint (cert, NULL)); if (msgdigest) From cvs at cvs.gnupg.org Thu Mar 26 12:33:54 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 26 Mar 2009 12:33:54 +0100 Subject: [svn] GnuPG - r4969 - in trunk: agent sm Message-ID: Author: wk Date: 2009-03-26 12:33:53 +0100 (Thu, 26 Mar 2009) New Revision: 4969 Modified: trunk/agent/ChangeLog trunk/agent/trustlist.c trunk/sm/ChangeLog trunk/sm/call-agent.c Log: Fixed a trustlist update problem. Pretty format the marktrusted pinentry prompt. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-25 16:05:16 UTC (rev 4968) +++ trunk/agent/ChangeLog 2009-03-26 11:33:53 UTC (rev 4969) @@ -1,3 +1,10 @@ +2009-03-26 Werner Koch + + * trustlist.c (reformat_name): New. + (agent_marktrusted): Use a reformatted name. Reload the table + before the update and always reload it at the end. + (agent_istrusted): Check early for the disabled flag. + 2009-03-25 Werner Koch * pkdecrypt.c (agent_pkdecrypt): Return a specific error message Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-25 16:05:16 UTC (rev 4968) +++ trunk/sm/ChangeLog 2009-03-26 11:33:53 UTC (rev 4969) @@ -1,7 +1,11 @@ +2009-03-26 Werner Koch + + * call-agent.c (gpgsm_agent_marktrusted): Format the issuer name. + 2009-03-25 Werner Koch - * decrypt.c (gpgsm_decrypt): Print ENC_TO and NO_SECKEY - stati. Fixes bug#1020. + * decrypt.c (gpgsm_decrypt): Print ENC_TO and NO_SECKEY stati. + Fixes bug#1020. * fingerprint.c (gpgsm_get_short_fingerprint): Add arg R_HIGH and change all callers. Modified: trunk/agent/trustlist.c =================================================================== --- trunk/agent/trustlist.c 2009-03-25 16:05:16 UTC (rev 4968) +++ trunk/agent/trustlist.c 2009-03-26 11:33:53 UTC (rev 4969) @@ -405,6 +405,9 @@ for (ti=trusttable, len = trusttablesize; len; ti++, len--) if (!memcmp (ti->fpr, fprbin, 20)) { + if (ti->flags.disabled && r_disabled) + *r_disabled = 1; + if (ti->flags.relax) { err = agent_write_status (ctrl, @@ -421,13 +424,7 @@ if (err) return err; } - if (ti->flags.disabled) - { - if (r_disabled) - *r_disabled = 1; - return gpg_error (GPG_ERR_NOT_TRUSTED); - } - return 0; /* Trusted. */ + return ti->flags.disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0; } } return gpg_error (GPG_ERR_NOT_TRUSTED); @@ -507,6 +504,42 @@ } +/* To pretty print DNs in the Pinentry, we replace slashes by + REPLSTRING. The caller needs to free the returned string. NULL is + returned on error with ERRNO set. */ +static char * +reformat_name (const char *name, const char *replstring) +{ + const char *s; + char *newname; + char *d; + size_t count; + size_t replstringlen = strlen (replstring); + + /* If the name does not start with a slash it is not a preformatted + DN and thus we don't bother to reformat it. */ + if (*name != '/') + return xtrystrdup (name); + + /* Count the names. Note that a slash contained in a DN part is + expected to be C style escaped and thus the slashes we see here + are the actual part delimiters. */ + for (s=name+1, count=0; *s; s++) + if (*s == '/') + count++; + newname = xtrymalloc (strlen (name) + count*replstringlen + 1); + if (!newname) + return NULL; + for (s=name+1, d=newname; *s; s++) + if (*s == '/') + d = stpcpy (d, replstring); + else + *d++ = *s; + *d = 0; + return newname; +} + + /* Insert the given fpr into our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'. This function does first check whether that key has already been put @@ -521,6 +554,7 @@ char *fname; FILE *fp; char *fprformatted; + char *nameformatted; int is_disabled; int yes_i_trust; @@ -558,6 +592,9 @@ /* Insert a new one. */ + nameformatted = reformat_name (name, "%0A "); + if (!nameformatted) + return gpg_error_from_syserror (); /* First a general question whether this is trusted. */ desc = xtryasprintf ( @@ -567,14 +604,17 @@ percent sign is actually needed because it is also a printf format string. If you need to insert a plain % sign, you need to encode it as "%%25". The - "%s" gets replaced by the name as store in the + "%s" gets replaced by the name as stored in the certificate. */ _("Do you ultimately trust%%0A" " \"%s\"%%0A" "to correctly certify user certificates?"), - name); + nameformatted); if (!desc) - return out_of_core (); + { + xfree (nameformatted); + return out_of_core (); + } err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No")); xfree (desc); if (!err) @@ -582,12 +622,18 @@ else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED) yes_i_trust = 0; else - return err; + { + xfree (nameformatted); + return err; + } + - fprformatted = insert_colons (fpr); if (!fprformatted) - return out_of_core (); + { + xfree (nameformatted); + return out_of_core (); + } /* If the user trusts this certificate he has to verify the fingerprint of course. */ @@ -606,10 +652,11 @@ _("Please verify that the certificate identified as:%%0A" " \"%s\"%%0A" "has the fingerprint:%%0A" - " %s"), name, fprformatted); + " %s"), nameformatted, fprformatted); if (!desc) { xfree (fprformatted); + xfree (nameformatted); return out_of_core (); } @@ -623,28 +670,24 @@ else if (err) { xfree (fprformatted); + xfree (nameformatted); return err; } } /* Now check again to avoid duplicates. We take the lock to make - sure that nobody else plays with our file. Frankly we don't work - with the trusttable but using this lock is just fine for our - purpose. */ + sure that nobody else plays with our file and force a reread. */ lock_trusttable (); - { - int now_disabled; + agent_reload_trustlist (); + if (!agent_istrusted (ctrl, fpr, &is_disabled) || is_disabled) + { + unlock_trusttable (); + xfree (fprformatted); + xfree (nameformatted); + return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0; + } - if (!agent_istrusted (ctrl, fpr, &now_disabled) || now_disabled) - { - unlock_trusttable (); - xfree (fprformatted); - return now_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0; - } - } - - fname = make_filename (opt.homedir, "trustlist.txt", NULL); if ( access (fname, F_OK) && errno == ENOENT) { @@ -656,6 +699,7 @@ xfree (fname); unlock_trusttable (); xfree (fprformatted); + xfree (nameformatted); return err; } fputs (headerblurb, fp); @@ -669,12 +713,22 @@ xfree (fname); unlock_trusttable (); xfree (fprformatted); + xfree (nameformatted); return err; } /* Append the key. */ fputs ("\n# ", fp); - print_sanitized_string (fp, name, 0); + xfree (nameformatted); + nameformatted = reformat_name (name, "\n# "); + if (!nameformatted || strchr (name, '\n')) + { + /* Note that there should never be a LF in NAME but we better + play safe and print a sanitized version in this case. */ + print_sanitized_string (fp, name, 0); + } + else + fputs (nameformatted, fp); fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag); if (ferror (fp)) err = gpg_error_from_syserror (); @@ -682,11 +736,11 @@ if (fclose (fp)) err = gpg_error_from_syserror (); - if (!err) - agent_reload_trustlist (); + agent_reload_trustlist (); xfree (fname); unlock_trusttable (); xfree (fprformatted); + xfree (nameformatted); return err; } Modified: trunk/sm/call-agent.c =================================================================== --- trunk/sm/call-agent.c 2009-03-25 16:05:16 UTC (rev 4968) +++ trunk/sm/call-agent.c 2009-03-26 11:33:53 UTC (rev 4969) @@ -612,7 +612,7 @@ gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert) { int rc; - char *fpr, *dn; + char *fpr, *dn, *dnfmt; char line[ASSUAN_LINELENGTH]; rc = start_agent (ctrl); @@ -632,9 +632,13 @@ xfree (fpr); return gpg_error (GPG_ERR_GENERAL); } - snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn); + dnfmt = gpgsm_format_name2 (dn, 0); + xfree (dn); + if (!dnfmt) + return gpg_error_from_syserror (); + snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dnfmt); line[DIM(line)-1] = 0; - ksba_free (dn); + ksba_free (dnfmt); xfree (fpr); rc = assuan_transact (agent_ctx, line, NULL, NULL, From cvs at cvs.gnupg.org Thu Mar 26 20:27:05 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 26 Mar 2009 20:27:05 +0100 Subject: [svn] GnuPG - r4970 - in trunk: . agent doc scd sm Message-ID: Author: wk Date: 2009-03-26 20:27:04 +0100 (Thu, 26 Mar 2009) New Revision: 4970 Modified: trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/command.c trunk/doc/gpgsm.texi trunk/scd/ChangeLog trunk/scd/apdu.c trunk/scd/app-nks.c trunk/scd/command.c trunk/scd/scdaemon.h trunk/sm/ChangeLog trunk/sm/gpgsm.c trunk/sm/gpgsm.h trunk/sm/sign.c Log: Signing using Netkey 3 cards does now work. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/agent/ChangeLog 2009-03-26 19:27:04 UTC (rev 4970) @@ -1,5 +1,9 @@ 2009-03-26 Werner Koch + * agent.h (MAX_DIGEST_LEN): Change to 64. + * command.c (cmd_sethash): Allow digest length of 48 and 64. + (cmd_sethash): Allow more hash algos. + * trustlist.c (reformat_name): New. (agent_marktrusted): Use a reformatted name. Reload the table before the update and always reload it at the end. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/scd/ChangeLog 2009-03-26 19:27:04 UTC (rev 4970) @@ -1,3 +1,16 @@ +2009-03-26 Werner Koch + + * command.c (cmd_pksign): Allow more hash algorithms. + + * scdaemon.h (MAX_DIGEST_LEN): Change to 64. + + * apdu.c (open_ccid_reader): Clear the is_to flag. + + * app-nks.c (filelist): Add field KID. + (do_getattr): Change standard authentication key. + (do_sign): Setup a security environment for TCOS 3 cards and support + all SHA-2 algorithms. + 2009-03-24 Werner Koch * command.c (struct server_local_s): Add flag Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/sm/ChangeLog 2009-03-26 19:27:04 UTC (rev 4970) @@ -1,5 +1,12 @@ 2009-03-26 Werner Koch + * gpgsm.c (main): s/def_digest_string/forced_digest_algo/ and + activate the --digest-algo option. + * gpgsm.h (struct opt): s/def_digest_algo/forced_digest_algo/. + * sign.c (gpgsm_sign): Implement --digest-algo. + + * sign.c (MAX_DIGEST_LEN): Change to 64. + * call-agent.c (gpgsm_agent_marktrusted): Format the issuer name. 2009-03-25 Werner Koch Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/NEWS 2009-03-26 19:27:04 UTC (rev 4970) @@ -17,7 +17,9 @@ * Better synchronization of several smartcard sessions. + * Support for the Telesec Netkey 3 cards. + Noteworthy changes in version 2.0.11 (2009-03-03) ------------------------------------------------- Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/agent/agent.h 2009-03-26 19:27:04 UTC (rev 4970) @@ -42,7 +42,7 @@ #define MD_USER_TLS_MD5SHA1 (GCRY_MODULE_ID_USER+1) /* Maximum length of a digest. */ -#define MAX_DIGEST_LEN 36 +#define MAX_DIGEST_LEN 64 /* A large struct name "opt" to keep global flags */ struct Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/agent/command.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -637,8 +637,14 @@ { if (has_option (line, "--hash=sha1")) algo = GCRY_MD_SHA1; + else if (has_option (line, "--hash=sha224")) + algo = GCRY_MD_SHA224; else if (has_option (line, "--hash=sha256")) algo = GCRY_MD_SHA256; + else if (has_option (line, "--hash=sha384")) + algo = GCRY_MD_SHA384; + else if (has_option (line, "--hash=sha512")) + algo = GCRY_MD_SHA512; else if (has_option (line, "--hash=rmd160")) algo = GCRY_MD_RMD160; else if (has_option (line, "--hash=md5")) @@ -671,7 +677,8 @@ n /= 2; if (algo == MD_USER_TLS_MD5SHA1 && n == 36) ; - else if (n != 16 && n != 20 && n != 24 && n != 32) + else if (n != 16 && n != 20 && n != 24 + && n != 28 && n != 32 && n != 48 && n != 64) return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash"); if (n > MAX_DIGEST_LEN) Modified: trunk/doc/gpgsm.texi =================================================================== --- trunk/doc/gpgsm.texi 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/doc/gpgsm.texi 2009-03-26 19:27:04 UTC (rev 4970) @@ -568,6 +568,12 @@ @code{AES256} may be used instead of their OIDs. The default is @code{3DES} (1.2.840.113549.3.7). + at item --digest-algo @code{name} +Use @code{name} as the message digest algorithm. Usually this +algorithm is deduced from the respective signing certificate. This +option forces the use of the given algorithm and may lead to severe +interoperability problems. + @end table Modified: trunk/scd/apdu.c =================================================================== --- trunk/scd/apdu.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/scd/apdu.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -1951,6 +1951,9 @@ reader_table[slot].send_apdu_reader = send_apdu_ccid; reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].dump_status_reader = dump_ccid_reader_status; + /* Our CCID reader code does not support T=0 at all, thus reset the + flag. */ + reader_table[slot].is_t0 = 0; dump_reader_status (slot); return slot; @@ -2839,10 +2842,10 @@ if (lc != -1 && (lc > 255 || lc < 0)) { - /* Data does not fit into an APDU. What we do now dependes on + /* Data does not fit into an APDU. What we do now depends on the EXTENDED_MODE parameter. */ if (!extended_mode) - return SW_WRONG_LENGTH; /* No way. to send such an APDU. */ + return SW_WRONG_LENGTH; /* No way to send such an APDU. */ else if (extended_mode > 0) return SW_HOST_NOT_SUPPORTED; /* FIXME. */ else if (extended_mode < 0) Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/scd/app-nks.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -19,11 +19,12 @@ /* Notes: - - This is still work in progress. We are now targeting TCOS 3 cards - but try to keep compatibility to TCOS 2. Both are not fully - working as of now. TCOS 3 PIN management seems to work. Use GPA - from SVN trunk to test it. + - We are now targeting TCOS 3 cards and it may happen that there is + a regression towards TCOS 2 cards. Please report. + - The TKS3 AUT key is not used by our authentication command but + accessible via the decrypt command. + - If required, we automagically switch between the NKS application and the SigG application. This avoids to use the DINSIG application which is somewhat limited, has no support for Secure @@ -63,25 +64,26 @@ int fid; /* File ID. */ int nks_ver; /* 0 for NKS version 2, 3 for version 3. */ int certtype; /* Type of certificate or 0 if it is not a certificate. */ - int iskeypair; /* If true has the FID of the correspoding certificate. */ + int iskeypair; /* If true has the FID of the corresponding certificate. */ int issignkey; /* True if file is a key usable for signing. */ int isenckey; /* True if file is a key usable for decryption. */ + unsigned char kid; /* Corresponding key references. */ } filelist[] = { - { 0, 0x4531, 0, 0, 0xC000, 1, 0 }, /* EF_PK.NKS.SIG */ - { 1, 0x4531, 3, 0, 0x0000, 1, 1 }, /* EF_PK.CH.SIG */ - { 0, 0xC000, 0, 101 }, /* EF_C.NKS.SIG */ - { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */ + { 0, 0x4531, 0, 0, 0xC000, 1, 0, 0x80 }, /* EF_PK.NKS.SIG */ + { 1, 0x4531, 3, 0, 0x0000, 1, 1, 0x84 }, /* EF_PK.CH.SIG */ + { 0, 0xC000, 0, 101 }, /* EF_C.NKS.SIG */ + { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */ { 0, 0x4331, 0, 100 }, { 0, 0x4332, 0, 100 }, - { 0, 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */ - { 0, 0x45B1, 0, 0, 0xC200, 0, 1 }, /* EF_PK.NKS.ENC */ - { 0, 0xC200, 0, 101 }, /* EF_C.NKS.ENC */ + { 0, 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */ + { 0, 0x45B1, 0, 0, 0xC200, 0, 1, 0x81 }, /* EF_PK.NKS.ENC */ + { 0, 0xC200, 0, 101 }, /* EF_C.NKS.ENC */ { 0, 0x43B1, 0, 100 }, { 0, 0x43B2, 0, 100 }, - { 0, 0x4571, 3, 0, 0xc500, 0, 0 }, /* EF_PK.NKS.AUT */ - { 0, 0xC500, 3, 101 }, /* EF_C.NKS.AUT */ - { 0, 0x45B2, 3, 0, 0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */ - { 0, 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */ + { 0, 0x4571, 3, 0, 0xc500, 0, 0, 0x82 }, /* EF_PK.NKS.AUT */ + { 0, 0xC500, 3, 101 }, /* EF_C.NKS.AUT */ + { 0, 0x45B2, 3, 0, 0xC201, 0, 1, 0x83 }, /* EF_PK.NKS.ENC1024 */ + { 0, 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */ /* { 1, 0xB000, 3, ... */ { 0, 0 } }; @@ -303,10 +305,12 @@ { case 1: /* $AUTHKEYID */ { - /* NetKey 3.0 cards define this key for authentication. - FIXME: We don't have the readkey command, so this - information is pretty useless. */ - char const tmp[] = "NKS-NKS3.4571"; + /* NetKey 3.0 cards define an authentication key but according + to the specs this key is only usable for encryption and not + signing. it might work anyway but it has not yet been + tested - fixme. Thus for now we use the NKS signature key + for authentication. */ + char const tmp[] = "NKS-NKS3.4531"; send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); } break; @@ -685,13 +689,18 @@ int rc, i; int is_sigg = 0; int fid; - unsigned char data[35]; /* Must be large enough for a SHA-1 digest - + the largest OID _prefix above. */ + unsigned char kid; + unsigned char data[83]; /* Must be large enough for a SHA-1 digest + + the largest OID prefix. */ + size_t datalen; if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); - if (indatalen != 20 && indatalen != 16 && indatalen != 35) - return gpg_error (GPG_ERR_INV_VALUE); + switch (indatalen) + { + case 16: case 20: case 35: case 47: case 51: case 67: case 83: break; + default: return gpg_error (GPG_ERR_INV_VALUE); + } /* Check that the provided ID is valid. This is not really needed but we do it to enforce correct usage by the caller. */ @@ -721,22 +730,35 @@ return gpg_error (GPG_ERR_NOT_FOUND); if (!filelist[i].issignkey) return gpg_error (GPG_ERR_INV_ID); + kid = filelist[i].kid; - /* Prepare the DER object from INDATA. */ - if (indatalen == 35) + /* Prepare the DER object from INDATA. */ + if (app->app_local->nks_version > 2 && (indatalen == 35 + || indatalen == 47 + || indatalen == 51 + || indatalen == 67 + || indatalen == 83)) { + /* The caller send data matching the length of the ASN.1 encoded + hash for SHA-{1,224,256,384,512}. Assume that is okay. */ + assert (indatalen <= sizeof data); + memcpy (data, indata, indatalen); + datalen = indatalen; + } + else if (indatalen == 35) + { /* Alright, the caller was so kind to send us an already - prepared DER object. Check that it is waht we want and that - it matches the hash algorithm. */ + prepared DER object. This is for TCOS 2. */ if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15)) ; - else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15)) + else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata,rmd160_prefix,15)) ; else return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); memcpy (data, indata, indatalen); + datalen = 35; } - else + else if (indatalen == 20) { if (hashalgo == GCRY_MD_SHA1) memcpy (data, sha1_prefix, 15); @@ -745,11 +767,32 @@ else return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); memcpy (data+15, indata, indatalen); + datalen = 35; } + else + return gpg_error (GPG_ERR_INV_VALUE); - rc = verify_pin (app, 0, NULL, pincb, pincb_arg); + + /* Send an MSE for PSO:Computer_Signature. */ + if (app->app_local->nks_version > 2) + { + unsigned char mse[6]; + + mse[0] = 0x80; /* Algorithm reference. */ + mse[1] = 1; + mse[2] = 2; /* RSA, card does pkcs#1 v1.5 padding, no ASN.1 check. */ + mse[3] = 0x84; /* Private key reference. */ + mse[4] = 1; + mse[5] = kid; + rc = iso7816_manage_security_env (app->slot, 0x41, 0xB6, + mse, sizeof mse); + } + /* Verify using PW1.CH. */ if (!rc) - rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + rc = verify_pin (app, 0, NULL, pincb, pincb_arg); + /* Compute the signature. */ + if (!rc) + rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); return rc; } Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/scd/command.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -905,7 +905,7 @@ } -/* PKSIGN [--hash=[rmd160|sha1|md5]] +/* PKSIGN [--hash=[rmd160|sha{1,224,256,384,512}|md5]] The --hash option is optional; the default is SHA1. @@ -924,6 +924,14 @@ hash_algo = GCRY_MD_RMD160; else if (has_option (line, "--hash=sha1")) hash_algo = GCRY_MD_SHA1; + else if (has_option (line, "--hash=sha224")) + hash_algo = GCRY_MD_SHA224; + else if (has_option (line, "--hash=sha256")) + hash_algo = GCRY_MD_SHA256; + else if (has_option (line, "--hash=sha384")) + hash_algo = GCRY_MD_SHA384; + else if (has_option (line, "--hash=sha512")) + hash_algo = GCRY_MD_SHA512; else if (has_option (line, "--hash=md5")) hash_algo = GCRY_MD_MD5; else if (!strstr (line, "--")) Modified: trunk/scd/scdaemon.h =================================================================== --- trunk/scd/scdaemon.h 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/scd/scdaemon.h 2009-03-26 19:27:04 UTC (rev 4970) @@ -39,7 +39,7 @@ #define MD_USER_TLS_MD5SHA1 (GCRY_MODULE_ID_USER+1) /* Maximum length of a digest. */ -#define MAX_DIGEST_LEN 36 +#define MAX_DIGEST_LEN 64 Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/sm/gpgsm.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -843,8 +843,8 @@ int use_random_seed = 1; int no_common_certs_import = 0; int with_fpr = 0; - char *def_digest_string = NULL; - char *extra_digest_algo = NULL; + const char *forced_digest_algo = NULL; + const char *extra_digest_algo = NULL; enum cmd_and_opt_values cmd = 0; struct server_control_s ctrl; certlist_t recplist = NULL; @@ -1301,7 +1301,7 @@ break; case oDigestAlgo: - /* Dummy for now. */ + forced_digest_algo = pargs.r.ret_str; break; case oExtraDigestAlgo: @@ -1460,12 +1460,10 @@ || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid)) log_error (_("selected cipher algorithm is invalid\n")); - if (def_digest_string) + if (forced_digest_algo) { - opt.def_digest_algo = gcry_md_map_name (def_digest_string); - xfree (def_digest_string); - def_digest_string = NULL; - if (our_md_test_algo(opt.def_digest_algo) ) + opt.forced_digest_algo = gcry_md_map_name (forced_digest_algo); + if (our_md_test_algo(opt.forced_digest_algo) ) log_error (_("selected digest algorithm is invalid\n")); } if (extra_digest_algo) Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/sm/gpgsm.h 2009-03-26 19:27:04 UTC (rev 4970) @@ -33,7 +33,7 @@ #include "../common/estream.h" #include "../common/audit.h" -#define MAX_DIGEST_LEN 24 +#define MAX_DIGEST_LEN 64 struct keyserver_spec { @@ -92,9 +92,10 @@ const char *def_cipher_algoid; /* cipher algorithm to use if nothing else is specified */ - int def_digest_algo; /* Ditto for hash algorithm */ int def_compress_algo; /* Ditto for compress algorithm */ + int forced_digest_algo; /* User forced hash algorithm. */ + char *def_recipient; /* userID of the default recipient */ int def_recipient_self; /* The default recipient is the default key */ Modified: trunk/sm/sign.c =================================================================== --- trunk/sm/sign.c 2009-03-26 11:33:53 UTC (rev 4969) +++ trunk/sm/sign.c 2009-03-26 19:27:04 UTC (rev 4970) @@ -399,11 +399,22 @@ /* Figure out the hash algorithm to use. We do not want to use the one for the certificate but if possible an OID for the plain algorithm. */ + if (opt.forced_digest_algo && opt.verbose) + log_info ("user requested hash algorithm %d\n", opt.forced_digest_algo); for (i=0, cl=signerlist; cl; cl = cl->next, i++) { const char *oid = ksba_cert_get_digest_algo (cl->cert); - cl->hash_algo = oid ? gcry_md_map_name (oid) : 0; + if (opt.forced_digest_algo) + { + oid = NULL; + cl->hash_algo = opt.forced_digest_algo; + } + else + { + oid = ksba_cert_get_digest_algo (cl->cert); + cl->hash_algo = oid ? gcry_md_map_name (oid) : 0; + } switch (cl->hash_algo) { case GCRY_MD_SHA1: oid = "1.3.14.3.2.26"; break; @@ -427,6 +438,7 @@ } cl->hash_algo_oid = oid; } + if (opt.verbose) { for (i=0, cl=signerlist; cl; cl = cl->next, i++) From cvs at cvs.gnupg.org Thu Mar 26 20:27:46 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 26 Mar 2009 20:27:46 +0100 Subject: [svn] ksba - r302 - in trunk: . src Message-ID: Author: wk Date: 2009-03-26 20:27:46 +0100 (Thu, 26 Mar 2009) New Revision: 302 Modified: trunk/NEWS trunk/src/ChangeLog trunk/src/cms.h Log: Support SHA-384 and -512. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2009-01-14 12:55:36 UTC (rev 301) +++ trunk/src/ChangeLog 2009-03-26 19:27:46 UTC (rev 302) @@ -1,3 +1,7 @@ +2009-03-26 Werner Koch + + * cms.h (struct certlist_s): Allow for SHA-512. + 2009-01-14 Werner Koch * ocsp.c (ksba_ocsp_set_requestor, ksba_ocsp_hash_request) Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2009-01-14 12:55:36 UTC (rev 301) +++ trunk/NEWS 2009-03-26 19:27:46 UTC (rev 302) @@ -1,7 +1,9 @@ Noteworthy changes in version 1.0.6 ------------------------------------------------ + * Support SHA-{384,512} based signature generation. + Noteworthy changes in version 1.0.5 (2009-01-09) ------------------------------------------------ Modified: trunk/src/cms.h =================================================================== --- trunk/src/cms.h 2009-01-14 12:55:36 UTC (rev 301) +++ trunk/src/cms.h 2009-03-26 19:27:46 UTC (rev 302) @@ -62,7 +62,7 @@ struct certlist_s *next; ksba_cert_t cert; int msg_digest_len; /* used length of .. */ - char msg_digest[32]; /* enough space to store a SHA-256 hash */ + char msg_digest[64]; /* enough space to store a SHA-512 hash */ ksba_isotime_t signing_time; struct { AsnNode root; From cvs at cvs.gnupg.org Sun Mar 29 18:27:20 2009 From: cvs at cvs.gnupg.org (svn author mo) Date: Sun, 29 Mar 2009 18:27:20 +0200 Subject: [svn] gpg-error - r213 - trunk/po Message-ID: Author: mo Date: 2009-03-29 18:27:19 +0200 (Sun, 29 Mar 2009) New Revision: 213 Modified: trunk/po/ChangeLog trunk/po/de.po Log: 2009-03-29 Moritz * de.po: Fixed typo. Modified: trunk/po/ChangeLog =================================================================== --- trunk/po/ChangeLog 2008-11-26 14:42:42 UTC (rev 212) +++ trunk/po/ChangeLog 2009-03-29 16:27:19 UTC (rev 213) @@ -1,3 +1,7 @@ +2009-03-29 Moritz + + * de.po: Fixed typo. + 2008-11-12 Werner Koch * de.po: Fixed typo. Modified: trunk/po/de.po [not shown] From cvs at cvs.gnupg.org Mon Mar 30 14:46:07 2009 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 30 Mar 2009 14:46:07 +0200 Subject: [svn] GnuPG - r4971 - in trunk: . agent scd Message-ID: Author: wk Date: 2009-03-30 14:46:06 +0200 (Mon, 30 Mar 2009) New Revision: 4971 Modified: trunk/TODO trunk/agent/ChangeLog trunk/agent/learncard.c trunk/scd/ChangeLog trunk/scd/apdu.c trunk/scd/apdu.h trunk/scd/app-help.c trunk/scd/app-nks.c trunk/scd/app-openpgp.c trunk/scd/ccid-driver.c trunk/scd/command.c trunk/scd/iso7816.c trunk/scd/iso7816.h Log: Implement decryption for TCOS 3 cards. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/agent/ChangeLog 2009-03-30 12:46:06 UTC (rev 4971) @@ -1,3 +1,7 @@ +2009-03-27 Werner Koch + + * learncard.c (agent_handle_learn): Add new certtype 111. + 2009-03-26 Werner Koch * agent.h (MAX_DIGEST_LEN): Change to 64. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/ChangeLog 2009-03-30 12:46:06 UTC (rev 4971) @@ -1,3 +1,16 @@ +2009-03-30 Werner Koch + + * app-nks.c (do_decipher): Make it work for TCOS 3. + * iso7816.c (iso7816_decipher): Add arg EXTENDED_MODE. + * apdu.c (apdu_send): Add arg EXTENDED_MODE and change all callers. + (apdu_send_le): Ditto. + (apdu_send_direct): Ditto, but not yet functional. + (send_le): Fix command chaining. Implement extended length option. + * ccid-driver.c (ccid_transceive): Remove restriction on apdu length. + (struct ccid_driver_s): Add field IFSC. + (ccid_get_atr): Set IFSC. + (ccid_transceive): Use negotiated IFSC and support S(IFS) command. + 2009-03-26 Werner Koch * command.c (cmd_pksign): Allow more hash algorithms. Modified: trunk/TODO =================================================================== --- trunk/TODO 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/TODO 2009-03-30 12:46:06 UTC (rev 4971) @@ -23,8 +23,11 @@ ** mark all unimplemented commands and options. ** Implement --default-key ** support the anyPolicy semantic +** Should we prefer nonRepudiation certs over plain signing certs? + Also: Do we need a way to allow the selection of a qualSig cert + over a plain one? The background is that the Telesec cards have 3 + certs capable of signing all with the same subject name. - * sm/keydb.c ** Check file permissions ** Check that all error code mapping is done. Modified: trunk/agent/learncard.c =================================================================== --- trunk/agent/learncard.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/agent/learncard.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -298,10 +298,12 @@ char *p; int i; static int certtype_list[] = { + 111, /* Root CA */ 101, /* trusted */ 102, /* useful */ 100, /* regular */ - /* We don't include 110 here because gpgsm can't handle it. */ + /* We don't include 110 here because gpgsm can't handle that + special root CA format. */ -1 /* end of list */ }; Modified: trunk/scd/apdu.c =================================================================== --- trunk/scd/apdu.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/apdu.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -414,6 +414,7 @@ case SW_FILE_NOT_FOUND : return "file not found"; case SW_RECORD_NOT_FOUND:return "record not found"; case SW_REF_NOT_FOUND : return "reference not found"; + case SW_BAD_LC : return "bad Lc"; case SW_BAD_P0_P1 : return "bad P0 or P1"; case SW_INS_NOT_SUP : return "instruction not supported"; case SW_CLA_NOT_SUP : return "class not supported"; @@ -2806,14 +2807,18 @@ /* Core APDU tranceiver function. Parameters are described at apdu_send_le with the exception of PININFO which indicates keypad - related operations if not NULL. If EXTENDED_MODE is not NULL + related operations if not NULL. If EXTENDED_MODE is not 0 command chaining or extended length will be used according to these values: n < 0 := Use command chaining with the data part limited to -n in each chunk. If -1 is used a default value is used. + n == 0 := No extended mode or command chaining. n == 1 := Use extended length for input and output without a length limit. n > 1 := Use extended length with up to N bytes. + + FIXME: We don't support extended length return values larger + than 256 bytes due to a static buffer. */ static int send_le (int slot, int class, int ins, int p0, int p1, @@ -2825,12 +2830,16 @@ unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in the driver. */ size_t resultlen; - unsigned char apdu[5+256+1]; + unsigned char short_apdu_buffer[5+256+1]; + unsigned char *apdu_buffer = NULL; + size_t apdu_buffer_size; + unsigned char *apdu; size_t apdulen; int sw; long rc; /* We need a long here due to PC/SC. */ int did_exact_length_hack = 0; int use_chaining = 0; + int use_extended_length = 0; int lc_chunk; if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) @@ -2847,7 +2856,7 @@ if (!extended_mode) return SW_WRONG_LENGTH; /* No way to send such an APDU. */ else if (extended_mode > 0) - return SW_HOST_NOT_SUPPORTED; /* FIXME. */ + use_extended_length = 1; else if (extended_mode < 0) { /* Send APDU using chaining mode. */ @@ -2861,51 +2870,99 @@ else return SW_HOST_INV_VALUE; } + else if (lc == -1 && extended_mode > 0) + use_extended_length = 1; + if (le != -1 && (le > 256 || le < 0)) return SW_WRONG_LENGTH; if ((!data && lc != -1) || (data && lc == -1)) return SW_HOST_INV_VALUE; + if (use_extended_length) + { + if (reader_table[slot].is_t0) + return SW_HOST_NOT_SUPPORTED; + + /* Space for: cls/ins/p1/p2+Z+2_byte_Lc+Lc+2_byte_Le. */ + apdu_buffer_size = 4 + 1 + (lc >= 0? (2+lc):0) + 2; + apdu_buffer = xtrymalloc (apdu_buffer_size); + if (!apdu_buffer) + return SW_HOST_OUT_OF_CORE; + apdu = apdu_buffer; + } + else + { + apdu_buffer_size = sizeof short_apdu_buffer; + apdu = short_apdu_buffer; + } + if ((sw = lock_slot (slot))) return sw; do { - apdulen = 0; - apdu[apdulen] = class; - if (use_chaining && lc > 255) + if (use_extended_length) { - apdu[apdulen] |= 0x10; - assert (use_chaining < 256); - lc_chunk = use_chaining; - lc -= use_chaining; + use_chaining = 0; + apdulen = 0; + apdu[apdulen++] = class; + apdu[apdulen++] = ins; + apdu[apdulen++] = p0; + apdu[apdulen++] = p1; + apdu[apdulen++] = 0; /* Z byte: Extended length marker. */ + if (lc >= 0) + { + apdu[apdulen++] = ((lc >> 8) & 0xff); + apdu[apdulen++] = (lc & 0xff); + memcpy (apdu+apdulen, data, lc); + data += lc; + apdulen += lc; + } + if (le != -1) + { + apdu[apdulen++] = ((le >> 8) & 0xff); + apdu[apdulen++] = (le & 0xff); + } } else { - use_chaining = 0; - lc_chunk = lc; + apdulen = 0; + apdu[apdulen] = class; + if (use_chaining && lc > 255) + { + apdu[apdulen] |= 0x10; + assert (use_chaining < 256); + lc_chunk = use_chaining; + lc -= use_chaining; + } + else + { + use_chaining = 0; + lc_chunk = lc; + } + apdulen++; + apdu[apdulen++] = ins; + apdu[apdulen++] = p0; + apdu[apdulen++] = p1; + if (lc_chunk != -1) + { + apdu[apdulen++] = lc_chunk; + memcpy (apdu+apdulen, data, lc_chunk); + data += lc_chunk; + apdulen += lc_chunk; + /* T=0 does not allow the use of Lc together with Le; + thus disable Le in this case. */ + if (reader_table[slot].is_t0) + le = -1; + } + if (le != -1 && !use_chaining) + apdu[apdulen++] = le; /* Truncation is okay (0 means 256). */ } - apdulen++; - apdu[apdulen++] = ins; - apdu[apdulen++] = p0; - apdu[apdulen++] = p1; - if (lc_chunk != -1) - { - apdu[apdulen++] = lc_chunk; - memcpy (apdu+apdulen, data, lc_chunk); - data += lc_chunk; - apdulen += lc_chunk; - /* T=0 does not allow the use of Lc together with Le; thus - disable Le in this case. */ - if (reader_table[slot].is_t0) - le = -1; - } - if (le != -1) - apdu[apdulen++] = le; /* Truncation is okay because 0 means 256. */ - /* As safeguard don't pass any garbage from the stack to the driver. */ - assert (sizeof (apdu) >= apdulen); - memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + exact_length_hack: + /* As a safeguard don't pass any garbage to the driver. */ + assert (apdulen <= apdu_buffer_size); + memset (apdu+apdulen, 0, apdu_buffer_size - apdulen); resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo); if (rc || resultlen < 2) @@ -2916,7 +2973,8 @@ return rc? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; - if (!did_exact_length_hack && SW_EXACT_LENGTH_P (sw)) + if (!use_extended_length + && !did_exact_length_hack && SW_EXACT_LENGTH_P (sw)) { apdu[apdulen-1] = (sw & 0x00ff); did_exact_length_hack = 1; @@ -2925,6 +2983,13 @@ } while (use_chaining && sw == SW_SUCCESS); + if (apdu_buffer) + { + xfree (apdu_buffer); + apdu_buffer = NULL; + apdu_buffer_size = 0; + } + /* Store away the returned data but strip the statusword. */ resultlen -= 2; if (DBG_CARD_IO) @@ -2976,13 +3041,16 @@ if (DBG_CARD_IO) log_debug ("apdu_send_simple(%d): %d more bytes available\n", slot, len); + apdu_buffer_size = sizeof short_apdu_buffer; + apdu = short_apdu_buffer; apdulen = 0; apdu[apdulen++] = class; apdu[apdulen++] = 0xC0; apdu[apdulen++] = 0; apdu[apdulen++] = 0; apdu[apdulen++] = len; - memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + assert (apdulen <= apdu_buffer_size); + memset (apdu+apdulen, 0, apdu_buffer_size - apdulen); resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL); if (rc || resultlen < 2) @@ -3052,47 +3120,52 @@ /* Send an APDU to the card in SLOT. The APDU is created from all given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1 for LC won't sent this field and the data field; in this case DATA - must also be passed as NULL. The return value is the status word - or -1 for an invalid SLOT or other non card related error. If - RETBUF is not NULL, it will receive an allocated buffer with the - returned data. The length of that data will be put into - *RETBUFLEN. The caller is reponsible for releasing the buffer even - in case of errors. */ + must also be passed as NULL. If EXTENDED_MODE is not 0 command + chaining or extended length will be used; see send_le for details. + The return value is the status word or -1 for an invalid SLOT or + other non card related error. If RETBUF is not NULL, it will + receive an allocated buffer with the returned data. The length of + that data will be put into *RETBUFLEN. The caller is reponsible + for releasing the buffer even in case of errors. */ int -apdu_send_le(int slot, int class, int ins, int p0, int p1, +apdu_send_le(int slot, int extended_mode, + int class, int ins, int p0, int p1, int lc, const char *data, int le, unsigned char **retbuf, size_t *retbuflen) { return send_le (slot, class, ins, p0, p1, lc, data, le, retbuf, retbuflen, - NULL, 0); + NULL, extended_mode); } /* Send an APDU to the card in SLOT. The APDU is created from all given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for LC won't sent this field and the data field; in this case DATA must - also be passed as NULL. The return value is the status word or -1 - for an invalid SLOT or other non card related error. If RETBUF is - not NULL, it will receive an allocated buffer with the returned - data. The length of that data will be put into *RETBUFLEN. The - caller is reponsible for releasing the buffer even in case of - errors. */ + also be passed as NULL. If EXTENDED_MODE is not 0 command chaining + or extended length will be used; see send_le for details. The + return value is the status word or -1 for an invalid SLOT or other + non card related error. If RETBUF is not NULL, it will receive an + allocated buffer with the returned data. The length of that data + will be put into *RETBUFLEN. The caller is reponsible for + releasing the buffer even in case of errors. */ int -apdu_send (int slot, int class, int ins, int p0, int p1, +apdu_send (int slot, int extended_mode, + int class, int ins, int p0, int p1, int lc, const char *data, unsigned char **retbuf, size_t *retbuflen) { return send_le (slot, class, ins, p0, p1, lc, data, 256, - retbuf, retbuflen, NULL, 0); + retbuf, retbuflen, NULL, extended_mode); } /* Send an APDU to the card in SLOT. The APDU is created from all given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for LC won't sent this field and the data field; in this case DATA must - also be passed as NULL. The return value is the status word or -1 - for an invalid SLOT or other non card related error. No data will be - returned. */ + also be passed as NULL. If EXTENDED_MODE is not 0 command chaining + or extended length will be used; see send_le for details. The + return value is the status word or -1 for an invalid SLOT or other + non card related error. No data will be returned. */ int apdu_send_simple (int slot, int extended_mode, int class, int ins, int p0, int p1, @@ -3126,11 +3199,13 @@ and returns with an APDU including the status word. With HANDLE_MORE set to true this function will handle the MORE DATA status and return all APDUs concatenated with one status word at - the end. The function does not return a regular status word but 0 - on success. If the slot is locked, the function returns - immediately with an error. */ + the end. If EXTENDED_MODE is not 0 command chaining or extended + length will be used; see send_le for details. The function does + not return a regular status word but 0 on success. If the slot is + locked, the function returns immediately with an error. */ int -apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, +apdu_send_direct (int slot, int extended_mode, + const unsigned char *apdudata, size_t apdudatalen, int handle_more, unsigned char **retbuf, size_t *retbuflen) { @@ -3147,6 +3222,9 @@ if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; + if (extended_mode) + return SW_HOST_NOT_SUPPORTED; /* FIXME. */ + if ((sw = trylock_slot (slot))) return sw; Modified: trunk/scd/apdu.h =================================================================== --- trunk/scd/apdu.h 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/apdu.h 2009-03-30 12:46:06 UTC (rev 4971) @@ -41,6 +41,7 @@ SW_NOT_SUPPORTED = 0x6a81, SW_FILE_NOT_FOUND = 0x6a82, SW_RECORD_NOT_FOUND = 0x6a83, + SW_BAD_LC = 0x6a87, /* Lc does not match command or p1/p2. */ SW_REF_NOT_FOUND = 0x6a88, SW_BAD_P0_P1 = 0x6b00, SW_EXACT_LENGTH = 0x6c00, @@ -117,13 +118,14 @@ int lc, const char *data, int pin_mode, int pinlen_min, int pinlen_max, int pin_padlen); -int apdu_send (int slot, int class, int ins, int p0, int p1, - int lc, const char *data, +int apdu_send (int slot, int extended_mode, + int class, int ins, int p0, int p1, int lc, const char *data, unsigned char **retbuf, size_t *retbuflen); -int apdu_send_le (int slot, int class, int ins, int p0, int p1, +int apdu_send_le (int slot, int extended_mode, + int class, int ins, int p0, int p1, int lc, const char *data, int le, unsigned char **retbuf, size_t *retbuflen); -int apdu_send_direct (int slot, +int apdu_send_direct (int slot, int extended_mode, const unsigned char *apdudata, size_t apdudatalen, int handle_more, unsigned char **retbuf, size_t *retbuflen); Modified: trunk/scd/app-help.c =================================================================== --- trunk/scd/app-help.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/app-help.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -121,8 +121,7 @@ if ( !(class == CLASS_UNIVERSAL && constructed && (tag == TAG_SEQUENCE || tag == TAG_SET))) { - log_info ("contents of FID 0x%04X does not look like a certificate\n", - fid); + log_info ("data at FID 0x%04X does not look like a certificate\n", fid); return 0; } Modified: trunk/scd/app-nks.c =================================================================== --- trunk/scd/app-nks.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/app-nks.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -22,8 +22,11 @@ - We are now targeting TCOS 3 cards and it may happen that there is a regression towards TCOS 2 cards. Please report. - - The TKS3 AUT key is not used by our authentication command but - accessible via the decrypt command. + - The TKS3 AUT key is not used. It seems that it is only useful for + the internal authentication command and not accessible by other + applications. The key itself is in the encryption class but the + corresponding certificate has only the digitalSignature + capability. - If required, we automagically switch between the NKS application and the SigG application. This avoids to use the DINSIG @@ -70,9 +73,7 @@ unsigned char kid; /* Corresponding key references. */ } filelist[] = { { 0, 0x4531, 0, 0, 0xC000, 1, 0, 0x80 }, /* EF_PK.NKS.SIG */ - { 1, 0x4531, 3, 0, 0x0000, 1, 1, 0x84 }, /* EF_PK.CH.SIG */ { 0, 0xC000, 0, 101 }, /* EF_C.NKS.SIG */ - { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */ { 0, 0x4331, 0, 100 }, { 0, 0x4332, 0, 100 }, { 0, 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */ @@ -80,11 +81,15 @@ { 0, 0xC200, 0, 101 }, /* EF_C.NKS.ENC */ { 0, 0x43B1, 0, 100 }, { 0, 0x43B2, 0, 100 }, - { 0, 0x4571, 3, 0, 0xc500, 0, 0, 0x82 }, /* EF_PK.NKS.AUT */ - { 0, 0xC500, 3, 101 }, /* EF_C.NKS.AUT */ +/* The authentication key is not used. */ +/* { 0, 0x4571, 3, 0, 0xC500, 0, 0, 0x82 }, /\* EF_PK.NKS.AUT *\/ */ +/* { 0, 0xC500, 3, 101 }, /\* EF_C.NKS.AUT *\/ */ { 0, 0x45B2, 3, 0, 0xC201, 0, 1, 0x83 }, /* EF_PK.NKS.ENC1024 */ { 0, 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */ -/* { 1, 0xB000, 3, ... */ + { 1, 0x4531, 3, 0, 0xC000, 1, 1, 0x84 }, /* EF_PK.CH.SIG */ + { 1, 0xC000, 0, 101 }, /* EF_C.CH.SIG */ + { 1, 0xC008, 3, 101 }, /* EF_C.CA.SIG */ + { 1, 0xC00E, 3, 111 }, /* EF_C.RCA.SIG */ { 0, 0 } }; @@ -249,7 +254,7 @@ command[2] = 0x00; command[3] = pwid; - if (apdu_send_direct (app->slot, command, 4, 0, &result, &resultlen)) + if (apdu_send_direct (app->slot, 0, command, 4, 0, &result, &resultlen)) rc = -1; /* Error. */ else if (resultlen < 2) rc = -1; /* Error. */ @@ -808,13 +813,10 @@ const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) { - static const unsigned char mse_parm[] = { - 0x80, 1, 0x10, /* Select algorithm RSA. */ - 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */ - }; int rc, i; int is_sigg = 0; int fid; + int kid; if (!keyidstr || !*keyidstr || !indatalen) return gpg_error (GPG_ERR_INV_VALUE); @@ -847,15 +849,40 @@ return gpg_error (GPG_ERR_NOT_FOUND); if (!filelist[i].isenckey) return gpg_error (GPG_ERR_INV_ID); + kid = filelist[i].kid; - /* Do the TCOS specific MSE. */ - rc = iso7816_manage_security_env (app->slot, - 0xC1, 0xB8, - mse_parm, sizeof mse_parm); + if (app->app_local->nks_version > 2) + { + unsigned char mse[6]; + mse[0] = 0x80; /* Algorithm reference. */ + mse[1] = 1; + mse[2] = 0x0a; /* RSA no padding. (0x1A is pkcs#1.5 padding.) */ + mse[3] = 0x84; /* Private key reference. */ + mse[4] = 1; + mse[5] = kid; + rc = iso7816_manage_security_env (app->slot, 0x41, 0xB8, + mse, sizeof mse); + } + else + { + static const unsigned char mse[] = + { + 0x80, 1, 0x10, /* Select algorithm RSA. */ + 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */ + }; + rc = iso7816_manage_security_env (app->slot, 0xC1, 0xB8, + mse, sizeof mse); + + } + if (!rc) rc = verify_pin (app, 0, NULL, pincb, pincb_arg); + + /* Note that we need to use extended length APDUs for TCOS 3 cards. + Command chaining does not work. */ if (!rc) - rc = iso7816_decipher (app->slot, indata, indatalen, 0x81, + rc = iso7816_decipher (app->slot, app->app_local->nks_version > 2? 1:0, + indata, indatalen, 0x81, outdata, outdatalen); return rc; } Modified: trunk/scd/app-openpgp.c =================================================================== --- trunk/scd/app-openpgp.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/app-openpgp.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -3066,14 +3066,16 @@ { memset (fixbuf, 0, fixuplen); memcpy (fixbuf+fixuplen, indata, indatalen); - rc = iso7816_decipher (app->slot, fixbuf, fixuplen+indatalen, -1, + rc = iso7816_decipher (app->slot, 0, + fixbuf, fixuplen+indatalen, -1, outdata, outdatalen); xfree (fixbuf); } } else - rc = iso7816_decipher (app->slot, indata, indatalen, 0, + rc = iso7816_decipher (app->slot, 0, + indata, indatalen, 0, outdata, outdatalen); } return rc; Modified: trunk/scd/ccid-driver.c =================================================================== --- trunk/scd/ccid-driver.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/ccid-driver.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -243,6 +243,7 @@ int auto_ifsd; int max_ifsd; int ifsd; + int ifsc; int powered_off; int has_pinpad; int apdu_level; /* Reader supports short APDU level exchange. */ @@ -1840,7 +1841,6 @@ *nread = msglen = rc; } - if (msglen < 10) { DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen); @@ -1880,7 +1880,6 @@ return CCID_DRIVER_ERR_INV_VALUE; } - if (debug_level && (!no_debug || debug_level >= 3)) { switch (buffer[0]) @@ -2326,6 +2325,11 @@ if (rc) DEBUGOUT ("SetParameters failed (ignored)\n"); + if (!rc && msglen > 15 && msg[15] >= 16 && msg[15] <= 254 ) + handle->ifsc = msg[15]; + else + handle->ifsc = 128; /* Something went wrong, assume 128 bytes. */ + handle->t1_ns = 0; handle->t1_nr = 0; @@ -2582,22 +2586,15 @@ assert (apdulen); /* Construct an I-Block. */ - /* Fixme: I am not sure whether limiting the length to 259 - as per CCID spec is required. The code blow chops the - APDU anyway into 128 byte blocks. Needs to be addressed - when supporting extended length APDUs. */ - if (apdulen > 259) - return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */ - tpdu = msg+10; /* NAD: DAD=1, SAD=0 */ tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */ - if (apdulen > 128 /* fixme: replace by ifsc */) + if (apdulen > handle->ifsc ) { - apdulen = 128; - apdu_buf += 128; - apdu_buflen -= 128; + apdulen = handle->ifsc; + apdu_buf += handle->ifsc; + apdu_buflen -= handle->ifsc; tpdu[1] |= (1 << 5); /* Set more bit. */ } tpdu[2] = apdulen; @@ -2752,8 +2749,31 @@ DEBUGOUT_2 ("T=1 S-block %s received cmd=%d\n", (tpdu[1] & 0x20)? "response": "request", (tpdu[1] & 0x1f)); - if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2]) - { /* Wait time extension request. */ + if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 1 && tpdu[2] == 1) + { + /* Information field size request. */ + unsigned char ifsc = tpdu[3]; + + if (ifsc < 16 || ifsc > 254) + return CCID_DRIVER_ERR_CARD_IO_ERROR; + + msg = send_buffer; + tpdu = msg+10; + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; + tpdu[1] = (0xc0 | 0x20 | 1); /* S-block response */ + tpdu[2] = 1; + tpdu[3] = ifsc; + tpdulen = 4; + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; + DEBUGOUT_1 ("T=1 requesting an ifsc=%d\n", ifsc); + } + else if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2]) + { + /* Wait time extension request. */ unsigned char bwi = tpdu[3]; msg = send_buffer; tpdu = msg+10; Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/command.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -596,7 +596,8 @@ 100 := Regular X.509 cert 101 := Trusted X.509 cert 102 := Useful X.509 cert - 110 := Root CA cert (e.g. DINSIG) + 110 := Root CA cert in a special format (e.g. DINSIG) + 111 := Root CA cert as standard X509 cert. For certain cards, more information will be returned: @@ -963,7 +964,7 @@ xfree (keyidstr); if (rc) { - log_error ("card_sign failed: %s\n", gpg_strerror (rc)); + log_error ("app_sign failed: %s\n", gpg_strerror (rc)); } else { @@ -1013,7 +1014,7 @@ xfree (keyidstr); if (rc) { - log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc)); + log_error ("app_auth failed: %s\n", gpg_strerror (rc)); } else { @@ -1057,7 +1058,7 @@ xfree (keyidstr); if (rc) { - log_error ("card_create_signature failed: %s\n", gpg_strerror (rc)); + log_error ("app_decipher failed: %s\n", gpg_strerror (rc)); } else { @@ -1821,7 +1822,7 @@ unsigned char *result = NULL; size_t resultlen; - rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more, + rc = apdu_send_direct (ctrl->reader_slot, 0, apdu, apdulen, handle_more, &result, &resultlen); if (rc) log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc)); Modified: trunk/scd/iso7816.c =================================================================== --- trunk/scd/iso7816.c 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/iso7816.c 2009-03-30 12:46:06 UTC (rev 4971) @@ -213,7 +213,7 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x80, 0xAA, list_dirs? 1:2, 0, -1, NULL, + sw = apdu_send (slot, 0, 0x80, 0xAA, list_dirs? 1:2, 0, -1, NULL, result, resultlen); if (sw != SW_SUCCESS) { @@ -244,7 +244,7 @@ *result = NULL; *resultlen = 0; - sw = apdu_send_direct (slot, apdudata, apdudatalen, handle_more, + sw = apdu_send_direct (slot, 0, apdudata, apdudatalen, handle_more, result, resultlen); if (!sw) { @@ -430,7 +430,7 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x00, CMD_GET_DATA, + sw = apdu_send (slot, 0, 0x00, CMD_GET_DATA, ((tag >> 8) & 0xff), (tag & 0xff), -1, NULL, result, resultlen); if (sw != SW_SUCCESS) @@ -462,7 +462,7 @@ return map_sw (sw); } -/* Same as iso7816_put_data but uses an odd instrcution byte. */ +/* Same as iso7816_put_data but uses an odd instruction byte. */ gpg_error_t iso7816_put_data_odd (int slot, int extended_mode, int tag, const unsigned char *data, size_t datalen) @@ -509,7 +509,8 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, + sw = apdu_send (slot, 0, + 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { @@ -530,7 +531,8 @@ and the plaintext is available in a newly allocated buffer stored at RESULT with its length stored at RESULTLEN. */ gpg_error_t -iso7816_decipher (int slot, const unsigned char *data, size_t datalen, +iso7816_decipher (int slot, int extended_mode, + const unsigned char *data, size_t datalen, int padind, unsigned char **result, size_t *resultlen) { int sw; @@ -547,17 +549,19 @@ buf = xtrymalloc (datalen + 1); if (!buf) return gpg_error (gpg_err_code_from_errno (errno)); - + *buf = padind; /* Padding indicator. */ memcpy (buf+1, data, datalen); - sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, + sw = apdu_send (slot, extended_mode, + 0x00, CMD_PSO, 0x80, 0x86, datalen+1, (char*)buf, result, resultlen); xfree (buf); } else { - sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, + sw = apdu_send (slot, extended_mode, + 0x00, CMD_PSO, 0x80, 0x86, datalen, (const char *)data, result, resultlen); } @@ -586,7 +590,7 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, + sw = apdu_send (slot, 0, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { @@ -613,7 +617,8 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0, + sw = apdu_send (slot, 0, + 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { @@ -661,8 +666,8 @@ { result = NULL; n = length > 254? 254 : length; - sw = apdu_send_le (slot, 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL, - n, + sw = apdu_send_le (slot, 0, + 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL, n, &result, &resultlen); if (sw != SW_SUCCESS) { @@ -711,13 +716,13 @@ buffer = NULL; bufferlen = 0; n = read_all? 0 : nmax; - sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, + sw = apdu_send_le (slot, 0, 0x00, CMD_READ_BINARY, ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, n, &buffer, &bufferlen); if ( SW_EXACT_LENGTH_P(sw) ) { n = (sw & 0x00ff); - sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, + sw = apdu_send_le (slot, 0, 0x00, CMD_READ_BINARY, ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, n, &buffer, &bufferlen); } @@ -804,7 +809,7 @@ buffer = NULL; bufferlen = 0; - sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD, + sw = apdu_send_le (slot, 0, 0x00, CMD_READ_RECORD, recno, short_ef? short_ef : 0x04, -1, NULL, Modified: trunk/scd/iso7816.h =================================================================== --- trunk/scd/iso7816.h 2009-03-26 19:27:04 UTC (rev 4970) +++ trunk/scd/iso7816.h 2009-03-30 12:46:06 UTC (rev 4971) @@ -96,7 +96,7 @@ gpg_error_t iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen); -gpg_error_t iso7816_decipher (int slot, +gpg_error_t iso7816_decipher (int slot, int extended_mode, const unsigned char *data, size_t datalen, int padind, unsigned char **result, size_t *resultlen);