GNUPG-1-9-BRANCH gnupg (22 files)
cvs user wk
cvs at cvs.gnupg.org
Thu Dec 2 08:40:40 CET 2004
Date: Thursday, December 2, 2004 @ 08:48:09
Author: wk
Path: /cvs/gnupg/gnupg
Tag: GNUPG-1-9-BRANCH
Added: common/simple-gettext.c common/strsep.c common/w32reg.c
scd/app-p15.c
Modified: ChangeLog agent/gpg-agent.c common/ChangeLog common/Makefile.am
common/fseeko.c common/ftello.c common/simple-pwquery.c
common/util.h configure.ac jnlib/ChangeLog jnlib/logging.c
jnlib/types.h kbx/ChangeLog kbx/Makefile.am kbx/keybox-defs.h
kbx/keybox-update.c sm/ChangeLog sm/gpgsm.c
First take on a W32 port
-------------------------+
ChangeLog | 6
agent/gpg-agent.c | 12
common/ChangeLog | 9
common/Makefile.am | 2
common/fseeko.c | 1
common/ftello.c | 1
common/simple-gettext.c | 437 +++++++++++++++++++++++++++++
common/simple-pwquery.c | 8
common/strsep.c | 73 ++++
common/util.h | 4
common/w32reg.c | 172 +++++++++++
configure.ac | 18 -
jnlib/ChangeLog | 4
jnlib/logging.c | 4
jnlib/types.h | 4
kbx/ChangeLog | 6
kbx/Makefile.am | 7
kbx/keybox-defs.h | 5
kbx/keybox-update.c | 2
scd/app-p15.c | 691 ++++++++++++++++++++++++++++++++++++++++++++++
sm/ChangeLog | 7
sm/gpgsm.c | 44 +-
22 files changed, 1476 insertions(+), 41 deletions(-)
Index: gnupg/ChangeLog
diff -u gnupg/ChangeLog:1.131.2.57 gnupg/ChangeLog:1.131.2.58
--- gnupg/ChangeLog:1.131.2.57 Fri Oct 22 21:48:12 2004
+++ gnupg/ChangeLog Thu Dec 2 08:48:09 2004
@@ -1,3 +1,9 @@
+2004-11-26 Werner Koch <wk at g10code.com>
+
+ * configure.ac: Replace strsep. Replaced use of "target" by
+ "host".
+
+
2004-10-22 Werner Koch <wk at g10code.com>
Released 1.9.12.
Index: gnupg/agent/gpg-agent.c
diff -u gnupg/agent/gpg-agent.c:1.31.2.19 gnupg/agent/gpg-agent.c:1.31.2.20
--- gnupg/agent/gpg-agent.c:1.31.2.19 Fri Oct 22 11:39:47 2004
+++ gnupg/agent/gpg-agent.c Thu Dec 2 08:48:09 2004
@@ -244,12 +244,12 @@
}
-/* Setup the debugging. With a LEVEL of NULL only the active debug
- flags are propagated to the subsystems. With LEVEL set, a specific
- set of debug flags is set; thus overriding all flags already
- set. Note that we don't fail here, because it is important to keep
- gpg-agent running even after re-reading the options due to a
- SIGHUP. */
+/* Setup the debugging. With the global variable DEBUG_LEVEL set to NULL
+ only the active debug flags are propagated to the subsystems. With
+ DEBUG_LEVEL set, a specific set of debug flags is set; thus overriding
+ all flags already set. Note that we don't fail here, because it is
+ important to keep gpg-agent running even after re-reading the
+ options due to a SIGHUP. */
static void
set_debug (void)
{
Index: gnupg/common/ChangeLog
diff -u gnupg/common/ChangeLog:1.30.2.29 gnupg/common/ChangeLog:1.30.2.30
--- gnupg/common/ChangeLog:1.30.2.29 Tue Nov 23 18:09:51 2004
+++ gnupg/common/ChangeLog Thu Dec 2 08:48:09 2004
@@ -1,3 +1,12 @@
+2004-11-26 Werner Koch <wk at g10code.com>
+
+ * simple-gettext.c: New taken from gnupg 1.3.x
+
+ * simple-pwquery.c [_WIN32]: Include winsock2.h.
+ (agent_open): Disable it until we have our AF_UNIX implementation
+ ready.
+ * fseeko.c, ftello.c: Include sys/types for the sake of W32.
+
2004-11-23 Werner Koch <wk at g10code.com>
* b64enc.c: Include stdio.h and string.h
Index: gnupg/common/Makefile.am
diff -u gnupg/common/Makefile.am:1.15.2.8 gnupg/common/Makefile.am:1.15.2.9
--- gnupg/common/Makefile.am:1.15.2.8 Mon Jun 14 10:32:07 2004
+++ gnupg/common/Makefile.am Thu Dec 2 08:48:09 2004
@@ -41,6 +41,8 @@
iobuf.c iobuf.h \
ttyio.c ttyio.h \
asshelp.c asshelp.h \
+ simple-gettext.c \
+ w32reg.c \
signal.c \
dynload.h
Index: gnupg/common/fseeko.c
diff -u gnupg/common/fseeko.c:1.1 gnupg/common/fseeko.c:1.1.2.1
--- gnupg/common/fseeko.c:1.1 Mon Jul 22 12:20:39 2002
+++ gnupg/common/fseeko.c Thu Dec 2 08:48:09 2004
@@ -22,6 +22,7 @@
#include <config.h>
#endif
#include <stdio.h>
+#include <sys/types.h> /* Defines off_t under W32. */
int
fseeko (FILE *stream, off_t off, int whence)
Index: gnupg/common/ftello.c
diff -u gnupg/common/ftello.c:1.1 gnupg/common/ftello.c:1.1.2.1
--- gnupg/common/ftello.c:1.1 Mon Jul 22 12:20:39 2002
+++ gnupg/common/ftello.c Thu Dec 2 08:48:09 2004
@@ -22,6 +22,7 @@
#include <config.h>
#endif
#include <stdio.h>
+#include <sys/types.h> /* Defines off_t under W32. */
off_t
ftello (FILE *stream)
Index: gnupg/common/simple-gettext.c
diff -u /dev/null gnupg/common/simple-gettext.c:1.1.2.1
--- /dev/null Thu Dec 2 08:48:09 2004
+++ gnupg/common/simple-gettext.c Thu Dec 2 08:48:09 2004
@@ -0,0 +1,437 @@
+/* simple-gettext.c - a simplified version of gettext.
+ * Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/* This is a simplified version of gettext written by Ulrich Drepper.
+ * It is used for the Win32 version of GnuPG beucase all the overhead
+ * of gettext is not needed and we have to do some special Win32 stuff.
+ * I decided that this is far easier than to tweak gettext for the special
+ * cases (I tried it but it is a lot of code). wk 15.09.99
+ */
+
+#include <config.h>
+#ifdef USE_SIMPLE_GETTEXT
+#if !defined (_WIN32) && !defined (__CYGWIN32__)
+#error This file can only be used under Windows or Cygwin32
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "util.h"
+
+
+/* The magic number of the GNU message catalog format. */
+#define MAGIC 0x950412de
+#define MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format. */
+#define MO_REVISION_NUMBER 0
+
+
+/* Header for binary .mo file format. */
+struct mo_file_header
+{
+ /* The magic number. */
+ u32 magic;
+ /* The revision number of the file format. */
+ u32 revision;
+ /* The number of strings pairs. */
+ u32 nstrings;
+ /* Offset of table with start offsets of original strings. */
+ u32 orig_tab_offset;
+ /* Offset of table with start offsets of translation strings. */
+ u32 trans_tab_offset;
+ /* Size of hashing table. */
+ u32 hash_tab_size;
+ /* Offset of first hashing entry. */
+ u32 hash_tab_offset;
+};
+
+struct string_desc
+{
+ /* Length of addressed string. */
+ u32 length;
+ /* Offset of string in file. */
+ u32 offset;
+};
+
+
+struct overflow_space_s
+{
+ struct overflow_space_s *next;
+ u32 idx;
+ char d[1];
+};
+
+struct loaded_domain
+{
+ char *data;
+ int must_swap;
+ u32 nstrings;
+ char *mapped; /* 0 = not yet mapped, 1 = mapped,
+ 2 = mapped to
+ overflow space */
+ struct overflow_space_s *overflow_space;
+ struct string_desc *orig_tab;
+ struct string_desc *trans_tab;
+ u32 hash_size;
+ u32 *hash_tab;
+};
+
+
+static struct loaded_domain *the_domain;
+
+static __inline__ u32
+do_swap_u32( u32 i )
+{
+ return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+
+#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
+
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+/* The so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+
+static __inline__ ulong
+hash_string( const char *str_param )
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned long int) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
+
+
+static struct loaded_domain *
+load_domain( const char *filename )
+{
+ FILE *fp;
+ size_t size;
+ struct stat st;
+ struct mo_file_header *data = NULL;
+ struct loaded_domain *domain = NULL;
+ size_t to_read;
+ char *read_ptr;
+
+ fp = fopen( filename, "rb" );
+ if( !fp )
+ return NULL; /* can't open the file */
+ /* we must know about the size of the file */
+ if( fstat( fileno(fp ), &st )
+ || (size = (size_t)st.st_size) != st.st_size
+ || size < sizeof (struct mo_file_header) ) {
+ fclose( fp );
+ return NULL;
+ }
+
+ data = malloc( size );
+ if( !data ) {
+ fclose( fp );
+ return NULL; /* out of memory */
+ }
+
+ to_read = size;
+ read_ptr = (char *) data;
+ do {
+ long int nb = fread( read_ptr, 1, to_read, fp );
+ if( nb < to_read ) {
+ fclose (fp);
+ free(data);
+ return NULL; /* read error */
+ }
+ read_ptr += nb;
+ to_read -= nb;
+ } while( to_read > 0 );
+ fclose (fp);
+
+ /* Using the magic number we can test whether it really is a message
+ * catalog file. */
+ if( data->magic != MAGIC && data->magic != MAGIC_SWAPPED ) {
+ /* The magic number is wrong: not a message catalog file. */
+ free( data );
+ return NULL;
+ }
+
+ domain = calloc( 1, sizeof *domain );
+ if( !domain ) {
+ free( data );
+ return NULL;
+ }
+ domain->data = (char *) data;
+ domain->must_swap = data->magic != MAGIC;
+
+ /* Fill in the information about the available tables. */
+ switch( SWAPIT(domain->must_swap, data->revision) ) {
+ case 0:
+ domain->nstrings = SWAPIT(domain->must_swap, data->nstrings);
+ domain->orig_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset));
+ domain->trans_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset));
+ domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size);
+ domain->hash_tab = (u32 *)
+ ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset));
+ break;
+
+ default: /* This is an invalid revision. */
+ free( data );
+ free( domain );
+ return NULL;
+ }
+
+ /* Allocate an array to keep track of code page mappings. */
+ domain->mapped = calloc( 1, domain->nstrings );
+ if( !domain->mapped ) {
+ free( data );
+ free( domain );
+ return NULL;
+ }
+
+ return domain;
+}
+
+
+/****************
+ * Set the file used for translations. Pass a NULL to disable
+ * translation. A new filename may be set at anytime.
+ * WARNING: After changing the filename you should not access any data
+ * retrieved by gettext().
+ */
+int
+set_gettext_file( const char *filename )
+{
+ struct loaded_domain *domain = NULL;
+
+ if( filename && *filename ) {
+ if( filename[0] == '/'
+#ifdef HAVE_DRIVE_LETTERS
+ || ( isalpha(filename[0])
+ && filename[1] == ':'
+ && (filename[2] == '/' || filename[2] == '\\') )
+#endif
+ ) {
+ /* absolute path - use it as is */
+ domain = load_domain( filename );
+ }
+ else { /* relative path - append ".mo" and get dir from the environment */
+ char *buf = NULL;
+ char *dir;
+ char *p;
+
+ dir = read_w32_registry_string( NULL,
+ "Control Panel\\Mingw32\\NLS",
+ "MODir" );
+ if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) {
+ strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo");
+ /* Better make sure that we don't mix forward and
+ backward slashes. It seems that some Windoze
+ versions don't accept this. */
+ for (p=buf; *p; p++)
+ {
+ if (*p == '/')
+ *p = '\\';
+ }
+ domain = load_domain( buf );
+ free(buf);
+ }
+ free(dir);
+ }
+ if( !domain )
+ return -1;
+ }
+
+ if( the_domain ) {
+ struct overflow_space_s *os, *os2;
+ free( the_domain->data );
+ free( the_domain->mapped );
+ for (os=the_domain->overflow_space; os; os = os2) {
+ os2 = os->next;
+ free (os);
+ }
+ free( the_domain );
+ the_domain = NULL;
+ }
+ the_domain = domain;
+ return 0;
+}
+
+
+static const char*
+get_string( struct loaded_domain *domain, u32 idx )
+{
+ struct overflow_space_s *os;
+ char *p;
+
+ p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
+ if (!domain->mapped[idx])
+ {
+ size_t plen, buflen;
+ char *buf;
+
+ domain->mapped[idx] = 1;
+
+ plen = strlen (p);
+ buf = utf8_to_native (p, plen, -1);
+ buflen = strlen (buf);
+ if (buflen <= plen)
+ strcpy (p, buf);
+ else
+ {
+ /* There is not enough space for the translation - store it
+ in the overflow_space else and mark that in the mapped
+ array. Because we expect that this won't happen too
+ often, we use a simple linked list. */
+ os = malloc (sizeof *os + buflen);
+ if (os)
+ {
+ os->idx = idx;
+ strcpy (os->d, buf);
+ os->next = domain->overflow_space;
+ domain->overflow_space = os;
+ p = os->d;
+ }
+ else
+ p = "ERROR in GETTEXT MALLOC";
+ }
+ xfree (buf);
+ }
+ else if (domain->mapped[idx] == 2)
+ { /* We need to get the string from the overflow_space. */
+ for (os=domain->overflow_space; os; os = os->next)
+ if (os->idx == idx)
+ return (const char*)os->d;
+ p = "ERROR in GETTEXT\n";
+ }
+ return (const char*)p;
+}
+
+
+
+const char *
+gettext( const char *msgid )
+{
+ struct loaded_domain *domain;
+ size_t act = 0;
+ size_t top, bottom;
+
+ if( !(domain = the_domain) )
+ goto not_found;
+
+ /* Locate the MSGID and its translation. */
+ if( domain->hash_size > 2 && domain->hash_tab ) {
+ /* Use the hashing table. */
+ u32 len = strlen (msgid);
+ u32 hash_val = hash_string (msgid);
+ u32 idx = hash_val % domain->hash_size;
+ u32 incr = 1 + (hash_val % (domain->hash_size - 2));
+ u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
+
+ if ( !nstr ) /* Hash table entry is empty. */
+ goto not_found;
+
+ if( SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp( msgid,
+ domain->data + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].offset)) )
+ return get_string( domain, nstr - 1 );
+
+ for(;;) {
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+
+ nstr = SWAPIT(domain->must_swap, domain->hash_tab[idx]);
+ if( !nstr )
+ goto not_found; /* Hash table entry is empty. */
+
+ if ( SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp (msgid,
+ domain->data + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].offset)))
+ return get_string( domain, nstr-1 );
+ }
+ /* NOTREACHED */
+ }
+
+ /* Now we try the default method: binary search in the sorted
+ array of messages. */
+ bottom = 0;
+ top = domain->nstrings;
+ while( bottom < top ) {
+ int cmp_val;
+
+ act = (bottom + top) / 2;
+ cmp_val = strcmp(msgid, domain->data
+ + SWAPIT(domain->must_swap,
+ domain->orig_tab[act].offset));
+ if (cmp_val < 0)
+ top = act;
+ else if (cmp_val > 0)
+ bottom = act + 1;
+ else
+ return get_string( domain, act );
+ }
+
+ not_found:
+ return msgid;
+}
+
+#if 0
+ unsigned int cp1, cp2;
+
+ cp1 = GetConsoleCP();
+ cp2 = GetConsoleOutputCP();
+
+ log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 );
+
+ if( !SetConsoleOutputCP( 1252 ) )
+ log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0));
+
+ cp1 = GetConsoleCP();
+ cp2 = GetConsoleOutputCP();
+ log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 );
+#endif
+
+#endif /* USE_SIMPLE_GETTEXT */
Index: gnupg/common/simple-pwquery.c
diff -u gnupg/common/simple-pwquery.c:1.1.2.4 gnupg/common/simple-pwquery.c:1.1.2.5
--- gnupg/common/simple-pwquery.c:1.1.2.4 Wed Aug 18 16:37:22 2004
+++ gnupg/common/simple-pwquery.c Thu Dec 2 08:48:09 2004
@@ -31,8 +31,12 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#ifdef _WIN32
+#include <winsock2.h>
+#else
#include <sys/socket.h>
#include <sys/un.h>
+#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
@@ -255,6 +259,9 @@
static int
agent_open (int *rfd)
{
+#ifdef _WIN32
+ return SPWQ_NO_AGENT; /* FIXME */
+#else
int rc;
int fd;
char *infostr, *p;
@@ -346,6 +353,7 @@
*rfd = fd;
return 0;
+#endif
}
Index: gnupg/common/strsep.c
diff -u /dev/null gnupg/common/strsep.c:1.1.2.1
--- /dev/null Thu Dec 2 08:48:09 2004
+++ gnupg/common/strsep.c Thu Dec 2 08:48:09 2004
@@ -0,0 +1,73 @@
+/* strsep.c - Replacement for strsep().
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+/* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
+#warning need to get the correct copyright years from glibc
+char *
+strsep (char **stringp, const char *delim)
+{
+ char *begin, *end;
+
+ begin = *stringp;
+ if (begin == NULL)
+ return NULL;
+
+ /* A frequent case is when the delimiter string contains only one
+ character. Here we don't need to call the expensive `strpbrk'
+ function and instead work using `strchr'. */
+ if (delim[0] == '\0' || delim[1] == '\0')
+ {
+ char ch = delim[0];
+
+ if (ch == '\0')
+ end = NULL;
+ else
+ {
+ if (*begin == ch)
+ end = begin;
+ else if (*begin == '\0')
+ end = NULL;
+ else
+ end = strchr (begin + 1, ch);
+ }
+ }
+ else
+ /* Find the end of the token. */
+ end = strpbrk (begin, delim);
+
+ if (end)
+ {
+ /* Terminate the token and set *STRINGP past NUL character. */
+ *end++ = '\0';
+ *stringp = end;
+ }
+ else
+ /* No more delimiters; this is the last token. */
+ *stringp = NULL;
+
+ return begin;
+}
+
Index: gnupg/common/util.h
diff -u gnupg/common/util.h:1.12.2.9 gnupg/common/util.h:1.12.2.10
--- gnupg/common/util.h:1.12.2.9 Mon Jun 14 10:32:07 2004
+++ gnupg/common/util.h Thu Dec 2 08:48:09 2004
@@ -144,7 +144,9 @@
int vasprintf (char **result, const char *format, va_list args);
int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3);
#endif
-
+#ifndef HAVE_STRSEP
+char *strsep (char **stringp, const char *delim);
+#endif
/*-- some macros to replace ctype ones and avoid locale problems --*/
Index: gnupg/common/w32reg.c
diff -u /dev/null gnupg/common/w32reg.c:1.1.2.1
--- /dev/null Thu Dec 2 08:48:09 2004
+++ gnupg/common/w32reg.c Thu Dec 2 08:48:09 2004
@@ -0,0 +1,172 @@
+/* w32reg.c - MS-Windows Registry access
+ * Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#if defined (_WIN32) || defined (__CYGWIN32__)
+ /* This module is only used in this environment */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <windows.h>
+
+#include "util.h"
+
+static HKEY
+get_root_key(const char *root)
+{
+ HKEY root_key;
+
+ if( !root )
+ root_key = HKEY_CURRENT_USER;
+ else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
+ root_key = HKEY_CLASSES_ROOT;
+ else if( !strcmp( root, "HKEY_CURRENT_USER" ) )
+ root_key = HKEY_CURRENT_USER;
+ else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
+ root_key = HKEY_LOCAL_MACHINE;
+ else if( !strcmp( root, "HKEY_USERS" ) )
+ root_key = HKEY_USERS;
+ else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
+ root_key = HKEY_PERFORMANCE_DATA;
+ else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
+ root_key = HKEY_CURRENT_CONFIG;
+ else
+ return NULL;
+
+ return root_key;
+}
+
+
+/****************
+ * Return a string from the Win32 Registry or NULL in case of
+ * error. Caller must release the return value. A NULL for root
+ * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.
+ * NOTE: The value is allocated with a plain malloc() - use free() and not
+ * the usual m_free()!!!
+ */
+char *
+read_w32_registry_string( const char *root, const char *dir, const char *name )
+{
+ HKEY root_key, key_handle;
+ DWORD n1, nbytes, type;
+ char *result = NULL;
+
+ if ( !(root_key = get_root_key(root) ) )
+ return NULL;
+
+ if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
+ {
+ if (root)
+ return NULL; /* no need for a RegClose, so return direct */
+ /* It seems to be common practise to fall back to HLM. */
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
+ return NULL; /* still no need for a RegClose, so return direct */
+ }
+
+ nbytes = 1;
+ if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
+ goto leave;
+ result = malloc( (n1=nbytes+1) );
+ if( !result )
+ goto leave;
+ if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) {
+ free(result); result = NULL;
+ goto leave;
+ }
+ result[nbytes] = 0; /* make sure it is really a string */
+ if (type == REG_EXPAND_SZ && strchr (result, '%')) {
+ char *tmp;
+
+ n1 += 1000;
+ tmp = malloc (n1+1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1) {
+ free (tmp);
+ n1 = nbytes;
+ tmp = malloc (n1 + 1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1) {
+ free (tmp); /* oops - truncated, better don't expand at all */
+ goto leave;
+ }
+ tmp[nbytes] = 0;
+ free (result);
+ result = tmp;
+ }
+ else if (nbytes) { /* okay, reduce the length */
+ tmp[nbytes] = 0;
+ free (result);
+ result = malloc (strlen (tmp)+1);
+ if (!result)
+ result = tmp;
+ else {
+ strcpy (result, tmp);
+ free (tmp);
+ }
+ }
+ else { /* error - don't expand */
+ free (tmp);
+ }
+ }
+
+ leave:
+ RegCloseKey( key_handle );
+ return result;
+}
+
+
+int
+write_w32_registry_string(const char *root, const char *dir,
+ const char *name, const char *value)
+{
+ HKEY root_key, reg_key;
+
+ if ( !(root_key = get_root_key(root) ) )
+ return -1;
+
+ if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key )
+ != ERROR_SUCCESS )
+ return -1;
+
+ if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value,
+ strlen( value ) ) != ERROR_SUCCESS ) {
+ if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) {
+ RegCloseKey(reg_key);
+ return -1;
+ }
+ if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value,
+ strlen( value ) ) != ERROR_SUCCESS ) {
+ RegCloseKey(reg_key);
+ return -1;
+ }
+ }
+
+ RegCloseKey( reg_key );
+
+ return 0;
+}
+
+#endif /* __MINGW32__ || __CYGWIN32__ */
Index: gnupg/configure.ac
diff -u gnupg/configure.ac:1.36.2.67 gnupg/configure.ac:1.36.2.68
--- gnupg/configure.ac:1.36.2.67 Fri Oct 22 21:57:03 2004
+++ gnupg/configure.ac Thu Dec 2 08:48:09 2004
@@ -343,7 +343,7 @@
try_gettext=yes
have_dosish_system=no
-case "${target}" in
+case "${host}" in
*-*-mingw32*)
# special stuff for Windoze NT
ac_cv_have_dev_random=no
@@ -660,7 +660,7 @@
AC_SUBST(GPGKEYS_MAILTO)
-case "${target}" in
+case "${host}" in
*-*-mingw32*)
PRINTABLE_OS_NAME="MingW32"
;;
@@ -782,7 +782,7 @@
AC_REPLACE_FUNCS(fseeko ftello)
AC_REPLACE_FUNCS(isascii)
AC_REPLACE_FUNCS(putc_unlocked)
-
+AC_REPLACE_FUNCS(strsep)
@@ -970,7 +970,7 @@
# add some extra libs here so that previous tests don't fail for
# mysterious reasons - the final link step should bail out.
-case "${target}" in
+case "${host}" in
*-*-mingw32*)
W32LIBS="-lwsock32"
;;
@@ -1038,6 +1038,14 @@
build_scdaemon=no
fi
+# We don't yet want to build some parts for W32
+case "${host}" in
+ *-mingw32*)
+ build_gpg=no
+ ;;
+esac
+
+
AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes")
AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes")
AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes")
@@ -1140,7 +1148,7 @@
echo "
GnuPG v${VERSION} has been configured as follows:
- Platform: $PRINTABLE_OS_NAME ($target)
+ Platform: $PRINTABLE_OS_NAME ($host)
OpenPGP: $build_gpg
S/MIME: $build_gpgsm
Index: gnupg/jnlib/ChangeLog
diff -u gnupg/jnlib/ChangeLog:1.3.2.18 gnupg/jnlib/ChangeLog:1.3.2.19
--- gnupg/jnlib/ChangeLog:1.3.2.18 Tue Nov 30 10:48:37 2004
+++ gnupg/jnlib/ChangeLog Thu Dec 2 08:48:09 2004
@@ -1,3 +1,7 @@
+2004-11-26 Werner Koch <wk at g10code.com>
+
+ * logging.c [_WIN32]: Don't include socket headers.
+
2004-11-30 Timo Schulz <ts at g10code.com>
* w32-afunix.c: New. AF_UNIX emulation for W32.
Index: gnupg/jnlib/logging.c
diff -u gnupg/jnlib/logging.c:1.2.2.10 gnupg/jnlib/logging.c:1.2.2.11
--- gnupg/jnlib/logging.c:1.2.2.10 Tue Nov 23 18:09:51 2004
+++ gnupg/jnlib/logging.c Thu Dec 2 08:48:09 2004
@@ -34,9 +34,11 @@
#include <errno.h>
#include <time.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/stat.h>
+#ifndef _WIN32
+#include <sys/socket.h>
#include <sys/un.h>
+#endif
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
Index: gnupg/jnlib/types.h
diff -u gnupg/jnlib/types.h:1.1.2.1 gnupg/jnlib/types.h:1.1.2.2
--- gnupg/jnlib/types.h:1.1.2.1 Thu Jan 9 13:36:05 2003
+++ gnupg/jnlib/types.h Thu Dec 2 08:48:09 2004
@@ -42,7 +42,11 @@
#ifndef HAVE_BYTE_TYPEDEF
#undef byte /* maybe there is a macro with this name */
+/* Windows typedefs byte in the rpc headers. Avoid warning about
+ double definition. */
+#if !(defined(_WIN32) && defined(cbNDRContext))
typedef unsigned char byte;
+#endif
#define HAVE_BYTE_TYPEDEF
#endif
Index: gnupg/kbx/ChangeLog
diff -u gnupg/kbx/ChangeLog:1.15.2.8 gnupg/kbx/ChangeLog:1.15.2.9
--- gnupg/kbx/ChangeLog:1.15.2.8 Thu Sep 30 23:37:08 2004
+++ gnupg/kbx/ChangeLog Thu Dec 2 08:48:08 2004
@@ -1,3 +1,9 @@
+2004-11-26 Werner Koch <wk at g10code.com>
+
+ * Makefile.am (kbxutil_LDADD): Add ../common/libcommon.a
+
+ * keybox-defs.h: Include stringhelp.h.
+
2004-09-30 Werner Koch <wk at g10code.com>
* kbxutil.c (i18n_init): Always use LC_ALL.
Index: gnupg/kbx/Makefile.am
diff -u gnupg/kbx/Makefile.am:1.8.2.2 gnupg/kbx/Makefile.am:1.8.2.3
--- gnupg/kbx/Makefile.am:1.8.2.2 Thu Sep 30 16:34:27 2004
+++ gnupg/kbx/Makefile.am Thu Dec 2 08:48:08 2004
@@ -43,11 +43,8 @@
libkeybox_a_SOURCES = $(common_sources)
+# Note that libcommon is only required to resolve the LIBOBJS.
kbxutil_SOURCES = kbxutil.c $(common_sources)
kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \
- -lgpg-error @LIBINTL@
-
-
-
-
+ -lgpg-error $(LIBINTL) ../common/libcommon.a
Index: gnupg/kbx/keybox-defs.h
diff -u gnupg/kbx/keybox-defs.h:1.6.2.7 gnupg/kbx/keybox-defs.h:1.6.2.8
--- gnupg/kbx/keybox-defs.h:1.6.2.7 Tue Aug 24 21:55:47 2004
+++ gnupg/kbx/keybox-defs.h Thu Dec 2 08:48:08 2004
@@ -31,8 +31,11 @@
/* We include the type defintions from jnlib instead of defining our
owns here. This will not allow us build KBX in a standalone way
- but tehre is currently no need for it anyway. */
+ but there is currently no need for it anyway. Same goes for
+ stringhelp.h which for example provides a replacement for stpcpy -
+ fixme: Better the LIBOBJ mechnism. */
#include "../jnlib/types.h"
+#include "../jnlib/stringhelp.h"
#include "keybox.h"
Index: gnupg/kbx/keybox-update.c
diff -u gnupg/kbx/keybox-update.c:1.4.2.3 gnupg/kbx/keybox-update.c:1.4.2.4
--- gnupg/kbx/keybox-update.c:1.4.2.3 Mon Apr 26 10:09:22 2004
+++ gnupg/kbx/keybox-update.c Thu Dec 2 08:48:08 2004
@@ -66,7 +66,7 @@
strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
}
else
- { /* file does not end with kbx; hmmm */
+ { /* File does not end with kbx; hmmm. */
bakfname = xtrymalloc ( strlen (template) + 5);
if (!bakfname)
return gpg_error (gpg_err_code_from_errno (errno));
Index: gnupg/scd/app-p15.c
diff -u /dev/null gnupg/scd/app-p15.c:1.1.2.1
--- /dev/null Thu Dec 2 08:48:10 2004
+++ gnupg/scd/app-p15.c Thu Dec 2 08:48:08 2004
@@ -0,0 +1,691 @@
+/* app-p15.c - The pkcs#15 card application.
+ * Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "scdaemon.h"
+
+#include "iso7816.h"
+#include "app-common.h"
+#include "tlv.h"
+
+
+/* Context local to this application. */
+struct app_local_s
+{
+ unsigned short home_df; /* The home DF. Note, that we don't yet
+ support a multilevel hierachy. Thus we
+ assume this is directly below the MF. */
+ struct
+ {
+ unsigned short private_keys;
+ unsigned short public_keys;
+ unsigned short trusted_public_keys;
+ unsigned short secret_keys;
+ unsigned short certificates;
+ unsigned short trusted_certificates;
+ unsigned short useful_certificates;
+ unsigned short data_objects;
+ unsigned short auth_objects;
+ } odf;
+
+
+};
+
+
+
+
+/* Do a select and a read for the file with EFID. EFID is a
+ desctription of the EF to be used with error messages. On success
+ BUFFER and BUFLEN contain the entire content of the EF. The caller
+ must free BUFFER but only on success. */
+static gpg_error_t
+select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
+ unsigned char **buffer, size_t *buflen)
+{
+ gpg_error_t err;
+
+ err = iso7816_select_file (slot, efid, 0, NULL, NULL);
+ if (err)
+ {
+ log_error ("error selecting %s (0x%04X): %s\n",
+ efid_desc, efid, gpg_strerror (err));
+ return err;
+ }
+ err = iso7816_read_binary (slot, 0, 0, buffer, buflen);
+ if (err)
+ {
+ log_error ("error reading %s (0x%04X): %s\n",
+ efid_desc, efid, gpg_strerror (err));
+ return err;
+ }
+ return 0;
+}
+
+
+
+
+/* Read and parse the Object Directory File and store away the
+ pointers.
+
+ Example of such a file:
+
+ A0 06 30 04 04 02 60 34 = Private Keys
+ A4 06 30 04 04 02 60 35 = Certificates
+ A5 06 30 04 04 02 60 36 = TrustedCertificates
+ A7 06 30 04 04 02 60 37 = DataObjects
+ A8 06 30 04 04 02 60 38 = AuthObjects
+
+ These are all PathOrObjects using the path CHOICE. The paths are
+ octet strings of length 2. Using this Path CHOICE is recommended,
+ so we only implement that for now.
+*/
+static gpg_error_t
+read_ef_odf (app_t app)
+{
+ gpg_error_t err;
+ unsigned char *buffer, *p;
+ size_t buflen;
+ unsigned short value;
+
+ err = select_and_read_binary (app->slot, 0x5031, "ODF", &buffer, &buflen);
+ if (err)
+ return err;
+
+ if (len < 8)
+ {
+ log_error ("error: ODF too short\n");
+ xfree (buffer);
+ return gpg_error (GPG_ERR_INV_OBJ);
+ }
+ for (p=buffer; buflen >= 8; p += 8, buflen -= 8)
+ {
+ if ( (p[0] & 0xf0) != 0xA0
+ || memcmp (p+1, "\x06\x30\x04\x04\x02", 5) )
+ {
+ log_error ("ODF format is not supported by us\n");
+ xfree (buffer);
+ return gpg_error (GPG_ERR_INV_OBJ);
+ }
+ switch ((p[0] & 0x0f))
+ {
+ case 0: value = app->app_local->odf.private_keys; break;
+ case 1: value = app->app_local->odf.public_keys; break;
+ case 2: value = app->app_local->odf.trusted_public_keys; break;
+ case 3: value = app->app_local->odf.secret_keys; break;
+ case 4: value = app->app_local->odf.certificates; break;
+ case 5: value = app->app_local->odf.trusted_certificates; break;
+ case 6: value = app->app_local->odf.useful_certificates; break;
+ case 7: value = app->app_local->odf.data_objects; break;
+ case 8: value = app->app_local->odf.auth_objects; break;
+ default: value = 0; break;
+ }
+ if (value)
+ {
+ log_error ("duplicate object type %d in ODF ignored\n",(p[0)&0x0f));
+ continue;
+ }
+ value = ((p[6] << 8) | p[7]);
+ switch ((p[0] & 0x0f))
+ {
+ case 0: app->app_local->odf.private_keys = value; break;
+ case 1: app->app_local->odf.public_keys = value; break;
+ case 2: app->app_local->odf.trusted_public_keys = value; break;
+ case 3: app->app_local->odf.secret_keys = value; break;
+ case 4: app->app_local->odf.certificates = value; break;
+ case 5: app->app_local->odf.trusted_certificates = value; break;
+ case 6: app->app_local->odf.useful_certificates = value; break;
+ case 7: app->app_local->odf.data_objects = value; break;
+ case 8: app->app_local->odf.auth_objects = value; break;
+ default:
+ log_error ("unknown object type %d in ODF ignored\n", (p[0)&0x0f));
+ }
+ }
+
+ if (buflen)
+ log_info ("warning: %u bytes of garbage detected at end of ODF\n", buflen);
+
+ xfree (buffer);
+ return 0;
+}
+
+
+
+/* Read and parse the Private Key Directory Files. */
+/*
+ 6034 (privatekeys)
+
+30 33 30 11 0C 08 53 4B 2E 43 48 2E 44 53 03 02 030...SK.CH.DS..
+06 80 04 01 07 30 0C 04 01 01 03 03 06 00 40 02 .....0........ at .
+02 00 50 A1 10 30 0E 30 08 04 06 3F 00 40 16 00 ..P..0.0...?. at ..
+50 02 02 04 00 30 33 30 11 0C 08 53 4B 2E 43 48 P....030...SK.CH
+2E 4B 45 03 02 06 80 04 01 0A 30 0C 04 01 0C 03 .KE.......0.....
+03 06 44 00 02 02 00 52 A1 10 30 0E 30 08 04 06 ..D....R..0.0...
+3F 00 40 16 00 52 02 02 04 00 30 34 30 12 0C 09 ?. at ..R....040...
+53 4B 2E 43 48 2E 41 55 54 03 02 06 80 04 01 0A SK.CH.AUT.......
+30 0C 04 01 0D 03 03 06 20 00 02 02 00 51 A1 10 0....... ....Q..
+30 0E 30 08 04 06 3F 00 40 16 00 51 02 02 04 00 0.0...?. at ..Q....
+30 37 30 15 0C 0C 53 4B 2E 43 48 2E 44 53 2D 53 070...SK.CH.DS-S
+50 58 03 02 06 80 04 01 0A 30 0C 04 01 02 03 03 PX.......0......
+06 20 00 02 02 00 53 A1 10 30 0E 30 08 04 06 3F . ....S..0.0...?
+00 40 16 00 53 02 02 04 00 00 00 00 00 00 00 00 . at ..S...........
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+
+*/
+static gpg_error_t
+read_ef_prkdf (app_t app)
+{
+
+
+}
+
+/* Read and parse the Public Key Directory Files. */
+static gpg_error_t
+read_ef_pukdf (app_t app)
+{
+
+
+}
+
+
+/* Read and parse the Certificate Directory Files. */
+/*
+
+6035 (certificates)
+
+30 2A 30 15 0C 0C 43 5F 58 35 30 39 2E 43 48 2E 0*0...C_X509.CH.
+44 53 03 02 06 40 04 01 0A 30 03 04 01 01 A1 0C DS... at ...0......
+30 0A 30 08 04 06 3F 00 40 16 C0 00 30 2A 30 15 0.0...?. at ...0*0.
+0C 0C 43 5F 58 35 30 39 2E 43 48 2E 4B 45 03 02 ..C_X509.CH.KE..
+06 40 04 01 0A 30 03 04 01 0C A1 0C 30 0A 30 08 . at ...0......0.0.
+04 06 3F 00 40 16 C2 00 30 2B 30 16 0C 0D 43 5F ..?. at ...0+0...C_
+58 35 30 39 2E 43 48 2E 41 55 54 03 02 06 40 04 X509.CH.AUT... at .
+01 0A 30 03 04 01 0D A1 0C 30 0A 30 08 04 06 3F ..0......0.0...?
+00 40 16 C5 00 30 2E 30 19 0C 10 43 5F 58 35 30 . at ...0.0...C_X50
+39 2E 43 48 2E 44 53 2D 53 50 58 03 02 06 40 04 9.CH.DS-SPX... at .
+01 0A 30 03 04 01 02 A1 0C 30 0A 30 08 04 06 3F ..0......0.0...?
+00 40 16 C1 20 00 00 00 00 00 00 00 00 00 00 00 . at .. ...........
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+
+ 0 42: SEQUENCE {
+ 2 21: SEQUENCE { -- commonObjectAttributes
+ 4 12: UTF8String 'C_X509.CH.DS'
+ 18 2: BIT STRING 6 unused bits
+ : '10'B (bit 1)
+ 22 1: OCTET STRING 0A
+ : }
+ 25 3: SEQUENCE { -- commonCertificateAttributes
+ 27 1: OCTET STRING 01
+ : }
+ 30 12: [1] { -- certAttributes
+ 32 10: SEQUENCE {
+ 34 8: SEQUENCE {
+ 36 6: OCTET STRING 3F 00 40 16 C0 00
+ : }
+ : }
+ : }
+ : }
+
+
+
+6036 (trustedcertificates)
+
+30 35 30 06 03 02 00 00 04 00 30 16 04 14 2D 36 050.......0...-6
+33 39 33 33 39 34 30 33 39 37 37 36 34 30 31 32 3933940397764012
+31 36 A1 13 30 11 30 0F 04 06 3F 00 40 16 C7 08 16..0.0...?. at ...
+02 01 00 80 02 02 29 30 35 30 06 03 02 00 00 04 ......)050......
+00 30 16 04 14 2D 34 30 31 39 30 35 32 37 32 36 .0...-4019052726
+38 30 31 36 39 33 34 39 32 A1 13 30 11 30 0F 04 801693492..0.0..
+06 3F 00 40 16 C7 0E 02 01 00 80 02 04 12 30 34 .?. at ..........04
+30 06 03 02 00 00 04 00 30 15 04 13 37 39 36 33 0.......0...7963
+32 38 33 36 35 30 37 36 36 34 38 32 39 36 30 A1 283650766482960.
+13 30 11 30 0F 04 06 3F 00 40 16 C0 08 02 01 00 .0.0...?. at ......
+80 02 04 11 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+
+ 0 53: SEQUENCE {
+ 2 6: SEQUENCE {
+ 4 2: BIT STRING
+ : '00000000'B
+ : Error: Spurious zero bits in bitstring.
+ 8 0: OCTET STRING
+ : Error: Object has zero length.
+ : }
+ 10 22: SEQUENCE {
+ 12 20: OCTET STRING '-6393394039776401216'
+ : }
+ 34 19: [1] {
+ 36 17: SEQUENCE {
+ 38 15: SEQUENCE {
+ 40 6: OCTET STRING 3F 00 40 16 C7 08
+ 48 1: INTEGER 0 -- index
+ 51 2: [0] 02 29 -- length
+ : }
+ : }
+ : }
+ : }
+
+
+*/
+static gpg_error_t
+read_ef_cdf (app_t app)
+{
+ gpg_error_t err;
+ unsigned char *buffer = NULL;
+ size_t buflen;
+ unsigned short value;
+ unsigned short fid;
+ const unsigned char *p;
+ size_t n, objlen, hdrlen;
+ int class, tag, constructed, ndef;
+
+ fid = app->app_local->odf.certificates;
+ if (!fid)
+ return 0; /* No certificates. */
+
+ err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen);
+ if (err)
+ return err;
+
+ p = buffer;
+ n = buflen;
+
+ /* Loop over the records. We stop as soon as we detect a new record
+ starting with 0x00 or 0xff as these values are commonly used to pad
+ the the read datablocks and are no valid ASN.1 encoding. */
+ while (n && *p && *p == 0xff)
+ {
+ const unsigned char *pp;
+ size_t nn;
+
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > n || tag != TAG_SEQUENCE))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ {
+ log_error ("error parsing CDF record: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ pp = p;
+ nn = objlen;
+ p += objlen;
+ n -= objlen;
+
+ /* Skip the commonObjectAttributes. */
+ err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > nn || tag != TAG_SEQUENCE))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ {
+ log_error ("error parsing CDF record: %s - skipped\n",
+ gpg_strerror (err));
+ continue;
+ }
+ pp += objlen;
+ nn -= objlen;
+
+ /* Skip the commonCertificateAttributes. */
+ err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (!err && (objlen > nn || tag != TAG_SEQUENCE))
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ if (err)
+ {
+ log_error ("error parsing CDF record: %s - skipped\n",
+ gpg_strerror (err));
+ continue;
+ }
+ pp += objlen;
+ nn -= objlen;
+
+ /* FIXME: Check that this is a reference to a certificate. */
+
+
+ }
+
+
+ leave:
+ xfree (buffer);
+ return err;
+}
+
+/* Read and parse Authentication Object Directory Files. */
+static gpg_error_t
+read_ef_aodf (app_t app)
+{
+
+}
+
+
+/* 6037 (dataobjects)
+
+30 1E 30 0B 0C 06 45 46 2E 47 44 4F 04 01 0A 30 0.0...EF.GDO...0
+02 0C 00 A1 0B 30 09 04 04 3F 00 2F 02 80 01 0E .....0...?./....
+30 30 30 18 0C 0F 64 69 73 70 6C 61 79 20 6D 65 000...display me
+73 73 61 67 65 03 02 06 C0 04 01 0A 30 05 0C 03 ssage.......0...
+42 53 53 A1 0D 30 0B 04 06 3F 00 40 16 D0 00 80 BSS..0...?. at ....
+01 20 30 2B 30 0C 0C 03 53 53 4F 03 02 06 C0 04 . 0+0...SSO.....
+01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 64 A1 ..0...SafeGuard.
+0E 30 0C 04 06 3F 00 0F FF 30 02 80 02 03 00 30 .0...?...0.....0
+30 30 11 0C 08 53 47 41 53 64 61 74 61 03 02 06 00...SGASdata...
+C0 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 ....0...SafeGuar
+64 A1 0E 30 0C 04 06 3F 00 0F FF 40 01 80 02 00 d..0...?... at ....
+80 30 30 30 11 0C 08 55 73 65 72 64 61 74 61 03 .000...Userdata.
+02 06 40 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 .. at ...0...SafeGu
+61 72 64 A1 0E 30 0C 04 06 3F 00 0F FF 30 01 80 ard..0...?...0..
+02 01 00 30 2C 30 13 0C 0A 62 61 73 69 63 20 64 ...0,0...basic d
+61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 44 ata.......0...ID
+44 A1 0E 30 0C 04 06 3F 00 40 17 D0 01 80 02 02 D..0...?. at ......
+00 30 2F 30 16 0C 0D 65 78 74 65 6E 64 65 64 20 .0/0...extended
+64 61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 data.......0...I
+44 44 A1 0E 30 0C 04 06 3F 00 40 17 D0 02 80 02 DD..0...?. at .....
+08 00 30 34 30 1B 0C 12 73 70 65 63 69 61 6C 20 ..040...special
+70 72 69 76 69 6C 65 67 65 73 03 02 06 C0 04 01 privileges......
+0A 30 05 0C 03 49 44 44 A1 0E 30 0C 04 06 3F 00 .0...IDD..0...?.
+40 17 D0 03 80 02 04 00 @.......
+
+ 0 30: SEQUENCE {
+ 2 11: SEQUENCE {
+ 4 6: UTF8String 'EF.GDO'
+ 12 1: OCTET STRING 0A
+ : }
+ 15 2: SEQUENCE {
+ 17 0: UTF8String
+ : Error: Object has zero length.
+ : }
+ 19 11: [1] {
+ 21 9: SEQUENCE {
+ 23 4: OCTET STRING 3F 00 2F 02
+ 29 1: [0] 0E
+ : }
+ : }
+ : }
+
+
+
+6038 (authobjects)
+
+30 2A 30 0B 0C 05 62 61 73 69 63 03 02 00 C0 30 0*0...basic....0
+03 04 01 0A A1 16 30 14 03 03 00 0C 10 0A 01 01 ......0.........
+02 01 06 02 01 06 02 01 08 80 01 01 30 51 30 19 ............0Q0.
+0C 13 73 70 65 63 69 66 69 63 20 50 49 4E 20 66 ..specific PIN f
+6F 72 20 44 53 03 02 00 C0 30 03 04 01 07 A1 2F or DS....0...../
+30 2D 03 03 00 4C 10 0A 01 01 02 01 06 02 01 06 0-...L..........
+02 01 08 80 01 02 18 0F 32 30 30 32 30 34 31 39 ........20020419
+31 32 31 33 34 31 5A 30 06 04 04 3F 00 40 16 121341Z0...?. at .
+
+ 0 42: SEQUENCE {
+ 2 11: SEQUENCE {
+ 4 5: UTF8String 'basic'
+ 11 2: BIT STRING
+ : '00000011'B
+ : Error: Spurious zero bits in bitstring.
+ : }
+ 15 3: SEQUENCE {
+ 17 1: OCTET STRING 0A
+ : }
+ 20 22: [1] {
+ 22 20: SEQUENCE {
+ 24 3: BIT STRING
+ : '0000100000110000'B
+ : Error: Spurious zero bits in bitstring.
+ 29 1: ENUMERATED 1
+ 32 1: INTEGER 6
+ 35 1: INTEGER 6
+ 38 1: INTEGER 8
+ 41 1: [0] 01
+ : }
+ : }
+ : }
+
+
+
+*/
+
+
+/* Read and parse the EF(TokenInfo).
+
+TokenInfo ::= SEQUENCE {
+ version INTEGER {v1(0)} (v1,...),
+ serialNumber OCTET STRING,
+ manufacturerID Label OPTIONAL,
+ label [0] Label OPTIONAL,
+ tokenflags TokenFlags,
+ seInfo SEQUENCE OF SecurityEnvironmentInfo OPTIONAL,
+ recordInfo [1] RecordInfo OPTIONAL,
+ supportedAlgorithms [2] SEQUENCE OF AlgorithmInfo OPTIONAL,
+ ...,
+ issuerId [3] Label OPTIONAL,
+ holderId [4] Label OPTIONAL,
+ lastUpdate [5] LastUpdate OPTIONAL,
+ preferredLanguage PrintableString OPTIONAL -- In accordance with
+ -- IETF RFC 1766
+} (CONSTRAINED BY { -- Each AlgorithmInfo.reference value must be unique --})
+
+TokenFlags ::= BIT STRING {
+ readonly (0),
+ loginRequired (1),
+ prnGeneration (2),
+ eidCompliant (3)
+}
+
+
+ 5032:
+
+30 31 02 01 00 04 04 05 45 36 9F 0C 0C 44 2D 54 01......E6...D-T
+72 75 73 74 20 47 6D 62 48 80 14 4F 66 66 69 63 rust GmbH..Offic
+65 20 69 64 65 6E 74 69 74 79 20 63 61 72 64 03 e identity card.
+02 00 40 20 63 61 72 64 03 02 00 40 00 00 00 00 ..@ card... at ....
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+
+ 0 49: SEQUENCE {
+ 2 1: INTEGER 0
+ 5 4: OCTET STRING 05 45 36 9F
+ 11 12: UTF8String 'D-Trust GmbH'
+ 25 20: [0] 'Office identity card'
+ 47 2: BIT STRING
+ : '00000010'B (bit 1)
+ : Error: Spurious zero bits in bitstring.
+ : }
+
+
+
+
+ */
+static gpg_error_t
+read_ef_tokeninfo (app_t app)
+{
+ unsigned short efid = 0x5032;
+
+}
+
+
+/* Get all the basic information from the pkcs#15 card, check the
+ structure and init our context. This is used once at application
+ initialization. */
+static gpg_error_t
+read_p15_info (app_t app)
+{
+ gpg_error_t err;
+
+ err = read_ed_odf (app);
+ if (err)
+ return err;
+
+}
+
+
+static int
+do_learn_status (APP app, CTRL ctrl)
+{
+ gpg_error_t err;
+ char ct_buf[100], id_buf[100];
+ int i;
+
+ /* Output information about all useful objects. */
+ for (i=0; objlist[i].fid; i++)
+ {
+ 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. */
+ sprintf (ct_buf, "%d", filelist[i].certtype);
+ sprintf (id_buf, "P15-DF01.%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->slot, 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
+ {
+ sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid);
+ send_status_info (ctrl, "KEYPAIRINFO",
+ gripstr, 40,
+ id_buf, strlen (id_buf),
+ NULL, (size_t)0);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+/* Release all resources. */
+static void
+do_deinit (app_t app)
+{
+ if (app && app->app_local)
+ {
+ xfree (app->app_local);
+ app->app_local = NULL;
+ }
+}
+
+
+/* Select the PKCS#15 application on the card in SLOT. */
+int
+app_select_p15 (APP app)
+{
+ static char const aid[] = { 0xA0, 0, 0, 0, 0x63,
+ 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
+ int slot = app->slot;
+ int rc;
+
+ rc = iso7816_select_application (slot, aid, sizeof aid);
+ if (!rc)
+ {
+ app->apptype = "P15";
+
+ app->app_local = xtrycalloc (1, sizeof *app->app_local);
+ if (!app->app_local)
+ {
+ rc = gpg_error_from_errno (errno);
+ goto leave;
+ }
+
+ /* Read basic information and check whether this is a real
+ card. */
+ rc = read_p15_info (app);
+
+ /* Special serial number munging. We need to do one case here
+ because we need to access the EF(TokenInfo). */
+ if (app->serialnolen == 12
+ && !memcmp (app->serial, "\xD2\x76\0\0\0\0\0\0\0\0\0\0", 12))
+ {
+ /* This is a German card with a silly serial number. Try to get
+ the serial number from the EF(TokenInfo). We indicate such a
+ serial number by the using the prefix: "FF0100". */
+ const char *efser = card->p15card->serial_number;
+ char *p;
+
+ if (!efser)
+ efser = "";
+
+ xfree (*serial);
+ *serial = NULL;
+ p = xtrymalloc (strlen (efser) + 7);
+ if (!p)
+ rc = gpg_error (gpg_err_code_from_errno (errno));
+ else
+ {
+ strcpy (p, "FF0100");
+ strcpy (p+6, efser);
+ *serial = p;
+ }
+ }
+ else
+ rc = app_munge_serialno (app);
+
+ app->fnc.deinit = do_deinit;
+ app->fnc.learn_status = do_learn_status;
+ app->fnc.readcert = do_readcert;
+ app->fnc.getattr = NULL;
+ app->fnc.setattr = NULL;
+ app->fnc.genkey = NULL;
+ app->fnc.sign = do_sign;
+ app->fnc.auth = NULL;
+ app->fnc.decipher = do_decipher;
+ app->fnc.change_pin = NULL;
+ app->fnc.check_pin = NULL;
+
+ leave:
+ if (rc)
+ {
+ xfree (app->app_local);
+ app->app_local = NULL;
+ }
+
+ }
+
+ return rc;
+}
+
+
Index: gnupg/sm/ChangeLog
diff -u gnupg/sm/ChangeLog:1.101.2.74 gnupg/sm/ChangeLog:1.101.2.75
--- gnupg/sm/ChangeLog:1.101.2.74 Tue Nov 23 18:09:51 2004
+++ gnupg/sm/ChangeLog Thu Dec 2 08:48:08 2004
@@ -1,3 +1,10 @@
+2004-11-29 Werner Koch <wk at g10code.com>
+
+ * gpgsm.c (set_debug): Changed to use a globals DEBUG_LEVEL and
+ DEBUG_VALUE.
+ (main): Made DEBUG_LEVEL global and introduced DEBUG_VALUE. This
+ now allows to add debug flags on top of a debug-level setting.
+
2004-11-23 Werner Koch <wk at g10code.com>
* gpgsm.c: New option --prefer-system-dirmngr.
Index: gnupg/sm/gpgsm.c
diff -u gnupg/sm/gpgsm.c:1.67.2.31 gnupg/sm/gpgsm.c:1.67.2.32
--- gnupg/sm/gpgsm.c:1.67.2.31 Tue Nov 23 18:09:51 2004
+++ gnupg/sm/gpgsm.c Thu Dec 2 08:48:08 2004
@@ -438,6 +438,10 @@
/* It is possible that we are currentlu running under setuid permissions */
static int maybe_setuid = 1;
+/* Helper to implement --debug-level and --debug*/
+static const char *debug_level;
+static unsigned int debug_value;
+
/* Option --enable-special-filenames */
static int allow_special_filenames;
@@ -580,45 +584,44 @@
}
-/* Setup the debugging. With a LEVEL of NULL only the active debug
- flags are propagated to the subsystems. With LEVEL set, a specific
- set of debug flags is set; thus overriding all flags already
- set. */
+/* Setup the debugging. With a DEBUG_LEVEL of NULL only the active
+ debug flags are propagated to the subsystems. With DEBUG_LEVEL
+ set, a specific set of debug flags is set; and individual debugging
+ flags will be added on top. */
static void
-set_debug (const char *level)
+set_debug (void)
{
- if (!level)
+ if (!debug_level)
;
- else if (!strcmp (level, "none"))
+ else if (!strcmp (debug_level, "none"))
opt.debug = 0;
- else if (!strcmp (level, "basic"))
+ else if (!strcmp (debug_level, "basic"))
opt.debug = DBG_ASSUAN_VALUE;
- else if (!strcmp (level, "advanced"))
+ else if (!strcmp (debug_level, "advanced"))
opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
- else if (!strcmp (level, "expert"))
+ else if (!strcmp (debug_level, "expert"))
opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
|DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
- else if (!strcmp (level, "guru"))
+ else if (!strcmp (debug_level, "guru"))
opt.debug = ~0;
else
{
- log_error (_("invalid debug-level `%s' given\n"), level);
+ log_error (_("invalid debug-level `%s' given\n"), debug_level);
gpgsm_exit(2);
}
+ opt.debug |= debug_value;
if (opt.debug && !opt.verbose)
- {
- opt.verbose = 1;
- gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
- }
- if (opt.debug && opt.quiet)
+ opt.verbose = 1;
+ if (opt.debug)
opt.quiet = 0;
if (opt.debug & DBG_MPI_VALUE)
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
+ gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
}
@@ -695,7 +698,6 @@
int greeting = 0;
int nogreeting = 0;
int debug_wait = 0;
- const char *debug_level = NULL;
int use_random_seed = 1;
int with_fpr = 0;
char *def_digest_string = NULL;
@@ -1010,8 +1012,8 @@
case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
- case oDebug: opt.debug |= pargs.r.ret_ulong; break;
- case oDebugAll: opt.debug = ~0; break;
+ case oDebug: debug_value |= pargs.r.ret_ulong; break;
+ case oDebugAll: debug_value = ~0; break;
case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oDebugAllowCoreDump:
@@ -1201,7 +1203,7 @@
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
- set_debug (debug_level);
+ set_debug ();
/* Although we alwasy use gpgsm_exit, we better install a regualr
exit handler so that at least the secure memory gets wiped
More information about the Gnupg-commits
mailing list