mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
First take on a W32 port
This commit is contained in:
parent
e0e1585fc8
commit
4a73d94757
@ -1,3 +1,9 @@
|
|||||||
|
2004-11-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* configure.ac: Replace strsep. Replaced use of "target" by
|
||||||
|
"host".
|
||||||
|
|
||||||
|
|
||||||
2004-10-22 Werner Koch <wk@g10code.com>
|
2004-10-22 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
Released 1.9.12.
|
Released 1.9.12.
|
||||||
|
@ -244,12 +244,12 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Setup the debugging. With a LEVEL of NULL only the active debug
|
/* Setup the debugging. With the global variable DEBUG_LEVEL set to NULL
|
||||||
flags are propagated to the subsystems. With LEVEL set, a specific
|
only the active debug flags are propagated to the subsystems. With
|
||||||
set of debug flags is set; thus overriding all flags already
|
DEBUG_LEVEL set, a specific set of debug flags is set; thus overriding
|
||||||
set. Note that we don't fail here, because it is important to keep
|
all flags already set. Note that we don't fail here, because it is
|
||||||
gpg-agent running even after re-reading the options due to a
|
important to keep gpg-agent running even after re-reading the
|
||||||
SIGHUP. */
|
options due to a SIGHUP. */
|
||||||
static void
|
static void
|
||||||
set_debug (void)
|
set_debug (void)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2004-11-26 Werner Koch <wk@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@g10code.com>
|
2004-11-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* b64enc.c: Include stdio.h and string.h
|
* b64enc.c: Include stdio.h and string.h
|
||||||
|
@ -41,6 +41,8 @@ libcommon_a_SOURCES = \
|
|||||||
iobuf.c iobuf.h \
|
iobuf.c iobuf.h \
|
||||||
ttyio.c ttyio.h \
|
ttyio.c ttyio.h \
|
||||||
asshelp.c asshelp.h \
|
asshelp.c asshelp.h \
|
||||||
|
simple-gettext.c \
|
||||||
|
w32reg.c \
|
||||||
signal.c \
|
signal.c \
|
||||||
dynload.h
|
dynload.h
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h> /* Defines off_t under W32. */
|
||||||
|
|
||||||
int
|
int
|
||||||
fseeko (FILE *stream, off_t off, int whence)
|
fseeko (FILE *stream, off_t off, int whence)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h> /* Defines off_t under W32. */
|
||||||
|
|
||||||
off_t
|
off_t
|
||||||
ftello (FILE *stream)
|
ftello (FILE *stream)
|
||||||
|
437
common/simple-gettext.c
Normal file
437
common/simple-gettext.c
Normal file
@ -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 */
|
@ -31,8 +31,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
@ -255,6 +259,9 @@ agent_send_all_options (int fd)
|
|||||||
static int
|
static int
|
||||||
agent_open (int *rfd)
|
agent_open (int *rfd)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return SPWQ_NO_AGENT; /* FIXME */
|
||||||
|
#else
|
||||||
int rc;
|
int rc;
|
||||||
int fd;
|
int fd;
|
||||||
char *infostr, *p;
|
char *infostr, *p;
|
||||||
@ -346,6 +353,7 @@ agent_open (int *rfd)
|
|||||||
|
|
||||||
*rfd = fd;
|
*rfd = fd;
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
73
common/strsep.c
Normal file
73
common/strsep.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -144,7 +144,9 @@ int is_file_compressed (const char *s, int *ret_rc);
|
|||||||
int vasprintf (char **result, const char *format, va_list args);
|
int vasprintf (char **result, const char *format, va_list args);
|
||||||
int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3);
|
int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HAVE_STRSEP
|
||||||
|
char *strsep (char **stringp, const char *delim);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-- some macros to replace ctype ones and avoid locale problems --*/
|
/*-- some macros to replace ctype ones and avoid locale problems --*/
|
||||||
|
172
common/w32reg.c
Normal file
172
common/w32reg.c
Normal file
@ -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__ */
|
18
configure.ac
18
configure.ac
@ -343,7 +343,7 @@ GNUPG_CHECK_DOCBOOK_TO_TEXI
|
|||||||
|
|
||||||
try_gettext=yes
|
try_gettext=yes
|
||||||
have_dosish_system=no
|
have_dosish_system=no
|
||||||
case "${target}" in
|
case "${host}" in
|
||||||
*-*-mingw32*)
|
*-*-mingw32*)
|
||||||
# special stuff for Windoze NT
|
# special stuff for Windoze NT
|
||||||
ac_cv_have_dev_random=no
|
ac_cv_have_dev_random=no
|
||||||
@ -660,7 +660,7 @@ fi
|
|||||||
|
|
||||||
AC_SUBST(GPGKEYS_MAILTO)
|
AC_SUBST(GPGKEYS_MAILTO)
|
||||||
|
|
||||||
case "${target}" in
|
case "${host}" in
|
||||||
*-*-mingw32*)
|
*-*-mingw32*)
|
||||||
PRINTABLE_OS_NAME="MingW32"
|
PRINTABLE_OS_NAME="MingW32"
|
||||||
;;
|
;;
|
||||||
@ -782,7 +782,7 @@ AC_REPLACE_FUNCS(mkdtemp)
|
|||||||
AC_REPLACE_FUNCS(fseeko ftello)
|
AC_REPLACE_FUNCS(fseeko ftello)
|
||||||
AC_REPLACE_FUNCS(isascii)
|
AC_REPLACE_FUNCS(isascii)
|
||||||
AC_REPLACE_FUNCS(putc_unlocked)
|
AC_REPLACE_FUNCS(putc_unlocked)
|
||||||
|
AC_REPLACE_FUNCS(strsep)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -970,7 +970,7 @@ GNUPG_CHECK_GNUMAKE
|
|||||||
|
|
||||||
# add some extra libs here so that previous tests don't fail for
|
# add some extra libs here so that previous tests don't fail for
|
||||||
# mysterious reasons - the final link step should bail out.
|
# mysterious reasons - the final link step should bail out.
|
||||||
case "${target}" in
|
case "${host}" in
|
||||||
*-*-mingw32*)
|
*-*-mingw32*)
|
||||||
W32LIBS="-lwsock32"
|
W32LIBS="-lwsock32"
|
||||||
;;
|
;;
|
||||||
@ -1038,6 +1038,14 @@ if test "$build_agent_only" = "yes" ; then
|
|||||||
build_scdaemon=no
|
build_scdaemon=no
|
||||||
fi
|
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_GPG, test "$build_gpg" = "yes")
|
||||||
AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes")
|
AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes")
|
||||||
AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes")
|
AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes")
|
||||||
@ -1140,7 +1148,7 @@ AC_OUTPUT
|
|||||||
echo "
|
echo "
|
||||||
GnuPG v${VERSION} has been configured as follows:
|
GnuPG v${VERSION} has been configured as follows:
|
||||||
|
|
||||||
Platform: $PRINTABLE_OS_NAME ($target)
|
Platform: $PRINTABLE_OS_NAME ($host)
|
||||||
|
|
||||||
OpenPGP: $build_gpg
|
OpenPGP: $build_gpg
|
||||||
S/MIME: $build_gpgsm
|
S/MIME: $build_gpgsm
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2004-11-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* logging.c [_WIN32]: Don't include socket headers.
|
||||||
|
|
||||||
2004-11-30 Timo Schulz <ts@g10code.com>
|
2004-11-30 Timo Schulz <ts@g10code.com>
|
||||||
|
|
||||||
* w32-afunix.c: New. AF_UNIX emulation for W32.
|
* w32-afunix.c: New. AF_UNIX emulation for W32.
|
||||||
|
@ -34,9 +34,11 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -42,7 +42,11 @@
|
|||||||
|
|
||||||
#ifndef HAVE_BYTE_TYPEDEF
|
#ifndef HAVE_BYTE_TYPEDEF
|
||||||
#undef byte /* maybe there is a macro with this name */
|
#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;
|
typedef unsigned char byte;
|
||||||
|
#endif
|
||||||
#define HAVE_BYTE_TYPEDEF
|
#define HAVE_BYTE_TYPEDEF
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2004-11-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* Makefile.am (kbxutil_LDADD): Add ../common/libcommon.a
|
||||||
|
|
||||||
|
* keybox-defs.h: Include stringhelp.h.
|
||||||
|
|
||||||
2004-09-30 Werner Koch <wk@g10code.com>
|
2004-09-30 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* kbxutil.c (i18n_init): Always use LC_ALL.
|
* kbxutil.c (i18n_init): Always use LC_ALL.
|
||||||
|
@ -43,11 +43,8 @@ common_sources = \
|
|||||||
|
|
||||||
libkeybox_a_SOURCES = $(common_sources)
|
libkeybox_a_SOURCES = $(common_sources)
|
||||||
|
|
||||||
|
# Note that libcommon is only required to resolve the LIBOBJS.
|
||||||
kbxutil_SOURCES = kbxutil.c $(common_sources)
|
kbxutil_SOURCES = kbxutil.c $(common_sources)
|
||||||
kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \
|
kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \
|
||||||
-lgpg-error @LIBINTL@
|
-lgpg-error $(LIBINTL) ../common/libcommon.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,8 +31,11 @@
|
|||||||
|
|
||||||
/* We include the type defintions from jnlib instead of defining our
|
/* We include the type defintions from jnlib instead of defining our
|
||||||
owns here. This will not allow us build KBX in a standalone way
|
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/types.h"
|
||||||
|
#include "../jnlib/stringhelp.h"
|
||||||
|
|
||||||
#include "keybox.h"
|
#include "keybox.h"
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ create_tmp_file (const char *template,
|
|||||||
strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
|
strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* file does not end with kbx; hmmm */
|
{ /* File does not end with kbx; hmmm. */
|
||||||
bakfname = xtrymalloc ( strlen (template) + 5);
|
bakfname = xtrymalloc ( strlen (template) + 5);
|
||||||
if (!bakfname)
|
if (!bakfname)
|
||||||
return gpg_error (gpg_err_code_from_errno (errno));
|
return gpg_error (gpg_err_code_from_errno (errno));
|
||||||
|
691
scd/app-p15.c
Normal file
691
scd/app-p15.c
Normal file
@ -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........@.
|
||||||
|
02 00 50 A1 10 30 0E 30 08 04 06 3F 00 40 16 00 ..P..0.0...?.@..
|
||||||
|
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 ?.@..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...?.@..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 .@..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...@...0......
|
||||||
|
30 0A 30 08 04 06 3F 00 40 16 C0 00 30 2A 30 15 0.0...?.@...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 .@...0......0.0.
|
||||||
|
04 06 3F 00 40 16 C2 00 30 2B 30 16 0C 0D 43 5F ..?.@...0+0...C_
|
||||||
|
58 35 30 39 2E 43 48 2E 41 55 54 03 02 06 40 04 X509.CH.AUT...@.
|
||||||
|
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 .@...0.0...C_X50
|
||||||
|
39 2E 43 48 2E 44 53 2D 53 50 58 03 02 06 40 04 9.CH.DS-SPX...@.
|
||||||
|
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 .@.. ...........
|
||||||
|
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...?.@...
|
||||||
|
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 .?.@..........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...?.@......
|
||||||
|
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...?.@....
|
||||||
|
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...?...@....
|
||||||
|
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 ..@...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...?.@......
|
||||||
|
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...?.@.....
|
||||||
|
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...?.@.
|
||||||
|
|
||||||
|
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...@....
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
|||||||
|
2004-11-29 Werner Koch <wk@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@g10code.com>
|
2004-11-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpgsm.c: New option --prefer-system-dirmngr.
|
* gpgsm.c: New option --prefer-system-dirmngr.
|
||||||
|
44
sm/gpgsm.c
44
sm/gpgsm.c
@ -438,6 +438,10 @@ int gpgsm_errors_seen = 0;
|
|||||||
/* It is possible that we are currentlu running under setuid permissions */
|
/* It is possible that we are currentlu running under setuid permissions */
|
||||||
static int maybe_setuid = 1;
|
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 */
|
/* Option --enable-special-filenames */
|
||||||
static int allow_special_filenames;
|
static int allow_special_filenames;
|
||||||
|
|
||||||
@ -580,45 +584,44 @@ wrong_args (const char *text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Setup the debugging. With a LEVEL of NULL only the active debug
|
/* Setup the debugging. With a DEBUG_LEVEL of NULL only the active
|
||||||
flags are propagated to the subsystems. With LEVEL set, a specific
|
debug flags are propagated to the subsystems. With DEBUG_LEVEL
|
||||||
set of debug flags is set; thus overriding all flags already
|
set, a specific set of debug flags is set; and individual debugging
|
||||||
set. */
|
flags will be added on top. */
|
||||||
static void
|
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;
|
opt.debug = 0;
|
||||||
else if (!strcmp (level, "basic"))
|
else if (!strcmp (debug_level, "basic"))
|
||||||
opt.debug = DBG_ASSUAN_VALUE;
|
opt.debug = DBG_ASSUAN_VALUE;
|
||||||
else if (!strcmp (level, "advanced"))
|
else if (!strcmp (debug_level, "advanced"))
|
||||||
opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
|
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
|
opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
|
||||||
|DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
|
|DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
|
||||||
else if (!strcmp (level, "guru"))
|
else if (!strcmp (debug_level, "guru"))
|
||||||
opt.debug = ~0;
|
opt.debug = ~0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error (_("invalid debug-level `%s' given\n"), level);
|
log_error (_("invalid debug-level `%s' given\n"), debug_level);
|
||||||
gpgsm_exit(2);
|
gpgsm_exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt.debug |= debug_value;
|
||||||
|
|
||||||
if (opt.debug && !opt.verbose)
|
if (opt.debug && !opt.verbose)
|
||||||
{
|
opt.verbose = 1;
|
||||||
opt.verbose = 1;
|
if (opt.debug)
|
||||||
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
|
|
||||||
}
|
|
||||||
if (opt.debug && opt.quiet)
|
|
||||||
opt.quiet = 0;
|
opt.quiet = 0;
|
||||||
|
|
||||||
if (opt.debug & DBG_MPI_VALUE)
|
if (opt.debug & DBG_MPI_VALUE)
|
||||||
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
|
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
|
||||||
if (opt.debug & DBG_CRYPTO_VALUE )
|
if (opt.debug & DBG_CRYPTO_VALUE )
|
||||||
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
|
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
|
||||||
|
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -695,7 +698,6 @@ main ( int argc, char **argv)
|
|||||||
int greeting = 0;
|
int greeting = 0;
|
||||||
int nogreeting = 0;
|
int nogreeting = 0;
|
||||||
int debug_wait = 0;
|
int debug_wait = 0;
|
||||||
const char *debug_level = NULL;
|
|
||||||
int use_random_seed = 1;
|
int use_random_seed = 1;
|
||||||
int with_fpr = 0;
|
int with_fpr = 0;
|
||||||
char *def_digest_string = NULL;
|
char *def_digest_string = NULL;
|
||||||
@ -1010,8 +1012,8 @@ main ( int argc, char **argv)
|
|||||||
|
|
||||||
case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
|
case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
|
||||||
|
|
||||||
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
|
case oDebug: debug_value |= pargs.r.ret_ulong; break;
|
||||||
case oDebugAll: opt.debug = ~0; break;
|
case oDebugAll: debug_value = ~0; break;
|
||||||
case oDebugLevel: debug_level = pargs.r.ret_str; break;
|
case oDebugLevel: debug_level = pargs.r.ret_str; break;
|
||||||
case oDebugWait: debug_wait = pargs.r.ret_int; break;
|
case oDebugWait: debug_wait = pargs.r.ret_int; break;
|
||||||
case oDebugAllowCoreDump:
|
case oDebugAllowCoreDump:
|
||||||
@ -1201,7 +1203,7 @@ main ( int argc, char **argv)
|
|||||||
|
|
||||||
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
|
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
|
||||||
|
|
||||||
set_debug (debug_level);
|
set_debug ();
|
||||||
|
|
||||||
/* Although we alwasy use gpgsm_exit, we better install a regualr
|
/* Although we alwasy use gpgsm_exit, we better install a regualr
|
||||||
exit handler so that at least the secure memory gets wiped
|
exit handler so that at least the secure memory gets wiped
|
||||||
|
Loading…
x
Reference in New Issue
Block a user