From cvs at cvs.gnupg.org Wed Aug 1 20:14:00 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 01 Aug 2007 20:14:00 +0200 Subject: [svn] GnuPG - r4554 - trunk/common Message-ID: Author: wk Date: 2007-08-01 20:13:31 +0200 (Wed, 01 Aug 2007) New Revision: 4554 Modified: trunk/common/ChangeLog trunk/common/estream-printf.c Log: Removed unportable testing code. Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-07-29 02:58:26 UTC (rev 4553) +++ trunk/common/ChangeLog 2007-08-01 18:13:31 UTC (rev 4554) @@ -1,3 +1,9 @@ +2007-08-01 Werner Koch + + * estream-printf.c (read_dummy_value): Removed as it is useless now. + (read_values): Remove check on !vaargs which is not anymore needed + and anyway not portable. Reported by Peter O'Gorman. + 2007-07-16 Werner Koch * estream.c (es_func_file_create): Clear NO_CLOSE flag. Modified: trunk/common/estream-printf.c =================================================================== --- trunk/common/estream-printf.c 2007-07-29 02:58:26 UTC (rev 4553) +++ trunk/common/estream-printf.c 2007-08-01 18:13:31 UTC (rev 4554) @@ -644,57 +644,7 @@ return -1; } -/* This function is used for testing to provide default arguments. */ -static int -read_dummy_value (value_t *value, valtype_t vt) -{ - switch (vt) - { - case VALTYPE_CHAR: value->a_char = 'a'; break; - case VALTYPE_CHAR_PTR: value->a_char_ptr = NULL; break; - case VALTYPE_SCHAR: value->a_schar = 'a'; break; - case VALTYPE_SCHAR_PTR: value->a_schar_ptr = NULL; break; - case VALTYPE_UCHAR: value->a_uchar = 'a'; break; - case VALTYPE_SHORT: value->a_short = -4711; break; - case VALTYPE_USHORT: value->a_ushort = 4711; break; - case VALTYPE_SHORT_PTR: value->a_short_ptr = NULL; break; - case VALTYPE_INT: value->a_int = 42; break; - case VALTYPE_INT_PTR: value->a_int_ptr = NULL; break; - case VALTYPE_UINT: value->a_uint = 65535; break; - case VALTYPE_LONG: value->a_long = 11071961; break; - case VALTYPE_ULONG: value->a_ulong = 19610711; break; - case VALTYPE_LONG_PTR: value->a_long_ptr = NULL; break; -#ifdef HAVE_LONG_LONG_INT - case VALTYPE_LONGLONG: value->a_longlong = 11223344; break; - case VALTYPE_ULONGLONG: value->a_ulonglong = 2233445566u; break; - case VALTYPE_LONGLONG_PTR: value->a_longlong_ptr = NULL; break; -#endif - case VALTYPE_DOUBLE: value->a_double = 3.1415926535; break; -#ifdef HAVE_LONG_DOUBLE - case VALTYPE_LONGDOUBLE: value->a_longdouble = 2.7; break; -#endif - case VALTYPE_STRING: value->a_string = "heart of gold"; break; - case VALTYPE_POINTER: value->a_void_ptr = (void*)0xdeadbeef; break; -#ifdef HAVE_INTMAX_T - case VALTYPE_INTMAX: value->a_intmax = 100; break; - case VALTYPE_INTMAX_PTR: value->a_intmax_ptr = NULL; break; -#endif -#ifdef HAVE_UINTMAX_T - case VALTYPE_UINTMAX: value->a_uintmax = 200; break; -#endif - case VALTYPE_SIZE: value->a_size = 65537; break; - case VALTYPE_SIZE_PTR: value->a_size_ptr = NULL; break; -#ifdef HAVE_PTRDIFF_T - case VALTYPE_PTRDIFF: value->a_ptrdiff = 2; break; - case VALTYPE_PTRDIFF_PTR: value->a_ptrdiff_ptr = NULL; break; -#endif - default: /* Unsupported type. */ - return -1; - } - return 0; -} - /* This function reads all the values as specified by VALUETABLE into VALUETABLE. The values are expected in VAARGS. The function returns -1 if a specified type is not supported. */ @@ -708,102 +658,94 @@ value_t *value = &valuetable[validx].value; valtype_t vt = valuetable[validx].vt; - if (!vaargs) + switch (vt) { - if (read_dummy_value (value, vt)) - return -1; - } - else - { - switch (vt) - { - case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break; - case VALTYPE_CHAR_PTR: - value->a_char_ptr = va_arg (vaargs, char *); - break; - case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break; - case VALTYPE_SCHAR_PTR: - value->a_schar_ptr = va_arg (vaargs, signed char *); - break; - case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break; - case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break; - case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break; - case VALTYPE_SHORT_PTR: - value->a_short_ptr = va_arg (vaargs, short *); - break; - case VALTYPE_INT: - value->a_int = va_arg (vaargs, int); - break; - case VALTYPE_INT_PTR: - value->a_int_ptr = va_arg (vaargs, int *); - break; - case VALTYPE_UINT: - value->a_uint = va_arg (vaargs, unsigned int); - break; - case VALTYPE_LONG: - value->a_long = va_arg (vaargs, long); - break; - case VALTYPE_ULONG: - value->a_ulong = va_arg (vaargs, unsigned long); - break; - case VALTYPE_LONG_PTR: - value->a_long_ptr = va_arg (vaargs, long *); - break; + case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break; + case VALTYPE_CHAR_PTR: + value->a_char_ptr = va_arg (vaargs, char *); + break; + case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break; + case VALTYPE_SCHAR_PTR: + value->a_schar_ptr = va_arg (vaargs, signed char *); + break; + case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break; + case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break; + case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break; + case VALTYPE_SHORT_PTR: + value->a_short_ptr = va_arg (vaargs, short *); + break; + case VALTYPE_INT: + value->a_int = va_arg (vaargs, int); + break; + case VALTYPE_INT_PTR: + value->a_int_ptr = va_arg (vaargs, int *); + break; + case VALTYPE_UINT: + value->a_uint = va_arg (vaargs, unsigned int); + break; + case VALTYPE_LONG: + value->a_long = va_arg (vaargs, long); + break; + case VALTYPE_ULONG: + value->a_ulong = va_arg (vaargs, unsigned long); + break; + case VALTYPE_LONG_PTR: + value->a_long_ptr = va_arg (vaargs, long *); + break; #ifdef HAVE_LONG_LONG_INT - case VALTYPE_LONGLONG: - value->a_longlong = va_arg (vaargs, long long int); - break; - case VALTYPE_ULONGLONG: - value->a_ulonglong = va_arg (vaargs, unsigned long long int); - break; - case VALTYPE_LONGLONG_PTR: - value->a_longlong_ptr = va_arg (vaargs, long long *); - break; + case VALTYPE_LONGLONG: + value->a_longlong = va_arg (vaargs, long long int); + break; + case VALTYPE_ULONGLONG: + value->a_ulonglong = va_arg (vaargs, unsigned long long int); + break; + case VALTYPE_LONGLONG_PTR: + value->a_longlong_ptr = va_arg (vaargs, long long *); + break; #endif - case VALTYPE_DOUBLE: - value->a_double = va_arg (vaargs, double); - break; + case VALTYPE_DOUBLE: + value->a_double = va_arg (vaargs, double); + break; #ifdef HAVE_LONG_DOUBLE - case VALTYPE_LONGDOUBLE: - value->a_longdouble = va_arg (vaargs, long double); - break; + case VALTYPE_LONGDOUBLE: + value->a_longdouble = va_arg (vaargs, long double); + break; #endif - case VALTYPE_STRING: - value->a_string = va_arg (vaargs, const char *); - break; - case VALTYPE_POINTER: - value->a_void_ptr = va_arg (vaargs, void *); - break; + case VALTYPE_STRING: + value->a_string = va_arg (vaargs, const char *); + break; + case VALTYPE_POINTER: + value->a_void_ptr = va_arg (vaargs, void *); + break; #ifdef HAVE_INTMAX_T - case VALTYPE_INTMAX: - value->a_intmax = va_arg (vaargs, intmax_t); - break; - case VALTYPE_INTMAX_PTR: - value->a_intmax_ptr = va_arg (vaargs, intmax_t *); - break; + case VALTYPE_INTMAX: + value->a_intmax = va_arg (vaargs, intmax_t); + break; + case VALTYPE_INTMAX_PTR: + value->a_intmax_ptr = va_arg (vaargs, intmax_t *); + break; #endif #ifdef HAVE_UINTMAX_T - case VALTYPE_UINTMAX: - value->a_uintmax = va_arg (vaargs, uintmax_t); - break; + case VALTYPE_UINTMAX: + value->a_uintmax = va_arg (vaargs, uintmax_t); + break; #endif - case VALTYPE_SIZE: - value->a_size = va_arg (vaargs, size_t); - break; - case VALTYPE_SIZE_PTR: - value->a_size_ptr = va_arg (vaargs, size_t *); - break; + case VALTYPE_SIZE: + value->a_size = va_arg (vaargs, size_t); + break; + case VALTYPE_SIZE_PTR: + value->a_size_ptr = va_arg (vaargs, size_t *); + break; #ifdef HAVE_PTRDIFF_T - case VALTYPE_PTRDIFF: - value->a_ptrdiff = va_arg (vaargs, ptrdiff_t); - break; - case VALTYPE_PTRDIFF_PTR: - value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *); - break; + case VALTYPE_PTRDIFF: + value->a_ptrdiff = va_arg (vaargs, ptrdiff_t); + break; + case VALTYPE_PTRDIFF_PTR: + value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *); + break; #endif - default: /* Unsupported type. */ - return -1; - } + default: /* Unsupported type. */ + return -1; } } return 0; From cvs at cvs.gnupg.org Wed Aug 1 20:26:02 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 01 Aug 2007 20:26:02 +0200 Subject: [svn] GnuPG - r4555 - trunk/scd Message-ID: Author: wk Date: 2007-08-01 20:25:32 +0200 (Wed, 01 Aug 2007) New Revision: 4555 Modified: trunk/scd/ChangeLog trunk/scd/apdu.c Log: Applied exact length hack. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2007-08-01 18:13:31 UTC (rev 4554) +++ trunk/scd/ChangeLog 2007-08-01 18:25:32 UTC (rev 4555) @@ -1,3 +1,8 @@ +2007-08-01 Werner Koch + + * apdu.c (send_le): Implement exact length hack. Suggested by + Sten Lindgren. + 2007-07-05 Werner Koch * command.c (has_option_name, skip_options): New. Modified: trunk/scd/apdu.c =================================================================== --- trunk/scd/apdu.c 2007-08-01 18:13:31 UTC (rev 4554) +++ trunk/scd/apdu.c 2007-08-01 18:25:32 UTC (rev 4555) @@ -2609,7 +2609,8 @@ unsigned char apdu[5+256+1]; size_t apdulen; int sw; - long rc; /* we need a long here due to PC/SC. */ + long rc; /* We need a long here due to PC/SC. */ + int did_exact_length_hack = 0; if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; @@ -2648,6 +2649,7 @@ assert (sizeof (apdu) >= apdulen); /* As safeguard don't pass any garbage from the stack to the driver. */ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + exact_length_hack: resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo); if (rc || resultlen < 2) @@ -2658,7 +2660,14 @@ return rc? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; - /* store away the returned data but strip the statusword. */ + if (!did_exact_length_hack && SW_EXACT_LENGTH_P (sw)) + { + apdu[apdulen-1] = (sw & 0x00ff); + did_exact_length_hack = 1; + goto exact_length_hack; + } + + /* Store away the returned data but strip the statusword. */ resultlen -= 2; if (DBG_CARD_IO) { From cvs at cvs.gnupg.org Thu Aug 2 15:17:55 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Thu, 02 Aug 2007 15:17:55 +0200 Subject: [svn] GnuPG - r4556 - branches/STABLE-BRANCH-1-4/m4 Message-ID: Author: dshaw Date: 2007-08-02 15:17:27 +0200 (Thu, 02 Aug 2007) New Revision: 4556 Modified: branches/STABLE-BRANCH-1-4/m4/ChangeLog branches/STABLE-BRANCH-1-4/m4/ldap.m4 Log: * ldap.m4: Revert the mozldap change: mozldap has some significant differences around TLS compared to OpenLDAP, and will segfault (!) if the NSS library is not initialized first. Nothing impossible to do, but I think I'll wait until someone actually asks us for mozldap support. Modified: branches/STABLE-BRANCH-1-4/m4/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/m4/ChangeLog 2007-08-01 18:25:32 UTC (rev 4555) +++ branches/STABLE-BRANCH-1-4/m4/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) @@ -1,3 +1,11 @@ +2007-08-02 David Shaw + + * ldap.m4: Revert the mozldap change: mozldap has some significant + differences around TLS compared to OpenLDAP, and will segfault (!) + if the NSS library is not initialized first. Nothing impossible + to do, but I think I'll wait until someone actually asks us for + mozldap support. + 2007-07-27 David Shaw * ldap.m4: If we don't find ldap or winldap, try for mozldap. Modified: branches/STABLE-BRANCH-1-4/m4/ldap.m4 =================================================================== --- branches/STABLE-BRANCH-1-4/m4/ldap.m4 2007-08-01 18:25:32 UTC (rev 4555) +++ branches/STABLE-BRANCH-1-4/m4/ldap.m4 2007-08-02 13:17:27 UTC (rev 4556) @@ -1,5 +1,5 @@ dnl Check for LDAP -dnl Copyright (C) 2005, 2007 Free Software Foundation, Inc. +dnl Copyright (C) 2005 Free Software Foundation, Inc. dnl dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -33,12 +33,11 @@ CPPFLAGS="${LDAP_CPPFLAGS} ${CPPFLAGS}" _ldap_save_ldflags=$LDFLAGS LDFLAGS="${LDAP_LDFLAGS} ${LDFLAGS}" - _ldap_save_libs=$LIBS for MY_LDAPLIBS in ${LDAPLIBS+"$LDAPLIBS"} "-lldap" "-lldap -llber" "-lldap -llber -lresolv" "-lwldap32"; do + _ldap_save_libs=$LIBS + LIBS="$MY_LDAPLIBS $1 $LIBS" - LIBS="$MY_LDAPLIBS $1 $_ldap_save_libs" - AC_MSG_CHECKING([whether LDAP via \"$MY_LDAPLIBS\" is present and sane]) AC_TRY_LINK([ #ifdef _WIN32 @@ -60,62 +59,39 @@ fi if test "$gnupg_cv_func_ldaplber_init" = yes ; then - AC_DEFINE(NEED_LBER_H,1, - [Define if the LDAP library requires including lber.h before ldap.h]) + AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h]) fi if test "$gnupg_cv_func_ldap_init" = yes || \ test "$gnupg_cv_func_ldaplber_init" = yes ; then LDAPLIBS="$LDAP_LDFLAGS $MY_LDAPLIBS" GPGKEYS_LDAP="gpgkeys_ldap$EXEEXT" - break - fi - done - if test "$GPGKEYS_LDAP" = "" ; then - # It didn't work, so try for mozldap. We only do this via - # pkg-config due to a really impressive dependency list. - AC_PATH_PROG([_pkg_config],[pkg-config]) - if test x$_pkg_config != x ; then - AC_MSG_CHECKING([for mozldap]) - LDAPLIBS=`$_pkg_config --libs mozldap 2>/dev/null` - LDAP_CPPFLAGS=`$_pkg_config --cflags mozldap 2>/dev/null` - if test x"$LDAPLIBS" = x && test x"$LDAP_CPPFLAGS" = x; then - AC_MSG_RESULT([no]) - else - AC_MSG_RESULT([yes]) - LIBS="$LDAPLIBS" - GPGKEYS_LDAP="gpgkeys_ldap$EXEEXT" - CPPFLAGS="${LDAP_CPPFLAGS} ${CPPFLAGS}" - AC_CHECK_HEADERS([ldap_ssl.h],,,[#include ]) - fi - fi - fi + AC_CHECK_FUNCS(ldap_get_option ldap_set_option ldap_start_tls_s) - if test "$GPGKEYS_LDAP" != "" ; then - # Whichever library we ended up with, check for some features... - AC_CHECK_FUNCS(ldap_get_option ldap_set_option ldap_start_tls_s) + if test "$ac_cv_func_ldap_get_option" != yes ; then + AC_MSG_CHECKING([whether LDAP supports ld_errno]) + AC_TRY_LINK([#include ],[LDAP *ldap; ldap->ld_errno;], + [gnupg_cv_func_ldap_ld_errno=yes], + [gnupg_cv_func_ldap_ld_errno=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno]) - if test "$ac_cv_func_ldap_get_option" != yes ; then - AC_MSG_CHECKING([whether LDAP supports ld_errno]) - AC_TRY_LINK([#include ],[LDAP *ldap; ldap->ld_errno;], - [gnupg_cv_func_ldap_ld_errno=yes], - [gnupg_cv_func_ldap_ld_errno=no]) - AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno]) + if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then + AC_DEFINE(HAVE_LDAP_LD_ERRNO,1,[Define if the LDAP library supports ld_errno]) + fi + fi + fi - if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then - AC_DEFINE(HAVE_LDAP_LD_ERRNO,1, - [Define if the LDAP library supports ld_errno]) - fi - fi - fi + LIBS=$_ldap_save_libs - LIBS=$_ldap_save_libs - CPPFLAGS=$_ldap_save_cppflags - LDFLAGS=$_ldap_save_ldflags + if test "$GPGKEYS_LDAP" != "" ; then break; fi + done AC_SUBST(GPGKEYS_LDAP) AC_SUBST(LDAPLIBS) AC_SUBST(LDAP_CPPFLAGS) + + CPPFLAGS=$_ldap_save_cppflags + LDFLAGS=$_ldap_save_ldflags fi ])dnl From cvs at cvs.gnupg.org Thu Aug 2 16:59:33 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 02 Aug 2007 16:59:33 +0200 Subject: [svn] gpgme - r1243 - in trunk: assuan gpgme Message-ID: Author: wk Date: 2007-08-02 16:59:01 +0200 (Thu, 02 Aug 2007) New Revision: 1243 Modified: trunk/assuan/ChangeLog trunk/assuan/assuan-logging.c trunk/assuan/assuan-pipe-connect.c trunk/assuan/assuan.h trunk/gpgme/ChangeLog trunk/gpgme/debug.c trunk/gpgme/debug.h trunk/gpgme/gpgme.h trunk/gpgme/version.c trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-io.c Log: Improved debug support: Assuan logging is now directed to the gpgme debug stream. Create processes detached. Modified: trunk/assuan/ChangeLog =================================================================== --- trunk/assuan/ChangeLog 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/assuan/ChangeLog 2007-08-02 14:59:01 UTC (rev 1243) @@ -1,3 +1,11 @@ +2007-08-02 Werner Koch + + * assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. + (pipe_connect_w32): Use DETACHED_PROCESS flag. + * assuan-logging.c (log_level): New. Use this to disable logging. + (assuan_set_assuan_log_level): New. + * assuan.h: Add prototype. + 2007-07-12 Werner Koch * assuan-handler.c (assuan_get_active_fds): Use get_osfhandle for Modified: trunk/assuan/assuan-logging.c =================================================================== --- trunk/assuan/assuan-logging.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/assuan/assuan-logging.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -37,7 +37,24 @@ static char prefix_buffer[80]; static FILE *_assuan_log; static int full_logging; +static int log_level = 1; /* Defaults to logging enabled. */ + +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previosu log level. */ +int +assuan_set_assuan_log_level (int level) +{ + int old = log_level; + + if (level != -1) + log_level = level; + return old; +} + + void _assuan_set_default_log_stream (FILE *fp) { @@ -105,6 +122,9 @@ FILE *fp; const char *prf; int save_errno = errno; + + if (!log_level) + return; fp = assuan_get_assuan_log_stream (); prf = assuan_get_assuan_log_prefix (); @@ -128,6 +148,9 @@ const unsigned char *s; int n; + if (!log_level) + return; + for (n=length,s=buffer; n; n--, s++) if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80)) break; @@ -166,11 +189,16 @@ _assuan_log_sanitized_string (const char *string) { const unsigned char *s = (const unsigned char *) string; - FILE *fp = assuan_get_assuan_log_stream (); + FILE *fp; - if (! *s) + if (!log_level) return; + if (!*s) + return; + + fp = assuan_get_assuan_log_stream (); + #ifdef HAVE_FLOCKFILE flockfile (fp); #endif Modified: trunk/assuan/assuan-pipe-connect.c =================================================================== --- trunk/assuan/assuan-pipe-connect.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/assuan/assuan-pipe-connect.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -641,6 +641,9 @@ w = h; } + _assuan_log_printf ("created pipe: read=%p%s, write=%p%s\n", + r, for_write? " (inherit)":"", + w, for_write? "":" (inherit)"); filedes[0] = handle_to_fd (r); filedes[1] = handle_to_fd (w); return 0; @@ -752,6 +755,7 @@ nullfd = CreateFile ("nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + _assuan_log_printf ("created nul device, hd=%p\n", nullfd); if (nullfd == INVALID_HANDLE_VALUE) { _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1)); @@ -772,14 +776,17 @@ /* Note: We inherit all handles flagged as inheritable. This seems to be a security flaw but there seems to be no way of selecting handles to inherit. */ - /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */ - /* name, cmdline); */ + _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", + name, cmdline); + _assuan_log_printf (" stdin=%p stdout=%p stderr=%p\n", + si.hStdInput, si.hStdOutput, si.hStdError); if (!CreateProcess (name, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ &sec_attr, /* Thread security attributes. */ TRUE, /* Inherit handles. */ (CREATE_DEFAULT_ERROR_MODE + | DETACHED_PROCESS | GetPriorityClass (GetCurrentProcess ()) | CREATE_SUSPENDED), /* Creation flags. */ NULL, /* Environment. */ @@ -807,13 +814,15 @@ nullfd = INVALID_HANDLE_VALUE; } + _assuan_log_printf ("closing handles %p and %p\n", + fd_to_handle (rp[1]), fd_to_handle (wp[0]) ); CloseHandle (fd_to_handle (rp[1])); CloseHandle (fd_to_handle (wp[0])); - /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); ResumeThread (pi.hThread); CloseHandle (pi.hThread); Modified: trunk/assuan/assuan.h =================================================================== --- trunk/assuan/assuan.h 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/assuan/assuan.h 2007-08-02 14:59:01 UTC (rev 1243) @@ -137,6 +137,7 @@ #define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd) #define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd) #define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks) +#define assuan_set_assuan_log_level _ASSUAN_PREFIX(assuan_set_assuan_log_level) #define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream) #define assuan_set_error _ASSUAN_PREFIX(assuan_set_error) #define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer) @@ -532,6 +533,14 @@ /*-- assuan-logging.c --*/ +/* Set the log level for general assuan commands. 0 is no logging at + all, 1 is the standard logging and the default. Higher leveles may + be defined in the future. Passing a level of -1 will not change + the current log level. Returns previous log level. Note, that + this function is not thread-safe and should in general be used + right at startup. */ +int assuan_set_assuan_log_level (int level); + /* Set the stream to which assuan should log message not associated with a context. By default, this is stderr. The default value will be changed when the first log stream is associated with a Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/ChangeLog 2007-08-02 14:59:01 UTC (rev 1243) @@ -1,3 +1,15 @@ +2007-08-02 Werner Koch + + * w32-glib-io.c (_gpgme_io_spawn): Use DETACHED_PROCESS flag. + * w32-io.c (_gpgme_io_spawn): Ditto. + (_gpgme_io_write): Map ERROR_NO_DATA to EPIPE. + * debug.c (_gpgme_debug): Enable assuan logging. + (_gpgme_debug_subsystem_init): New. * version.c + (do_subsystem_inits): Disable assuan logging and initialize de + debug system. + (gpgme_check_version): Do not trace before the subsystems are + initialized. + 2007-07-17 Marcus Brinkmann * debug.c:;5B Include and "debug.h". @@ -5394,7 +5406,7 @@ * data.c (gpgme_data_rewind): Allow to rewind data_type_none. - Copyright 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + Copyright 2001,2002,2003,2004,2005,2006,2007 g10 Code GmbH This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without Modified: trunk/gpgme/debug.c =================================================================== --- trunk/gpgme/debug.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/debug.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -16,8 +16,8 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ #if HAVE_CONFIG_H #include @@ -30,12 +30,16 @@ #include #include #ifndef HAVE_DOSISH_SYSTEM - #include - #include - #include +# include +# include +# include #endif #include +#ifdef HAVE_ASSUAN_H +#include "assuan.h" +#endif + #include "util.h" #include "sema.h" #include "debug.h" @@ -138,11 +142,29 @@ } if (debug_level > 0) - fprintf (errfp, "gpgme_debug: level=%d\n", debug_level); + fprintf (errfp, "gpgme_debug: level=%d\n", debug_level); +#ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_prefix ("gpgme-assuan"); + assuan_set_assuan_log_stream (errfp); + assuan_set_assuan_log_level (debug_level >= 0? debug_level:0); +#endif /* HAVE_ASSUAN_H*/ } UNLOCK (debug_lock); } + + +/* This should be called as soon as the locks are intialized. It is + required so that the assuan logging gets conncted to the gpgme log + stream as early as possible. */ +void +_gpgme_debug_subsystem_init (void) +{ + debug_init (); +} + + + /* Log the formatted string FORMAT at debug level LEVEL or higher. */ void Modified: trunk/gpgme/debug.h =================================================================== --- trunk/gpgme/debug.h 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/debug.h 2007-08-02 14:59:01 UTC (rev 1243) @@ -50,6 +50,9 @@ return s? s+1:file; } +/* Called early to initialize the logging. */ +void _gpgme_debug_subsystem_init (void); + /* Log the formatted string FORMAT at debug level LEVEL or higher. */ void _gpgme_debug (int level, const char *format, ...); Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/gpgme.h 2007-08-02 14:59:01 UTC (rev 1243) @@ -16,8 +16,8 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ #ifndef GPGME_H #define GPGME_H Modified: trunk/gpgme/version.c =================================================================== --- trunk/gpgme/version.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/version.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -55,18 +55,20 @@ return; _gpgme_sema_subsystem_init (); - _gpgme_io_subsystem_init (); #ifdef HAVE_ASSUAN_H + assuan_set_assuan_log_level (0); assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME); -#ifdef HAVE_W32_SYSTEM +#endif /*HAVE_ASSUAN_H*/ + _gpgme_debug_subsystem_init (); +#if defined(HAVE_W32_SYSTEM) && defined(HAVE_ASSUAN_H) + _gpgme_io_subsystem_init (); /* We need to make sure that the sockets are initialized. */ { WSADATA wsadat; WSAStartup (0x202, &wsadat); } -#endif /*HAVE_W32_SYSTEM*/ -#endif /*HAVE_ASSUAN_H*/ +#endif /*HAVE_W32_SYSTEM && HAVE_ASSUAN_H*/ done = 1; } @@ -170,10 +172,15 @@ const char * gpgme_check_version (const char *req_version) { + do_subsystem_inits (); + + /* Catch-22: We need to get at least the debug subsystem ready + before using the tarce facility. If we won't the tarce would + automagically initialize the debug system with out the locks + being initialized and missing the assuan log level setting. */ TRACE2 (DEBUG_INIT, "gpgme_check_version: ", 0, "req_version=%s, VERSION=%s", req_version, VERSION); - - do_subsystem_inits (); + return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL; } Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/w32-glib-io.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -522,7 +522,8 @@ } } - cr_flags |= CREATE_SUSPENDED; + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; if (!CreateProcessA (path, arg_string, &sec_attr, /* process security attributes */ Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-07-17 12:42:42 UTC (rev 1242) +++ trunk/gpgme/w32-io.c 2007-08-02 14:59:01 UTC (rev 1243) @@ -752,7 +752,10 @@ if (ctx->error) { UNLOCK (ctx->mutex); - errno = ctx->error_code; + if (ctx->error_code == ERROR_NO_DATA) + errno = EPIPE; + else + errno = EIO; return TRACE_SYSRES (-1); } @@ -1104,6 +1107,7 @@ } cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; if (!CreateProcessA (path, arg_string, &sec_attr, /* process security attributes */ From cvs at cvs.gnupg.org Thu Aug 2 20:13:16 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 02 Aug 2007 20:13:16 +0200 Subject: [svn] GnuPG - r4557 - in trunk: . agent common doc g10 jnlib scd sm tools Message-ID: Author: wk Date: 2007-08-02 20:12:43 +0200 (Thu, 02 Aug 2007) New Revision: 4557 Added: trunk/common/gc-opt-flags.h Modified: trunk/THANKS trunk/TODO trunk/agent/ChangeLog trunk/agent/gpg-agent.c trunk/common/ChangeLog trunk/common/Makefile.am trunk/doc/ChangeLog trunk/doc/scdaemon.texi trunk/g10/ChangeLog trunk/g10/gpg.c trunk/jnlib/ChangeLog trunk/jnlib/stringhelp.c trunk/jnlib/t-stringhelp.c trunk/scd/ChangeLog trunk/scd/scdaemon.c trunk/sm/ChangeLog trunk/sm/gpgsm.c trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Factored common gpgconf constants out Fixed W32 compare_filenames Modified: trunk/THANKS =================================================================== --- trunk/THANKS 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/THANKS 2007-08-02 18:12:43 UTC (rev 4557) @@ -214,6 +214,7 @@ Sebastian Klemke packet at convergence.de Serge Munhoven munhoven at mema.ucl.ac.be SL Baur steve at xemacs.org +Sten Lindgren ged at solace dot miun dot se Stefan Bellon sbellon at sbellon.de Dr.Stefan.Dalibor Dr.Stefan.Dalibor at bfa.de Stefan Karrmann S.Karrmann at gmx.net Modified: trunk/TODO =================================================================== --- trunk/TODO 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/TODO 2007-08-02 18:12:43 UTC (rev 4557) @@ -125,3 +125,10 @@ ** Migrate OpenPGP keys to another system +* do_add_recipient + Prints wrong error message even when decrypting. + *Decrypt* does even not work in this case. + +* Duplicate certifciates + This may happen and lead to an Ambiguous Name error. Solution is to + check the certs for identity beforethorwin this error. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/agent/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,8 @@ +2007-08-02 Werner Koch + + * gpg-agent.c: Include gc-opt-flags.h and remove their definition + here. + 2007-07-13 Werner Koch * genkey.c (check_passphrase_constraints): Require a confirmation Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/agent/gpg-agent.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -48,6 +48,7 @@ # include "../jnlib/w32-afunix.h" #endif #include "setenv.h" +#include "gc-opt-flags.h" enum cmd_and_opt_values @@ -698,24 +699,6 @@ char *filename_esc; /* List options and default values in the GPG Conf format. */ - - /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ - /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL - /* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - /* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - /* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) - /* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - filename = make_filename (opt.homedir, "gpg-agent.conf", NULL ); filename_esc = percent_escape (filename, NULL); Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/common/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,7 @@ +2007-08-02 Werner Koch + + * gc-opt-flags.h: New. + 2007-08-01 Werner Koch * estream-printf.c (read_dummy_value): Removed as it is useless now. Modified: trunk/common/Makefile.am =================================================================== --- trunk/common/Makefile.am 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/common/Makefile.am 2007-08-02 18:12:43 UTC (rev 4557) @@ -33,6 +33,7 @@ util.h i18n.c i18n.h \ errors.h \ openpgpdefs.h \ + gc-opt-flags.h \ keyserver.h \ sexp-parse.h \ init.c init.h \ Added: trunk/common/gc-opt-flags.h =================================================================== --- trunk/common/gc-opt-flags.h 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/common/gc-opt-flags.h 2007-08-02 18:12:43 UTC (rev 4557) @@ -0,0 +1,40 @@ +/* gc-opt-flags.h - gpgconf constants used by the backends. + * Copyright (C) 2004, 2007 Free Software Foundation, Inc. + * + * This file is free software; as a special exception the author gives + * unlimited permission to copy and/or distribute it, with or without + * modifications, as long as this notice is preserved. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY, to the extent permitted by law; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +#ifndef GNUPG_GC_OPT_FLAGS_H +#define GNUPG_GC_OPT_FLAGS_H + +/* Public option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE + EXISTING FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. See + gnupg/tools/gpgconf-comp.c for details. */ + +#define GC_OPT_FLAG_NONE 0UL + +/* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + +/* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + +/* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + +/* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + +#endif /*GNUPG_GC_OPT_FLAGS_H*/ Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/doc/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,7 @@ +2007-07-23 Werner Koch + + * scdaemon.texi (Scdaemon Commands): Remove obsolete --print-atr. + 2007-07-17 Werner Koch * gpgsm.texi (Input and Output): Document --default-key. Modified: trunk/doc/scdaemon.texi =================================================================== --- trunk/doc/scdaemon.texi 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/doc/scdaemon.texi 2007-08-02 18:12:43 UTC (rev 4557) @@ -93,11 +93,6 @@ Run the program in the background. This option is required to prevent it from being accidently running in the background. - at item --print-atr - at opindex print-atr -This is mainly a debugging command, used to print the ATR -(Answer-To-Reset) of a card and exit immediately. - @end table Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/g10/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,7 @@ +2007-08-02 Werner Koch + + * gpg.c: Include gc-opt-flags.h and remove their definition here. + 2007-07-17 Werner Koch * gpg.c (gpgconf_list): Declare --encrypt-to and --default-key. Modified: trunk/g10/gpg.c =================================================================== --- trunk/g10/gpg.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/g10/gpg.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -55,8 +55,8 @@ #include "status.h" #include "keyserver-internal.h" #include "exec.h" +#include "gc-opt-flags.h" - #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) #define MY_O_BINARY O_BINARY #ifndef S_IRGRP @@ -1457,10 +1457,6 @@ { char *configfile_esc = percent_escape (configfile, NULL); - /* The following definitions are taken from gnupg/tools/gpgconf-comp.c. */ -#define GC_OPT_FLAG_NONE 0UL -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - printf ("gpgconf-gpg.conf:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, configfile_esc ? configfile_esc : "/dev/null"); printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE); Modified: trunk/jnlib/ChangeLog =================================================================== --- trunk/jnlib/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/jnlib/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,11 @@ +2007-08-02 Werner Koch + + * t-stringhelp.c (test_compare_filenames): New. + + * stringhelp.c (compare_filenames) [HAVE_DRIVE_LETTERS]: Fixed + comparison to take slash and backslash in account. + (make_filename): Avoid mixing / and \. + 2007-07-04 Werner Koch * utf8conv.c (load_libiconv): Remove URL from translatble string. Modified: trunk/jnlib/stringhelp.c =================================================================== --- trunk/jnlib/stringhelp.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/jnlib/stringhelp.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -271,10 +271,10 @@ char *p; if ( !(p=strrchr(filepath, '/')) ) - #ifdef HAVE_DRIVE_LETTERS +#ifdef HAVE_DRIVE_LETTERS if ( !(p=strrchr(filepath, '\\')) ) if ( !(p=strrchr(filepath, ':')) ) - #endif +#endif { return jnlib_xstrdup("."); } @@ -296,42 +296,67 @@ char * make_filename( const char *first_part, ... ) { - va_list arg_ptr ; - size_t n; - const char *s; - char *name, *home, *p; + va_list arg_ptr ; + size_t n; + const char *s; + char *name, *home, *p; + + va_start (arg_ptr, first_part); + n = strlen (first_part) + 1; + while ( (s = va_arg (arg_ptr, const char *)) ) + n += strlen(s) + 1; + va_end(arg_ptr); + + home = NULL; + if ( *first_part == '~' && first_part[1] == '/' + && (home = getenv("HOME")) && *home ) + n += strlen (home); + + name = jnlib_xmalloc (n); + p = (home + ? stpcpy (stpcpy (name,home), first_part + 1) + : stpcpy(name, first_part)); - va_start( arg_ptr, first_part ) ; - n = strlen(first_part)+1; - while( (s=va_arg(arg_ptr, const char *)) ) - n += strlen(s) + 1; - va_end(arg_ptr); + va_start (arg_ptr, first_part) ; + while ( (s = va_arg(arg_ptr, const char *)) ) + p = stpcpy (stpcpy (p,"/"), s); + va_end(arg_ptr); - home = NULL; - if( *first_part == '~' && first_part[1] == '/' - && (home = getenv("HOME")) && *home ) - n += strlen(home); - - name = jnlib_xmalloc(n); - p = home ? stpcpy(stpcpy(name,home), first_part+1) - : stpcpy(name, first_part); - va_start( arg_ptr, first_part ) ; - while( (s=va_arg(arg_ptr, const char *)) ) - p = stpcpy(stpcpy(p,"/"), s); - va_end(arg_ptr); - - return name; +#ifdef HAVE_DRIVE_LETTERS + /* We better avoid mixing slashes and backslashes and prefer + backslashes. There is usual no problem with mixing them, however + a very few W32 API calls can't grok plain slashes. Printing + filenames with mixed slashes also looks a bit strange. */ + if (strchr (name, '\\')) + { + for (p=name; *p; p++) + if (*p == '/') + *p = '\\'; + } +#endif /*HAVE_DRIVE_LETTERS*/ + return name; } int -compare_filenames( const char *a, const char *b ) +compare_filenames (const char *a, const char *b) { - /* ? check whether this is an absolute filename and - * resolve symlinks? - */ + /* ? check whether this is an absolute filename and resolve + symlinks? */ #ifdef HAVE_DRIVE_LETTERS - return stricmp(a,b); + for ( ; *a && *b; a++, b++ ) + { + if (*a != *b + && (toupper (*(const unsigned char*)a) + != toupper (*(const unsigned char*)b) ) + && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))) + break; + } + if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) + return 0; + else + return (toupper (*(const unsigned char*)a) + - toupper (*(const unsigned char*)b)); #else return strcmp(a,b); #endif Modified: trunk/jnlib/t-stringhelp.c =================================================================== --- trunk/jnlib/t-stringhelp.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/jnlib/t-stringhelp.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -80,12 +80,49 @@ } +static void +test_compare_filenames (void) +{ + struct { + const char *a; + const char *b; + int result; + } tests[] = { + { "", "", 0 }, + { "", "a", -1 }, + { "a", "", 1 }, + { "a", "a", 0 }, + { "a", "aa", -1 }, + { "aa", "a", 1 }, + { "a", "b", -1 }, +#ifdef HAVE_W32_SYSTEM + { "a", "A", 0 }, + { "A", "a", 0 }, + { "foo/bar", "foo\\bar", 0 }, + { "foo\\bar", "foo/bar", 0 }, + { "foo\\", "foo/", 0 }, + { "foo/", "foo\\", 0 }, +#endif /*HAVE_W32_SYSTEM*/ + { NULL, NULL, 0} + }; + int testno, result; + for (testno=0; tests[testno].a; testno++) + { + result = compare_filenames (tests[testno].a, tests[testno].b); + result = result < 0? -1 : result > 0? 1 : 0; + if (result != tests[testno].result) + fail (testno); + } +} + + int main (int argc, char **argv) { test_percent_escape (); + test_compare_filenames (); return 0; } Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/scd/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,8 @@ +2007-08-02 Werner Koch + + * scdaemon.c: Include gc-opt-flags.h and remove their definition + here. + 2007-08-01 Werner Koch * apdu.c (send_le): Implement exact length hack. Suggested by Modified: trunk/scd/scdaemon.c =================================================================== --- trunk/scd/scdaemon.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/scd/scdaemon.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,5 +1,6 @@ /* scdaemon.c - The GnuPG Smartcard Daemon - * Copyright (C) 2001, 2002, 2004, 2005, 2007 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2005, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -51,7 +52,9 @@ #endif #include "ccid-driver.h" #include "mkdtemp.h" +#include "gc-opt-flags.h" + enum cmd_and_opt_values { aNull = 0, oCsh = 'c', @@ -545,22 +548,6 @@ char *filename = NULL; char *filename_esc; - /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ - /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL - /* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - /* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - /* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) - /* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) if (!config_filename) filename = make_filename (opt.homedir, "scdaemon.conf", NULL ); filename_esc = percent_escape (filename, NULL); Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/sm/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,7 @@ +2007-08-02 Werner Koch + + * gpgsm.c (main): Factored GC_OPT_FLAGS out to gc-opt-flags.h. + 2007-07-17 Werner Koch * gpgsm.c (main): Implement --default-key. Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/sm/gpgsm.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -36,6 +36,7 @@ #include "i18n.h" #include "keydb.h" #include "sysutils.h" +#include "gc-opt-flags.h" #ifndef O_BINARY @@ -1292,17 +1293,18 @@ gpgsm_exit(2); /* Set the random seed file. */ - if (use_random_seed) { - char *p = make_filename (opt.homedir, "random_seed", NULL); - gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); - xfree(p); - } - - + if (use_random_seed) + { + char *p = make_filename (opt.homedir, "random_seed", NULL); + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); + xfree(p); + } + if (!cmd && opt.fingerprint && !with_fpr) set_cmd (&cmd, aListKeys); - if (!nrings && default_keyring) /* Add default keybox. */ + /* Add default keybox. */ + if (!nrings && default_keyring) { int created; @@ -1353,7 +1355,7 @@ } /* Build the recipient list. We first add the regular ones and then - the encrypt-to ones because the underlying function will silenty + the encrypt-to ones because the underlying function will silently ignore duplicates and we can't allow to keep a duplicate which is flagged as encrypt-to as the actually encrypt function would then complain about no (regular) recipients. */ @@ -1369,7 +1371,7 @@ } if (log_get_errorcount(0)) - gpgsm_exit(1); /* must stop for invalid recipients */ + gpgsm_exit(1); /* Must stop for invalid recipients. */ fname = argc? *argv : NULL; @@ -1377,24 +1379,6 @@ { case aGPGConfList: { /* List options and default values in the GPG Conf format. */ - - /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ - /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL - /* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - /* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - /* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) - /* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - char *config_filename_esc = percent_escape (opt.config_filename, NULL); printf ("gpgconf-gpgsm.conf:%lu:\"%s\n", Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/tools/ChangeLog 2007-08-02 18:12:43 UTC (rev 4557) @@ -1,3 +1,8 @@ +2007-08-02 Werner Koch + + * gpgconf-comp.c: Factor the public GC_OPT_FLAG constants out and + include gc-opt-flags.h. + 2007-07-17 Werner Koch * gpgconf-comp.c: Add --encrypt-to and --default-key to gpg and Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-08-02 13:17:27 UTC (rev 4556) +++ trunk/tools/gpgconf-comp.c 2007-08-02 18:12:43 UTC (rev 4557) @@ -44,6 +44,7 @@ #include "util.h" #include "i18n.h" +#include "gc-opt-flags.h" #include "gpgconf.h" @@ -308,9 +309,12 @@ }; -/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL +/* Option flags. The flags which are used by the backends are defined + by gc-opt-flags.h, included above. + + YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE + PART OF THE EXTERNAL INTERFACE. */ + /* Some entries in the option list are not options, but mark the beginning of a new group of options. These entries have the GROUP flag set. */ @@ -322,26 +326,13 @@ several times. A comma separated list of arguments is used as the argument value. */ #define GC_OPT_FLAG_LIST (1UL << 2) -/* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - -/* The following flags are incorporated from the backend. */ -/* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) -/* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) -/* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) /* The NO_CHANGE flag for an option indicates that the user should not be allowed to chnage this option using the standard gpgconf method. - Frontends using gpgconf should grey out such otions, so that only + Frontends using gpgconf should grey out such options, so that only the current value is displayed. */ #define GC_OPT_FLAG_NO_CHANGE (1UL <<7) + /* A human-readable description for each flag. */ static struct { From cvs at cvs.gnupg.org Fri Aug 3 10:08:35 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 03 Aug 2007 10:08:35 +0200 Subject: [svn] dirmngr - r257 - trunk/src Message-ID: Author: marcus Date: 2007-08-03 10:08:07 +0200 (Fri, 03 Aug 2007) New Revision: 257 Added: trunk/src/get-path.c Modified: trunk/src/ChangeLog Log: 2007-08-03 Marcus Brinkmann * get-path.c: Really add the file this time. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-07-30 22:19:44 UTC (rev 256) +++ trunk/src/ChangeLog 2007-08-03 08:08:07 UTC (rev 257) @@ -1,3 +1,7 @@ +2007-08-03 Marcus Brinkmann + + * get-path.c: Really add the file this time. + 2007-07-31 Marcus Brinkmann * crlfetch.c: Include "estream.h". Added: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-07-30 22:19:44 UTC (rev 256) +++ trunk/src/get-path.c 2007-08-03 08:08:07 UTC (rev 257) @@ -0,0 +1,366 @@ +/* get-path.c - Utility functions for the W32 API + Copyright (C) 1999 Free Software Foundation, Inc + Copyright (C) 2001 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH + + This file is part of DirMngr. + + DirMngr 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. + + DirMngr 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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_W32_SYSTEM +#include +#include +#include +#endif + +#include "util.h" + +#ifdef HAVE_W32_SYSTEM +#define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" +#elif defined(__VMS) +#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg" +#else +#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" +#endif + + +#if HAVE_W32_SYSTEM +#define RTLD_LAZY 0 + +static __inline__ void * +dlopen (const char * name, int flag) +{ + void * hd = LoadLibrary (name); + return hd; +} + +static __inline__ void * +dlsym (void * hd, const char * sym) +{ + if (hd && sym) + { + void * fnc = GetProcAddress (hd, sym); + if (!fnc) + return NULL; + return fnc; + } + return NULL; +} + +static __inline__ int +dlclose (void * hd) +{ + if (hd) + { + FreeLibrary (hd); + return 0; + } + return -1; +} + + +/* Return a string from the W32 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. */ +static 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 ) + 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; + + 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 HKLM. */ + 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 ) ) + { + if (root) + goto leave; + /* Try to fallback to HKLM also vor a missing value. */ + RegCloseKey (key_handle); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* Nope. */ + 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; +} + + +/* This is a helper function to load and run a Windows function from + either of one DLLs. */ +static HRESULT +w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) +{ + static int initialized; + static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR); + + if (!initialized) + { + static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL }; + void *handle; + int i; + + initialized = 1; + + for (i=0, handle = NULL; !handle && dllnames[i]; i++) + { + handle = dlopen (dllnames[i], RTLD_LAZY); + if (handle) + { + func = dlsym (handle, "SHGetFolderPathA"); + if (!func) + { + dlclose (handle); + handle = NULL; + } + } + } + } + + if (func) + return func (a,b,c,d,e); + else + return -1; +} + +static char * +find_program_at_standard_place (const char *name) +{ + char path[MAX_PATH]; + char *result = NULL; + + if (w32_shgetfolderpath (NULL, CSIDL_PROGRAM_FILES, NULL, 0, path) >= 0) + { + result = malloc (strlen (path) + 1 + strlen (name) + 1); + if (result) + { + strcpy (stpcpy (stpcpy (result, path), "\\"), name); + if (access (result, F_OK)) + { + free (result); + result = NULL; + } + } + } + return result; +} +#endif + + +const char * +get_dirmngr_ldap_path (void) +{ + static char *pgmname; + +#ifdef HAVE_W32_SYSTEM + if (!pgmname) + pgmname = find_program_at_standard_place ("GNU\\GnuPG\\dirmngr_ldap.exe"); +#endif + if (!pgmname) + pgmname = DIRMNGR_LIBEXECDIR "/dirmngr_ldap"; + return pgmname; +} + + + +/* Home directory. */ + +#ifdef HAVE_W32_SYSTEM +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif +#endif /*HAVE_W32_SYSTEM*/ + +/* Get the standard home directory. In general this function should + not be used as it does not consider a registry value (under W32) or + the GNUPGHOME encironment variable. It is better to use + default_homedir(). */ +const char * +standard_homedir (void) +{ +#ifdef HAVE_W32_SYSTEM + static const char *dir; + + if (!dir) + { + char path[MAX_PATH]; + + /* It might be better to use LOCAL_APPDATA because this is + defined as "non roaming" and thus more likely to be kept + locally. For private keys this is desired. However, given + that many users copy private keys anyway forth and back, + using a system roaming services might be better than to let + them do it manually. A security conscious user will anyway + use the registry entry to have better control. */ + if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) + { + char *tmp = xmalloc (strlen (path) + 6 +1); + strcpy (stpcpy (tmp, path), "\\gnupg"); + dir = tmp; + + /* Try to create the directory if it does not yet exists. */ + if (access (dir, F_OK)) + CreateDirectory (dir, NULL); + } + else + dir = GNUPG_DEFAULT_HOMEDIR; + } + return dir; +#else/*!HAVE_W32_SYSTEM*/ + return GNUPG_DEFAULT_HOMEDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + +/* Set up the default home directory. The usual --homedir option + should be parsed later. */ +const char * +default_homedir (void) +{ + const char *dir; + + dir = getenv ("GNUPGHOME"); +#ifdef HAVE_W32_SYSTEM + if (!dir || !*dir) + { + static const char *saved_dir; + + if (!saved_dir) + { + if (!dir || !*dir) + { + char *tmp; + + tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", + "HomeDir"); + if (tmp && *tmp) + { + xfree (tmp); + tmp = NULL; + } + if (tmp) + saved_dir = tmp; + } + + if (!saved_dir) + saved_dir = standard_homedir (); + } + dir = saved_dir; + } +#endif /*HAVE_W32_SYSTEM*/ + if (!dir || !*dir) + dir = GNUPG_DEFAULT_HOMEDIR; + + return dir; +} From cvs at cvs.gnupg.org Fri Aug 3 10:29:01 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 03 Aug 2007 10:29:01 +0200 Subject: [svn] gpg-error - r195 - in trunk: . lang/cl Message-ID: Author: marcus Date: 2007-08-03 10:28:32 +0200 (Fri, 03 Aug 2007) New Revision: 195 Modified: trunk/ChangeLog trunk/autogen.sh trunk/configure.ac trunk/lang/cl/Makefile.am Log: 2007-08-03 Marcus Brinkmann * configure.ac: Call AM_PROG_CC_C_O. * autogen.sh: Use = not == in test. * lang/cl/Makefile.am: Do not use :=, but =. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-06-27 19:59:00 UTC (rev 194) +++ trunk/ChangeLog 2007-08-03 08:28:32 UTC (rev 195) @@ -1,3 +1,9 @@ +2007-08-03 Marcus Brinkmann + + * configure.ac: Call AM_PROG_CC_C_O. + * autogen.sh: Use = not == in test. + * lang/cl/Makefile.am: Do not use :=, but =. + 2007-05-19 Marcus Brinkmann * lang/cl/gpg-error.lisp (gpg-err-source-t): Add Modified: trunk/autogen.sh =================================================================== --- trunk/autogen.sh 2007-06-27 19:59:00 UTC (rev 194) +++ trunk/autogen.sh 2007-08-03 08:28:32 UTC (rev 195) @@ -30,7 +30,7 @@ DIE=no FORCE= -if test "$1" == "--force"; then +if test "$1" = "--force"; then FORCE=" --force" shift fi Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-06-27 19:59:00 UTC (rev 194) +++ trunk/configure.ac 2007-08-03 08:28:32 UTC (rev 195) @@ -57,6 +57,7 @@ # Checks for programs. AC_PROG_CC +AM_PROG_CC_C_O AC_PROG_CPP AC_PROG_AWK AC_CHECK_TOOL(AR, ar, :) Modified: trunk/lang/cl/Makefile.am =================================================================== --- trunk/lang/cl/Makefile.am 2007-06-27 19:59:00 UTC (rev 194) +++ trunk/lang/cl/Makefile.am 2007-08-03 08:28:32 UTC (rev 195) @@ -32,8 +32,8 @@ EXTRA_DIST = README mkerrcodes.awk CLEANFILES = gpg-error-codes.lisp -codes_file := $(top_srcdir)/src/err-codes.h.in -errno_file := $(top_srcdir)/src/errnos.in +codes_file = $(top_srcdir)/src/err-codes.h.in +errno_file = $(top_srcdir)/src/errnos.in gpg-error-codes.lisp: Makefile mkerrcodes.awk $(codes_file) $(errno_file) echo '@errnos@' | cat $(codes_file) - $(errno_file) \ From cvs at cvs.gnupg.org Fri Aug 3 11:02:02 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 03 Aug 2007 11:02:02 +0200 Subject: [svn] gpg-error - r196 - in trunk: . m4 Message-ID: Author: marcus Date: 2007-08-03 11:01:33 +0200 (Fri, 03 Aug 2007) New Revision: 196 Added: trunk/m4/inttypes-h.m4 trunk/m4/lock.m4 trunk/m4/visibility.m4 Modified: trunk/ChangeLog trunk/Makefile.am trunk/configure.ac Log: 2007-08-03 Marcus Brinkmann * configure.ac: Allow --disable-languages. * Makefile.am [!LANGUAGES_SOME]: Don't add lang to subdirs. * m4/inttypes-h.m4, m4/lock.m4, m4/visibility.m4: New files. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/ChangeLog 2007-08-03 09:01:33 UTC (rev 196) @@ -1,8 +1,10 @@ 2007-08-03 Marcus Brinkmann - * configure.ac: Call AM_PROG_CC_C_O. + * configure.ac: Call AM_PROG_CC_C_O. Allow --disable-languages. * autogen.sh: Use = not == in test. * lang/cl/Makefile.am: Do not use :=, but =. + * Makefile.am [!LANGUAGES_SOME]: Don't add lang to subdirs. + * m4/inttypes-h.m4, m4/lock.m4, m4/visibility.m4: New files. 2007-05-19 Marcus Brinkmann Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/Makefile.am 2007-08-03 09:01:33 UTC (rev 196) @@ -1,5 +1,5 @@ # Makefile.am for libgpg-error. -# Copyright (C) 2003, 2006 g10 Code GmbH +# Copyright (C) 2003, 2006, 2007 g10 Code GmbH # # This file is part of libgpg-error. # @@ -22,9 +22,15 @@ EXTRA_DIST = autogen.sh config.rpath libgpg-error.spec.in -SUBDIRS = m4 src tests po lang +if LANGUAGES_SOME +lang_subdirs = lang +else +lang_subdirs = +endif +SUBDIRS = m4 src tests po $(lang_subdirs) + dist-hook: sed -e 's/@pkg_version@/$(VERSION)/g' \ $(top_srcdir)/libgpg-error.spec.in > $(distdir)/libgpg-error.spec Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/configure.ac 2007-08-03 09:01:33 UTC (rev 196) @@ -151,6 +151,12 @@ AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) +AC_ARG_ENABLE(languages, +[ --disable-languages do not build support for other languages than C]) +AM_CONDITIONAL([LANGUAGES_SOME], [test "x$enable_languages" != xno]) + + + # Substitution AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([po/Makefile.in m4/Makefile]) Added: trunk/m4/inttypes-h.m4 =================================================================== --- trunk/m4/inttypes-h.m4 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/m4/inttypes-h.m4 2007-08-03 09:01:33 UTC (rev 196) @@ -0,0 +1,25 @@ +# inttypes-h.m4 serial 1 (gettext-0.15) +dnl Copyright (C) 1997-2002, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H if exists and doesn't clash with +# . + +AC_DEFUN([gl_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, + [ + AC_TRY_COMPILE( + [#include +#include ], + [], gl_cv_header_inttypes_h=yes, gl_cv_header_inttypes_h=no) + ]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, + [Define if exists and doesn't clash with .]) + fi +]) Added: trunk/m4/lock.m4 =================================================================== --- trunk/m4/lock.m4 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/m4/lock.m4 2007-08-03 09:01:33 UTC (rev 196) @@ -0,0 +1,289 @@ +# lock.m4 serial 2 (gettext-0.15) +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_LOCK_BODY]) +]) + +dnl The guts of gl_LOCK. Needs to be expanded only once. + +AC_DEFUN([gl_LOCK_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_GNU_SOURCE]) dnl needed for pthread_rwlock_t on glibc systems + dnl Check for multithreading. + AC_ARG_ENABLE(threads, +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + gl_use_threads=$enableval, gl_use_threads=yes) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_MSG_CHECKING([whether imported symbols can be declared weak]) + gl_have_weak=no + AC_TRY_LINK([extern void xyzzy (); +#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes]) + AC_MSG_RESULT([$gl_have_weak]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . + gl_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no) + CPPFLAGS="$gl_save_CPPFLAGS" + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_TRY_LINK([#include ], + [pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB(pthread, pthread_kill, + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1, + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB(pthread, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB(c_r, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], 1, + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], 1, + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1, + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_TRY_COMPILE([#include ], + [#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +#endif], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1, + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_TRY_LINK([#include +#include ], + [thr_self();], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], 1, + [Define if the old Solaris multithreading library can be used.]) + if test $gl_have_weak = yes; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1, + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS(pth) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_TRY_LINK([#include ], [pth_self();], gl_have_pth=yes) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], 1, + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_PTH_THREADS_WEAK], 1, + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], 1, + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST(LIBTHREAD) + AC_SUBST(LTLIBTHREAD) + AC_SUBST(LIBMULTITHREAD) + AC_SUBST(LTLIBMULTITHREAD) + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. Added: trunk/m4/visibility.m4 =================================================================== --- trunk/m4/visibility.m4 2007-08-03 08:28:32 UTC (rev 195) +++ trunk/m4/visibility.m4 2007-08-03 09:01:33 UTC (rev 196) @@ -0,0 +1,52 @@ +# visibility.m4 serial 1 (gettext-0.15) +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL(gl_cv_cc_visibility, [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + AC_TRY_COMPILE( + [extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void);], + [], + gl_cv_cc_visibility=yes, + gl_cv_cc_visibility=no) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) From cvs at cvs.gnupg.org Sat Aug 4 05:40:05 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Sat, 04 Aug 2007 05:40:05 +0200 Subject: [svn] dirmngr - r258 - trunk/src Message-ID: Author: marcus Date: 2007-08-04 05:39:35 +0200 (Sat, 04 Aug 2007) New Revision: 258 Modified: trunk/src/ChangeLog trunk/src/dirmngr.c trunk/src/dirmngr.h trunk/src/get-path.c trunk/src/util.h Log: 2007-08-04 Marcus Brinkmann * dirmngr.h (opt): Add member system_service. * dirmngr.c (opts) [HAVE_W32_SYSTEM]: New entry for option --service. (DEFAULT_SOCKET_NAME): Removed. (service_handle, service_status, w32_service_control) [HAVE_W32_SYSTEM]: New symbols. (main) [HAVE_W32_SYSTEM]: New entry point for --service. Rename old function to ... (real_main) [HAVE_W32_SYSTEM]: ... this. Use default_socket_name instead of DEFAULT_SOCKET_NAME, and similar for other paths. Allow colons in Windows socket path name, and implement --service option. * util.h (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir, dirmngr_cachedir, default_socket_name): New prototypes. * get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir, dirmngr_cachedir, default_socket_name): New functions. (DIRSEP_C, DIRSEP_S): New macros. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-03 08:08:07 UTC (rev 257) +++ trunk/src/ChangeLog 2007-08-04 03:39:35 UTC (rev 258) @@ -1,3 +1,24 @@ +2007-08-04 Marcus Brinkmann + + * dirmngr.h (opt): Add member system_service. + * dirmngr.c (opts) [HAVE_W32_SYSTEM]: New entry for option + --service. + (DEFAULT_SOCKET_NAME): Removed. + (service_handle, service_status, + w32_service_control) [HAVE_W32_SYSTEM]: New symbols. + (main) [HAVE_W32_SYSTEM]: New entry point for --service. Rename + old function to ... + (real_main) [HAVE_W32_SYSTEM]: ... this. Use default_socket_name + instead of DEFAULT_SOCKET_NAME, and similar for other paths. + Allow colons in Windows socket path name, and implement --service + option. + * util.h (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir, + dirmngr_cachedir, default_socket_name): New prototypes. + * get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir, + dirmngr_datadir, dirmngr_cachedir, default_socket_name): New + functions. + (DIRSEP_C, DIRSEP_S): New macros. + 2007-08-03 Marcus Brinkmann * get-path.c: Really add the file this time. Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-08-03 08:08:07 UTC (rev 257) +++ trunk/src/dirmngr.c 2007-08-04 03:39:35 UTC (rev 258) @@ -66,6 +66,7 @@ aServer, aDaemon, + aService, aListCRLs, aLoadCRL, aFetchCRL, @@ -118,6 +119,9 @@ { aServer, "server", 256, N_("run in server mode (foreground)") }, { aDaemon, "daemon", 256, N_("run in daemon mode (background)") }, +#if HAVE_W32_SYSTEM + { aService, "service", 256, N_("run as windows service (background)") }, +#endif { aListCRLs, "list-crls", 256, N_("list the contents of the CRL cache")}, { aLoadCRL, "load-crl", 256, N_("|FILE|load CRL from FILE into cache")}, { aFetchCRL, "fetch-crl", 256, N_("|URL|fetch a CRL from URL")}, @@ -195,7 +199,6 @@ #define DEFAULT_MAX_REPLIES 10 #define DEFAULT_LDAP_TIMEOUT 100 /* arbitrary large timeout */ -#define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket" /* For the cleanup handler we need to keep track of the socket's name. */ static const char *socket_name; @@ -471,8 +474,43 @@ return 1; /* Handled. */ } + +#ifdef HAVE_W32_SYSTEM +/* The global status of our service. */ +SERVICE_STATUS_HANDLE service_handle; +SERVICE_STATUS service_status; + +DWORD WINAPI +w32_service_control (DWORD control, DWORD event_type, LPVOID event_data, + LPVOID context) +{ + /* event_type and event_data are not used here. */ + switch (control) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + service_status.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus (service_handle, &service_status); + + if (!shutdown_pending) + log_info (_("SIGTERM received - shutting down ...\n")); + shutdown_pending++; + break; + + default: + log_info (_("unhandled control request %lu\n"), control); + break; + } + return 0; +} +#endif + int -main (int argc, char **argv ) +#ifdef HAVE_W32_SYSTEM +real_main (int argc, char **argv) +#else +main (int argc, char **argv) +#endif { enum cmd_and_opt_values cmd = 0; ARGPARSE_ARGS pargs; @@ -494,6 +532,29 @@ int rc; int homedir_seen = 0; +#ifdef HAVE_W32_SYSTEM + /* The option will be set by main() below if we should run as a + system daemon. */ + if (opt.system_service) + { + service_handle + = RegisterServiceCtrlHandlerEx ("DirMngr", + &w32_service_control, NULL /*FIXME*/); + if (service_handle == 0) + log_error ("failed to register service control handler: ec=%d", + (int) GetLastError ()); + service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + service_status.dwCurrentState = SERVICE_START_PENDING; + service_status.dwControlsAccepted + = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + service_status.dwWin32ExitCode = NO_ERROR; + service_status.dwServiceSpecificExitCode = NO_ERROR; + service_status.dwCheckPoint = 0; + service_status.dwWaitHint = 10000; /* 10 seconds timeout. */ + SetServiceStatus (service_handle, &service_status); + } +#endif + set_strusage (my_strusage); log_set_prefix ("dirmngr", 1|4); @@ -555,7 +616,7 @@ opt.ldaptimeout = DEFAULT_LDAP_TIMEOUT; /* Other defaults. */ - socket_name = DEFAULT_SOCKET_NAME; + socket_name = default_socket_name (); /* Check whether we have a config file given on the commandline */ @@ -583,6 +644,12 @@ } else if (pargs.r_opt == aDaemon) opt.system_daemon = 1; + else if (pargs.r_opt == aService) + { + /* Redundant. The main function takes care of it. */ + opt.system_service = 1; + opt.system_daemon = 1; + } } /* If --daemon has been given on the command line but not --homedir, @@ -590,9 +657,9 @@ this also overrides the GNUPGHOME environment variable. */ if (opt.system_daemon && !homedir_seen) { - opt.homedir = DIRMNGR_SYSCONFDIR; - opt.homedir_data = DIRMNGR_DATADIR; - opt.homedir_cache = DIRMNGR_CACHEDIR; + opt.homedir = dirmngr_sysconfdir (); + opt.homedir_data = dirmngr_datadir (); + opt.homedir_cache = dirmngr_cachedir (); } if (default_config) @@ -638,6 +705,7 @@ { case aServer: case aDaemon: + case aService: case aShutdown: case aFlush: case aListCRLs: @@ -803,17 +871,19 @@ current_logfile = xstrdup (logfile); } - if (strchr (socket_name, ':') ) +#ifndef HAVE_W32_SYSTEM + if (strchr (socket_name, ':')) { log_error (_("colons are not allowed in the socket name\n")); dirmngr_exit (1); } +#endif if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) { log_error (_("name of socket too long\n")); dirmngr_exit (1); } - + #ifdef HAVE_W32_SYSTEM fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); #else @@ -951,9 +1021,23 @@ launch_reaper_thread (); cert_cache_init (); crl_cache_init (); +#ifdef HAVE_W32_SYSTEM + if (opt.system_service) + { + service_status.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus (service_handle, &service_status); + } +#endif handle_connections (fd); close (fd); shutdown_reaper (); +#ifdef HAVE_W32_SYSTEM + if (opt.system_service) + { + service_status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus (service_handle, &service_status); + } +#endif } else if (cmd == aListCRLs) { @@ -1094,6 +1178,42 @@ } +#ifdef HAVE_W32_SYSTEM +int +main (int argc, char *argv[]) +{ + int i; + + /* Find out if we run in daemon mode or on the command line. */ + for (i = 1; i < argc; i++) + if (!strcmp (argv[i], "--service")) + { + opt.system_service = 1; + opt.system_daemon = 1; + break; + } + + if (!opt.system_service) + return real_main (argc, argv); + else + { + SERVICE_TABLE_ENTRY DispatchTable [] = + { + /* Ignore warning. */ + { "DirMngr", &real_main }, + { NULL, NULL } + }; + + if (!StartServiceCtrlDispatcher (DispatchTable)) + log_error (_("failed to start service ctrl dispatcher: ec=%d\n"), + (int) GetLastError ()); + + return 0; + } +} +#endif + + static void cleanup (void) { Modified: trunk/src/dirmngr.h =================================================================== --- trunk/src/dirmngr.h 2007-08-03 08:08:07 UTC (rev 257) +++ trunk/src/dirmngr.h 2007-08-04 03:39:35 UTC (rev 258) @@ -72,6 +72,7 @@ char *http_wrapper_program; /* Override value for the HTTP wrapper program. */ + int system_service; /* We are running as W32 service (implies daemon). */ int system_daemon; /* We are running in system daemon mode. */ int running_detached; /* We are running in detached mode. */ Modified: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-08-03 08:08:07 UTC (rev 257) +++ trunk/src/get-path.c 2007-08-04 03:39:35 UTC (rev 258) @@ -48,6 +48,14 @@ #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" #endif +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\' +#define DIRSEP_S "\\" +#else +#define DIRSEP_C '/' +#define DIRSEP_S "/" +#endif + #if HAVE_W32_SYSTEM #define RTLD_LAZY 0 @@ -364,3 +372,140 @@ return dir; } + + +#ifdef HAVE_W32_SYSTEM +static const char * +w32_rootdir (void) +{ + static int got_dir; + static char dir[MAX_PATH+5]; + + if (!got_dir) + { + char *p; + + if ( !GetModuleFileName ( NULL, dir, MAX_PATH) ) + { + log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0)); + *dir = 0; + } + got_dir = 1; + p = strrchr (dir, DIRSEP_C); + if (p) + *p = 0; + else + { + log_debug ("bad filename `%s' returned for this process\n", dir); + *dir = 0; + } + } + + if (*dir) + return dir; + /* Fallback to the hardwired value. */ + return DIRMNGR_LIBEXECDIR; +} +#endif /*HAVE_W32_SYSTEM*/ + + + + +/* Return the name of the sysconfdir. This is a static string. This + function is required because under Windows we can't simply compile + it in. */ +const char * +dirmngr_sysconfdir (void) +{ +#ifdef HAVE_W32_SYSTEM + static char *name; + + if (!name) + { + const char *s1, *s2; + s1 = w32_rootdir (); + s2 = DIRSEP_S "etc" DIRSEP_S "dirmngr"; + name = xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (stpcpy (name, s1), s2); + } + return name; +#else /*!HAVE_W32_SYSTEM*/ + return DIRMNGR_SYSCONFDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Return the name of the libexec directory. The name is allocated in + a static area on the first use. This function won't fail. */ +const char * +dirmngr_libexecdir (void) +{ +#ifdef HAVE_W32_SYSTEM + return w32_rootdir (); +#else /*!HAVE_W32_SYSTEM*/ + return DIRMNGR_LIBEXECDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +const char * +dirmngr_datadir (void) +{ +#ifdef HAVE_W32_SYSTEM + static char *name; + + if (!name) + { + const char *s1, *s2; + s1 = w32_rootdir (); /* FIXME: /var in windows? */ + s2 = DIRSEP_S "lib" DIRSEP_S "dirmngr"; + name = xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (stpcpy (name, s1), s2); + } + return name; +#else /*!HAVE_W32_SYSTEM*/ + return DIRMNGR_DATADIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +const char * +dirmngr_cachedir (void) +{ +#ifdef HAVE_W32_SYSTEM + static char *name; + + if (!name) + { + const char *s1, *s2; + s1 = w32_rootdir (); /* FIXME: /var in windows? */ + s2 = DIRSEP_S "cache" DIRSEP_S "dirmngr"; + name = xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (stpcpy (name, s1), s2); + } + return name; +#else /*!HAVE_W32_SYSTEM*/ + return DIRMNGR_CACHEDIR; +#endif /*!HAVE_W32_SYSTEM*/ +} + + +const char * +default_socket_name (void) +{ +#ifdef HAVE_W32_SYSTEM + static char *name; + + if (!name) + { + const char *s1, *s2; + s1 = w32_rootdir (); /* FIXME: /var in windows? */ + s2 = DIRSEP_S "S.dirmngr"; + name = xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (stpcpy (name, s1), s2); + } + return name; +#else /*!HAVE_W32_SYSTEM*/ + return "/var/run/dirmngr/socket" +#endif /*!HAVE_W32_SYSTEM*/ +} Modified: trunk/src/util.h =================================================================== --- trunk/src/util.h 2007-08-03 08:08:07 UTC (rev 257) +++ trunk/src/util.h 2007-08-04 03:39:35 UTC (rev 258) @@ -87,5 +87,10 @@ /* Find the dirmngr_ldap program image. */ const char *get_dirmngr_ldap_path (void); +const char *dirmngr_sysconfdir (void); +const char *dirmngr_libexecdir (void); +const char *dirmngr_datadir (void); +const char *dirmngr_cachedir (void); +const char *default_socket_name (void); #endif /*UTIL_H*/ From cvs at cvs.gnupg.org Tue Aug 7 17:22:21 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 07 Aug 2007 17:22:21 +0200 Subject: [svn] gpgme - r1244 - in trunk: . doc gpgme Message-ID: Author: wk Date: 2007-08-07 17:21:50 +0200 (Tue, 07 Aug 2007) New Revision: 1244 Modified: trunk/NEWS trunk/doc/ChangeLog trunk/doc/gpgme.texi trunk/gpgme/ChangeLog trunk/gpgme/gpgme.h trunk/gpgme/verify.c Log: Add new signature_t member chain_model. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/NEWS 2007-08-07 15:21:50 UTC (rev 1244) @@ -2,7 +2,11 @@ ------------------------------------------------ + * Interface changes relative to the 1.1.1 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gpgme_signature_t EXTENDED: New field chain_model. + Noteworthy changes in version 1.1.5 (2007-07-09) ------------------------------------------------ Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/doc/ChangeLog 2007-08-07 15:21:50 UTC (rev 1244) @@ -1,3 +1,7 @@ +2007-08-07 Werner Koch + + * gpgme.texi (Verify): Describe chain_model. + 2007-07-12 Werner Koch * gpgme.texi (Library Version Check): Add remark that the socket Modified: trunk/doc/gpgme.texi =================================================================== --- trunk/doc/gpgme.texi 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/doc/gpgme.texi 2007-08-07 15:21:50 UTC (rev 1244) @@ -4076,6 +4076,16 @@ Depending on the configuration of the engine, this metric may also be reflected by the validity of the signature. + at item unsigned int chain_model : 1 +This is true if the validity of the signature has been checked using the +chain model. In the chain model the time the signature has been created +must be within the validity period of the certificate and the time the +certificate itself has been created must be within the validity period +of the issuing certificate. In contrast the default validation model +checks the validity of signature as well at the entire certificate chain +at the current time. + + @item gpgme_validity_t validity The validity of the signature. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/gpgme/ChangeLog 2007-08-07 15:21:50 UTC (rev 1244) @@ -1,3 +1,8 @@ +2007-08-07 Werner Koch + + * gpgme.h (struct _gpgme_signature): Add member CHAIN_MODEL. + * verify.c (parse_trust): Set Chain_MODEL. + 2007-08-02 Werner Koch * w32-glib-io.c (_gpgme_io_spawn): Use DETACHED_PROCESS flag. @@ -12,7 +17,7 @@ 2007-07-17 Marcus Brinkmann - * debug.c:;5B Include and "debug.h". + * debug.c: Include and "debug.h". (_gpgme_debug): Save and restore ERRNO. (TOHEX): New macro. (_gpgme_debug_buffer): New function. Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/gpgme/gpgme.h 2007-08-07 15:21:50 UTC (rev 1244) @@ -1,6 +1,6 @@ /* gpgme.h - Public interface to GnuPG Made Easy. Copyright (C) 2000 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH This file is part of GPGME. @@ -1323,8 +1323,11 @@ /* PKA status: 0 = not available, 1 = bad, 2 = okay, 3 = RFU. */ unsigned int pka_trust : 2; + /* Validity has been verified using the chain model. */ + unsigned int chain_model : 1; + /* Internal to GPGME, do not use. */ - int _unused : 29; + int _unused : 28; gpgme_validity_t validity; gpgme_error_t validity_reason; Modified: trunk/gpgme/verify.c =================================================================== --- trunk/gpgme/verify.c 2007-08-02 14:59:01 UTC (rev 1243) +++ trunk/gpgme/verify.c 2007-08-07 15:21:50 UTC (rev 1244) @@ -541,10 +541,21 @@ break; } + sig->validity_reason = 0; + sig->chain_model = 0; if (*args) - sig->validity_reason = _gpgme_map_gnupg_error (args); - else - sig->validity_reason = 0; + { + sig->validity_reason = _gpgme_map_gnupg_error (args); + while (*args && *args != ' ') + args++; + if (*args) + { + while (*args == ' ') + args++; + if (!strncmp (args, "cm", 2) && (args[2] == ' ' || !args[2])) + sig->chain_model = 1; + } + } return 0; } From cvs at cvs.gnupg.org Wed Aug 8 11:11:28 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 08 Aug 2007 11:11:28 +0200 Subject: [svn] ksba - r278 - trunk Message-ID: Author: wk Date: 2007-08-08 11:10:58 +0200 (Wed, 08 Aug 2007) New Revision: 278 Modified: trunk/ChangeLog trunk/NEWS trunk/configure.ac Log: Use $host and not $target in configure Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-07-04 12:14:49 UTC (rev 277) +++ trunk/ChangeLog 2007-08-08 09:10:58 UTC (rev 278) @@ -1,3 +1,8 @@ +2007-08-08 Werner Koch + + * configure.ac: Use $host and not $target. Reported by Peter + Eisentraut . + 2007-07-04 Werner Koch Released 1.0.2. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-07-04 12:14:49 UTC (rev 277) +++ trunk/NEWS 2007-08-08 09:10:58 UTC (rev 278) @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.0.3 +------------------------------------------------ + + Noteworthy changes in version 1.0.2 (2007-07-04) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-07-04 12:14:49 UTC (rev 277) +++ trunk/configure.ac 2007-08-08 09:10:58 UTC (rev 278) @@ -24,8 +24,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.0.2]) -m4_define([my_issvn], [no]) +m4_define([my_version], [1.0.3]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) @@ -52,9 +52,9 @@ VERSION=$PACKAGE_VERSION AC_CONFIG_SRCDIR([src/ksba.h]) -AC_CANONICAL_TARGET AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST AB_INIT AC_GNU_SOURCE @@ -124,9 +124,9 @@ fi -# Setup some stuff depending on host/target. +# Setup some stuff depending on host. have_w32_system=no -case "${target}" in +case "${host}" in *-*-mingw32*) have_w32_system=yes ;; From cvs at cvs.gnupg.org Wed Aug 8 19:07:05 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 08 Aug 2007 19:07:05 +0200 Subject: [svn] dirmngr - r259 - in trunk: . doc m4 src Message-ID: Author: wk Date: 2007-08-08 19:06:34 +0200 (Wed, 08 Aug 2007) New Revision: 259 Removed: trunk/m4/Makefile trunk/m4/Makefile.in Modified: trunk/ChangeLog trunk/Makefile.am trunk/NEWS trunk/configure.ac trunk/doc/dirmngr.texi trunk/src/ChangeLog trunk/src/crlcache.c trunk/src/dirmngr.c trunk/src/dirmngr_ldap.c trunk/src/exechelp.c trunk/src/get-path.c trunk/src/ldap.c Log: Fixed dirmngr_wait_process. Typo fixes. LDAP fixes. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/ChangeLog 2007-08-08 17:06:34 UTC (rev 259) @@ -1,3 +1,10 @@ +2007-08-07 Werner Koch + + * configure.ac (COPYRIGHT_YEAR_NAME): Set to 2007. + + * Makefile.am (dist-hook, stowinstall): New. + (AUTOMAKE_OPTIONS): Do not create gzip tarballs. + 2007-07-26 Marcus Brinkmann * Makefile.am (tests): New variable. Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/Makefile.am 2007-08-08 17:06:34 UTC (rev 259) @@ -20,7 +20,7 @@ ## Process this file with automake to produce Makefile.in ACLOCAL_AMFLAGS = -I m4 -AUTOMAKE_OPTIONS = dist-bzip2 +AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip EXTRA_DIST = config.rpath autogen.sh @@ -31,3 +31,9 @@ endif SUBDIRS = m4 jnlib src po doc $(tests) + +dist-hook: + echo "$(VERSION)" > $(distdir)/VERSION + +stowinstall: + $(MAKE) $(AM_MAKEFLAGS) install prefix=/usr/local/stow/dirmngr Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/NEWS 2007-08-08 17:06:34 UTC (rev 259) @@ -1,6 +1,10 @@ -Noteworthy changes in version 1.0 0 (2006-11-29) +Noteworthy changes in version 1.0.1 ------------------------------------------------ + +Noteworthy changes in version 1.0.0 (2006-11-29) +------------------------------------------------ + * Bumbed the version number. * Removed included gettext. We now require the system to provide a Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/configure.ac 2007-08-08 17:06:34 UTC (rev 259) @@ -26,8 +26,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.0.0]) -m4_define([my_issvn], [no]) +m4_define([my_version], [1.0.1]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) @@ -45,7 +45,7 @@ NEED_KSBA_API=1 NEED_KSBA_VERSION=1.0.0 -COPYRIGHT_YEAR_NAME="2006 g10 Code GmbH" +COPYRIGHT_YEAR_NAME="2007 g10 Code GmbH" PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION Modified: trunk/doc/dirmngr.texi =================================================================== --- trunk/doc/dirmngr.texi 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/doc/dirmngr.texi 2007-08-08 17:06:34 UTC (rev 259) @@ -460,13 +460,13 @@ Lines starting with a @samp{#} are comments. -Note that as usual all strings entered are expected to be UTF_8 encoded. +Note that as usual all strings entered are expected to be UTF-8 encoded. Obviously this will lead to problems if the password has orginally been -encoded as Latin-1. tehre isno solutionhere than to put such a password -in the binary encoding into the file (i.e. non-ascii characters won't -show up readable). at footnote{The @command{gpgconf} tool might be helpful -for frontends as it allows to edit this configuration file suing percent -escaped strings.} +encoded as Latin-1. There is no other solution here than to put such a +password in the binary encoding into the file (i.e. non-ascii characters +won't show up readable). at footnote{The @command{gpgconf} tool might be +helpful for frontends as it allows to edit this configuration file using +percent escaped strings.} @item --ldaptimeout @var{secs} Deleted: trunk/m4/Makefile Deleted: trunk/m4/Makefile.in Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/ChangeLog 2007-08-08 17:06:34 UTC (rev 259) @@ -1,3 +1,25 @@ +2007-08-08 Werner Koch + + * crlcache.c (crl_parse_insert): Hack to allow for a missing + nextUpdate. + + * dirmngr_ldap.c (print_ldap_entries): Strip the extension from + the want_attr. + + * exechelp.c (dirmngr_wait_process): Reworked for clear error + semantics. + * ldap.c (ldap_wrapper_thread): Adjust for new + dirmngr_wait_process semantics. + +2007-08-07 Werner Koch + + * get-path.c (default_socket_name) [!W32]: Fixed syntax error. + + * ldap.c (X509CACERT, make_url, fetch_next_cert_ldap): Support + x509caCert as used by the Bundesnetzagentur. + (ldap_wrapper): Do not pass the prgtram name as the first + argument. dirmngr_spawn_process takes care of that. + 2007-08-04 Marcus Brinkmann * dirmngr.h (opt): Add member system_service. @@ -14,8 +36,8 @@ option. * util.h (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir, dirmngr_cachedir, default_socket_name): New prototypes. - * get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir, - dirmngr_datadir, dirmngr_cachedir, default_socket_name): New + * get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir) + (dirmngr_datadir, dirmngr_cachedir, default_socket_name): New functions. (DIRSEP_C, DIRSEP_S): New macros. @@ -42,7 +64,8 @@ 2007-07-30 Marcus Brinkmann - * ldap-url.c (ldap_str2charray): Fix buglet in ldap_utf8_strchr invocation. + * ldap-url.c (ldap_str2charray): Fix buglet in ldap_utf8_strchr + invocation. 2007-07-27 Marcus Brinkmann Modified: trunk/src/crlcache.c =================================================================== --- trunk/src/crlcache.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/crlcache.c 2007-08-08 17:06:34 UTC (rev 259) @@ -1586,9 +1586,16 @@ goto failure; } - if (opt.verbose) + if (opt.verbose || !*nextupdate) log_info (_("update times of this CRL: this=%s next=%s\n"), thisupdate, nextupdate); + if (!*nextupdate) + { + log_info (_("nextUpdate not given; " + "assuming a validity period of one day\n")); + copy_time (nextupdate, thisupdate); + add_isotime (nextupdate, 86400); + } } break; Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/dirmngr.c 2007-08-08 17:06:34 UTC (rev 259) @@ -1,6 +1,6 @@ /* dirmngr.c - LDAP access * Copyright (C) 2002 Klar?lvdalens Datakonsult AB - * Copyright (C) 2003, 2004, 2006 g10 Code GmbH + * Copyright (C) 2003, 2004, 2006, 2007 g10 Code GmbH * * This file is part of DirMngr. * Modified: trunk/src/dirmngr_ldap.c =================================================================== --- trunk/src/dirmngr_ldap.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/dirmngr_ldap.c 2007-08-08 17:06:34 UTC (rev 259) @@ -343,22 +343,31 @@ /* I case we want only one attribute we do a case insensitive compare without the optional extension - (i.e. ";binary"). case insensive is not really correct - but the best we can do. */ + (i.e. ";binary"). Case insensitive is not really correct + but the best we can do. */ if (want_attr) { - char *cp = strchr (attr, ';'); - if (cp) - *cp = 0; - if ( ascii_strcasecmp (want_attr, attr) ) + char *cp1, *cp2; + int cmpres; + + cp1 = strchr (want_attr, ';'); + if (cp1) + *cp1 = 0; + cp2 = strchr (attr, ';'); + if (cp2) + *cp2 = 0; + cmpres = ascii_strcasecmp (want_attr, attr); + if (cp1) + *cp1 = ';'; + if (cp2) + *cp2 = ';'; + if (cmpres) { ldap_memfree (attr); continue; /* Not found: Try next attribute. */ } - if (cp) - *cp = ';'; } - + values = ldap_get_values_len (ld, item, attr); if (!values) @@ -559,7 +568,7 @@ -/* Main processing. Take the URL and run the DLAP query. The result +/* Main processing. Take the URL and run the LDAP query. The result is printed to stdout, errors are logged to the log stream. */ static int process_url (const char *url) Modified: trunk/src/exechelp.c =================================================================== --- trunk/src/exechelp.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/exechelp.c 2007-08-08 17:06:34 UTC (rev 259) @@ -72,7 +72,7 @@ p = stpcpy (p, "\"\""); else if (strpbrk (string, " \t\n\v\f\"")) { - /* Need top do some kind of quoting. */ + /* Need to do some kind of quoting. */ p = stpcpy (p, "\""); for (s=string; *s; s++) { @@ -102,13 +102,13 @@ *cmdline = NULL; n = 0; s = pgmname; - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ for (; *s; s++) if (*s == '\"') n++; /* Need to double inner quotes. */ for (i=0; (s=argv[i]); i++) { - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ for (; *s; s++) if (*s == '\"') n++; /* Need to double inner quotes. */ @@ -426,12 +426,25 @@ } -/* Wait for the process identified by PID to terminate. PGMNAME should - be the same as suplieed to the spawn fucntion and is only used for - diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for - any failures of the spawned program or other error codes.*/ +/* If HANG is true, waits for the process identified by PID to exit. + If HANG is false, checks whether the process has terminated. + Return values: + + GPG_ERR_NO_ERROR + The process exited. The exit code of process is then stored at + R_STATUS. An exit code of -1 indicates that the process + terminated abnormally (e.g. due to a signal). + + GPG_ERR_TIMEOUT + The process is still running (returned only if HANG is false). + + GPG_ERR_INV_VALUE + An invalid PID has been specified. + + Other error codes may be returned as well. Unless otherwise noted, + -1 will be stored at R_STATUS. */ gpg_error_t -dirmngr_wait_process (pid_t pid, int hang, int *status) +dirmngr_wait_process (pid_t pid, int hang, int *r_status) { gpg_err_code_t ec; @@ -440,7 +453,7 @@ int code; DWORD exc; - *status = 0; + *r_status = -1; if (pid == (pid_t)(-1)) return gpg_error (GPG_ERR_INV_VALUE); @@ -451,12 +464,13 @@ switch (code) { case WAIT_TIMEOUT: - + ec = GPG_ERR_TIMEOUT; break; + case WAIT_FAILED: log_error (_("waiting for process %d to terminate failed: %s\n"), (int)pid, w32_strerror (-1)); - ec = GPG_ERR_GENERAL; + ec = 0; break; case WAIT_OBJECT_0: @@ -466,15 +480,14 @@ (int)pid, w32_strerror (-1) ); ec = GPG_ERR_GENERAL; } - else if (exc) + else { - log_error (_("error detected in waitpid: exit status %d\n"), - (int) exc); - ec = GPG_ERR_GENERAL; + *r_status = exc; + if (exc) + log_error (_("error detected: exit status %d%s\n"), + *r_status, ""); + ec = 0; } - else - ec = 0; - *status = 1; break; default: @@ -486,44 +499,39 @@ #else /* !HAVE_W32_SYSTEM */ int i; - int r_status; + int status; - *status = 0; + *r_status = -1; + if (pid == (pid_t)(-1)) return gpg_error (GPG_ERR_INV_VALUE); - i = pth_waitpid (pid, &r_status, 0); + i = pth_waitpid (pid, &status, hang? 0 : WNOHANG); if (i == (pid_t)(-1)) { + ec = gpg_err_code_from_syserror (); log_error (_("waiting for process %d to terminate failed: %s\n"), (int)pid, strerror (errno)); - ec = gpg_err_code_from_errno (errno); } - if (i == 0) + else if (i == 0) { - *status = 0; - ec = 0; + /* The process is still running. */ + ec = GPG_ERR_TIMEOUT; } - else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) + else if (WIFEXITED (status)) { - log_error (_("error detected: program probably not installed\n")); - ec = GPG_ERR_CONFIGURATION; + ec = 0; + *r_status = WEXITSTATUS (status); + if (*r_status) + log_error (_("error detected: exit status %d%s\n"), *r_status, + *r_status == 127? _(" (program probably not installed)") + /* */ :""); } - else if (WIFEXITED (status) && WEXITSTATUS (status)) + else { - log_error (_("error detected: exit status %d\n"), WEXITSTATUS (status)); - ec = GPG_ERR_GENERAL; - } - else if (!WIFEXITED (status)) - { + ec = 0; log_error (_("error detected: terminated\n")); - ec = GPG_ERR_GENERAL; } - else - { - *status = 1; - ec = 0; - } #endif /* !HAVE_W32_SYSTEM */ return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); Modified: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/get-path.c 2007-08-08 17:06:34 UTC (rev 259) @@ -506,6 +506,6 @@ } return name; #else /*!HAVE_W32_SYSTEM*/ - return "/var/run/dirmngr/socket" + return "/var/run/dirmngr/socket"; #endif /*!HAVE_W32_SYSTEM*/ } Modified: trunk/src/ldap.c =================================================================== --- trunk/src/ldap.c 2007-08-04 03:39:35 UTC (rev 258) +++ trunk/src/ldap.c 2007-08-08 17:06:34 UTC (rev 259) @@ -1,6 +1,6 @@ /* ldap.c - LDAP access * Copyright (C) 2002 Klar?lvdalens Datakonsult AB - * Copyright (C) 2003, 2004, 2005 g10 Code GmbH + * Copyright (C) 2003, 2004, 2005, 2007 g10 Code GmbH * * This file is part of DirMngr. * @@ -61,6 +61,7 @@ "$-_.+!*'()," #define USERCERTIFICATE "userCertificate" #define CACERTIFICATE "caCertificate" +#define X509CACERT "x509caCert" #define USERSMIMECERTIFICATE "userSMIMECertificate" @@ -322,16 +323,19 @@ int status; err = dirmngr_wait_process (ctx->pid, 0, &status); - - if (err == -1) - log_error (_("waiting for ldap wrapper %d failed: %s\n"), - (int)ctx->pid, gpg_strerror (err)); - else if (status) + if (!err) { - log_info (_("ldap wrapper %d ready"), (int)ctx->pid); + log_info (status == 10 ? + _("ldap wrapper %d ready: timeout\n") : + _("ldap wrapper %d ready"), (int)ctx->pid); ctx->ready = 1; ctx->pid = (pid_t)(-1); } + else if (gpg_err_code (err) != GPG_ERR_TIMEOUT) + { + log_error (_("waiting for ldap wrapper %d failed: %s\n"), + (int)ctx->pid, gpg_strerror (err)); + } } /* Check whether we should terminate the process. */ @@ -514,9 +518,8 @@ } /* Fork and exec the LDAP wrapper and returns a new libksba reader - object at READER. ARGV is a NULL terminated list or argumenst for - the wrapper; however the function adds the program's name as the - first arg. The function returns 0 on success or an error code. + object at READER. ARGV is a NULL terminated list or arguments for + the wrapper. The function returns 0 on success or an error code. We can't use LDAP directly for these reasons: @@ -530,20 +533,20 @@ 3. There is no easy way for timeouts. In particular the timeout value does not work for DNS lookups (well, this is usual) and it seems not to work while loading a large attribute like a - CRL. Having a separate process allows us to either tell than + CRL. Having a separate process allows us to either tell the process to commit suicide or have our own housekepping function kill it after some time. The latter also allows proper - cancellation of a query at any point. + cancellation of a query at any point of time. 4. Given that we are going out to the network and usually get back - a long response, the frok/exec overhead is acceptable. + a long response, the fork/exec overhead is acceptable. Special hack to avoid passing a password through the command line which is globally visible: If the first element of ARGV is "--pass" it will be removed and instead the environment variable DIRMNGR_LDAP_PASS will be set to the next value of ARGV. On modern - OSes the environment is not visible to other other user. For those - old systems where it can't be avoided, we don't want to go into the + OSes the environment is not visible to other users. For those old + systems where it can't be avoided, we don't want to go into the hassle of passing the password via stdin; it's just too complicated and an LDAP password used for public directory lookups should not be that confidential. */ @@ -581,13 +584,8 @@ /* Create command line argument array. */ for (i = 0; argv[i]; i++) ; - arg_list = xcalloc (i + 3, sizeof *arg_list); - arg_list[0] = strrchr (pgmname, '/'); - if (arg_list[0]) - arg_list[0]++; - else - arg_list[0] = pgmname; - for (i = 0, j = 1; argv[i]; i++, j++) + arg_list = xcalloc (i + 2, sizeof *arg_list); + for (i = j = 0; argv[i]; i++, j++) if (!i && argv[i + 1] && !strcmp (*argv, "--pass")) { arg_list[j] = "--env-pass"; @@ -987,7 +985,8 @@ char *u_dn, *u_filter; char const attrs[] = (USERCERTIFICATE "," /* USERSMIMECERTIFICATE "," */ - CACERTIFICATE); + CACERTIFICATE "," + X509CACERT ); *url = NULL; @@ -1329,6 +1328,13 @@ CACERTIFICATE); okay = 1; } + else if (!ascii_strcasecmp (p, X509CACERT)) + { + if (DBG_LOOKUP) + log_debug ("fetch_next_cert_ldap: got attribute `%s'\n", + CACERTIFICATE); + okay = 1; + } /* else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */ /* { */ /* if (DBG_LOOKUP) */ From cvs at cvs.gnupg.org Thu Aug 9 12:44:32 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 09 Aug 2007 12:44:32 +0200 Subject: [svn] assuan - r247 - in trunk: doc src Message-ID: Author: marcus Date: 2007-08-09 12:44:02 +0200 (Thu, 09 Aug 2007) New Revision: 247 Modified: trunk/doc/ChangeLog trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-defs.h trunk/src/assuan-handler.c trunk/src/assuan-inquire.c trunk/src/assuan-pipe-server.c trunk/src/assuan.h trunk/src/mkerrors Log: doc/ 2007-08-09 Marcus Brinkmann * assuan.texi (External I/O Loop): New chapter. src/ 2007-08-09 Marcus Brinkmann * assuan.h (assuan_process_done, assuan_inquire_ext): New prototypes. * assuan-defs.h (struct assuan_context_s): New members in_process_next, in_command, inquire_cb, inquire_cb_data, inquire_r_buffer, inquire_r_buffer_len, inquire_membuf. (_assuan_inquire_ext_cb, _assuan_inquire_release): New prototypes. * assuan-handler.c (PROCESS_DONE): New macro. (dummy_handler, std_handler_nop, std_handler_cancel) (std_handler_option, std_handler_bye, std_handler_auth) (std_handler_reset, std_handler_end): Use PROCESS_DONE to optionally call assuan_process_done if CTX->in_process_next is true. (assuan_process_done, process_next): New functions. (assuan_process_next): Rewritten to support external event handling. * mkerrors: Do not clear high bits of -1 for old style EOF. * assuan-inquire.c (_assuan_inquire_release) (_assuan_inquire_ext_cb, assuan_inquire_ext): New functions. * assuan-pipe-server.c (_assuan_release_context): Call _assuan_inquire_release. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/doc/ChangeLog 2007-08-09 10:44:02 UTC (rev 247) @@ -1,3 +1,7 @@ +2007-08-09 Marcus Brinkmann + + * assuan.texi (External I/O Loop): New chapter. + 2007-07-12 Werner Koch * assuan.texi (Utilities): Document that under W32 we return a Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/doc/assuan.texi 2007-08-09 10:44:02 UTC (rev 247) @@ -115,6 +115,7 @@ * Generalities:: Initialization code and data types used. * Client code:: How to develop an Assuan client. * Server code:: How to develop an Assuan server. +* External I/O Loop:: How to use external I/O event loops. * Utilities:: Utility functions. Miscellaneous @@ -1085,13 +1086,6 @@ @end deftypefun - at deftypefun assuan_error_t assuan_process_next (@w{assuan_context_t @var{ctx}}) - -This is the same as @code{assuan_process} but the caller has to provide -the outer loop. He should loop as long as the return code is zero and -stop otherwise; @code{-1} or @code{GPG_ERR_EOF} indicate a regular end. - at end deftypefun - @noindent After the loop has terminated, the Assuan context needs to be released: @@ -1110,7 +1104,206 @@ also allowed to modify that line which makes parsing much easier. + at c + at c E x t e r n a l I / O L o o p s + at c + at node External I/O Loop + at chapter How to use external I/O event loops +The above implementations of an Assuan client and server are +synchronous, insofar the main routines block until a request or client +connection is completely processed. In some programs, for example GUI +applications, this is undesirable. Instead, Assuan operations should +be non-blocking, and the caller should be able to poll all involved +file descriptors to determine when the next Assuan function can be +invoked without blocking. + +To make this possible, client and server have to adhere to some rules: + at itemize @bullet + at item +Either partner should always write full lines. If partial lines are +written, the remainder of the line should b sent without delay. + at item +Either partner should eagerly receive status messages. While +receiving and sending bulk data may be delayed, the status +communication channel is different: Both partners may send status +messages in blocking mode at any time the protocol allows them to send +such status messages. To ensure that these send operations do not +actually block the sender, the recipient must be ready to receive +without undue delay. + at item +If descriptor passing is used over a socket, the descriptor must be +sent after the corresponding command without undue delay. + at end itemize + +Together, these restrictions allow to limit the need for asynchronous +I/O operations to bulk data and the inbound status file descriptor. + +In addition to the above rules, client and server should adhere to the +following implementation guidelines. + + at menu +* External I/O Loop Client:: External I/O event loops in the client. +* External I/O Loop Server:: External I/O event loops in the server. + at end menu + + at node External I/O Loop Client + at section External I/O event loops in the client. + +The reference implementation for using external I/O event loops in the +client is the GPGME library, which exports its own external I/O event +loop mechanism and utilizes the Assuan library transparently for the +user. The following steps document how GPGME achieves this. + + at enumerate + at item +Before connecting, set up pipes for bulk data transfer (using the +INPUT/OUTPUT commands, for example). These are passed to the server +either by inheritance (using a pipe server) or by FD passing (using a +socket server). + + at item +Then you need to connect to the server. GPGME uses a pipe server, so +it just spawns a server process, which is a non-blocking operation. +FIXME: Currently, using a client with external event loop over a +socket connection is not supported. It is easy to support (we just +need a variation of @code{assuan_socket_connect} which takes an +already connected socket FD and turns it into an Assuan context), so +if you need this let us know. + + at item +After connecting, get the inbound status FD with + at code{assuan_get_active_fds} (the first one returned is the status +FD). This FD can be duplicated if it is convenient (GPGME does this +to be able to close this FD and associated callback handlers without +disrupting Assuan's internals). + + at item +Then register the Assuan inbound status FD and all bulk data FDs with +the I/O event mechanism. In general, this requires setting up +callback handlers for these FDs and registering them with the main +event loop. + + at item +When bulk data FDs become ready, you can simply perform the +corresponding read or write operations. When the inbound status FD +becomes ready, you can receive the next server line with +assuan_read_line(). + + at item +You should close and unregister the bulk data FDs when you wrote all +data (for outbound FDs) or receive an EOF (for inbound FDs). When you +receive an ERR from the server, or an OK for the final operation, you +can unregister the inbound status FD and call @code{assuan_disconnect} +to close it. + + at item +As noted above, all send operations on the outbound status FD are done +immediate with blocking. In GPGME, this has never caused any problems. + + at item +The @code{INQUIRE} function can be handled in two ways: If the +requested data is immediately available, the client can just send the +data blockingly. If the requested data needs to be fetched from a +blocking source, a callback handler can be registered for the FD with +the main event loop. GPGME does not support the @code{INQUIRE} +function, so we do not have any practical experience with this. + at end enumerate + +Currently, the client can not cancel a pending operation gracefully. +It can, however, disconnect from the server at any time. It is the +responsibility of the server to periodically send status messages to +the client to probe if the connection remains alive. + + + at node External I/O Loop Server + at section External I/O event loops in the server. + +Currently, no Assuan server exists which uses external I/O event +loops. However, the following guidelines should lead to a usable +implementation: + + at enumerate + at item +For socket servers: You can not use @code{assuan_accept}, so you +should just implement the bind/connect/listen/accept stage yourself. +You can register the listen FD with your main event loop, accept the +connection when it becomes ready, and finally call + at code{assuan_init_socket_server_ext} with the final argument being 2 +to create an Assuan context for this connection. This way you can +also handle multiple connections in parallel. The reference +implementation for this approach is DirMngr. + +For pipe servers: @code{assuan_init_pipe_server} creates an Assuan +context valid for the pipe FDs. + + at item +Once you have a context for a single connection, you can get the +inbound status FD with @code{assuan_get_active_fds} (the first one +returned is the status FD). This FD can be duplicated if it is +convenient. Every time the inbound status FD is readable, you should +invoke the function @code{assuan_process_next} (see below) to process +the next incoming message. @code{assuan_process_next} processes as +many status lines as can be received by a single @code{read} +operation. When it returns, the inbound status FD may still be +readable, but Assuan does not check this. + +The function @code{assuan_process_next} returns 0 if it can not make +progress reliably, and it returns an end of file error code if the +client closed the connection. See below for more information on this +function. + + at item +The command will be dispatched by @code{assuan_process_next} just as +with @code{assuan_process}, however, you will want to implement the +command handlers in such a way that they do not block. For example, +the command handler may just register the bulk data FDs with the main +event loop and return. + +When the command is finished, irregardless if this happens directly in +the command handler or later, you must call @code{assuan_process_done} +with an appropriate error code (or 0 for success) to return an +appropriate status line to the client. You can do this at the end of +the command handler, for example by ending it with @code{return +assuan_process_done (error_code);}. Another possibility is to invoke + at code{assuan_process_done} from the place in the code which closes the +last active bulk FD registered with the main event loop for this +operation. + at end enumerate + +It is not possible to use @code{assuan_inquire} in a command handler, +as this function blocks on receiving the inquired data from the +client. Instead, the asynchronous version @code{assuan_inquire_ext} +needs to be used (see below), which invokes a callback when the client +provided the inquired data. A typical usage would be for the command +handler to register a continuation with @code{assuan_inquire_ext} and +return 0. Eventually, the continuation would be invoked by + at code{assuan_process_next} when the client data arrived. The +continuation could complete the command and eventually call + at code{assuan_process_done}. + +Cancellation is supported by returning an appropriate error code to +the client with @code{assuan_process_done}. For long running +operations, the server should send progress status messages to the +client in regular intervals to notice when the client disconnects. + + at deftypefun assuan_error_t assuan_process_next (@w{assuan_context_t @var{ctx}}) +This is the same as @code{assuan_process} but the caller has to +provide the outer loop. He should loop as long as the return code is +zero and stop otherwise; @code{-1} or @code{GPG_ERR_EOF} indicate a +regular end. + at end deftypefun + + at deftypefun assuan_error_t assuan_inquire_ext (@w{assuan_context_t @var{ctx}}, @w{const char *@var{keyword}}, @w{unsigned char **@var{r_buffer}}, @w{size_t *@var{r_length}}, @w{size_t @var{maxlen}}, @w{int (*@var{cb}) (void *cb_data, int rc)}, @w{void *@var{cb_data}}) + +This is the same as @code{assuan_inquire} but the caller has to +provide the outer loop (using @code{assuan_process_next}). The caller +should specify a continuation with @var{cb}, which receives + at var{cb_data} as its first argument. + at end deftypefun + + + @c @c U T I L I T I E S @c Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/ChangeLog 2007-08-09 10:44:02 UTC (rev 247) @@ -1,3 +1,26 @@ +2007-08-09 Marcus Brinkmann + + * assuan.h (assuan_process_done, assuan_inquire_ext): New + prototypes. + * assuan-defs.h (struct assuan_context_s): New members + in_process_next, in_command, inquire_cb, inquire_cb_data, + inquire_r_buffer, inquire_r_buffer_len, inquire_membuf. + (_assuan_inquire_ext_cb, _assuan_inquire_release): New prototypes. + * assuan-handler.c (PROCESS_DONE): New macro. + (dummy_handler, std_handler_nop, std_handler_cancel) + (std_handler_option, std_handler_bye, std_handler_auth) + (std_handler_reset, std_handler_end): Use PROCESS_DONE to + optionally call assuan_process_done if CTX->in_process_next is + true. + (assuan_process_done, process_next): New functions. + (assuan_process_next): Rewritten to support external event + handling. + * mkerrors: Do not clear high bits of -1 for old style EOF. + * assuan-inquire.c (_assuan_inquire_release) + (_assuan_inquire_ext_cb, assuan_inquire_ext): New functions. + * assuan-pipe-server.c (_assuan_release_context): Call + _assuan_inquire_release. + 2007-07-12 Werner Koch * assuan.h (assuan_fd_t): New. Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/assuan-defs.h 2007-08-09 10:44:02 UTC (rev 247) @@ -103,6 +103,16 @@ int confidential; int is_server; /* Set if this is context belongs to a server */ int in_inquire; + int in_process_next; + int in_command; + + /* The following members are used by assuan_inquire_ext. */ + int (*inquire_cb) (void *cb_data, int rc); + void *inquire_cb_data; + unsigned char **inquire_r_buffer; + size_t *inquire_r_buffer_len; + void *inquire_membuf; + char *hello_line; char *okay_line; /* See assuan_set_okay_line() */ @@ -229,17 +239,20 @@ /*-- assuan-error.c --*/ +/*-- assuan-inquire.c --*/ +int _assuan_inquire_ext_cb (assuan_context_t ctx); +void _assuan_inquire_release (assuan_context_t ctx); -/* Map error codes as used in this implementaion to the libgpg-error +/* Map error codes as used in this implementation to the libgpg-error codes. */ assuan_error_t _assuan_error (int oldcode); -/* Extrac the erro code from A. This works for both the old and the - new style error codes. This needs to be whenever an error code is - compared. */ +/* Extract the error code from A. This works for both the old and the + new style error codes. This needs to be used whenever an error + code is compared. */ #define err_code(a) ((a) & 0x00ffffff) -/* Check whether A is the erro code for EOF. We allow forold and new +/* Check whether A is the erro code for EOF. We allow for old and new style EOF error codes here. */ #define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383) Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/assuan-handler.c 2007-08-09 10:44:02 UTC (rev 247) @@ -33,18 +33,21 @@ static int my_strcasecmp (const char *a, const char *b); +#define PROCESS_DONE(ctx, rc) \ + ((ctx)->in_process_next ? assuan_process_done ((ctx), (rc)) : (rc)) static int dummy_handler (assuan_context_t ctx, char *line) { - return set_error (ctx, Server_Fault, "no handler registered"); + return + PROCESS_DONE (ctx, set_error (ctx, Server_Fault, "no handler registered")); } static int std_handler_nop (assuan_context_t ctx, char *line) { - return 0; /* okay */ + return PROCESS_DONE (ctx, 0); /* okay */ } static int @@ -52,7 +55,7 @@ { if (ctx->cancel_notify_fnc) ctx->cancel_notify_fnc (ctx); - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } static int @@ -63,9 +66,12 @@ for (key=line; spacep (key); key++) ; if (!*key) - return set_error (ctx, Syntax_Error, "argument required"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, "argument required")); if (*key == '=') - return set_error (ctx, Syntax_Error, "no option name given"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, + "no option name given")); for (value=key; *value && !spacep (value) && *value != '='; value++) ; if (*value) @@ -80,7 +86,9 @@ for (; spacep (value); value++) ; if (!*value) - return set_error (ctx, Syntax_Error, "option argument expected"); + return + PROCESS_DONE (ctx, set_error (ctx, Syntax_Error, + "option argument expected")); } if (*value) { @@ -94,12 +102,13 @@ if (*key == '-' && key[1] == '-' && key[2]) key += 2; /* the double dashes are optional */ if (*key == '-') - return set_error (ctx, Syntax_Error, - "option should not begin with one dash"); + return PROCESS_DONE (ctx, + set_error (ctx, Syntax_Error, + "option should not begin with one dash")); if (ctx->option_handler_fnc) - return ctx->option_handler_fnc (ctx, key, value); - return 0; + return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value)); + return PROCESS_DONE (ctx, 0); } static int @@ -109,13 +118,13 @@ ctx->bye_notify_fnc (ctx); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); - return -1; /* pretty simple :-) */ + return PROCESS_DONE (ctx, _assuan_error (-1)); /* pretty simple :-) */ } static int std_handler_auth (assuan_context_t ctx, char *line) { - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } static int @@ -126,13 +135,13 @@ assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); _assuan_uds_close_fds (ctx); - return 0; + return PROCESS_DONE (ctx, 0); } static int std_handler_end (assuan_context_t ctx, char *line) { - return set_error (ctx, Not_Implemented, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); } @@ -181,11 +190,11 @@ rc = assuan_command_parse_fd (ctx, line, &fd); if (rc) - return rc; + return PROCESS_DONE (ctx, rc); ctx->input_fd = fd; if (ctx->input_notify_fnc) ctx->input_notify_fnc (ctx, line); - return 0; + return PROCESS_DONE (ctx, 0); } /* Format is OUTPUT FD= */ @@ -197,11 +206,11 @@ rc = assuan_command_parse_fd (ctx, line, &fd); if (rc) - return rc; + return PROCESS_DONE (ctx, rc); ctx->output_fd = fd; if (ctx->output_notify_fnc) ctx->output_notify_fnc (ctx, line); - return 0; + return PROCESS_DONE (ctx, 0); } @@ -414,9 +423,10 @@ return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b); } + /* Parse the line, break out the command, find it in the command table, remove leading and white spaces from the arguments, call the - handler with the argument line and return the error */ + handler with the argument line and return the error. */ static int dispatch_command (assuan_context_t ctx, char *line, int linelen) { @@ -461,42 +471,34 @@ return ctx->cmdtbl[i].handler (ctx, line); } - - -static int -process_request (assuan_context_t ctx) +/* Call this to acknowledge the current command. */ +int +assuan_process_done (assuan_context_t ctx, int rc) { - int rc; + if (!ctx->in_command) + return _assuan_error (ASSUAN_General_Error); - if (ctx->in_inquire) - return _assuan_error (ASSUAN_Nested_Commands); + ctx->in_command = 0; - rc = _assuan_read_line (ctx); - if (rc) - return rc; - if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) - return 0; /* comment line - ignore */ - - ctx->outbound.data.error = 0; - ctx->outbound.data.linelen = 0; - /* dispatch command and return reply */ - rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); - /* check from data write errors */ + /* Check for data write errors. */ if (ctx->outbound.data.fp) - { /* Flush the data lines */ + { + /* Flush the data lines. */ fclose (ctx->outbound.data.fp); ctx->outbound.data.fp = NULL; if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; + rc = ctx->outbound.data.error; } - else /* flush any data send w/o using the data fp */ + else { + /* Flush any data send without using the data FP. */ assuan_send_data (ctx, NULL, 0); if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; + rc = ctx->outbound.data.error; } - /* Error handling */ + + /* Error handling. */ if (!rc) { rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); @@ -509,26 +511,26 @@ else { char errline[300]; - + if (rc < 100) sprintf (errline, "ERR %d server fault (%.50s)", _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc)); else { const char *text = ctx->err_no == rc? ctx->err_str:NULL; - + #if defined(HAVE_W32_SYSTEM) unsigned int source, code; char ebuf[50]; const char *esrc; - + source = ((rc >> 24) & 0xff); code = (rc & 0x00ffffff); if (source && !_assuan_gpg_strerror_r (rc, ebuf, sizeof ebuf) && (esrc=_assuan_gpg_strsource (rc))) { - /* Assume this is an libgpg-error. */ + /* Assume this is an libgpg-error. */ sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", rc, ebuf, esrc, text? " - ":"", text?text:""); @@ -562,7 +564,7 @@ { /* Assume this is an libgpg-error. */ char ebuf[50]; - + gpg_strerror_r (rc, ebuf, sizeof ebuf ); sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", rc, @@ -577,19 +579,117 @@ } rc = assuan_write_line (ctx, errline); } - + if (ctx->post_cmd_notify_fnc) ctx->post_cmd_notify_fnc (ctx, rc); - + ctx->confidential = 0; if (ctx->okay_line) { xfree (ctx->okay_line); ctx->okay_line = NULL; } + return rc; } + +static int +process_next (assuan_context_t ctx) +{ + int rc; + + /* What the next thing to do is depends on the current state. + However, we will always first read the next line. The client is + required to write full lines without blocking long after starting + a partial line. */ + rc = _assuan_read_line (ctx); + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + /* Comment lines are ignored. */ + return 0; + + /* Now we have a line that really means something. It could be one + of the following things: First, if we are not in a command + already, it is the next command to dispatch. Second, if we are + in a command, it can only be the response to an INQUIRE + reply. */ + + if (!ctx->in_command) + { + ctx->in_command = 1; + + ctx->outbound.data.error = 0; + ctx->outbound.data.linelen = 0; + /* Dispatch command and return reply. */ + ctx->in_process_next = 1; + rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + ctx->in_process_next = 0; + } + else if (ctx->in_inquire) + { + /* FIXME: Pick up the continuation. */ + rc = _assuan_inquire_ext_cb (ctx); + } + else + { + /* Should not happen. The client is sending data while we are + in a command and not waiting for an inquire. We log an error + and discard it. */ + _assuan_log_printf ("unexpected client data\n"); + rc = 0; + } + + return rc; +} + + +/* This function should be invoked when the assuan connected FD is + ready for reading. If the equivalent to EWOULDBLOCK is returned + (this should be done by the command handler), assuan_process_next + should be invoked the next time the connected FD is readable. + Eventually, the caller will finish by invoking + assuan_process_done. */ +int +assuan_process_next (assuan_context_t ctx) +{ + int rc; + + do + { + rc = process_next (ctx); + } + while (!rc && assuan_pending_line (ctx)); + + return rc; +} + + + +static int +process_request (assuan_context_t ctx) +{ + int rc; + + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + rc = _assuan_read_line (ctx); + if (rc) + return rc; + if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) + return 0; /* comment line - ignore */ + + ctx->in_command = 1; + ctx->outbound.data.error = 0; + ctx->outbound.data.linelen = 0; + /* dispatch command and return reply */ + rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); + + return assuan_process_done (ctx, rc); +} + /** * assuan_process: * @ctx: assuan context @@ -618,24 +718,6 @@ /** - * assuan_process_next: - * @ctx: Assuan context - * - * Same as assuan_process() but the user has to provide the outer - * loop. He should loop as long as the return code is zero and stop - * otherwise; -1 is regular end. - * - * See also: assuan_get_active_fds() - * Return value: -1 for end of server, 0 on success or an error code - **/ -int -assuan_process_next (assuan_context_t ctx) -{ - return process_request (ctx); -} - - -/** * assuan_get_active_fds: * @ctx: Assuan context * @what: 0 for read fds, 1 for write fds Modified: trunk/src/assuan-inquire.c =================================================================== --- trunk/src/assuan-inquire.c 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/assuan-inquire.c 2007-08-09 10:44:02 UTC (rev 247) @@ -42,7 +42,7 @@ -/* A simple implemnation of a dynamic buffer. Use init_membuf() to +/* A simple implementation of a dynamic buffer. Use init_membuf() to create a buffer, put_membuf to append bytes and get_membuf to release and return the buffer. Allocation errors are detected but only returned at the final get_membuf(), this helps not to clutter @@ -232,8 +232,157 @@ return rc; } + +void +_assuan_inquire_release (assuan_context_t ctx) +{ + if (ctx->in_inquire) + { + if (ctx->inquire_membuf) + { + free_membuf (ctx->inquire_membuf); + free (ctx->inquire_membuf); + } + ctx->in_inquire = 0; + } +} +int +_assuan_inquire_ext_cb (assuan_context_t ctx) +{ + int rc; + unsigned char *line; + int linelen; + struct membuf *mb; + unsigned char *p; + line = (unsigned char *) ctx->inbound.line; + linelen = ctx->inbound.linelen; + mb = ctx->inquire_membuf; + if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') + { + rc = _assuan_error (ASSUAN_Canceled); + goto leave; + } + if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (!line[3] || line[3] == ' ')) + { + rc = 0; + goto leave; + } + if (line[0] != 'D' || line[1] != ' ' || mb == NULL) + { + rc = _assuan_error (ASSUAN_Unexpected_Command); + goto leave; + } + + if (linelen < 3) + return 0; + line += 2; + linelen -= 2; + + p = line; + while (linelen) + { + for (;linelen && *p != '%'; linelen--, p++) + ; + put_membuf (mb, line, p-line); + if (linelen > 2) + { /* handle escaping */ + unsigned char tmp[1]; + p++; + *tmp = xtoi_2 (p); + p += 2; + linelen -= 3; + put_membuf (mb, tmp, 1); + } + line = p; + } + if (mb->too_large) + { + rc = _assuan_error (ASSUAN_Too_Much_Data); + goto leave; + } + + return 0; + + leave: + if (mb) + { + *(ctx->inquire_r_buffer) = get_membuf (mb, ctx->inquire_r_buffer_len); + if (!*(ctx->inquire_r_buffer)) + rc = _assuan_error (ASSUAN_Out_Of_Core); + free_membuf (mb); + free (mb); + } + (ctx->inquire_cb) (ctx->inquire_cb_data, rc); + return rc; +} + +/** + * assuan_inquire_ext: + * @ctx: An assuan context + * @keyword: The keyword used for the inquire + * @r_buffer: Returns an allocated buffer + * @r_length: Returns the length of this buffer + * @maxlen: If not 0, the size limit of the inquired data. + * @cb: A callback handler which is invoked after the operation completed. + * @cb_data: A user-provided value passed to the callback handler. + * + * A Server may use this to Send an inquire. r_buffer, r_length and + * maxlen may all be NULL/0 to indicate that no real data is expected. + * When this function returns, + * + * Return value: 0 on success or an ASSUAN error code + **/ +assuan_error_t +assuan_inquire_ext (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, size_t maxlen, + int (*cb) (void *cb_data, int rc), void *cb_data) +{ + assuan_error_t rc; + struct membuf *mb = NULL; + char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ + int nodataexpected; + + if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) + return _assuan_error (ASSUAN_Invalid_Value); + nodataexpected = !r_buffer && !r_length && !maxlen; + if (!nodataexpected && (!r_buffer || !r_length)) + return _assuan_error (ASSUAN_Invalid_Value); + if (!ctx->is_server) + return _assuan_error (ASSUAN_Not_A_Server); + if (ctx->in_inquire) + return _assuan_error (ASSUAN_Nested_Commands); + + if (!nodataexpected) + { + mb = malloc (sizeof (struct membuf)); + if (!mb) + return _assuan_error (ASSUAN_Out_Of_Core); + init_membuf (mb, maxlen ? maxlen : 1024, maxlen); + } + + strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); + rc = assuan_write_line (ctx, cmdbuf); + if (rc) + { + free_membuf (mb); + free (mb); + return rc; + } + + ctx->in_inquire = 1; + + /* Set up the continuation. */ + ctx->inquire_cb = cb; + ctx->inquire_cb_data = cb_data; + ctx->inquire_membuf = mb; + ctx->inquire_r_buffer = r_buffer; + ctx->inquire_r_buffer_len = r_length; + + return 0; +} Modified: trunk/src/assuan-pipe-server.c =================================================================== --- trunk/src/assuan-pipe-server.c 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/assuan-pipe-server.c 2007-08-09 10:44:02 UTC (rev 247) @@ -167,6 +167,7 @@ { if (ctx) { + _assuan_inquire_release (ctx); xfree (ctx->hello_line); xfree (ctx->okay_line); xfree (ctx->cmdtbl); Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/assuan.h 2007-08-09 10:44:02 UTC (rev 247) @@ -75,6 +75,7 @@ _ASSUAN_PREFIX(assuan_register_option_handler) #define assuan_process _ASSUAN_PREFIX(assuan_process) #define assuan_process_next _ASSUAN_PREFIX(assuan_process_next) +#define assuan_process_done _ASSUAN_PREFIX(assuan_process_done) #define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds) #define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp) #define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line) @@ -102,6 +103,7 @@ #define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred) #define assuan_transact _ASSUAN_PREFIX(assuan_transact) #define assuan_inquire _ASSUAN_PREFIX(assuan_inquire) +#define assuan_inquire_ext _ASSUAN_PREFIX(assuan_inquire_ext) #define assuan_read_line _ASSUAN_PREFIX(assuan_read_line) #define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line) #define assuan_write_line _ASSUAN_PREFIX(assuan_write_line) @@ -372,6 +374,7 @@ int assuan_process (assuan_context_t ctx); int assuan_process_next (assuan_context_t ctx); +int assuan_process_done (assuan_context_t ctx, int rc); int assuan_get_active_fds (assuan_context_t ctx, int what, assuan_fd_t *fdarray, int fdarraysize); @@ -462,7 +465,11 @@ assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword, unsigned char **r_buffer, size_t *r_length, size_t maxlen); - +assuan_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword, + unsigned char **r_buffer, size_t *r_length, + size_t maxlen, + int (*cb) (void *cb_data, int rc), + void *cb_data); /*-- assuan-buffer.c --*/ assuan_error_t assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen); Modified: trunk/src/mkerrors =================================================================== --- trunk/src/mkerrors 2007-07-12 15:26:33 UTC (rev 246) +++ trunk/src/mkerrors 2007-08-09 10:44:02 UTC (rev 247) @@ -56,8 +56,13 @@ unsigned int n; if (!err_source) - return (oldcode & 0x00ffffff); /* Make sure that the gpg-error - source part is cleared. */ + { + if (oldcode == -1) + return -1; + else + return (oldcode & 0x00ffffff); /* Make sure that the gpg-error + source part is cleared. */ + } switch (oldcode) { From cvs at cvs.gnupg.org Thu Aug 9 17:51:45 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 09 Aug 2007 17:51:45 +0200 Subject: [svn] dirmngr - r260 - in trunk: . doc jnlib src Message-ID: Author: wk Date: 2007-08-09 17:51:16 +0200 (Thu, 09 Aug 2007) New Revision: 260 Modified: trunk/ChangeLog trunk/NEWS trunk/doc/dirmngr.texi trunk/jnlib/ChangeLog trunk/jnlib/argparse.c trunk/jnlib/stringhelp.c trunk/src/ChangeLog trunk/src/crlfetch.c trunk/src/dirmngr-client.c trunk/src/dirmngr.c trunk/src/dirmngr.h trunk/src/estream-printf.c trunk/src/estream.h trunk/src/ocsp.c trunk/src/ocsp.h trunk/src/server.c Log: Fixed OCSP stuff New OCSP features. General cleanup. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/ChangeLog 2007-08-09 15:51:16 UTC (rev 260) @@ -1,3 +1,9 @@ +2007-08-09 Werner Koch + + * doc/dirmngr.texi (Dirmngr Options): Describe the new format of + --ocsp-signer. + (Dirmngr ISVALID): Rework. + 2007-08-07 Werner Koch * configure.ac (COPYRIGHT_YEAR_NAME): Set to 2007. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/NEWS 2007-08-09 15:51:16 UTC (rev 260) @@ -1,7 +1,16 @@ Noteworthy changes in version 1.0.1 ------------------------------------------------ + * The option --ocsp-signer may now take a filename to allow several + certificates to be valid signers for the default responder. + * New option --ocsp-max-period and improved the OCSP time checks. + + * New option --force-default-signer for dirmngr-client. + + * Ported to Windows. + + Noteworthy changes in version 1.0.0 (2006-11-29) ------------------------------------------------ Modified: trunk/doc/dirmngr.texi =================================================================== --- trunk/doc/dirmngr.texi 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/doc/dirmngr.texi 2007-08-09 15:51:16 UTC (rev 260) @@ -32,7 +32,7 @@ Copyright @copyright{} 2002 Klar?lvdalens Datakonsult AB -Copyright @copyright{} 2004, 2005, 2006 g10 Code GmbH +Copyright @copyright{} 2004, 2005, 2006, 2007 g10 Code GmbH @quotation Permission is granted to copy, distribute and/or modify this document @@ -134,7 +134,7 @@ Dirmngr is a server for managing and downloading certificate revocation lists (CRLs) for X.509 certificates and for downloading the certificates themselves. Dirmngr also handles OCSP requests as an alternative to -CRLs. Dirmngr is either invoked internally by gpgsm (from gnupg 1.9) or +CRLs. Dirmngr is either invoked internally by gpgsm (from GnuPG 2) or when running as a system daemon through the @command{dirmngr-client} tool. @manpause @@ -146,7 +146,7 @@ Installation is decribed in the file @file{INSTALL} and given that you are already reading this documentation we can only give some hints on further configuration. If you plan to use dirmngr as a system daemon -and not only as a part of gnupg 1.9, you should read on. +and not only as a part of GnuPG 2, you should read on. If @command{dirmngr} is started in system daemon mode, it uses a directory layout as common for system daemon and does not make use of @@ -421,6 +421,11 @@ the @acronym{LDAP} scheme. Both options may be combined resulting in ignoring DPs entirely. + at item --ignore-ocsp-service-url + at opindex ignore-ocsp-service-url +Ignore all OCSP URLs contained in the certificate. The effect is to +force the use of the default responder. + @item --honor-http-proxy @opindex honor-http-proxy If the environment variable @env{http_proxy} has been set, use its @@ -507,24 +512,42 @@ not contain information about an assigned responder. Note, that @code{--ocsp-signer} must also be set to a valid certificate. - at item --ocsp-signer @var{fpr} + at item --ocsp-signer @var{fpr}|@var{file} @opindex ocsp-signer Use the certificate with the fingerprint @var{fpr} to check the -responses of the default OCSP Responder. Dirmngr will retrieve this -certificate from the current client. +responses of the default OCSP Responder. Alternativly a filename can be +given in which case the respinse is expected to be signed by one of the +certificates described in that file. Any argument which contains a +slash, dot or tilde is considered a filename. Usual filename expansion +takes place: A tilde at the start followed by a slash is replaced by the +content of @env{HOME}, no slash at start describes a relative filename +which will be searched at the home directory. To make sure that the + at var{file} is searched in the home directory, either prepend the name +with "./" or use a name which contains a dot. -If a response has been signed by this certificate no further check upon -the validity of this certificate is done! +If a response has been signed by a certificate described by these +fingerprints no further check upon the validity of this certificate is +done. +The format of the @var{FILE} is a list of SHA-1 fingerprint, one per +line with optional colons between the bytes. Empty lines and lines +prefix with a hash mark are ignored. + + @item --ocsp-max-clock-skew @var{n} @opindex ocsp-max-clock-skew -The number of seconds a skew between the OCSP respinder and them local +The number of seconds a skew between the OCSP responder and them local clock is accepted. Default is 600 (20 minutes). + at item --ocsp-max-period @var{n} + at opindex ocsp-max-period +Seconds a response is at maximum considered valid after the time given +in the thisUpdate field. Default is 7776000 (90 days). + @item --ocsp-current-period @var{n} @opindex ocsp-current-period -The number of seconds an OCSP reponse is valid after the time given in -the NEXT_UPDATE datum. Default is 10800 (3 hours). +The number of seconds an OCSP response is considered valid after the +time given in the NEXT_UPDATE datum. Default is 10800 (3 hours). @item --max-replies @var{n} @@ -584,15 +607,18 @@ The way to start the dirmngr in the foreground (as done by tools if no dirmngr is running in the background) is to use: + @example dirmngr --server -v @end example If a dirmngr is supposed to be used as a system wide daemon, it should be started like: + @example dirmngr --daemon @end example + This will force it to go into the backround, read the default certificates (including the trusted root certificates) and listen on a socket for client requests. It does also print information about the @@ -657,44 +683,66 @@ @node Dirmngr ISVALID @section Validate a certificate using a CRL or OCSP -Check whether the certificate described by the certificate_ID (which -is a fingerprint) has been revoked. Due to caching, the Dirmngr is -able to answer immediately in most cases: + at example + ISVALID [--only-ocsp] [--force-default-responder] @var{certid}|@var{certfpr} + at end example - @code{S: OK} +Check whether the certificate described by the @var{certid} has been +revoked. Due to caching, the Dirmngr is able to answer immediately in +most cases. -Yes, the certificate is not revoked and we have a up-to-date -revocation list for that certificate. +The @var{certid} is a hex encoded string consisting of two parts, +delimited by a single dot. The first part is the SHA-1 hash of the +issuer name and the second part the serial number. - @code{S: E 301 certificate has been revoked} +Alternatively the certificate's SHA-1 fingerprint @var{certfpr} may be +given in which case an OCSP request is done before consulting the CRL. +If the option @option{--only-ocsp} is given, no fallback to a CRL check +will be used. If the option @option{--force-default-responder} is +given, only the default OCSP responder will be used and any other +methods of obtaining an OCSP responder URL won't be used. -The client may then issue another command to retrieve information on -the revocation reason. + at noindent +Common return values are: - @code{S: E 302 no CRL known for this certificate} + at table @code + at item GPG_ERR_NO_ERROR (0) +This is the positive answer: The certificate is not revoked and we have +an up-to-date revocation list for that certificate. If OCSP was used +the responder confirmed that the certificate has not been revoked. - @code{S: E 303 CRL is too old and a new one could not be retrieved} + at item GPG_ERR_CERT_REVOKED +This is the negative answer: The certificate has been revoked. Either +it is in a CRL and that list is up to date or an OCSP responder informed +us that it has been revoked. -If the DirMngr has not enough information about the given -certificate which is the case for not yet cached certificates -because the clients only passes the CertID, the DirMngr will will -inquire the missing data: + at item GPG_ERR_NO_CRL_KNOWN +No CRL is known for this certificate or the CRL is not valid or out of +date. + at item GPG_ERR_NO_DATA +The OCSP responder returned an ``unknown'' status. This means that it +is not aware of the certificate's status. + + at item GPG_ERR_NOT_SUPPORTED +This is commonly seen if OCSP support has not been enabled in the +configuration. + at end table + +If DirMngr has not enough information about the given certificate (which +is the case for not yet cached certificates), it will will inquire the +missing data: + @example S: INQUIRE SENDCERT C: D C: END @end example -A client should be aware the the DirMngr may ask for more than one Certificate. +A client should be aware that DirMngr may ask for more than one +certificate. -If the option @code{--allow-ocsp} is enabled, this command may -alternativly run an OCSP request. The client requests this by simply -using the fingerrpint instead of the certificate-id. There is no fall -back to CRL checking if the OCSP requests could not be done for -whatever reason. - @node Dirmngr CHECKCRL @section Validate a certificate using a CRL @@ -724,25 +772,34 @@ @node Dirmngr CHECKOCSP @section Validate a certificate using OCSP - Check whether the certificate with FINGERPRINT (SHA-1 hash of the - entire X.509 certificate blob) is valid or not by consulting the - appropiateOCSP responder. If the fingerprint has not - been given or the certificate is not know, the function - inquires the certificate using: + at example + CHECKOCSP [--force-default-responder] [@var{fingerprint}] + at end example +Check whether the certificate with @var{fingerprint} (the SHA-1 hash of +the entire X.509 certificate blob) is valid by consulting the appropiate +OCSP responder. If the fingerprint has not been given or the +certificate is not known by Dirmngr, the function inquires the +certificate using: + @example S: INQUIRE TARGETCERT C: D C: END @end example - Thus the caller is expected to return the certificate for the - request (which should match FINGERPRINT) as a binary blob. - Processing then takes place without further interaction; in - particular dirmngr tries to locate other required certificate by - its own mechanism which includes a local certificate store as well - as a list of trusted root certificates. +Thus the caller is expected to return the certificate for the request +(which should match @var{fingerprint}) as a binary blob. Processing +then takes place without further interaction; in particular dirmngr +tries to locate other required certificates by its own mechanism which +includes a local certificate store as well as a list of trusted root +certificates. +If the option @option{--force-default-responder} is given, only the +default OCSP responder is used. This option is the per-command variant +of the global option @option{--ignore-ocsp-service-url}. + + @noindent The return code is 0 for success; i.e. the certificate has not been revoked or one of the usual error codes from libgpg-error. @@ -889,8 +946,13 @@ @item --ocsp @opindex ocsp -Do the check using the COSP protocol and ignore any CRLs. +Do the check using the OCSP protocol and ignore any CRLs. + at item --force-default-responder + at opindex force-default-responder +When checking using the OCSP protocl, force the use of the default OCSP +responder. That is not to use the Reponder as given by the certificate. + @item --ping @opindex ping Check whether the dirmngr daemon is up and running. @@ -908,7 +970,7 @@ @item --load-crl @opindex load-crl This command expects a list of filenames with DER encoded CRL files. -All CRL will be vfalidated and then loaded into dirmngr's cache. +All CRL will be validated and then loaded into dirmngr's cache. @item --lookup @opindex lookup Modified: trunk/jnlib/ChangeLog =================================================================== --- trunk/jnlib/ChangeLog 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/jnlib/ChangeLog 2007-08-09 15:51:16 UTC (rev 260) @@ -1,3 +1,8 @@ +2007-08-09 Werner Koch + + * argparse.c (show_help): Expand the @EMAIL@ macro in the package + bug reporting address. + 2006-11-29 Werner Koch * argparse.c (strusage): Define 49 as error reporting address. Modified: trunk/jnlib/argparse.c =================================================================== --- trunk/jnlib/argparse.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/jnlib/argparse.c 2007-08-09 15:51:16 UTC (rev 260) @@ -834,8 +834,21 @@ puts("\n(A single dash may be used instead of the double ones)"); } if( (s=strusage(19)) ) { /* bug reports to ... */ + char *s2; + putchar('\n'); - fputs(s, stdout); + s2 = strstr (s, "@EMAIL@"); + if (s2) + { + if (s2-s) + fwrite (s, s2-s, 1, stdout); + fputs (PACKAGE_BUGREPORT, stdout); + s2 += 7; + if (*s2) + fputs (s2, stdout); + } + else + fputs(s, stdout); } fflush(stdout); exit(0); Modified: trunk/jnlib/stringhelp.c =================================================================== --- trunk/jnlib/stringhelp.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/jnlib/stringhelp.c 2007-08-09 15:51:16 UTC (rev 260) @@ -273,10 +273,10 @@ char *p; if ( !(p=strrchr(filepath, '/')) ) - #ifdef HAVE_DRIVE_LETTERS +#ifdef HAVE_DRIVE_LETTERS if ( !(p=strrchr(filepath, '\\')) ) if ( !(p=strrchr(filepath, ':')) ) - #endif +#endif { return jnlib_xstrdup("."); } Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/ChangeLog 2007-08-09 15:51:16 UTC (rev 260) @@ -1,3 +1,29 @@ +2007-08-09 Werner Koch + + * dirmngr.c (parse_ocsp_signer): New. + (parse_rereadable_options): Set opt.ocsp_signer to this. + * dirmngr.h (fingerprint_list_t): New. + * ocsp.c (ocsp_isvalid, check_signature, validate_responder_cert): + Allow for several default ocscp signers. + (ocsp_isvalid): Return GPG_ERR_NO_DATA for an unknwon status. + + * dirmngr-client.c: New option --force-default-responder. + + * server.c (has_option, skip_options): New. + (cmd_checkocsp): Add option --force-default-responder. + (cmd_isvalid): Ditto. Also add option --only-ocsp. + + * ocsp.c (ocsp_isvalid): New arg FORCE_DEFAULT_RESPONDER. + + * dirmngr.c: New option --ocsp-max-period. + * ocsp.c (ocsp_isvalid): Implement it and take care that a missing + next_update is to be ignored. + + * crlfetch.c (my_es_read): New. Use it instead of es_read. + + * estream.h, estream.c, estream-printf.c: Updated from current + libestream SVN. + 2007-08-08 Werner Koch * crlcache.c (crl_parse_insert): Hack to allow for a missing Modified: trunk/src/crlfetch.c =================================================================== --- trunk/src/crlfetch.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/crlfetch.c 2007-08-09 15:51:16 UTC (rev 260) @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include @@ -83,6 +84,14 @@ } + +static int +my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread) +{ + return es_read (opaque, buffer, nbytes, nread); +} + + /* Fetch CRL from URL and return the entire CRL using new ksba reader object in READER. Note that this reader object should be closed only using ldap_close_reader. */ @@ -143,7 +152,7 @@ err = ksba_reader_new (reader); if (!err) - err = ksba_reader_set_cb (*reader, &es_read, fp); + err = ksba_reader_set_cb (*reader, &my_es_read, fp); if (err) { log_error (_("error initializing reader object: %s\n"), Modified: trunk/src/dirmngr-client.c =================================================================== --- trunk/src/dirmngr-client.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/dirmngr-client.c 2007-08-09 15:51:16 UTC (rev 260) @@ -1,5 +1,5 @@ /* dirmngr-client.c - A client for the dirmngr daemon - * Copyright (C) 2004 g10 Code GmbH + * Copyright (C) 2004, 2007 g10 Code GmbH * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This file is part of DirMngr. @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include @@ -59,6 +60,7 @@ oSquidMode, oPEM, oEscapedPEM, + oForceDefaultResponder }; @@ -74,6 +76,8 @@ { oLoadCRL, "load-crl", 0, N_("load a CRL into the dirmngr")}, { oSquidMode,"squid-mode",0, N_("special mode for use by Squid")}, { oPEM, "pem", 0, N_("certificates are expected in PEM format")}, + { oForceDefaultResponder, "force-default-responder", 0, + N_("force the use of the default OCSP responder")}, { 0 } }; @@ -86,11 +90,12 @@ int verbose; const char *dirmngr_program; int force_pipe_server; + int force_default_responder; int pem; int escaped_pem; /* PEM is additional percent encoded. */ int use_ocsp; - + } opt; @@ -224,6 +229,7 @@ opt.escaped_pem = 1; cmd_squid_mode = 1; break; + case oForceDefaultResponder: opt.force_default_responder = 1; break; default : pargs.err = 2; break; } @@ -801,9 +807,11 @@ parm.cert = cert; parm.certlen = certlen; - err = assuan_transact (ctx, opt.use_ocsp? "CHECKOCSP":"CHECKCRL", NULL, NULL, - inq_cert, &parm, - status_cb, NULL); + err = assuan_transact (ctx, + (opt.use_ocsp && opt.force_default_responder + ? "CHECKOCSP --force-default-responder" + : opt.use_ocsp? "CHECKOCSP" : "CHECKCRL"), + NULL, NULL, inq_cert, &parm, status_cb, NULL); if (opt.verbose > 1) log_info ("response of dirmngr: %s\n", err? gpg_strerror (err): "okay"); return err; Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/dirmngr.c 2007-08-09 15:51:16 UTC (rev 260) @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include @@ -101,6 +102,7 @@ oOCSPResponder, oOCSPSigner, oOCSPMaxClockSkew, + oOCSPMaxPeriod, oOCSPCurrentPeriod, oMaxReplies, oFakedSystemTime, @@ -173,6 +175,7 @@ { oOCSPResponder, "ocsp-responder", 2, N_("|URL|use OCSP responder at URL")}, { oOCSPSigner, "ocsp-signer", 2, N_("|FPR|OCSP response signed by FPR")}, { oOCSPMaxClockSkew, "ocsp-max-clock-skew", 1, "@" }, + { oOCSPMaxPeriod, "ocsp-max-period", 1, "@" }, { oOCSPCurrentPeriod, "ocsp-current-period", 1, "@" }, { oMaxReplies, "max-replies", 1, @@ -218,6 +221,7 @@ static void cleanup (void); static ldap_server_t parse_ldapserver_file (const char* filename); static void free_ldapservers_list (ldap_server_t servers); +static fingerprint_list_t parse_ocsp_signer (const char *string); static void handle_connections (int listen_fd); /* Pth wrapper function definitions. */ @@ -235,8 +239,9 @@ case 13: p = VERSION; break; case 14: p = "Copyright (C) " COPYRIGHT_YEAR_NAME; break; case 17: p = PRINTABLE_OS_NAME; break; - /* TRANSLATORS: @EMAIL will get replaced by the actual bug - reporting address. */ + /* TRANSLATORS: @EMAIL@ will get replaced by the actual bug + reporting address. This is so that we can change the + reporting address without breaking the translations. */ case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break; case 49: p = PACKAGE_BUGREPORT; break; case 1: @@ -415,10 +420,16 @@ opt.ignore_ocsp_service_url = 0; opt.allow_ocsp = 0; opt.ocsp_responder = NULL; - opt.ocsp_signer = NULL; opt.ocsp_max_clock_skew = 10 * 60; /* 10 minutes. */ + opt.ocsp_max_period = 90 * 86400; /* 90 days. */ opt.ocsp_current_period = 3 * 60 * 60; /* 3 hours. */ opt.max_replies = DEFAULT_MAX_REPLIES; + while (opt.ocsp_signer) + { + fingerprint_list_t tmp = opt.ocsp_signer->next; + xfree (opt.ocsp_signer); + opt.ocsp_signer = tmp; + } return 1; } @@ -461,8 +472,11 @@ case oAllowOCSP: opt.allow_ocsp = 1; break; case oOCSPResponder: opt.ocsp_responder = pargs->r.ret_str; break; - case oOCSPSigner: opt.ocsp_signer = pargs->r.ret_str; break; + case oOCSPSigner: + opt.ocsp_signer = parse_ocsp_signer (pargs->r.ret_str); + break; case oOCSPMaxClockSkew: opt.ocsp_max_clock_skew = pargs->r.ret_int; break; + case oOCSPMaxPeriod: opt.ocsp_max_period = pargs->r.ret_int; break; case oOCSPCurrentPeriod: opt.ocsp_current_period = pargs->r.ret_int; break; case oMaxReplies: opt.max_replies = pargs->r.ret_int; break; @@ -1398,6 +1412,129 @@ } +static fingerprint_list_t +parse_ocsp_signer (const char *string) +{ + gpg_error_t err; + char *fname; + FILE *fp; + char line[256]; + char *p; + fingerprint_list_t list, *list_tail, item; + unsigned int lnr = 0; + int c, i, j; + int errflag = 0; + + + /* Check whether this is not a filename and treat it as a direct + fingerprint specification. */ + if (!strpbrk (string, "/.~\\")) + { + item = xcalloc (1, sizeof *item); + for (i=j=0; (string[i] == ':' || hexdigitp (string+i)) && j < 40; i++) + if ( string[i] != ':' ) + item->hexfpr[j++] = string[i] >= 'a'? (string[i] & 0xdf): string[i]; + item->hexfpr[j] = 0; + if (j != 40 || !(spacep (string+i) || !string[i])) + { + log_error (_("%s:%u: invalid fingerprint detected\n"), + "--ocsp-signer", 0); + xfree (item); + return NULL; + } + return item; + } + + /* Well, it is a filename. */ + if (*string == '/' || (*string == '~' && string[1] == '/')) + fname = make_filename (string, NULL); + else + { + if (string[0] == '.' && string[1] == '/' ) + string += 2; + fname = make_filename (opt.homedir, string, NULL); + } + + fp = fopen (fname, "r"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err)); + xfree (fname); + return NULL; + } + + list = NULL; + list_tail = &list; + for (;;) + { + if (!fgets (line, DIM(line)-1, fp) ) + { + if (!feof (fp)) + { + err = gpg_error_from_syserror (); + log_error (_("%s:%u: read error: %s\n"), + fname, lnr, gpg_strerror (err)); + errflag = 1; + } + fclose (fp); + if (errflag) + { + while (list) + { + fingerprint_list_t tmp = list->next; + xfree (list); + list = tmp; + } + } + xfree (fname); + return list; /* Ready. */ + } + + lnr++; + if (!*line || line[strlen(line)-1] != '\n') + { + /* Eat until end of line. */ + while ( (c=getc (fp)) != EOF && c != '\n') + ; + err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG + /* */: GPG_ERR_INCOMPLETE_LINE); + log_error (_("%s:%u: read error: %s\n"), + fname, lnr, gpg_strerror (err)); + errflag = 1; + continue; + } + + /* Allow for empty lines and spaces */ + for (p=line; spacep (p); p++) + ; + if (!*p || *p == '\n' || *p == '#') + continue; + + item = xcalloc (1, sizeof *item); + *list_tail = item; + list_tail = &item->next; + + for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++) + if ( p[i] != ':' ) + item->hexfpr[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; + item->hexfpr[j] = 0; + if (j != 40 || !(spacep (p+i) || p[i] == '\n')) + { + log_error (_("%s:%u: invalid fingerprint detected\n"), fname, lnr); + errflag = 1; + } + i++; + while (spacep (p+i)) + i++; + if (p[i] && p[i] != '\n') + log_info (_("%s:%u: garbage at end of line ignored\n"), fname, lnr); + } + /*NOTREACHED*/ +} + + + /* Stuff used in daemon mode. Modified: trunk/src/dirmngr.h =================================================================== --- trunk/src/dirmngr.h 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/dirmngr.h 2007-08-09 15:51:16 UTC (rev 260) @@ -51,7 +51,16 @@ typedef struct ldap_server_s *ldap_server_t; +/* A list of fingerprints. */ +struct fingerprint_list_s; +typedef struct fingerprint_list_s *fingerprint_list_t; +struct fingerprint_list_s +{ + fingerprint_list_t next; + char hexfpr[20+20+1]; +}; + /* A large struct name "opt" to keep global flags. */ struct { @@ -97,12 +106,15 @@ ldap_server_t ldapservers; int add_new_ldapservers; - const char *ocsp_responder; /* Standard OCSP responder's URL. */ - const char *ocsp_signer; /* The fingerprint of the standard OCSP - responder signer's certificate. */ - unsigned int ocsp_max_clock_skew; /* Allowed seconds of clocks skew. */ - unsigned int ocsp_current_period; /* Seconds a response is - considered current. */ + const char *ocsp_responder; /* Standard OCSP responder's URL. */ + fingerprint_list_t ocsp_signer; /* The list of fingerprints with allowed + standard OCSP signer certificates. */ + + unsigned int ocsp_max_clock_skew; /* Allowed seconds of clocks skew. */ + unsigned int ocsp_max_period; /* Seconds a response is at maximum + considered valid after thisUpdate. */ + unsigned int ocsp_current_period; /* Seconds a response is considered + current after nextUpdate. */ } opt; Modified: trunk/src/estream-printf.c =================================================================== --- trunk/src/estream-printf.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/estream-printf.c 2007-08-09 15:51:16 UTC (rev 260) @@ -17,8 +17,6 @@ * along with Libestream; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. - * - * $Id: estream-printf.c 56 2007-05-15 18:38:43Z wk $ */ /* Required autoconf tests: @@ -60,19 +58,20 @@ #endif #ifdef TEST # include +#else +# ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE +# include _ESTREAM_PRINTF_EXTRA_INCLUDE +# endif #endif -#ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE -#include _ESTREAM_PRINTF_EXTRA_INCLUDE -#endif #include "estream-printf.h" /* Allow redefinition of asprintf used malloc functions. */ -#ifdef _ESTREAM_PRINTF_MALLOC +#if defined(_ESTREAM_PRINTF_MALLOC) && !defined(TEST) #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a)) #else #define my_printf_malloc(a) malloc((a)) #endif -#ifdef _ESTREAM_PRINTF_FREE +#if defined(_ESTREAM_PRINTF_FREE) && !defined(TEST) #define my_printf_free(a) _ESTREAM_PRINTF_FREE((a)) #else #define my_printf_free(a) free((a)) @@ -645,57 +644,7 @@ return -1; } -/* This function is used for testing to provide default arguments. */ -static int -read_dummy_value (value_t *value, valtype_t vt) -{ - switch (vt) - { - case VALTYPE_CHAR: value->a_char = 'a'; break; - case VALTYPE_CHAR_PTR: value->a_char_ptr = NULL; break; - case VALTYPE_SCHAR: value->a_schar = 'a'; break; - case VALTYPE_SCHAR_PTR: value->a_schar_ptr = NULL; break; - case VALTYPE_UCHAR: value->a_uchar = 'a'; break; - case VALTYPE_SHORT: value->a_short = -4711; break; - case VALTYPE_USHORT: value->a_ushort = 4711; break; - case VALTYPE_SHORT_PTR: value->a_short_ptr = NULL; break; - case VALTYPE_INT: value->a_int = 42; break; - case VALTYPE_INT_PTR: value->a_int_ptr = NULL; break; - case VALTYPE_UINT: value->a_uint = 65535; break; - case VALTYPE_LONG: value->a_long = 11071961; break; - case VALTYPE_ULONG: value->a_ulong = 19610711; break; - case VALTYPE_LONG_PTR: value->a_long_ptr = NULL; break; -#ifdef HAVE_LONG_LONG_INT - case VALTYPE_LONGLONG: value->a_longlong = 11223344; break; - case VALTYPE_ULONGLONG: value->a_ulonglong = 2233445566u; break; - case VALTYPE_LONGLONG_PTR: value->a_longlong_ptr = NULL; break; -#endif - case VALTYPE_DOUBLE: value->a_double = 3.1415926535; break; -#ifdef HAVE_LONG_DOUBLE - case VALTYPE_LONGDOUBLE: value->a_longdouble = 2.7; break; -#endif - case VALTYPE_STRING: value->a_string = "heart of gold"; break; - case VALTYPE_POINTER: value->a_void_ptr = (void*)0xdeadbeef; break; -#ifdef HAVE_INTMAX_T - case VALTYPE_INTMAX: value->a_intmax = 100; break; - case VALTYPE_INTMAX_PTR: value->a_intmax_ptr = NULL; break; -#endif -#ifdef HAVE_UINTMAX_T - case VALTYPE_UINTMAX: value->a_uintmax = 200; break; -#endif - case VALTYPE_SIZE: value->a_size = 65537; break; - case VALTYPE_SIZE_PTR: value->a_size_ptr = NULL; break; -#ifdef HAVE_PTRDIFF_T - case VALTYPE_PTRDIFF: value->a_ptrdiff = 2; break; - case VALTYPE_PTRDIFF_PTR: value->a_ptrdiff_ptr = NULL; break; -#endif - default: /* Unsupported type. */ - return -1; - } - return 0; -} - /* This function reads all the values as specified by VALUETABLE into VALUETABLE. The values are expected in VAARGS. The function returns -1 if a specified type is not supported. */ @@ -709,102 +658,94 @@ value_t *value = &valuetable[validx].value; valtype_t vt = valuetable[validx].vt; - if (!vaargs) + switch (vt) { - if (read_dummy_value (value, vt)) - return -1; - } - else - { - switch (vt) - { - case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break; - case VALTYPE_CHAR_PTR: - value->a_char_ptr = va_arg (vaargs, char *); - break; - case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break; - case VALTYPE_SCHAR_PTR: - value->a_schar_ptr = va_arg (vaargs, signed char *); - break; - case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break; - case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break; - case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break; - case VALTYPE_SHORT_PTR: - value->a_short_ptr = va_arg (vaargs, short *); - break; - case VALTYPE_INT: - value->a_int = va_arg (vaargs, int); - break; - case VALTYPE_INT_PTR: - value->a_int_ptr = va_arg (vaargs, int *); - break; - case VALTYPE_UINT: - value->a_uint = va_arg (vaargs, unsigned int); - break; - case VALTYPE_LONG: - value->a_long = va_arg (vaargs, long); - break; - case VALTYPE_ULONG: - value->a_ulong = va_arg (vaargs, unsigned long); - break; - case VALTYPE_LONG_PTR: - value->a_long_ptr = va_arg (vaargs, long *); - break; + case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break; + case VALTYPE_CHAR_PTR: + value->a_char_ptr = va_arg (vaargs, char *); + break; + case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break; + case VALTYPE_SCHAR_PTR: + value->a_schar_ptr = va_arg (vaargs, signed char *); + break; + case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break; + case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break; + case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break; + case VALTYPE_SHORT_PTR: + value->a_short_ptr = va_arg (vaargs, short *); + break; + case VALTYPE_INT: + value->a_int = va_arg (vaargs, int); + break; + case VALTYPE_INT_PTR: + value->a_int_ptr = va_arg (vaargs, int *); + break; + case VALTYPE_UINT: + value->a_uint = va_arg (vaargs, unsigned int); + break; + case VALTYPE_LONG: + value->a_long = va_arg (vaargs, long); + break; + case VALTYPE_ULONG: + value->a_ulong = va_arg (vaargs, unsigned long); + break; + case VALTYPE_LONG_PTR: + value->a_long_ptr = va_arg (vaargs, long *); + break; #ifdef HAVE_LONG_LONG_INT - case VALTYPE_LONGLONG: - value->a_longlong = va_arg (vaargs, long long int); - break; - case VALTYPE_ULONGLONG: - value->a_ulonglong = va_arg (vaargs, unsigned long long int); - break; - case VALTYPE_LONGLONG_PTR: - value->a_longlong_ptr = va_arg (vaargs, long long *); - break; + case VALTYPE_LONGLONG: + value->a_longlong = va_arg (vaargs, long long int); + break; + case VALTYPE_ULONGLONG: + value->a_ulonglong = va_arg (vaargs, unsigned long long int); + break; + case VALTYPE_LONGLONG_PTR: + value->a_longlong_ptr = va_arg (vaargs, long long *); + break; #endif - case VALTYPE_DOUBLE: - value->a_double = va_arg (vaargs, double); - break; + case VALTYPE_DOUBLE: + value->a_double = va_arg (vaargs, double); + break; #ifdef HAVE_LONG_DOUBLE - case VALTYPE_LONGDOUBLE: - value->a_longdouble = va_arg (vaargs, long double); - break; + case VALTYPE_LONGDOUBLE: + value->a_longdouble = va_arg (vaargs, long double); + break; #endif - case VALTYPE_STRING: - value->a_string = va_arg (vaargs, const char *); - break; - case VALTYPE_POINTER: - value->a_void_ptr = va_arg (vaargs, void *); - break; + case VALTYPE_STRING: + value->a_string = va_arg (vaargs, const char *); + break; + case VALTYPE_POINTER: + value->a_void_ptr = va_arg (vaargs, void *); + break; #ifdef HAVE_INTMAX_T - case VALTYPE_INTMAX: - value->a_intmax = va_arg (vaargs, intmax_t); - break; - case VALTYPE_INTMAX_PTR: - value->a_intmax_ptr = va_arg (vaargs, intmax_t *); - break; + case VALTYPE_INTMAX: + value->a_intmax = va_arg (vaargs, intmax_t); + break; + case VALTYPE_INTMAX_PTR: + value->a_intmax_ptr = va_arg (vaargs, intmax_t *); + break; #endif #ifdef HAVE_UINTMAX_T - case VALTYPE_UINTMAX: - value->a_uintmax = va_arg (vaargs, uintmax_t); - break; + case VALTYPE_UINTMAX: + value->a_uintmax = va_arg (vaargs, uintmax_t); + break; #endif - case VALTYPE_SIZE: - value->a_size = va_arg (vaargs, size_t); - break; - case VALTYPE_SIZE_PTR: - value->a_size_ptr = va_arg (vaargs, size_t *); - break; + case VALTYPE_SIZE: + value->a_size = va_arg (vaargs, size_t); + break; + case VALTYPE_SIZE_PTR: + value->a_size_ptr = va_arg (vaargs, size_t *); + break; #ifdef HAVE_PTRDIFF_T - case VALTYPE_PTRDIFF: - value->a_ptrdiff = va_arg (vaargs, ptrdiff_t); - break; - case VALTYPE_PTRDIFF_PTR: - value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *); - break; + case VALTYPE_PTRDIFF: + value->a_ptrdiff = va_arg (vaargs, ptrdiff_t); + break; + case VALTYPE_PTRDIFF_PTR: + value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *); + break; #endif - default: /* Unsupported type. */ - return -1; - } + default: /* Unsupported type. */ + return -1; } } return 0; @@ -1329,7 +1270,7 @@ /* Run the actual formatting. OUTFNC and OUTFNCARG are the output functions. FORMAT is format string ARGSPECS is the parsed format string, ARGSPECS_LEN the number of items in ARGSPECS. VALUETABLE - holds the values and may be directly addressed using the poistion + holds the values and may be directly addressed using the position arguments given by ARGSPECS. MYERRNO is used for the "%m" conversion. NBYTES well be updated to reflect the number of bytes send to the output function. */ @@ -1449,8 +1390,8 @@ } /* Print out any trailing stuff. */ - s++; /* Need to output a terminating nul; take it from format. */ - rc = outfnc (outfncarg, format, (n=s - format)); + n = s - format; + rc = n? outfnc (outfncarg, format, n) : 0; if (!rc) *nbytes += n; @@ -1619,10 +1560,8 @@ { FILE *fp = (FILE*)outfncarg; - fputs ("OUT->", fp); if ( fwrite (buf, buflen, 1, fp) != 1 ) return -1; - fputs ("<-\n", fp); return 0; } @@ -1715,6 +1654,8 @@ parm.used = 0; parm.buffer = bufsize?buf:NULL; rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr); + if (!rc) + rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul. */ if (rc == -1) return -1; if (bufsize && buf && parm.count >= parm.size) @@ -1807,7 +1748,9 @@ } rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr); - + if (!rc) + rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul. */ + /* Fixme: Should we shrink the resulting buffer? */ if (rc != -1 && parm.error_flag) { rc = -1; @@ -1820,9 +1763,9 @@ *bufp = NULL; return -1; } - + assert (parm.used); /* We have at least the terminating Nul. */ *bufp = parm.buffer; - return parm.used - 1; /* Do not include the nul. */ + return parm.used - 1; /* Do not include that Nul. */ } /* A replacement for asprintf. As with the BSD of asprintf version -1 @@ -1891,8 +1834,7 @@ static void run_tests (void) { -#if 0 - one_test ("%d %% %'d", 17, 19681977); + /*one_test ("%d %% %'d", 17, 19681977);*/ one_test ("%d %% %d", 17, 768114563); one_test ("%d %% %d", 17, -768114563); @@ -2011,8 +1953,9 @@ one_test ("%50s", "the quick brown fox jumps over the lazy dogs back"); one_test ("%51s", "the quick brown fox jumps over the lazy dogs back"); one_test ("%-51s", "the quick brown fox jumps over the lazy dogs back"); -#endif + one_test ("/%s=", "CN"); + one_test ("%f", 3.1415926535); one_test ("%f", -3.1415926535); one_test ("%.10f", 3.1415926535); Modified: trunk/src/estream.h =================================================================== --- trunk/src/estream.h 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/estream.h 2007-08-09 15:51:16 UTC (rev 260) @@ -1,4 +1,4 @@ -/* estream.h - Extended stream I/O/ Library +/* estream.h - Extended stream I/O Library * Copyright (C) 2004, 2005, 2006, 2007 g10 Code GmbH * * This file is part of Libestream. Modified: trunk/src/ocsp.c =================================================================== --- trunk/src/ocsp.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/ocsp.c 2007-08-09 15:51:16 UTC (rev 260) @@ -1,5 +1,5 @@ /* ocsp.c - OCSP management - * Copyright (C) 2004 g10 Code GmbH + * Copyright (C) 2004, 2007 g10 Code GmbH * * This file is part of DirMngr. * @@ -298,26 +298,29 @@ /* Validate that CERT is indeed valid to sign an OCSP response. If - signer_fpr is not NULL we simply check that CERT matches this - fingerprint. */ + SIGNER_FPR_LIST is not NULL we simply check that CERT matches one + of the fingerprints in this list. */ static gpg_error_t -validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert, const char *signer_fpr) +validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert, + fingerprint_list_t signer_fpr_list) { gpg_error_t err; char *fpr; - if (signer_fpr) + if (signer_fpr_list) { - fpr = (strchr (signer_fpr, ':') - ? get_fingerprint_hexstring_colon (cert) - : get_fingerprint_hexstring (cert)); - if (ascii_strcasecmp (signer_fpr, fpr)) + fpr = get_fingerprint_hexstring (cert); + for (; signer_fpr_list && strcmp (signer_fpr_list->hexfpr, fpr); + signer_fpr_list = signer_fpr_list->next) + ; + if (signer_fpr_list) + err = 0; + else { - log_error (_("not signed by default OCSP signer certificate")); + log_error (_("not signed by a default OCSP signer's certificate")); err = gpg_error (GPG_ERR_BAD_CA_CERT); } - else - err = 0; + xfree (fpr); } else if (opt.system_daemon) { @@ -354,7 +357,7 @@ /* Helper for check_signature. */ static int check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig, - gcry_sexp_t s_hash, const char *signer_fpr) + gcry_sexp_t s_hash, fingerprint_list_t signer_fpr_list) { gpg_error_t err; ksba_sexp_t pubkey; @@ -369,7 +372,7 @@ if (!err) err = gcry_pk_verify (s_sig, s_hash, s_pkey); if (!err) - err = validate_responder_cert (ctrl, cert, signer_fpr); + err = validate_responder_cert (ctrl, cert, signer_fpr_list); if (!err) { gcry_sexp_release (s_pkey); @@ -385,13 +388,13 @@ /* Check the signature of an OCSP repsonse. OCSP is the context, S_SIG the signature value and MD the handle of the hash we used for the response. This function automagically finds the correct public - key. If SIGNER_FPR is not NULL, the default OCSP reponder has been - used and thus the certificate to be used is the one identified by - this fingerprint. */ + key. If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been + used and thus the certificate is one of those identified by + the fingerprints. */ static gpg_error_t check_signature (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_sexp_t s_sig, gcry_md_hd_t md, - const char *signer_fpr) + fingerprint_list_t signer_fpr_list) { gpg_error_t err; int algo, cert_idx; @@ -418,16 +421,18 @@ /* Get rid of old OCSP specific certificate references. */ release_ctrl_ocsp_certs (ctrl); - if (signer_fpr) + if (signer_fpr_list && !signer_fpr_list->next) { - /* We use the default OCSP responder's certificate. Get it from - the fingerprint. */ - cert = get_cert_byhexfpr (signer_fpr); + /* There is exactly one signer fingerprint given. Thus we use + the default OCSP responder's certificate and instantly know + the certificate to use. */ + cert = get_cert_byhexfpr (signer_fpr_list->hexfpr); if (!cert) - cert = get_cert_local (ctrl, signer_fpr); + cert = get_cert_local (ctrl, signer_fpr_list->hexfpr); if (cert) { - err = check_signature_core (ctrl, cert, s_sig, s_hash, signer_fpr); + err = check_signature_core (ctrl, cert, s_sig, s_hash, + signer_fpr_list); ksba_cert_release (cert); cert = NULL; if (!err) @@ -463,7 +468,7 @@ xfree (cref); } - /* Get the certificate by means of the respinder ID. */ + /* Get the certificate by means of the responder ID. */ err = ksba_ocsp_get_responder_id (ocsp, &name, &keyid); if (err) { @@ -490,7 +495,8 @@ if (cert) { - err = check_signature_core (ctrl, cert, s_sig, s_hash, NULL); + err = check_signature_core (ctrl, cert, s_sig, s_hash, + signer_fpr_list); ksba_cert_release (cert); if (!err) { @@ -508,9 +514,11 @@ /* Check whether the certificate either given by fingerprint CERT_FPR or directly through the CERT object is valid by running an OCSP - transaction. */ + transaction. With FORCE_DEFAULT_RESPONDER set only the configured + default responder is used. */ gpg_error_t -ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr) +ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr, + int force_default_responder) { gpg_error_t err; ksba_ocsp_t ocsp = NULL; @@ -528,7 +536,7 @@ int i, idx; char *oid; ksba_name_t name; - const char *default_signer = NULL; + fingerprint_list_t default_signer = NULL; /* Get the certificate. */ if (cert) @@ -578,7 +586,7 @@ 2. If this fails use the default responder, if any. */ url = NULL; - for (idx=0; !url && !opt.ignore_ocsp_service_url + for (idx=0; !url && !opt.ignore_ocsp_service_url && !force_default_responder && !(err=ksba_cert_get_authority_info_access (cert, idx, &oid, &name)); idx++) { @@ -610,7 +618,7 @@ err = gpg_error (GPG_ERR_CONFIGURATION); goto leave; } - if (!opt.ocsp_signer || !*opt.ocsp_signer) + if (!opt.ocsp_signer) { log_info (_("no default OCSP signer defined\n")); err = gpg_error (GPG_ERR_CONFIGURATION); @@ -717,31 +725,51 @@ if (status == KSBA_STATUS_REVOKED) err = gpg_error (GPG_ERR_CERT_REVOKED); + else if (status == KSBA_STATUS_UNKNOWN) + err = gpg_error (GPG_ERR_NO_DATA); else if (status != KSBA_STATUS_GOOD) err = gpg_error (GPG_ERR_GENERAL); + /* Allow for some clock skew. */ get_isotime (current_time); - /* Allow for some clock skew. Note, that NEXT_UPDATE is - optional. */ add_isotime (current_time, opt.ocsp_max_clock_skew); - if (*next_update && strcmp (next_update, current_time) < 0 ) + + if (strcmp (this_update, current_time) > 0 ) { - log_error (_("OCSP responder returned an too old status\n")); - log_info ("now: %s next_update: %s\n", current_time, next_update); + log_error (_("OCSP responder returned a status in the future\n")); + log_info ("used now: %s this_update: %s\n", current_time, this_update); if (!err) err = gpg_error (GPG_ERR_TIME_CONFLICT); } + /* Check that THIS_UPDATE is not too far back in the past. */ copy_time (tmp_time, this_update); - add_isotime (this_update, opt.ocsp_current_period + opt.ocsp_max_clock_skew); - if (!*this_update || strcmp (this_update, current_time) < 0 ) + add_isotime (tmp_time, opt.ocsp_max_period+opt.ocsp_max_clock_skew); + if (!*tmp_time || strcmp (tmp_time, current_time) < 0 ) { log_error (_("OCSP responder returned a non-current status\n")); - log_info ("now: %s this_update: %s\n", current_time, tmp_time); + log_info ("used now: %s this_update: %s\n", + current_time, this_update); if (!err) err = gpg_error (GPG_ERR_TIME_CONFLICT); } + /* Check that we are not beyound NEXT_UPDATE (plus some extra time). */ + if (*next_update) + { + copy_time (tmp_time, next_update); + add_isotime (tmp_time, opt.ocsp_current_period+opt.ocsp_max_clock_skew); + if (!*tmp_time && strcmp (tmp_time, current_time) < 0 ) + { + log_error (_("OCSP responder returned an too old status\n")); + log_info ("used now: %s next_update: %s\n", + current_time, next_update); + if (!err) + err = gpg_error (GPG_ERR_TIME_CONFLICT); + } + } + + leave: gcry_md_close (md); gcry_sexp_release (s_sig); Modified: trunk/src/ocsp.h =================================================================== --- trunk/src/ocsp.h 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/ocsp.h 2007-08-09 15:51:16 UTC (rev 260) @@ -15,13 +15,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef OCSP_H #define OCSP_H -gpg_error_t ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr); +gpg_error_t ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr, + int force_default_responder); /* Release the list of OCSP certificates hold in the CTRL object. */ void release_ctrl_ocsp_certs (ctrl_t ctrl); Modified: trunk/src/server.c =================================================================== --- trunk/src/server.c 2007-08-08 17:06:34 UTC (rev 259) +++ trunk/src/server.c 2007-08-09 15:51:16 UTC (rev 260) @@ -85,6 +85,53 @@ } +/* Check whether the option NAME appears in LINE */ +static int +has_option (const char *line, const char *name) +{ + const char *s; + int n = strlen (name); + + s = strstr (line, name); + return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); +} + + +/* Same as has_option but does only test for the name of the option + and ignores an argument, i.e. with NAME being "--hash" it would + return a pointer for "--hash" as well as for "--hash=foo". If + thhere is no such option NULL is returned. The pointer returned + points right behind the option name, this may be an equal sign, Nul + or a space. */ +/* static const char * */ +/* has_option_name (const char *line, const char *name) */ +/* { */ +/* const char *s; */ +/* int n = strlen (name); */ + +/* s = strstr (line, name); */ +/* return (s && (s == line || spacep (s-1)) */ +/* && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */ +/* } */ + + +/* Skip over options. It is assumed that leading spaces have been + removed (this is the case for lines passed to a handler from + assuan). Blanks after the options are also removed. */ +static char * +skip_options (char *line) +{ + while ( *line == '-' && line[1] == '-' ) + { + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + } + return line; +} + + /* Common code for get_cert_local and get_issuer_cert_local. */ static ksba_cert_t do_get_cert_local (ctrl_t ctrl, const char *name, const char *command) @@ -309,7 +356,8 @@ } -/* IS_VALID | +/* ISVALID [--only-ocsp] [--force-default-responder] + | This command checks whether the certificate identified by the certificate_id is valid. This is done by consulting CRLs or @@ -317,12 +365,19 @@ are from gpg-error.h. The command may callback using the inquire function. See the manual for details. - The certificate_id is a hex encoded string consisting of two parts, + The CERTIFICATE_ID is a hex encoded string consisting of two parts, delimited by a single dot. The first part is the SHA-1 hash of the issuer name and the second part the serial number. Alternatively the certificate's fingerprint may be given in which case an OCSP request is done before consulting the CRL. + + If the option --only-ocsp is given, no fallback to a CRL check will + be used. + + If the option --force-default-responder is given, only the default + OCSP responder will be used and any other methods of obtaining an + OCSP responder URL won't be used. */ static int @@ -333,7 +388,13 @@ gpg_error_t err; int did_inquire = 0; int ocsp_mode = 0; + int only_ocsp; + int force_default_responder; + only_ocsp = has_option (line, "--only-ocsp"); + force_default_responder = has_option (line, "--force-default-responder"); + line = skip_options (line); + issuerhash = xstrdup (line); /* We need to work on a copy of the line because that same Assuan context may be used for an inquiry. @@ -367,13 +428,15 @@ if (!opt.allow_ocsp) err = gpg_error (GPG_ERR_NOT_SUPPORTED); else - err = ocsp_isvalid (ctrl, NULL, NULL); - /* Fixme: If we got no ocsp response we should fall back to CRL - mode. Thus we need to clear OCSP_MODE, get the issuerhash - and the serialno from the current certificate and jump to - again. */ + err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder); + /* Fixme: If we got no ocsp response and --only-ocsp is not used + we should fall back to CRL mode. Thus we need to clear + OCSP_MODE, get the issuerhash and the serialno from the + current certificate and jump to again. */ } - else + else if (only_ocsp) + err = gpg_error (GPG_ERR_NO_CRL_KNOWN); + else { switch (crl_cache_isvalid (ctrl, issuerhash, serialno, @@ -523,13 +586,13 @@ } -/* CHECKOCSP [] +/* CHECKOCSP [--force-default-responder] [] Check whether the certificate with FINGERPRINT (SHA-1 hash of the entire X.509 certificate blob) is valid or not by asking an OCSP responder responsible for this certificate. The optional fingerprint may be used for a quick check in case an OCSP check has - been down for this certificate recently (we always cache OCSP + been done for this certificate recently (we always cache OCSP responses for a couple of minutes). If the fingerprint has not been given or there is no cached result, the function inquires the certificate using the @@ -543,6 +606,10 @@ its own mechanism which includes a local certificate store as well as a list of trusted root certifciates. + If the option --force-default-responder is given, only the default + OCSP responder will be used and any other methods of obtaining an + OCSP responder URL won't be used. + The return value is the usual gpg-error code or 0 for ducesss; i.e. the certificate validity has been confirmed by a valid CRL. */ @@ -553,6 +620,10 @@ gpg_error_t err; unsigned char fprbuffer[20], *fpr; ksba_cert_t cert; + int force_default_responder; + + force_default_responder = has_option (line, "--force-default-responder"); + line = skip_options (line); fpr = get_fingerprint_from_line (line, fprbuffer); cert = fpr? get_cert_byfpr (fpr) : NULL; @@ -590,7 +661,7 @@ if (!opt.allow_ocsp) err = gpg_error (GPG_ERR_NOT_SUPPORTED); else - err = ocsp_isvalid (ctrl, cert, NULL); + err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder); leave: if (err) From cvs at cvs.gnupg.org Fri Aug 10 09:17:58 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 10 Aug 2007 09:17:58 +0200 Subject: [svn] GPGol - r170 - trunk/src Message-ID: Author: wk Date: 2007-08-10 09:17:28 +0200 (Fri, 10 Aug 2007) New Revision: 170 Added: trunk/src/item-events.cpp trunk/src/item-events.h trunk/src/message.cpp trunk/src/message.h trunk/src/mimeparser.c trunk/src/mimeparser.h trunk/src/serpent.c trunk/src/serpent.h Log: Add missing files Added: trunk/src/item-events.cpp =================================================================== --- trunk/src/item-events.cpp 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/item-events.cpp 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,131 @@ +/* item-events.cpp - GpgolItemEvents implementation + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include "mymapi.h" +#include "mymapitags.h" +#include "myexchext.h" +#include "common.h" +#include "olflange-def.h" +#include "olflange.h" +#include "item-events.h" + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + + + +/* Our constructor. */ +GpgolItemEvents::GpgolItemEvents (GpgolExt *pParentInterface) +{ + m_pExchExt = pParentInterface; + m_ref = 0; +} + + +/* The QueryInterfac. */ +STDMETHODIMP +GpgolItemEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj) +{ + *ppvObj = NULL; + if (riid == IID_IOutlookExtItemEvents) + { + *ppvObj = (LPVOID)this; + AddRef (); + return S_OK; + } + if (riid == IID_IUnknown) + { + *ppvObj = (LPVOID)m_pExchExt; + m_pExchExt->AddRef (); + return S_OK; + } + return E_NOINTERFACE; +} + + +/* This method is called if an item is about to being displayed. + Possible return values are: + + S_FALSE - Let Outlook continue the operation. + + E_ABORT - Abort the open operation and the item is not being + displayed. +*/ +STDMETHODIMP +GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK peecb) +{ + log_debug ("%s:%s: received", SRCNAME, __func__); + return S_FALSE; +} + + +/* Like all the other Complete methods this one is called after OnOpen + has been called for all registred extensions. FLAGS may have tehse + values: + + 0 - The open action has not been canceled. + + EEME_FAILED or EEME_COMPLETE_FAILED - both indicate that the + open action has been canceled. + + Note that this method may be called more than once for each OnOpen + and may even occur without an OnOpen (i.e. while setting up a new + extension). + + The same return values as for OnOpen may be used.. +*/ +STDMETHODIMP +GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK peecb, ULONG flags) +{ + log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags); + return S_FALSE; +} + + +/* This method is called if an item's window received a close request. + Possible return values are: + + S_FALSE - Let Outlook continue the operation. + + E_ABORT - Abort the close operation and don't dismiss the window. +*/ +STDMETHODIMP +GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK peecb, ULONG save_options) +{ + log_debug ("%s:%s: received, options=%#lx", SRCNAME, __func__, save_options); + return S_FALSE; +} + + +/* This is the corresponding Complete method for OnClose. See + OnOpenComplete for a description. */ +STDMETHODIMP +GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK peecb, ULONG flags) +{ + log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags); + return S_FALSE; +} Added: trunk/src/item-events.h =================================================================== --- trunk/src/item-events.h 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/item-events.h 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,64 @@ +/* item-events.h - GpgolItemEvents definitions. + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + + +#ifndef ITEM_EVENTS_H +#define ITEM_EVENTS_H + +/* + GpgolItemEvents + + The GpgolItemEvents class implements the processing of events + related to certain items. This is currently open and close of an + inspector. + */ +class GpgolItemEvents : public IOutlookExtItemEvents +{ + public: + GpgolItemEvents (GpgolExt *pParentInterface); + + private: + GpgolExt *m_pExchExt; + ULONG m_ref; + + public: + STDMETHODIMP QueryInterface (REFIID riid, LPVOID FAR *ppvObj); + inline STDMETHODIMP_(ULONG) AddRef (void) + { + ++m_ref; + return m_ref; + } + inline STDMETHODIMP_(ULONG) Release (void) + { + ULONG count = --m_ref; + if (!count) + delete this; + return count; + } + + + STDMETHODIMP OnOpen (LPEXCHEXTCALLBACK peecb); + STDMETHODIMP OnOpenComplete (LPEXCHEXTCALLBACK peecb, ULONG flags); + STDMETHODIMP OnClose (LPEXCHEXTCALLBACK peecb, ULONG save_options); + STDMETHODIMP OnCloseComplete (LPEXCHEXTCALLBACK peecb, ULONG flags); +}; + +#endif /*ATTACHED_FILE_EVENTS_H*/ Added: trunk/src/message.cpp =================================================================== --- trunk/src/message.cpp 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/message.cpp 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,268 @@ +/* message.cpp - Functions for message handling + * Copyright (C) 2006, 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include "mymapi.h" +#include "mymapitags.h" +#include "myexchext.h" +#include "common.h" +#include "mapihelp.h" +#include "mimeparser.h" +#include "message.h" + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + + + +/* Verify MESSAGE and update the attachments as required. MSGTYPE + should be the type of the message so that the fucntion can decide + what to do. With FORCE set the verification is done regardlessless + of a cached signature result. */ +int +message_verify (LPMESSAGE message, msgtype_t msgtype, int force) +{ + mapi_attach_item_t *table; + int moss_idx = -1; + int i; + char *inbuf; + size_t inbuflen; + int err; + + switch (msgtype) + { + case MSGTYPE_GPGOL_MULTIPART_SIGNED: + break; + case MSGTYPE_GPGOL_OPAQUE_SIGNED: + log_debug ("Opaque signed message are not yet supported!"); + return 0; + case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED: + case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED: + return -1; /* Should not be called for such a message. */ + case MSGTYPE_UNKNOWN: + case MSGTYPE_GPGOL: + return 0; /* Nothing to do. */ + } + + /* If a verification is forced, we set the cached signature status + first to "?" to mark that no verification has yet happened. */ + if (force) + mapi_set_sig_status (message, "?"); + else if (mapi_has_sig_status (message)) + return 0; /* Already checked that message. */ + + table = mapi_create_attach_table (message, 0); + if (!table) + return -1; /* No attachment - this should not happen. */ + + + for (i=0; !table[i].end_of_table; i++) + if (table[i].attach_type == ATTACHTYPE_MOSS) + { + moss_idx = i; + break; + } + if (moss_idx == -1 && !table[0].end_of_table && table[1].end_of_table) + { + /* No MOSS flag found in the table but there is only one + attachment. Due to the message type we know that this is + the original MOSS message. We mark this attachment as + hidden, so that it won't get displayed. We further mark it + as our original MOSS attachment so that after parsing we have + a mean to find it again (see above). */ + moss_idx = 0; + mapi_mark_moss_attach (message, table+0); + } + + if (moss_idx == -1) + { + mapi_release_attach_table (table); + return -1; /* No original attachment - this should not happen. */ + } + + + inbuf = mapi_get_attach (message, table+0, &inbuflen); + if (!inbuf) + { + mapi_release_attach_table (table); + return -1; /* Problem getting the attachment. */ + } + + + err = mime_verify (inbuf, inbuflen, message, 0, + opt.passwd_ttl, NULL, NULL, 0); + log_debug ("mime_verify returned %d", err); + xfree (inbuf); + + if (err) + mapi_set_sig_status (message, gpg_strerror (err)); + else + mapi_set_sig_status (message, "Signature was good"); + + mapi_release_attach_table (table); + return 0; +} + +/* Decrypt MESSAGE, check signature and update the attachments as + required. MSGTYPE should be the type of the message so that the + function can decide what to do. With FORCE set the verification is + done regardlessless of a cached signature result - hmmm, should we + such a thing for an encrypted message? */ +int +message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force) +{ + mapi_attach_item_t *table; + int part2_idx; + int tblidx; + int retval = -1; + LPSTREAM cipherstream; + gpg_error_t err; + int is_opaque = 0; + int is_smime = 0; + + switch (msgtype) + { + case MSGTYPE_UNKNOWN: + case MSGTYPE_GPGOL: + case MSGTYPE_GPGOL_OPAQUE_SIGNED: + case MSGTYPE_GPGOL_MULTIPART_SIGNED: + return -1; /* Should not have been called for this. */ + case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED: + break; + case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED: + is_opaque = 1; + break; + } + + table = mapi_create_attach_table (message, 0); + if (!table) + return -1; /* No attachment - this should not happen. */ + + if (is_opaque) + { + /* S/MIME opaque encrypted message: We expect 1 attachment. As + we don't know ether we are called the first time, we first + try to find this attachment by looking at all attachments. + Only if this fails we identify it by its order. */ + part2_idx = -1; + for (tblidx=0; !table[tblidx].end_of_table; tblidx++) + if (table[tblidx].attach_type == ATTACHTYPE_MOSS) + { + if (part2_idx == -1 && table[tblidx].content_type + && (!strcmp (table[tblidx].content_type, + "application/pkcs7-mime") + || !strcmp (table[tblidx].content_type, + "application/x-pkcs7-mime"))) + part2_idx = tblidx; + } + if (part2_idx == -1 && tblidx >= 1) + { + /* We have attachments but none are marked. Thus we assume + that this is the first time we see this message and we + will set the mark now if we see appropriate content + types. */ + if (table[0].content_type + && (!strcmp (table[0].content_type, "application/pkcs7-mime") + || !strcmp (table[0].content_type, + "application/x-pkcs7-mime"))) + part2_idx = 0; + if (part2_idx != -1) + mapi_mark_moss_attach (message, table+part2_idx); + } + if (part2_idx == -1) + { + log_debug ("%s:%s: this is not an S/MIME encrypted message", + SRCNAME, __func__); + goto leave; + } + is_smime = 1; + } + else + { + /* Multipart/encrypted message: We expect 2 attachments. The + first one with the version number and the second one with the + ciphertext. As we don't know ether we are called the first + time, we first try to find these attachments by looking at + all attachments. Only if this fails we identify them by + their order (i.e. the first 2 attachments) and mark them as + part1 and part2. */ + int part1_idx; + + part1_idx = part2_idx = -1; + for (tblidx=0; !table[tblidx].end_of_table; tblidx++) + if (table[tblidx].attach_type == ATTACHTYPE_MOSS) + { + if (part1_idx == -1 && table[tblidx].content_type + && !strcmp (table[tblidx].content_type, + "application/pgp-encrypted")) + part1_idx = tblidx; + else if (part2_idx == -1 && table[tblidx].content_type + && !strcmp (table[tblidx].content_type, + "application/octet-stream")) + part2_idx = tblidx; + } + if (part1_idx == -1 && part2_idx == -1 && tblidx >= 2) + { + /* At least 2 attachments but none are marked. Thus we + assume that this is the first time we see this message + and we will set the mark now if we see appropriate + content types. */ + if (table[0].content_type + && !strcmp (table[0].content_type, "application/pgp-encrypted")) + part1_idx = 0; + if (table[1].content_type + && !strcmp (table[1].content_type, "application/octet-stream")) + part2_idx = 1; + if (part1_idx != -1 && part2_idx != -1) + { + mapi_mark_moss_attach (message, table+part1_idx); + mapi_mark_moss_attach (message, table+part2_idx); + } + } + if (part1_idx == -1 || part2_idx == -1) + { + log_debug ("%s:%s: this is not a PGP/MIME encrypted message", + SRCNAME, __func__); + goto leave; + } + } + + /* Get the attachment as an allocated buffer and let the mimeparser + work on it. */ + cipherstream = mapi_get_attach_as_stream (message, table+part2_idx); + if (!cipherstream) + goto leave; /* Problem getting the attachment. */ + + err = mime_decrypt (cipherstream, message, is_smime, opt.passwd_ttl, + NULL, NULL, 0); + log_debug ("mime_decrypt returned %d (%s)", err, gpg_strerror (err)); + cipherstream->Release (); + retval = 0; + + leave: + mapi_release_attach_table (table); + return retval; +} Added: trunk/src/message.h =================================================================== --- trunk/src/message.h 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/message.h 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,30 @@ +/* message.h - Declarations for message.c + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef MESSAGE_H +#define MESSAGE_H + + +int message_verify (LPMESSAGE message, msgtype_t msgtype, int force); +int message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force); + + +#endif /*MESSAGE_H*/ Added: trunk/src/mimeparser.c =================================================================== --- trunk/src/mimeparser.c 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/mimeparser.c 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,1104 @@ +/* mimeparser.c - Parse multipart MIME message + * Copyright (C) 2005, 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* + EXPLAIN what we are doing here. +*/ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#define COBJMACROS +#include +#include /* For IStream. */ + +#include + +#include "mymapi.h" +#include "mymapitags.h" + +#include "rfc822parse.h" +#include "common.h" +#include "engine.h" +#include "mapihelp.h" +#include "serpent.h" +#include "mimeparser.h" + +/* Define the next to get extra debug message for the MIME parser. */ +#define DEBUG_PARSER 1 + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + +static const char oid_mimetag[] = + {0x2A, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04}; + + + +/* The maximum length of a line we are able to process. RFC822 allows + only for 1000 bytes; thus 2000 seems to be a reasonable value. */ +#define LINEBUFSIZE 2000 + + +typedef enum + { + PROTOCOL_UNKNOWN = 0, + PROTOCOL_OPENPGP, + PROTOCOL_SMIME + } +protocol_t; + + +/* To keep track of the MIME message structures we use a linked list + with each item corresponding to one part. */ +struct mimestruct_item_s; +typedef struct mimestruct_item_s *mimestruct_item_t; +struct mimestruct_item_s +{ + mimestruct_item_t next; + unsigned int level; /* Level in the hierarchy of that part. 0 + indicates the outer body. */ + char *filename; /* Malloced fileanme or NULL. */ + char *charset; /* Malloced charset or NULL. */ + char content_type[1]; /* String with the content type. */ +}; + + + + +/* The context object we use to track information. */ +struct mime_context +{ + HWND hwnd; /* A window handle to be used for message boxes etc. */ + rfc822parse_t msg; /* The handle of the RFC822 parser. */ + + int preview; /* Do only decryption and pop up no message bozes. */ + + int protect_mode; /* Encrypt all attachments etc. (cf. SYMENC). */ + int verify_mode; /* True if we want to verify a signature. */ + + int nesting_level; /* Current MIME nesting level. */ + int in_data; /* We are currently in data (body or attachment). */ + int body_seen; /* True if we have seen a part we consider the + body of the message. */ + + gpgme_data_t signed_data;/* NULL or the data object used to collect + the signed data. It would be better to + just hash it but there is no support in + gpgme for this yet. */ + gpgme_data_t sig_data; /* NULL or data object to collect the + signature attachment which should be a + signature then. */ + + int collect_attachment; /* True if we are collecting an attachment + or the body. */ + int collect_signeddata; /* True if we are collecting the signed data. */ + int collect_signature; /* True if we are collecting a signature. */ + int start_hashing; /* Flag used to start collecting signed data. */ + int hashing_level; /* MIME level where we started hashing. */ + int is_qp_encoded; /* Current part is QP encoded. */ + int is_base64_encoded; /* Current part is base 64 encoded. */ + int is_utf8; /* Current part has charset utf-8. */ + protocol_t protocol; /* The detected crypto protocol. */ + + int part_counter; /* Counts the number of processed parts. */ + int any_boundary; /* Indicates whether we have seen any + boundary which means that we are actually + working on a MIME message and not just on + plain rfc822 message. */ + + /* A linked list describing the structure of the mime message. This + list gets build up while parsing the message. */ + mimestruct_item_t mimestruct; + mimestruct_item_t *mimestruct_tail; + mimestruct_item_t mimestruct_cur; + + LPMESSAGE mapi_message; /* The MAPI message object we are working on. */ + LPSTREAM outstream; /* NULL or a stream to write a part to. */ + LPATTACH mapi_attach; /* The attachment object we are writing. */ + symenc_t symenc; /* NULL or the context used to protect + attachments. */ + int any_attachments_created; /* True if we created a new atatchment. */ + + b64_state_t base64; /* The state of the Base-64 decoder. */ + + int line_too_long; /* Indicates that a received line was too long. */ + int parser_error; /* Indicates that we encountered a error from + the parser. */ + + /* Buffer used to constructed complete files. */ + size_t linebufsize; /* The allocated size of the buffer. */ + size_t linebufpos; /* The actual write posituion. */ + char linebuf[1]; /* The buffer. */ +}; +typedef struct mime_context *mime_context_t; + + +/* This function is a wrapper around gpgme_data_write to convert the + data to utf-8 first. We assume Latin-1 here. */ +/* static int */ +/* latin1_data_write (gpgme_data_t data, const char *line, size_t len) */ +/* { */ +/* const char *s; */ +/* char *buffer, *p; */ +/* size_t i, n; */ +/* int rc; */ + +/* for (s=line, i=0, n=0 ; i < len; s++, i++ ) */ +/* { */ +/* n++; */ +/* if (*s & 0x80) */ +/* n++; */ +/* } */ +/* buffer = xmalloc (n + 1); */ +/* for (s=line, i=0, p=buffer; i < len; s++, i++ ) */ +/* { */ +/* if (*s & 0x80) */ +/* { */ +/* *p++ = 0xc0 | ((*s >> 6) & 3); */ +/* *p++ = 0x80 | (*s & 0x3f); */ +/* } */ +/* else */ +/* *p++ = *s; */ +/* } */ +/* assert (p-buffer == n); */ +/* rc = gpgme_data_write (data, buffer, n); */ +/* xfree (buffer); */ +/* return rc; */ +/* } */ + + +/* Print the message event EVENT. */ +static void +debug_message_event (mime_context_t ctx, rfc822parse_event_t event) +{ + const char *s; + + switch (event) + { + case RFC822PARSE_OPEN: s= "Open"; break; + case RFC822PARSE_CLOSE: s= "Close"; break; + case RFC822PARSE_CANCEL: s= "Cancel"; break; + case RFC822PARSE_T2BODY: s= "T2Body"; break; + case RFC822PARSE_FINISH: s= "Finish"; break; + case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break; + case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break; + case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break; + case RFC822PARSE_BOUNDARY: s= "Boundary"; break; + case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break; + case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break; + case RFC822PARSE_PREAMBLE: s= "Preamble"; break; + case RFC822PARSE_EPILOGUE: s= "Epilogue"; break; + default: s= "[unknown event]"; break; + } +#ifdef DEBUG_PARSER + log_debug ("%s: ctx=%p, rfc822 event %s\n", SRCNAME, ctx, s); +#endif +} + + + +/* Start a new atatchment. With IS_BODY set, the attachment is + actually the body part of the message which is treated in a special + way. */ +static int +start_attachment (mime_context_t ctx, int is_body) +{ + int retval = -1; + HRESULT hr; + ULONG newpos; + SPropValue prop; + LPATTACH newatt = NULL; + LPSTREAM to = NULL; + LPUNKNOWN punk; + +#ifdef DEBUG_PARSER + log_debug ("%s:%s: for ctx=%p is_body=%d", SRCNAME, __func__, ctx, is_body); +#endif + + /* Just in case something has not been finished, do it here. */ + if (ctx->outstream) + { + IStream_Release (ctx->outstream); + ctx->outstream = NULL; + } + if (ctx->mapi_attach) + { + IAttach_Release (ctx->mapi_attach); + ctx->mapi_attach = NULL; + } + if (ctx->symenc) + { + symenc_close (ctx->symenc); + ctx->symenc = NULL; + } + + /* Before we start with the first attachment we need to delete all + attachments which might have been created already by a past + parser run. */ + if (!ctx->any_attachments_created) + { + mapi_attach_item_t *table; + int i; + + table = mapi_create_attach_table (ctx->mapi_message, 1); + if (table) + { + for (i=0; !table[i].end_of_table; i++) + if (table[i].attach_type == ATTACHTYPE_FROMMOSS) + { + hr = IMessage_DeleteAttach (ctx->mapi_message, + table[i].mapipos, + 0, NULL, 0); + if (hr) + log_error ("%s:%s: DeleteAttach failed: hr=%#lx\n", + SRCNAME, __func__, hr); + } + mapi_release_attach_table (table); + } + ctx->any_attachments_created = 1; + } + + /* Now create a new attachment. */ + hr = IMessage_CreateAttach (ctx->mapi_message, NULL, 0, &newpos, &newatt); + if (hr) + { + log_error ("%s:%s: can't create attachment: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + + prop.ulPropTag = PR_ATTACH_METHOD; + prop.Value.ul = ATTACH_BY_VALUE; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr != S_OK) + { + log_error ("%s:%s: can't set attach method: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + + /* Mark that attachment so that we know why it has been created. */ + if (get_gpgolattachtype_tag (ctx->mapi_message, &prop.ulPropTag) ) + goto leave; + prop.Value.l = ATTACHTYPE_FROMMOSS; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set %s property: hr=%#lx\n", + SRCNAME, __func__, "GpgOL Attach Type", hr); + goto leave; + } + + + /* The body attachment is special and should not be show in the list + of atatchments. */ + if (is_body) + { + prop.ulPropTag = PR_ATTACHMENT_HIDDEN; + prop.Value.b = TRUE; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set hidden attach flag: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + } + + + /* We need to insert a short filename . Without it, the _displayed_ + list of attachments won't get updated although the attachment has + been created. */ + prop.ulPropTag = PR_ATTACH_FILENAME_A; + { + char buf[100]; + + if (is_body) + prop.Value.lpszA = is_body == 2? "gpgol000.htm":"gpgol000.txt"; + else + { + snprintf (buf, 100, "gpgol%03d.dat", ctx->part_counter); + prop.Value.lpszA = buf; + } + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + } + if (hr) + { + log_error ("%s:%s: can't set attach filename: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + + /* And now for the real name. */ + if (ctx->mimestruct_cur && ctx->mimestruct_cur->filename) + { + prop.ulPropTag = PR_ATTACH_LONG_FILENAME_A; + prop.Value.lpszA = ctx->mimestruct_cur->filename; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set attach long filename: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + } + + prop.ulPropTag = PR_ATTACH_TAG; + prop.Value.bin.cb = sizeof oid_mimetag; + prop.Value.bin.lpb = (LPBYTE)oid_mimetag; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set attach tag: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + + assert (ctx->mimestruct_cur && ctx->mimestruct_cur->content_type); + prop.ulPropTag = PR_ATTACH_MIME_TAG_A; + prop.Value.lpszA = ctx->mimestruct_cur->content_type; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set attach mime tag: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + + + /* If we are in protect mode (i.e. working on a decrypted message, + we need to setup the symkey context to protect (encrypt) the + attachment in the MAPI. */ + if (ctx->protect_mode) + { + char *iv; + + if (get_gpgolprotectiv_tag (ctx->mapi_message, &prop.ulPropTag) ) + goto leave; + + iv = create_initialization_vector (16); + if (!iv) + { + log_error ("%s:%s: error creating initialization vector", + SRCNAME, __func__); + goto leave; + } + prop.Value.bin.cb = 16; + prop.Value.bin.lpb = iv; + hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop); + if (hr) + { + log_error ("%s:%s: can't set %s property: hr=%#lx\n", + SRCNAME, __func__, "GpgOL Protect IV", hr); + goto leave; + } + + ctx->symenc = symenc_open (get_128bit_session_key (), 16, iv, 16); + xfree (iv); + if (!ctx->symenc) + { + log_error ("%s:%s: error creating cipher context", + SRCNAME, __func__); + goto leave; + } + } + + + punk = (LPUNKNOWN)to; + hr = IAttach_OpenProperty (newatt, PR_ATTACH_DATA_BIN, &IID_IStream, 0, + MAPI_CREATE|MAPI_MODIFY, &punk); + if (FAILED (hr)) + { + log_error ("%s:%s: can't create output stream: hr=%#lx\n", + SRCNAME, __func__, hr); + goto leave; + } + to = (LPSTREAM)punk; + + ctx->outstream = to; + to = NULL; + ctx->mapi_attach = newatt; + newatt = NULL; + + if (ctx->symenc) + { + char tmpbuf[16]; + /* Write an encrypted fixed 16 byte string which we need to + check at decryption time to see whether we have actually + encrypted it using this session key. */ + symenc_cfb_encrypt (ctx->symenc, tmpbuf, "GpgOL attachment", 16); + IStream_Write (ctx->outstream, tmpbuf, 16, NULL); + } + retval = 0; /* Success. */ + + leave: + if (to) + { + IStream_Revert (to); + IStream_Release (to); + } + if (newatt) + IAttach_Release (newatt); + return retval; +} + + +static int +finish_attachment (mime_context_t ctx, int cancel) +{ + HRESULT hr; + int retval = -1; + +#ifdef DEBUG_PARSER + log_debug ("%s:%s: for ctx=%p cancel=%d", SRCNAME, __func__, ctx, cancel); +#endif + + if (ctx->outstream) + { + IStream_Commit (ctx->outstream, 0); + IStream_Release (ctx->outstream); + ctx->outstream = NULL; + + if (cancel) + retval = 0; + else if (ctx->mapi_attach) + { + hr = IAttach_SaveChanges (ctx->mapi_attach, KEEP_OPEN_READWRITE); + if (hr) + { + log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n", + SRCNAME, __func__, hr); + } + else + retval = 0; /* Success. */ + } + } + if (ctx->mapi_attach) + { + IAttach_Release (ctx->mapi_attach); + ctx->mapi_attach = NULL; + } + if (ctx->symenc) + { + symenc_close (ctx->symenc); + ctx->symenc = NULL; + } + return retval; +} + + +/* Process the transition to body event. + + This means we have received the empty line indicating the body and + should now check the headers to see what to do about this part. */ +static int +t2body (mime_context_t ctx, rfc822parse_t msg) +{ + rfc822parse_field_t field; + const char *ctmain, *ctsub; + const char *s; + size_t off; + char *p; + int is_text = 0; + int is_body = 0; + char *filename = NULL; + char *charset = NULL; + + + /* Figure out the encoding. */ + ctx->is_qp_encoded = 0; + ctx->is_base64_encoded = 0; + p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off); + if (p) + { + if (!stricmp (p+off, "quoted-printable")) + ctx->is_qp_encoded = 1; + else if (!stricmp (p+off, "base64")) + { + ctx->is_base64_encoded = 1; + b64_init (&ctx->base64); + } + free (p); + } + + /* Get the filename from the header. */ + field = rfc822parse_parse_field (msg, "Content-Disposition", -1); + if (field) + { + s = rfc822parse_query_parameter (field, "filename", 0); + if (s) + filename = xstrdup (s); + rfc822parse_release_field (field); + } + + /* Process the Content-type and all its parameters. */ + ctmain = ctsub = NULL; + field = rfc822parse_parse_field (msg, "Content-Type", -1); + if (field) + ctmain = rfc822parse_query_media_type (field, &ctsub); + if (!ctmain) + { + /* Either there is no content type field or it is faulty; in + both cases we fall back to text/plain. */ + ctmain = "text"; + ctsub = "plain"; + } + +#ifdef DEBUG_PARSER + log_debug ("%s:%s: ctx=%p, ct=`%s/%s'\n", + SRCNAME, __func__, ctx, ctmain, ctsub); +#endif + + /* We only support UTF-8 for now. Check here. */ + s = rfc822parse_query_parameter (field, "charset", 0); + if (s) + charset = xstrdup (s); + ctx->is_utf8 = (s && !strcmp (s, "utf-8")); + + /* Update our idea of the entire MIME structure. */ + { + mimestruct_item_t ms; + + ms = xmalloc (sizeof *ms + strlen (ctmain) + 1 + strlen (ctsub)); + ctx->mimestruct_cur = ms; + *ctx->mimestruct_tail = ms; + ctx->mimestruct_tail = &ms->next; + ms->next = NULL; + strcpy (stpcpy (stpcpy (ms->content_type, ctmain), "/"), ctsub); + ms->level = ctx->nesting_level; + ms->filename = filename; + filename = NULL; + ms->charset = charset; + charset = NULL; + + } + + + if (!strcmp (ctmain, "multipart")) + { + /* We don't care about the top level multipart layer but wait + until it comes to the actual parts which then will get stored + as attachments. + + For now encapsulated signed or encrypted containers are not + processed in a special way as they should. Except for the + simple verify mode. */ + if (ctx->verify_mode && !ctx->signed_data + && !strcmp (ctsub, "signed") + && (s = rfc822parse_query_parameter (field, "protocol", 0))) + { + if (!strcmp (s, "application/pgp-signature")) + ctx->protocol = PROTOCOL_OPENPGP; + else if (!strcmp (s, "application/pkcs7-signature") + || !strcmp (s, "application/x-pkcs7-signature")) + ctx->protocol = PROTOCOL_SMIME; + else + ctx->protocol = PROTOCOL_UNKNOWN; + + /* Need to start the hashing after the next boundary. */ + ctx->start_hashing = 1; + } + } + else if (!strcmp (ctmain, "text")) + { + is_text = !strcmp (ctsub, "html")? 2:1; + } + else if (ctx->verify_mode && ctx->nesting_level == 1 && !ctx->sig_data + && !strcmp (ctmain, "application") + && ((ctx->protocol == PROTOCOL_OPENPGP + && !strcmp (ctsub, "pgp-signature")) + || (ctx->protocol == PROTOCOL_SMIME + && (!strcmp (ctsub, "pkcs7-signature") + || !strcmp (ctsub, "x-pkcs7-signature"))))) + { + /* This is the second part of a MOSS signature. We only support + here full messages thus checking the nesting level is + sufficient. We do this only for the first signature (i.e. if + sig_data has not been set yet). We also do this only while + in verify mode because we don't want to write a full MUA. */ + if (!ctx->preview && !gpgme_data_new (&ctx->sig_data)) + ctx->collect_signature = 1; + } + else /* Other type. */ + { + if (!ctx->preview) + ctx->collect_attachment = 1; + } + rfc822parse_release_field (field); /* (Content-type) */ + ctx->in_data = 1; + +#ifdef DEBUG_PARSER + log_debug ("%s: this body: nesting=%d part_counter=%d is_text=%d\n", + SRCNAME, ctx->nesting_level, ctx->part_counter, is_text); +#endif + + /* If this is a text part, decide whether we treat it as our body. */ + if (is_text) + { + /* If this is the first text part at all we will start to + collect it and use it later as the regular body. */ + if (!ctx->body_seen) + { + ctx->body_seen = 1; + ctx->collect_attachment = 1; + is_body = 1; + } + else if (!ctx->preview) + ctx->collect_attachment = 1; + } + + + if (ctx->collect_attachment) + { + /* Now that if we have an attachment prepare a new MAPI + attachment. */ + if (start_attachment (ctx, is_body)) + return -1; + assert (ctx->outstream); + } + + return 0; +} + + +/* This routine gets called by the RFC822 parser for all kind of + events. OPAQUE carries in our case an smime context. Should + return 0 on success or -1 as well as setting errno on + failure. */ +static int +message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg) +{ + int retval = 0; + mime_context_t ctx = opaque; + + debug_message_event (ctx, event); + + if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY) + { + /* We need to check here whether to start collecting signed data + because attachments might come without header lines and thus + we won't see the BEGIN_HEADER event. */ + if (ctx->start_hashing == 1) + { + ctx->start_hashing = 2; + ctx->hashing_level = ctx->nesting_level; + ctx->collect_signeddata = 1; + gpgme_data_new (&ctx->signed_data); + } + } + + + switch (event) + { + case RFC822PARSE_T2BODY: + retval = t2body (ctx, msg); + break; + + case RFC822PARSE_LEVEL_DOWN: + ctx->nesting_level++; + break; + + case RFC822PARSE_LEVEL_UP: + if (ctx->nesting_level) + ctx->nesting_level--; + else + { + log_error ("%s: ctx=%p, invalid structure: bad nesting level\n", + SRCNAME, ctx); + ctx->parser_error = 1; + } + break; + + case RFC822PARSE_BOUNDARY: + case RFC822PARSE_LAST_BOUNDARY: + ctx->any_boundary = 1; + ctx->in_data = 0; + ctx->collect_attachment = 0; + + finish_attachment (ctx, 0); + assert (!ctx->outstream); + + if (ctx->start_hashing == 2 && ctx->hashing_level == ctx->nesting_level) + { + ctx->start_hashing = 3; /* Avoid triggering it again. */ + ctx->collect_signeddata = 0; + } + break; + + case RFC822PARSE_BEGIN_HEADER: + ctx->part_counter++; + break; + + default: /* Ignore all other events. */ + break; + } + + return retval; +} + + + +/* This handler is called by GPGME with the decrypted plaintext. */ +static ssize_t +plaintext_handler (void *handle, const void *buffer, size_t size) +{ + mime_context_t ctx = handle; + const char *s; + size_t nleft, pos, len; + + s = buffer; + pos = ctx->linebufpos; + nleft = size; + for (; nleft ; nleft--, s++) + { + if (pos >= ctx->linebufsize) + { + log_error ("%s: ctx=%p, rfc822 parser failed: line too long\n", + SRCNAME, ctx); + ctx->line_too_long = 1; + return 0; /* Error. */ + } + if (*s != '\n') + ctx->linebuf[pos++] = *s; + else + { /* Got a complete line. Remove the last CR */ + if (pos && ctx->linebuf[pos-1] == '\r') + pos--; + + if (rfc822parse_insert (ctx->msg, ctx->linebuf, pos)) + { + log_error ("%s: ctx=%p, rfc822 parser failed: %s\n", + SRCNAME, ctx, strerror (errno)); + ctx->parser_error = 1; + return 0; /* Error. */ + } + + + if (ctx->collect_signeddata && ctx->signed_data) + { + /* Save the signed data. Note that we need to delay + the CR/LF because the last line ending belongs to the + next boundary. */ + if (ctx->collect_signeddata == 2) + gpgme_data_write (ctx->signed_data, "\r\n", 2); + gpgme_data_write (ctx->signed_data, ctx->linebuf, pos); + ctx->collect_signeddata = 2; + } + + if (ctx->in_data && ctx->collect_attachment) + { + /* We are inside of an attachment part. Write it out. */ + if (ctx->collect_attachment == 1) /* Skip the first line. */ + ctx->collect_attachment = 2; + else if (ctx->outstream) + { + HRESULT hr = 0; + + if (ctx->is_qp_encoded) + len = qp_decode (ctx->linebuf, pos); + else if (ctx->is_base64_encoded) + len = b64_decode (&ctx->base64, ctx->linebuf, pos); + else + len = pos; + if (len) + { + if (ctx->symenc) + symenc_cfb_encrypt (ctx->symenc, ctx->linebuf, + ctx->linebuf, len); + hr = IStream_Write (ctx->outstream, ctx->linebuf, + len, NULL); + } + if (!hr && !ctx->is_base64_encoded) + { + char tmp[3] = "\r\n"; + + if (ctx->symenc) + symenc_cfb_encrypt (ctx->symenc, tmp, tmp, 2); + hr = IStream_Write (ctx->outstream, tmp, 2, NULL); + } + if (hr) + { + log_debug ("%s:%s: Write failed: hr=%#lx", + SRCNAME, __func__, hr); + if (!ctx->preview) + MessageBox (ctx->hwnd, _("Error writing to stream"), + _("I/O-Error"), MB_ICONERROR|MB_OK); + ctx->parser_error = 1; + return 0; /* Error. */ + } + } + } + else if (ctx->in_data && ctx->collect_signature) + { + /* We are inside of a signature attachment part. */ + if (ctx->collect_signature == 1) /* Skip the first line. */ + ctx->collect_signature = 2; + else if (ctx->sig_data) + { + if (ctx->is_qp_encoded) + len = qp_decode (ctx->linebuf, pos); + else if (ctx->is_base64_encoded) + len = b64_decode (&ctx->base64, ctx->linebuf, pos); + else + len = pos; + if (len) + gpgme_data_write (ctx->sig_data, ctx->linebuf, len); + if (!ctx->is_base64_encoded) + gpgme_data_write (ctx->sig_data, "\r\n", 2); + } + } + + /* Continue with next line. */ + pos = 0; + } + } + ctx->linebufpos = pos; + + return size; +} + + + +static void +show_mimestruct (mimestruct_item_t mimestruct) +{ + mimestruct_item_t ms; + + for (ms = mimestruct; ms; ms = ms->next) + log_debug ("MIMESTRUCT: %*s%s cs=%s fn=%s\n", + ms->level*2, "", ms->content_type, + ms->charset? ms->charset : "[none]", + ms->filename? ms->filename : "[none]"); +} + + + +int +mime_verify (const char *message, size_t messagelen, + LPMESSAGE mapi_message, int is_smime, + int ttl, gpgme_data_t attestation, HWND hwnd, int preview_mode) +{ + gpg_error_t err = 0; + mime_context_t ctx; + const char *s; + size_t len; + + (void)is_smime; /* Not yet used. */ + + log_debug ("%s:%s: enter", SRCNAME, __func__); + + ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE); + ctx->linebufsize = LINEBUFSIZE; + ctx->hwnd = hwnd; + ctx->preview = preview_mode; + ctx->verify_mode = 1; + ctx->mapi_message = mapi_message; + ctx->mimestruct_tail = &ctx->mimestruct; + + ctx->msg = rfc822parse_open (message_cb, ctx); + if (!ctx->msg) + { + err = gpg_error_from_syserror (); + log_error ("%s:%s: failed to open the RFC822 parser: %s", + SRCNAME, __func__, gpg_strerror (err)); + goto leave; + } + + /* Need to pass the data line by line to the handler. */ + while ( (s = memchr (message, '\n', messagelen)) ) + { + len = s - message + 1; + plaintext_handler (ctx, message, len); + if (ctx->parser_error || ctx->line_too_long) + { + err = gpg_error (GPG_ERR_GENERAL); + break; + } + message += len; + assert (messagelen >= len); + messagelen -= len; + } + /* Note: the last character should be a LF, if not we ignore such an + incomplete last line. */ + + + /* Now actually verify the signature. */ + if (!err && ctx->signed_data && ctx->sig_data) + { + char *tmp; + gpgme_protocol_t xprot; + int inv_prot = 0; + + gpgme_data_seek (ctx->signed_data, 0, SEEK_SET); + gpgme_data_seek (ctx->sig_data, 0, SEEK_SET); + if (ctx->protocol == PROTOCOL_OPENPGP) + { + tmp = native_to_utf8 (_("[OpenPGP signature]")); + xprot = GPGME_PROTOCOL_OpenPGP; + } + else if (ctx->protocol == PROTOCOL_SMIME) + { + tmp = native_to_utf8 (_("[S/MIME signature]")); + xprot = GPGME_PROTOCOL_CMS; + } + else + { + tmp = native_to_utf8 (_("[Unknown signature protocol]")); + inv_prot = 1; + } + + err = (inv_prot + ? gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL) + : op_verify_detached_sig_gpgme (xprot, + ctx->signed_data, ctx->sig_data, + tmp, attestation)); + log_debug ("%s:%s: checked signature: %s <%s>", + SRCNAME, __func__, gpg_strerror (err), op_strsource (err)); + xfree (tmp); + } + + + leave: + if (ctx) + { + /* Cancel any left open attachment. */ + finish_attachment (ctx, 1); + rfc822parse_close (ctx->msg); + if (ctx->signed_data) + gpgme_data_release (ctx->signed_data); + if (ctx->sig_data) + gpgme_data_release (ctx->sig_data); + show_mimestruct (ctx->mimestruct); + while (ctx->mimestruct) + { + mimestruct_item_t tmp = ctx->mimestruct->next; + xfree (ctx->mimestruct->filename); + xfree (ctx->mimestruct->charset); + xfree (ctx->mimestruct); + ctx->mimestruct = tmp; + } + symenc_close (ctx->symenc); + xfree (ctx); + } + return err; +} + + + +/* Decrypt the PGP or S/MIME message taken from INSTREAM. If + ATTESTATION is not NULL a text with the result of the signature + verification will get printed to it. HWND is the window to be used + for message box and such. In PREVIEW_MODE no verification will be + done, no messages saved and no messages boxes will pop up. */ +int +mime_decrypt (LPSTREAM instream, LPMESSAGE mapi_message, int is_smime, + int ttl, gpgme_data_t attestation, HWND hwnd, int preview_mode) +{ + gpg_error_t err; + struct gpgme_data_cbs cbs; + gpgme_data_t plaintext; + mime_context_t ctx; + char *title; + gpgme_protocol_t proto; + + log_debug ("%s:%s: enter", SRCNAME, __func__); + + memset (&cbs, 0, sizeof cbs); + cbs.write = plaintext_handler; + + ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE); + ctx->linebufsize = LINEBUFSIZE; + ctx->protect_mode = 1; + ctx->hwnd = hwnd; + ctx->preview = preview_mode; + ctx->mapi_message = mapi_message; + ctx->mimestruct_tail = &ctx->mimestruct; + + ctx->msg = rfc822parse_open (message_cb, ctx); + if (!ctx->msg) + { + err = gpg_error_from_syserror (); + log_error ("%s:%s: failed to open the RFC822 parser: %s", + SRCNAME, __func__, gpg_strerror (err)); + goto leave; + } + + err = gpgme_data_new_from_cbs (&plaintext, &cbs, ctx); + if (err) + goto leave; + + if (is_smime) + { + proto = GPGME_PROTOCOL_CMS; + title = native_to_utf8 (_("[Encrypted S/MIME message]")); + } + else + { + proto = GPGME_PROTOCOL_OpenPGP; + title = native_to_utf8 (_("[Encrypted PGP/MIME message]")); + } + err = op_decrypt_stream_to_gpgme (proto, instream, plaintext, ttl, title, + attestation, preview_mode); + xfree (title); + if (!err && (ctx->parser_error || ctx->line_too_long)) + err = gpg_error (GPG_ERR_GENERAL); + + + leave: + if (plaintext) + gpgme_data_release (plaintext); + if (ctx) + { + /* Cancel any left over attachment which means that the MIME + structure was not complete. However if we have not seen any + boundary the message is a non-MIME one but we way have + started the body attachment (gpgol000.txt) - this one needs + to be finished properly. */ + finish_attachment (ctx, ctx->any_boundary? 1: 0); + rfc822parse_close (ctx->msg); + if (ctx->signed_data) + gpgme_data_release (ctx->signed_data); + if (ctx->sig_data) + gpgme_data_release (ctx->sig_data); + show_mimestruct (ctx->mimestruct); + while (ctx->mimestruct) + { + mimestruct_item_t tmp = ctx->mimestruct->next; + xfree (ctx->mimestruct->filename); + xfree (ctx->mimestruct->charset); + xfree (ctx->mimestruct); + ctx->mimestruct = tmp; + } + symenc_close (ctx->symenc); + xfree (ctx); + } + return err; +} + Added: trunk/src/mimeparser.h =================================================================== --- trunk/src/mimeparser.h 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/mimeparser.h 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,44 @@ +/* mimeparse.h - Multipart MIME parser. + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef SMIME_H +#define SMIME_H + +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + + +int mime_verify (const char *message, size_t messagelen, + LPMESSAGE mapi_message, int is_smime, + int ttl, + gpgme_data_t attestation, HWND hwnd, int preview_mode); +int mime_decrypt (LPSTREAM instream, LPMESSAGE mapi_message, int is_smime, + int ttl, + gpgme_data_t attestation, HWND hwnd, int preview_mode); + + +#ifdef __cplusplus +} +#endif +#endif /*SMIME_H*/ Added: trunk/src/serpent.c =================================================================== --- trunk/src/serpent.c 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/serpent.c 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,1116 @@ +/* serpent.c - Implementation of the Serpent encryption algorithm. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* + Requirements: + + Big endian machines need to define WORDS_BIGENDIAN + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "serpent.h" + +/* Serpent is a 128 bit block cipher. */ +#define BLOCKSIZE 16 + +/* Number of rounds per Serpent encrypt/decrypt operation. */ +#define ROUNDS 32 + +/* Magic number, used during generating of the subkeys. */ +#define PHI 0x9E3779B9 + +/* Serpent works on 128 bit blocks. */ +typedef uint32_t serpent_block_t[4]; + +/* Serpent key, provided by the user. If the original key is shorter + than 256 bits, it is padded. */ +typedef uint32_t serpent_key_t[8]; + +/* The key schedule consists of 33 128 bit subkeys. */ +typedef uint32_t serpent_subkeys_t[ROUNDS + 1][4]; + +/* A Serpent context. Note that the public API uses symenc_t + instead. */ +struct symenc_context_s +{ + serpent_subkeys_t keys; /* Generated subkeys. */ + + union { + uint32_t dummy; /* Force alignment. */ + struct { + unsigned char iv[BLOCKSIZE]; /* The IV. */ + unsigned int unused; /* Unused bytes in the IV. */ + } cfb; + } u; +}; +typedef struct symenc_context_s serpent_context_t; + + +/* A prototype. */ +static const char *serpent_test (void); + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) + +#define byte_swap_32(x) \ + (0 \ + | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +/* These are the S-Boxes of Serpent. They are copied from Serpents + reference implementation (the optimized one, contained in + `floppy2') and are therefore: + + Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen. + + To quote the Serpent homepage + (http://www.cl.cam.ac.uk/~rja14/serpent.html): + + "Serpent is now completely in the public domain, and we impose no + restrictions on its use. This was announced on the 21st August at + the First AES Candidate Conference. The optimised implementations + in the submission package are now under the GNU PUBLIC LICENSE + (GPL), although some comments in the code still say otherwise. You + are welcome to use Serpent for any application." */ + +#define SBOX0(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t05, t06, t07, t08, t09; \ + uint32_t t11, t12, t13, t14, t15, t17, t01; \ + t01 = b ^ c ; \ + t02 = a | d ; \ + t03 = a ^ b ; \ + z = t02 ^ t01; \ + t05 = c | z ; \ + t06 = a ^ d ; \ + t07 = b | c ; \ + t08 = d & t05; \ + t09 = t03 & t07; \ + y = t09 ^ t08; \ + t11 = t09 & y ; \ + t12 = c ^ d ; \ + t13 = t07 ^ t11; \ + t14 = b & t06; \ + t15 = t06 ^ t13; \ + w = ~ t15; \ + t17 = w ^ t14; \ + x = t12 ^ t17; \ + } + +#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09, t10; \ + uint32_t t12, t13, t14, t15, t17, t18, t01; \ + t01 = c ^ d ; \ + t02 = a | b ; \ + t03 = b | c ; \ + t04 = c & t01; \ + t05 = t02 ^ t01; \ + t06 = a | t04; \ + y = ~ t05; \ + t08 = b ^ d ; \ + t09 = t03 & t08; \ + t10 = d | y ; \ + x = t09 ^ t06; \ + t12 = a | t05; \ + t13 = x ^ t12; \ + t14 = t03 ^ t10; \ + t15 = a ^ c ; \ + z = t14 ^ t13; \ + t17 = t05 & t13; \ + t18 = t14 | t17; \ + w = t15 ^ t18; \ + } + +#define SBOX1(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t t10, t11, t12, t13, t16, t17, t01; \ + t01 = a | d ; \ + t02 = c ^ d ; \ + t03 = ~ b ; \ + t04 = a ^ c ; \ + t05 = a | t03; \ + t06 = d & t04; \ + t07 = t01 & t02; \ + t08 = b | t06; \ + y = t02 ^ t05; \ + t10 = t07 ^ t08; \ + t11 = t01 ^ t10; \ + t12 = y ^ t11; \ + t13 = b & d ; \ + z = ~ t10; \ + x = t13 ^ t12; \ + t16 = t10 | x ; \ + t17 = t05 & t16; \ + w = c ^ t17; \ + } + +#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t t09, t10, t11, t14, t15, t17, t01; \ + t01 = a ^ b ; \ + t02 = b | d ; \ + t03 = a & c ; \ + t04 = c ^ t02; \ + t05 = a | t04; \ + t06 = t01 & t05; \ + t07 = d | t03; \ + t08 = b ^ t06; \ + t09 = t07 ^ t06; \ + t10 = t04 | t03; \ + t11 = d & t08; \ + y = ~ t09; \ + x = t10 ^ t11; \ + t14 = a | y ; \ + t15 = t06 ^ x ; \ + z = t01 ^ t04; \ + t17 = c ^ t15; \ + w = t14 ^ t17; \ + } + +#define SBOX2(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t05, t06, t07, t08; \ + uint32_t t09, t10, t12, t13, t14, t01; \ + t01 = a | c ; \ + t02 = a ^ b ; \ + t03 = d ^ t01; \ + w = t02 ^ t03; \ + t05 = c ^ w ; \ + t06 = b ^ t05; \ + t07 = b | t05; \ + t08 = t01 & t06; \ + t09 = t03 ^ t07; \ + t10 = t02 | t09; \ + x = t10 ^ t08; \ + t12 = a | d ; \ + t13 = t09 ^ x ; \ + t14 = b ^ t13; \ + z = ~ t09; \ + y = t12 ^ t14; \ + } + +#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t06, t07, t08, t09; \ + uint32_t t10, t11, t12, t15, t16, t17, t01; \ + t01 = a ^ d ; \ + t02 = c ^ d ; \ + t03 = a & c ; \ + t04 = b | t02; \ + w = t01 ^ t04; \ + t06 = a | c ; \ + t07 = d | w ; \ + t08 = ~ d ; \ + t09 = b & t06; \ + t10 = t08 | t03; \ + t11 = b & t07; \ + t12 = t06 & t02; \ + z = t09 ^ t10; \ + x = t12 ^ t11; \ + t15 = c & z ; \ + t16 = w ^ x ; \ + t17 = t10 ^ t15; \ + y = t16 ^ t17; \ + } + +#define SBOX3(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08; \ + uint32_t t09, t10, t11, t13, t14, t15, t01; \ + t01 = a ^ c ; \ + t02 = a | d ; \ + t03 = a & d ; \ + t04 = t01 & t02; \ + t05 = b | t03; \ + t06 = a & b ; \ + t07 = d ^ t04; \ + t08 = c | t06; \ + t09 = b ^ t07; \ + t10 = d & t05; \ + t11 = t02 ^ t10; \ + z = t08 ^ t09; \ + t13 = d | z ; \ + t14 = a | t07; \ + t15 = b & t13; \ + y = t08 ^ t11; \ + w = t14 ^ t15; \ + x = t05 ^ t04; \ + } + +#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t09; \ + uint32_t t11, t12, t13, t14, t16, t01; \ + t01 = c | d ; \ + t02 = a | d ; \ + t03 = c ^ t02; \ + t04 = b ^ t02; \ + t05 = a ^ d ; \ + t06 = t04 & t03; \ + t07 = b & t01; \ + y = t05 ^ t06; \ + t09 = a ^ t03; \ + w = t07 ^ t03; \ + t11 = w | t05; \ + t12 = t09 & t11; \ + t13 = a & y ; \ + t14 = t01 ^ t05; \ + x = b ^ t12; \ + t16 = b | t13; \ + z = t14 ^ t16; \ + } + +#define SBOX4(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09; \ + uint32_t t10, t11, t12, t13, t14, t15, t16, t01; \ + t01 = a | b ; \ + t02 = b | c ; \ + t03 = a ^ t02; \ + t04 = b ^ d ; \ + t05 = d | t03; \ + t06 = d & t01; \ + z = t03 ^ t06; \ + t08 = z & t04; \ + t09 = t04 & t05; \ + t10 = c ^ t06; \ + t11 = b & c ; \ + t12 = t04 ^ t08; \ + t13 = t11 | t03; \ + t14 = t10 ^ t09; \ + t15 = a & t05; \ + t16 = t11 | t12; \ + y = t13 ^ t08; \ + x = t15 ^ t16; \ + w = ~ t14; \ + } + +#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t09; \ + uint32_t t10, t11, t12, t13, t15, t01; \ + t01 = b | d ; \ + t02 = c | d ; \ + t03 = a & t01; \ + t04 = b ^ t02; \ + t05 = c ^ d ; \ + t06 = ~ t03; \ + t07 = a & t04; \ + x = t05 ^ t07; \ + t09 = x | t06; \ + t10 = a ^ t07; \ + t11 = t01 ^ t09; \ + t12 = d ^ t04; \ + t13 = c | t10; \ + z = t03 ^ t12; \ + t15 = a ^ t04; \ + y = t11 ^ t13; \ + w = t15 ^ t09; \ + } + +#define SBOX5(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09; \ + uint32_t t10, t11, t12, t13, t14, t01; \ + t01 = b ^ d ; \ + t02 = b | d ; \ + t03 = a & t01; \ + t04 = c ^ t02; \ + t05 = t03 ^ t04; \ + w = ~ t05; \ + t07 = a ^ t01; \ + t08 = d | w ; \ + t09 = b | t05; \ + t10 = d ^ t08; \ + t11 = b | t07; \ + t12 = t03 | w ; \ + t13 = t07 | t10; \ + t14 = t01 ^ t11; \ + y = t09 ^ t13; \ + x = t07 ^ t08; \ + z = t12 ^ t14; \ + } + +#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09; \ + uint32_t t10, t12, t13, t15, t16, t01; \ + t01 = a & d ; \ + t02 = c ^ t01; \ + t03 = a ^ d ; \ + t04 = b & t02; \ + t05 = a & c ; \ + w = t03 ^ t04; \ + t07 = a & w ; \ + t08 = t01 ^ w ; \ + t09 = b | t05; \ + t10 = ~ b ; \ + x = t08 ^ t09; \ + t12 = t10 | t07; \ + t13 = w | x ; \ + z = t02 ^ t12; \ + t15 = t02 ^ t13; \ + t16 = b ^ d ; \ + y = t16 ^ t15; \ + } + +#define SBOX6(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t07, t08, t09, t10; \ + uint32_t t11, t12, t13, t15, t17, t18, t01; \ + t01 = a & d ; \ + t02 = b ^ c ; \ + t03 = a ^ d ; \ + t04 = t01 ^ t02; \ + t05 = b | c ; \ + x = ~ t04; \ + t07 = t03 & t05; \ + t08 = b & x ; \ + t09 = a | c ; \ + t10 = t07 ^ t08; \ + t11 = b | d ; \ + t12 = c ^ t11; \ + t13 = t09 ^ t10; \ + y = ~ t13; \ + t15 = x & t03; \ + z = t12 ^ t07; \ + t17 = a ^ b ; \ + t18 = y ^ t15; \ + w = t17 ^ t18; \ + } + +#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t07, t08, t09; \ + uint32_t t12, t13, t14, t15, t16, t17, t01; \ + t01 = a ^ c ; \ + t02 = ~ c ; \ + t03 = b & t01; \ + t04 = b | t02; \ + t05 = d | t03; \ + t06 = b ^ d ; \ + t07 = a & t04; \ + t08 = a | t02; \ + t09 = t07 ^ t05; \ + x = t06 ^ t08; \ + w = ~ t09; \ + t12 = b & w ; \ + t13 = t01 & t05; \ + t14 = t01 ^ t12; \ + t15 = t07 ^ t13; \ + t16 = d | t02; \ + t17 = a ^ x ; \ + z = t17 ^ t15; \ + y = t16 ^ t14; \ + } + +#define SBOX7(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t05, t06, t08, t09, t10; \ + uint32_t t11, t13, t14, t15, t16, t17, t01; \ + t01 = a & c ; \ + t02 = ~ d ; \ + t03 = a & t02; \ + t04 = b | t01; \ + t05 = a & b ; \ + t06 = c ^ t04; \ + z = t03 ^ t06; \ + t08 = c | z ; \ + t09 = d | t05; \ + t10 = a ^ t08; \ + t11 = t04 & z ; \ + x = t09 ^ t10; \ + t13 = b ^ x ; \ + t14 = t01 ^ x ; \ + t15 = c ^ t05; \ + t16 = t11 | t13; \ + t17 = t02 | t14; \ + w = t15 ^ t17; \ + y = a ^ t16; \ + } + +#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \ + { \ + uint32_t t02, t03, t04, t06, t07, t08, t09; \ + uint32_t t10, t11, t13, t14, t15, t16, t01; \ + t01 = a & b ; \ + t02 = a | b ; \ + t03 = c | t01; \ + t04 = d & t02; \ + z = t03 ^ t04; \ + t06 = b ^ t04; \ + t07 = d ^ z ; \ + t08 = ~ t07; \ + t09 = t06 | t08; \ + t10 = b ^ d ; \ + t11 = a | d ; \ + x = a ^ t09; \ + t13 = c ^ t06; \ + t14 = c & t11; \ + t15 = d | x ; \ + t16 = t01 | t10; \ + w = t13 ^ t15; \ + y = t14 ^ t16; \ + } + +/* XOR BLOCK1 into BLOCK0. */ +#define BLOCK_XOR(block0, block1) \ + { \ + block0[0] ^= block1[0]; \ + block0[1] ^= block1[1]; \ + block0[2] ^= block1[2]; \ + block0[3] ^= block1[3]; \ + } + +/* Copy BLOCK_SRC to BLOCK_DST. */ +#define BLOCK_COPY(block_dst, block_src) \ + { \ + block_dst[0] = block_src[0]; \ + block_dst[1] = block_src[1]; \ + block_dst[2] = block_src[2]; \ + block_dst[3] = block_src[3]; \ + } + +/* Apply SBOX number WHICH to to the block found in ARRAY0 at index + INDEX, writing the output to the block found in ARRAY1 at index + INDEX. */ +#define SBOX(which, array0, array1, index) \ + SBOX##which (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at + index INDEX, writing the output to the block found in ARRAY1 at + index INDEX. */ +#define SBOX_INVERSE(which, array0, array1, index) \ + SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \ + array0[index + 2], array0[index + 3], \ + array1[index + 0], array1[index + 1], \ + array1[index + 2], array1[index + 3]); + +/* Apply the linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION(block) \ + { \ + block[0] = rol (block[0], 13); \ + block[2] = rol (block[2], 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = rol (block[1], 1); \ + block[3] = rol (block[3], 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = rol (block[0], 5); \ + block[2] = rol (block[2], 22); \ + } + +/* Apply the inverse linear transformation to BLOCK. */ +#define LINEAR_TRANSFORMATION_INVERSE(block) \ + { \ + block[2] = ror (block[2], 22); \ + block[0] = ror (block[0] , 5); \ + block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ + block[0] = block[0] ^ block[1] ^ block[3]; \ + block[3] = ror (block[3], 7); \ + block[1] = ror (block[1], 1); \ + block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ + block[1] = block[1] ^ block[0] ^ block[2]; \ + block[2] = ror (block[2], 3); \ + block[0] = ror (block[0], 13); \ + } + +/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the + subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. + This macro increments `round'. */ +#define ROUND(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + LINEAR_TRANSFORMATION (block_tmp); \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_LAST(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round++; \ + SBOX (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round++; \ + } + +/* Apply an inverse Serpent round to BLOCK, using the SBOX number + WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as + temporary storage. This macro increments `round'. */ +#define ROUND_INVERSE(which, subkey, block, block_tmp) \ + { \ + LINEAR_TRANSFORMATION_INVERSE (block); \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkey[round]); \ + round--; \ + BLOCK_COPY (block, block_tmp); \ + } + +/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH + and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary + storage. The result will be stored in BLOCK_TMP. This macro + increments `round'. */ +#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \ + { \ + BLOCK_XOR (block, subkeys[round]); \ + round--; \ + SBOX_INVERSE (which, block, block_tmp, 0); \ + BLOCK_XOR (block_tmp, subkeys[round]); \ + round--; \ + } + +/* Convert the user provided key KEY of KEY_LENGTH bytes into the + internally used format. */ +static void +serpent_key_prepare (const unsigned char *key, unsigned int key_length, + serpent_key_t key_prepared) +{ + unsigned int i; + + /* Copy key. */ + for (i = 0; i < key_length / 4; i++) + { +#ifdef WORDS_BIGENDIAN + key_prepared[i] = byte_swap_32 (((uint32_t *) key)[i]); +#else + key_prepared[i] = ((uint32_t *) key)[i]; +#endif + } + + if (i < 8) + { + /* Key must be padded according to the Serpent + specification. */ + key_prepared[i] = 0x00000001; + + for (i++; i < 8; i++) + key_prepared[i] = 0; + } +} + +/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ +static void +serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) +{ + uint32_t w_real[140]; /* The `prekey'. */ + uint32_t k[132]; + uint32_t *w = &w_real[8]; + int i, j; + + /* Initialize with key values. */ + for (i = 0; i < 8; i++) + w[i - 8] = key[i]; + + /* Expand to intermediate key using the affine recurrence. */ + for (i = 0; i < 132; i++) + w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); + + /* Calculate subkeys via S-Boxes, in bitslice mode. */ + SBOX (3, w, k, 0); + SBOX (2, w, k, 4); + SBOX (1, w, k, 8); + SBOX (0, w, k, 12); + SBOX (7, w, k, 16); + SBOX (6, w, k, 20); + SBOX (5, w, k, 24); + SBOX (4, w, k, 28); + SBOX (3, w, k, 32); + SBOX (2, w, k, 36); + SBOX (1, w, k, 40); + SBOX (0, w, k, 44); + SBOX (7, w, k, 48); + SBOX (6, w, k, 52); + SBOX (5, w, k, 56); + SBOX (4, w, k, 60); + SBOX (3, w, k, 64); + SBOX (2, w, k, 68); + SBOX (1, w, k, 72); + SBOX (0, w, k, 76); + SBOX (7, w, k, 80); + SBOX (6, w, k, 84); + SBOX (5, w, k, 88); + SBOX (4, w, k, 92); + SBOX (3, w, k, 96); + SBOX (2, w, k, 100); + SBOX (1, w, k, 104); + SBOX (0, w, k, 108); + SBOX (7, w, k, 112); + SBOX (6, w, k, 116); + SBOX (5, w, k, 120); + SBOX (4, w, k, 124); + SBOX (3, w, k, 128); + + /* Renumber subkeys. */ + for (i = 0; i < ROUNDS + 1; i++) + for (j = 0; j < 4; j++) + subkeys[i][j] = k[4 * i + j]; +} + +/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ +static void +serpent_setkey_internal (serpent_context_t *context, + const unsigned char *key, unsigned int key_length) +{ + serpent_key_t key_prepared; + + serpent_key_prepare (key, key_length, key_prepared); + serpent_subkeys_generate (key_prepared, context->keys); +} + + +/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ +static int +serpent_setkey (serpent_context_t *context, + const void *key, unsigned int key_length) +{ + static const char *serpent_test_ret; + static int serpent_init_done; + int ret = 0; + + if (!serpent_init_done) + { + /* Execute a self-test the first time, Serpent is used. */ + serpent_test_ret = serpent_test (); +#ifdef TEST + if (serpent_test_ret) + fprintf (stderr, "Serpent test failure: %s\n", serpent_test_ret); +#endif /*TEST*/ + serpent_init_done = 1; + } + + if (serpent_test_ret) + ret = -1; + else + serpent_setkey_internal (context, key, key_length); + + return ret; +} + + +static void +serpent_encrypt_internal (serpent_context_t *context, + const serpent_block_t input, serpent_block_t output) +{ + serpent_block_t b, b_next; + int round = 0; + +#ifdef WORDS_BIGENDIAN + b[0] = byte_swap_32 (input[0]); + b[1] = byte_swap_32 (input[1]); + b[2] = byte_swap_32 (input[2]); + b[3] = byte_swap_32 (input[3]); +#else + b[0] = input[0]; + b[1] = input[1]; + b[2] = input[2]; + b[3] = input[3]; +#endif + + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + ROUND (7, context->keys, b, b_next); + ROUND (0, context->keys, b, b_next); + ROUND (1, context->keys, b, b_next); + ROUND (2, context->keys, b, b_next); + ROUND (3, context->keys, b, b_next); + ROUND (4, context->keys, b, b_next); + ROUND (5, context->keys, b, b_next); + ROUND (6, context->keys, b, b_next); + + ROUND_LAST (7, context->keys, b, b_next); + +#ifdef WORDS_BIGENDIAN + output[0] = byte_swap_32 (b_next[0]); + output[1] = byte_swap_32 (b_next[1]); + output[2] = byte_swap_32 (b_next[2]); + output[3] = byte_swap_32 (b_next[3]); +#else + output[0] = b_next[0]; + output[1] = b_next[1]; + output[2] = b_next[2]; + output[3] = b_next[3]; +#endif +} + + +#ifdef TEST /* We only use CFB mode, thus tehre is no actual need for + the decryption fucntion. */ +static void +serpent_decrypt_internal (serpent_context_t *context, + const serpent_block_t input, serpent_block_t output) +{ + serpent_block_t b, b_next; + int round = ROUNDS; + +#ifdef WORDS_BIGENDIAN + b_next[0] = byte_swap_32 (input[0]); + b_next[1] = byte_swap_32 (input[1]); + b_next[2] = byte_swap_32 (input[2]); + b_next[3] = byte_swap_32 (input[3]); +#else + b_next[0] = input[0]; + b_next[1] = input[1]; + b_next[2] = input[2]; + b_next[3] = input[3]; +#endif + + ROUND_FIRST_INVERSE (7, context->keys, b_next, b); + + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + ROUND_INVERSE (7, context->keys, b, b_next); + ROUND_INVERSE (6, context->keys, b, b_next); + ROUND_INVERSE (5, context->keys, b, b_next); + ROUND_INVERSE (4, context->keys, b, b_next); + ROUND_INVERSE (3, context->keys, b, b_next); + ROUND_INVERSE (2, context->keys, b, b_next); + ROUND_INVERSE (1, context->keys, b, b_next); + ROUND_INVERSE (0, context->keys, b, b_next); + + +#ifdef WORDS_BIGENDIAN + output[0] = byte_swap_32 (b_next[0]); + output[1] = byte_swap_32 (b_next[1]); + output[2] = byte_swap_32 (b_next[2]); + output[3] = byte_swap_32 (b_next[3]); +#else + output[0] = b_next[0]; + output[1] = b_next[1]; + output[2] = b_next[2]; + output[3] = b_next[3]; +#endif +} +#endif /*TEST*/ + + +static const char * +serpent_test (void) +{ + serpent_context_t context; + unsigned char scratch[16]; + unsigned int i; + + static struct test + { + int key_length; + unsigned char key[32]; + unsigned char text_plain[16]; + unsigned char text_cipher[16]; + } test_data[] = + { + { + 16, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E", + "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D" + }, + { + 0 + } + }; + + for (i = 0; test_data[i].key_length; i++) + { + serpent_setkey_internal (&context, test_data[i].key, + test_data[i].key_length); + serpent_encrypt_internal (&context, + (const uint32_t *) test_data[i].text_plain, + (uint32_t *) scratch); + + if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) + return "Serpent test encryption failed"; + +#ifdef TEST + serpent_decrypt_internal (&context, + (const uint32_t *) test_data[i].text_cipher, + (uint32_t *) scratch); + if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) + return "Serpent test decryption failed."; +#endif /*TEST*/ + } + + return NULL; +} + +/* Open a new cipher instance with KEY and IV. On error the fucntion + returns NULL, otherwise a handle which needs to be provided to the + other functions. */ +symenc_t +symenc_open (const void *key, size_t keylen, const void *iv, size_t ivlen) +{ + symenc_t ctx; + + if (!key || keylen != 16 || !iv || ivlen != BLOCKSIZE) + return NULL; + ctx = calloc (1, sizeof *ctx); + if (!ctx) + return NULL; + if (serpent_setkey (ctx, key, keylen)) + { + free (ctx); + return NULL; + } + memcpy (ctx->u.cfb.iv, iv, BLOCKSIZE); + return ctx; +} + +/* Close a Serpent encryption context. */ +void +symenc_close (symenc_t ctx) +{ + if (ctx) + { + free (ctx); + } +} + + +void +symenc_cfb_encrypt (symenc_t ctx, + void *buffer_out, const void *buffer_in, size_t nbytes) +{ + const unsigned char *inbuf = buffer_in; + unsigned char *outbuf = buffer_out; + unsigned char *ivp; + int i; + + assert (ctx->u.cfb.unused <= BLOCKSIZE); + + /* If the input is short enough to be entirely encoded by the + remaining XOR mask, XOR the input with the IV and store input + into IV. */ + if (nbytes <= ctx->u.cfb.unused ) + { + for (ivp = ctx->u.cfb.iv + BLOCKSIZE - ctx->u.cfb.unused; + nbytes; nbytes--, ctx->u.cfb.unused--) + *outbuf++ = (*ivp++ ^= *inbuf++); + return; /* Ready. */ + } + + /* If there are still some bytes left in the XOR mask, XOR the input + with the IV and store input into IV. */ + if (ctx->u.cfb.unused) + { + nbytes -= ctx->u.cfb.unused; + for (ivp = ctx->u.cfb.iv + BLOCKSIZE - ctx->u.cfb.unused; + ctx->u.cfb.unused; ctx->u.cfb.unused--) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + + /* Now process complete blocks. */ + while (nbytes >= BLOCKSIZE) + { + serpent_encrypt_internal (ctx, (const uint32_t*)ctx->u.cfb.iv, + (uint32_t*)ctx->u.cfb.iv); + for (ivp = ctx->u.cfb.iv, i=0; i < BLOCKSIZE; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + nbytes -= BLOCKSIZE; + } + + /* Process any remaining bytes from the last block. */ + if (nbytes) + { + serpent_encrypt_internal (ctx, (const uint32_t*)ctx->u.cfb.iv, + (uint32_t*)ctx->u.cfb.iv); + ctx->u.cfb.unused = BLOCKSIZE - nbytes; + for (ivp = ctx->u.cfb.iv; nbytes; nbytes--) + *outbuf++ = (*ivp++ ^= *inbuf++); + } +} + + +void +symenc_cfb_decrypt (symenc_t ctx, + void *buffer_out, const void *buffer_in, size_t nbytes) +{ + const unsigned char *inbuf = buffer_in; + unsigned char *outbuf = buffer_out; + unsigned char *ivp; + uint32_t temp; + int i; + + assert (ctx->u.cfb.unused <= BLOCKSIZE); + + /* If the input is short enough to be entirely decoded by the + remaining XOR mask, XOR the input with the IV and store input + into IV. */ + if (nbytes <= ctx->u.cfb.unused) + { + for (ivp = ctx->u.cfb.iv + BLOCKSIZE - ctx->u.cfb.unused; + nbytes; nbytes--, ctx->u.cfb.unused--) + { + temp = *inbuf++; + *outbuf++ = (*ivp ^ temp); + *ivp++ = temp; + } + return; /* Ready. */ + } + + /* If there are still some bytes left in the XOR mask, XOR the input + with the IV and store input into IV. */ + if (ctx->u.cfb.unused) + { + nbytes -= ctx->u.cfb.unused; + for (ivp = ctx->u.cfb.iv + BLOCKSIZE - ctx->u.cfb.unused; + ctx->u.cfb.unused; ctx->u.cfb.unused--) + { + temp = *inbuf++; + *outbuf++ = (*ivp ^ temp); + *ivp++ = temp; + } + } + + /* Now process complete blocks. */ + while (nbytes >= BLOCKSIZE) + { + serpent_encrypt_internal (ctx, (const uint32_t*)ctx->u.cfb.iv, + (uint32_t*)ctx->u.cfb.iv); + for (ivp = ctx->u.cfb.iv, i=0; i < BLOCKSIZE; i++) + { + temp = *inbuf++; + *outbuf++ = (*ivp ^ temp); + *ivp++ = temp; + } + nbytes -= BLOCKSIZE; + } + + /* Process any remaining bytes from the last block. */ + if (nbytes) + { + serpent_encrypt_internal (ctx, (const uint32_t*)ctx->u.cfb.iv, + (uint32_t*)ctx->u.cfb.iv); + ctx->u.cfb.unused = BLOCKSIZE - nbytes; + for (ivp = ctx->u.cfb.iv; nbytes; nbytes--) + { + temp = *inbuf++; + *outbuf++ = (*ivp ^ temp); + *ivp++ = temp; + } + } +} + + + +#ifdef TEST +int +main (int argc, char** argv) +{ + int decmode; + symenc_t ctx; + char buf[255]; + size_t n; + + if (argc) { argc--, argv++; } + + decmode = (argc && !strcmp (*argv, "--decrypt")); + + ctx = symenc_open ("1234567890123456", 16, "abcdefghijklmnop", 16); + if (!ctx) + abort (); + + while ( (n=fread (buf, 1, 255, stdin)) ) + { + if (decmode) + symenc_cfb_decrypt (ctx, buf, buf, n); + else + symenc_cfb_encrypt (ctx, buf, buf, n); + if (fwrite (buf, 1, n, stdout) != n) + abort (); + } + + symenc_close (ctx); + return 0; +} + +#endif /*TEST*/ + + + +/* +Local Variables: +compile-command: "gcc -Wall -g -O2 -DTEST -o serpent serpent.c" +End: +*/ Added: trunk/src/serpent.h =================================================================== --- trunk/src/serpent.h 2007-08-06 10:48:33 UTC (rev 169) +++ trunk/src/serpent.h 2007-08-10 07:17:28 UTC (rev 170) @@ -0,0 +1,55 @@ +/* serpent.h - Definitions of the Serpent encryption algorithm. + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * GpgOL 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef SERPENT_H +#define SERPENT_H +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + + +/* Note that there is no special rason that we use Serpent and not AES + or even CAST5, blowfish or whatever. Any decent block cipher will + do; even the blocksize does not matter for our purpose. The + Serpent implementation was just the most convenient one top put + into this project. */ + +struct symenc_context_s; +typedef struct symenc_context_s *symenc_t; + + +symenc_t symenc_open (const void *key, size_t keylen, + const void *iv, size_t ivlen); +void symenc_close (symenc_t ctx); +void symenc_cfb_encrypt (symenc_t ctx, void *buffer_out, + const void *buffer_in, size_t nbytes); +void symenc_cfb_decrypt (symenc_t ctx, void *buffer_out, + const void *buffer_in, size_t nbytes); + + + +#ifdef __cplusplus +} +#endif +#endif /*SERPENT_H*/ From cvs at cvs.gnupg.org Mon Aug 13 15:33:20 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 13 Aug 2007 15:33:20 +0200 Subject: [svn] dirmngr - r261 - in trunk: . doc src Message-ID: Author: wk Date: 2007-08-13 15:32:46 +0200 (Mon, 13 Aug 2007) New Revision: 261 Modified: trunk/ChangeLog trunk/autogen.sh trunk/configure.ac trunk/doc/Makefile.am trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/dirmngr-client.c trunk/src/dirmngr.c trunk/src/get-path.c Log: Fixed a few W32 issues. starting and stopping a services does now work. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/ChangeLog 2007-08-13 13:32:46 UTC (rev 261) @@ -1,3 +1,11 @@ +2007-08-12 Werner Koch + + * doc/Makefile.am (yat2m): Change the way this helper is build. + * configure.ac (CC_FOR_BUILD): New. + + * autogen.sh: Update script to modern version and add --build-w32 + option. + 2007-08-09 Werner Koch * doc/dirmngr.texi (Dirmngr Options): Describe the new format of Modified: trunk/autogen.sh =================================================================== --- trunk/autogen.sh 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/autogen.sh 2007-08-13 13:32:46 UTC (rev 261) @@ -28,9 +28,77 @@ return 1 } +# Allow to override the default tool names +AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX} +AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX} + +AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX} +ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} + +GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX} +MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} + DIE=no +FORCE= +if test x"$1" = x"--force"; then + FORCE=" --force" + shift +fi +# ***** W32 build script ******* +# Used to cross-compile for Windows. +if test "$1" = "--build-w32"; then + tmp=`dirname $0` + tsdir=`cd "$tmp"; pwd` + shift + if [ ! -f $tsdir/config.guess ]; then + echo "$tsdir/config.guess not found" >&2 + exit 1 + fi + build=`$tsdir/config.guess` + + [ -z "$w32root" ] && w32root="$HOME/w32root" + echo "Using $w32root as standard install directory" >&2 + + # Locate the cross compiler + crossbindir= + for host in i586-mingw32msvc i386-mingw32msvc mingw32; do + if ${host}-gcc --version >/dev/null 2>&1 ; then + crossbindir=/usr/${host}/bin + conf_CC="CC=${host}-gcc" + break; + fi + done + if [ -z "$crossbindir" ]; then + echo "Cross compiler kit not installed" >&2 + echo "Under Debian GNU/Linux, you may install it using" >&2 + echo " apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2 + echo "Stop." >&2 + exit 1 + fi + + if [ -f "$tsdir/config.log" ]; then + if ! head $tsdir/config.log | grep "$host" >/dev/null; then + echo "Please run a 'make distclean' first" >&2 + exit 1 + fi + fi + + + ./configure --enable-maintainer-mode --prefix=${w32root} \ + --host=${host} --build=${build} \ + --with-gpg-error-prefix=${w32root} \ + --with-ksba-prefix=${w32root} \ + --with-libgcrypt-prefix=${w32root} \ + --with-libassuan-prefix=${w32root} \ + --with-pth-prefix=${w32root} + rc=$? + exit $rc +fi +# ***** end W32 build script ******* + + # ***** AMD64 cross build script ******* # Used to cross-compile for AMD64 (for testing) if test "$1" = "--build-amd64"; then @@ -108,17 +176,7 @@ exit 1 fi -# Allow to override the default tool names -AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX} -AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX} -AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX} -ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} - -GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX} -MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} - - if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf fi @@ -145,7 +203,7 @@ $AUTOHEADER echo "Running automake --gnu ..." $AUTOMAKE --gnu; -echo "Running autoconf..." -$AUTOCONF +echo "Running autoconf${FORCE} ..." +$AUTOCONF${FORCE} echo "You may now run \"./configure --enable-maintainer-mode --sysconfdir=/etc && make\"." Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/configure.ac 2007-08-13 13:32:46 UTC (rev 261) @@ -130,7 +130,22 @@ fi fi +# We need to compile and run a program on the build machine. A +# comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in +# the AC archive is broken for autoconf 2.57. Given that tehre is no +# newer version of that macro, we assume that it is also broken for +# autoconf 2.61 and thus we use a simple but usually sufficient +# approach. +AC_MSG_CHECKING(for cc for build) +if test "$cross_compiling" = "yes"; then + CC_FOR_BUILD="${CC_FOR_BUILD-cc}" +else + CC_FOR_BUILD="${CC_FOR_BUILD-$CC}" +fi +AC_MSG_RESULT($CC_FOR_BUILD) +AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler]) + # Tweaks for certain OSes. mmap_needed=yes have_w32_system=no Modified: trunk/doc/Makefile.am =================================================================== --- trunk/doc/Makefile.am 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/doc/Makefile.am 2007-08-13 13:32:46 UTC (rev 261) @@ -19,10 +19,8 @@ ## Process this file with automake to produce Makefile.in -EXTRA_DIST = internals.texi see-also-note.texi +EXTRA_DIST = internals.texi see-also-note.texi yat2m.c -noinst_PROGRAMS = yat2m - AM_MAKEFINFOFLAGS = -I $(srcdir) --css-include=/dev/null YAT2M_OPTIONS = -I $(srcdir) \ @@ -37,10 +35,14 @@ dirmngr_TEXINFOS = gpl.texi +CLEANFILES = yat2m + DISTCLEANFILES = dirmngr.ops yat2m-stamp.tmp yat2m-stamp $(myman_pages) -yat2m_SOURCES = yat2m.c +yat2m: yat2m.c + $(CC_FOR_BUILD) -o $@ $(srcdir)/yat2m.c + yat2m-stamp: $(myman_sources) @rm -f yat2m-stamp.tmp @touch yat2m-stamp.tmp Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/src/ChangeLog 2007-08-13 13:32:46 UTC (rev 261) @@ -1,3 +1,20 @@ +2007-08-13 Werner Koch + + * dirmngr.c (handle_connections): Use a timeout in the accept + fucntion. Block signals while creating a new thread. */ + (shutdown_pending): Needs to be volatile as also accessed bt the + service function. + (w32_service_control): Do not use the regular log fucntions here. + (handle_tick): New. + (main): With system_service in effect use aDaemon as default + command. + (main) [W32]: Only temporary redefine main for the sake of Emacs's + "C-x 4 a". + + * dirmngr-client.c (main) [W32]: Initialize sockets. + (start_dirmngr): Use default_socket_name instead of a constant. + * Makefile.am (dirmngr_client_SOURCES): Add get-path.c + 2007-08-09 Werner Koch * dirmngr.c (parse_ocsp_signer): New. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/src/Makefile.am 2007-08-13 13:32:46 UTC (rev 261) @@ -63,7 +63,7 @@ $(GPG_ERROR_LIBS) $(LDAPLIBS) $(LIBINTL) dirmngr_client_SOURCES = dirmngr-client.c i18n.h util.h b64enc.c \ - no-libgcrypt.c no-libgcrypt.h + get-path.c no-libgcrypt.c no-libgcrypt.h dirmngr_client_LDADD = ../jnlib/libjnlib.a $(LIBOBJS) $(LIBASSUAN_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) Modified: trunk/src/dirmngr-client.c =================================================================== --- trunk/src/dirmngr-client.c 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/src/dirmngr-client.c 2007-08-13 13:32:46 UTC (rev 261) @@ -81,7 +81,6 @@ { 0 } }; -#define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket" /* The usual structure for the program flags. */ static struct @@ -197,6 +196,16 @@ set_strusage (my_strusage); log_set_prefix ("dirmngr-client", JNLIB_LOG_WITH_PREFIX); + + /* For W32 we need to initialize the socket subsystem. Becuase we + don't use Pth we need to do this explicit. */ +#ifdef HAVE_W32_SYSTEM + { + WSADATA wsadat; + + WSAStartup (0x202, &wsadat); + } +#endif /*HAVE_W32_SYSTEM*/ /* Init Assuan. */ assuan_set_assuan_log_stream (log_get_stream ()); @@ -444,7 +453,7 @@ infostr = opt.force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); if (only_daemon && (!infostr || !*infostr)) { - infostr = DEFAULT_SOCKET_NAME; + infostr = xstrdup (default_socket_name ()); try_default = 1; } if (!infostr || !*infostr) Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/src/dirmngr.c 2007-08-13 13:32:46 UTC (rev 261) @@ -213,10 +213,20 @@ /* Helper to implement --debug-level. */ static const char *debug_level; /* Flag indicating that a shutdown has been requested. */ -static int shutdown_pending; +static volatile int shutdown_pending; /* Counter for the active connections. */ static int active_connections; +/* The timer tick used for housekeeping stuff. For Windows we use a + longer period as the SetWaitableTimer seems to signal earlier than + the 2 seconds. */ +#ifdef HAVE_W32_SYSTEM +#define TIMERTICK_INTERVAL (4) +#else +#define TIMERTICK_INTERVAL (2) /* Seconds. */ +#endif + + /* Prototypes. */ static void cleanup (void); static ldap_server_t parse_ldapserver_file (const char* filename); @@ -501,31 +511,36 @@ /* event_type and event_data are not used here. */ switch (control) { - case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: + /* For shutdown we will try to force termination. */ service_status.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus (service_handle, &service_status); + shutdown_pending = 3; + break; - if (!shutdown_pending) - log_info (_("SIGTERM received - shutting down ...\n")); - shutdown_pending++; + case SERVICE_CONTROL_STOP: + service_status.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus (service_handle, &service_status); + shutdown_pending = 1; break; default: - log_info (_("unhandled control request %lu\n"), control); break; } return 0; } +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +#define main real_main #endif - int +main (int argc, char **argv) +{ #ifdef HAVE_W32_SYSTEM -real_main (int argc, char **argv) -#else -main (int argc, char **argv) +#undef main #endif -{ enum cmd_and_opt_values cmd = 0; ARGPARSE_ARGS pargs; int orig_argc; @@ -567,7 +582,7 @@ service_status.dwWaitHint = 10000; /* 10 seconds timeout. */ SetServiceStatus (service_handle, &service_status); } -#endif +#endif /*HAVE_W32_SYSTEM*/ set_strusage (my_strusage); log_set_prefix ("dirmngr", 1|4); @@ -836,7 +851,9 @@ #endif /* Ready. Now to our duties. */ - if (!cmd) + if (!cmd && opt.system_service) + cmd = aDaemon; + else if (!cmd) cmd = aServer; rc = 0; @@ -1219,9 +1236,7 @@ }; if (!StartServiceCtrlDispatcher (DispatchTable)) - log_error (_("failed to start service ctrl dispatcher: ec=%d\n"), - (int) GetLastError ()); - + return 1; return 0; } } @@ -1644,7 +1659,28 @@ } +/* This is the worker for the ticker. It is called every few seconds + and may only do fast operations. */ +static void +handle_tick (void) +{ + /* Nothing real to do right now. Actually we need the timeout only + for W32 where we don't use signals and need a way for the loop to + check for the shutdown flag. */ +#ifdef HAVE_W32_SYSTEM + if (shutdown_pending) + log_info (_("SIGTERM received - shutting down ...\n")); + if (shutdown_pending > 2) + { + log_info (_("shutdown forced\n")); + log_info ("%s %s stopped\n", strusage(11), strusage(13) ); + cleanup (); + dirmngr_exit (0); + } +#endif /*HAVE_W32_SYSTEM*/ +} + /* Helper to call a connection's main fucntion. */ static void * start_connection_thread (void *arg) @@ -1670,8 +1706,8 @@ handle_connections (int listen_fd) { pth_attr_t tattr; - pth_event_t ev; - sigset_t sigs; + pth_event_t ev, time_ev; + sigset_t sigs, oldsigs; int signo; struct sockaddr_un paddr; socklen_t plen = sizeof( paddr ); @@ -1694,6 +1730,7 @@ sigs = 0; ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #endif + time_ev = NULL; for (;;) { @@ -1711,12 +1748,29 @@ continue; } + if (!time_ev) + time_ev = pth_event (PTH_EVENT_TIME, + pth_timeout (TIMERTICK_INTERVAL, 0)); + + if (time_ev) + pth_event_concat (ev, time_ev, NULL); fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (time_ev) + pth_event_isolate (time_ev); + if (fd == -1) { - if (pth_event_occurred (ev)) + if (pth_event_occurred (ev) + || (time_ev && pth_event_occurred (time_ev)) ) { - handle_signal (signo); + if (pth_event_occurred (ev)) + handle_signal (signo); + if (time_ev && pth_event_occurred (time_ev)) + { + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } continue; } log_error (_("accept failed: %s - waiting 1s\n"), strerror (errno)); @@ -1724,15 +1778,39 @@ continue; } + if (pth_event_occurred (ev)) + { + handle_signal (signo); + } + + if (time_ev && pth_event_occurred (time_ev)) + { + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } + + + /* We now might create a new thread and because we don't want + any signals (as we are handling them here) to be delivered to + a new thread we need to block those signals. */ + pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); + + /* Create thread to handle this connection. */ if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) { log_error (_("error spawning connection handler: %s\n"), strerror (errno) ); close (fd); } + + /* Restore the signal mask. */ + pth_sigmask (SIG_SETMASK, &oldsigs, NULL); } pth_event_free (ev, PTH_FREE_ALL); + if (time_ev) + pth_event_free (time_ev, PTH_FREE_ALL); cleanup (); log_info ("%s %s stopped\n", strusage(11), strusage(13)); } Modified: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-08-09 15:51:16 UTC (rev 260) +++ trunk/src/get-path.c 2007-08-13 13:32:46 UTC (rev 261) @@ -292,7 +292,7 @@ /* Get the standard home directory. In general this function should not be used as it does not consider a registry value (under W32) or - the GNUPGHOME encironment variable. It is better to use + the GNUPGHOME environment variable. It is better to use default_homedir(). */ const char * standard_homedir (void) From cvs at cvs.gnupg.org Mon Aug 13 16:58:04 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 13 Aug 2007 16:58:04 +0200 Subject: [svn] GPGol - r171 - trunk/src Message-ID: Author: marcus Date: 2007-08-13 16:57:34 +0200 (Mon, 13 Aug 2007) New Revision: 171 Modified: trunk/src/ChangeLog trunk/src/Makefile.am Log: 2007-08-13 Marcus Brinkmann * Makefile.am (gpgol_SOURCES): Add common.h. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-10 07:17:28 UTC (rev 170) +++ trunk/src/ChangeLog 2007-08-13 14:57:34 UTC (rev 171) @@ -1,3 +1,7 @@ +2007-08-13 Marcus Brinkmann + + * Makefile.am (gpgol_SOURCES): Add common.h. + 2007-08-06 Werner Koch Lots of changes to support S/MIME and to revamp most of the old Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-10 07:17:28 UTC (rev 170) +++ trunk/src/Makefile.am 2007-08-13 14:57:34 UTC (rev 171) @@ -37,7 +37,8 @@ msgcache.c msgcache.h \ engine-gpgme.c engine.h \ rfc822parse.c rfc822parse.h \ - common.c util.h xmalloc.h \ + common.h common.c util.h \ + xmalloc.h \ passcache.c passcache.h \ config-dialog.c \ passphrase-dialog.c \ From cvs at cvs.gnupg.org Mon Aug 13 17:02:38 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 13 Aug 2007 17:02:38 +0200 Subject: [svn] GPGol - r172 - trunk Message-ID: Author: marcus Date: 2007-08-13 17:02:04 +0200 (Mon, 13 Aug 2007) New Revision: 172 Modified: trunk/ChangeLog trunk/configure.ac Log: 2007-08-13 Marcus Brinkmann * configure.ac (svn_revision): Update to latest version from gnupg. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-13 14:57:34 UTC (rev 171) +++ trunk/ChangeLog 2007-08-13 15:02:04 UTC (rev 172) @@ -1,3 +1,7 @@ +2007-08-13 Marcus Brinkmann + + * configure.ac (svn_revision): Update to latest version from gnupg. + 2006-12-13 Werner Koch * po/LINGUAS: Added sv. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-13 14:57:34 UTC (rev 171) +++ trunk/configure.ac 2007-08-13 15:02:04 UTC (rev 172) @@ -19,8 +19,8 @@ m4_define([my_version], [0.9.92]) m4_define([my_issvn], [yes]) -m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ - || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')])) +m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ + || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) AC_INIT([gpgol], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), [bug-gpgol at g10code.com]) From cvs at cvs.gnupg.org Tue Aug 14 18:50:59 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 14 Aug 2007 18:50:59 +0200 Subject: [svn] GnuPG - r4559 - in trunk: . common doc sm Message-ID: Author: wk Date: 2007-08-14 18:50:27 +0200 (Tue, 14 Aug 2007) New Revision: 4559 Modified: trunk/NEWS trunk/TODO trunk/common/ChangeLog trunk/common/homedir.c trunk/common/util.h trunk/doc/ChangeLog trunk/doc/glossary.texi trunk/doc/gpg-agent.texi trunk/doc/gpgsm.texi trunk/doc/yat2m.c trunk/sm/ChangeLog trunk/sm/call-dirmngr.c trunk/sm/gpgsm.c Log: Documentaion updates. Support doe Dirmngr under W32. Fixed a yat2m bug. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/NEWS 2007-08-14 16:50:27 UTC (rev 4559) @@ -1,4 +1,4 @@ -Noteworthy changes in version 2.0.6 +Noteworthy changes in version 2.0.6 (2007-08-14) ------------------------------------------------ * GPGSM does now grok --default-key. @@ -8,6 +8,10 @@ * GPGSM does again correctly print the serial number as well the the various keyids. This was broken since 2.0.4. + * New option --validation-model and support for the chain-model. + + * Imporved Windows support. + Noteworthy changes in version 2.0.5 (2007-07-05) ------------------------------------------------ Modified: trunk/TODO =================================================================== --- trunk/TODO 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/TODO 2007-08-14 16:50:27 UTC (rev 4559) @@ -110,6 +110,7 @@ * Remove -sat PGP2 compatibility hack * UTF-8 specific TODOs + None. * Pinpad Reader We do not yet support P15 applications. The trivial thing using @@ -124,11 +125,7 @@ * Howtos ** Migrate OpenPGP keys to another system - -* do_add_recipient - Prints wrong error message even when decrypting. - *Decrypt* does even not work in this case. - * Duplicate certifciates This may happen and lead to an Ambiguous Name error. Solution is to - check the certs for identity beforethorwin this error. + check the certs for identity before throwing this error. + Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/common/ChangeLog 2007-08-14 16:50:27 UTC (rev 4559) @@ -1,3 +1,7 @@ +2007-08-14 Werner Koch + + * homedir.c (dirmngr_socket_name): New. + 2007-08-07 Werner Koch * tlv.c, tlv.h: Move from ../scd/. Modified: trunk/common/homedir.c =================================================================== --- trunk/common/homedir.c 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/common/homedir.c 2007-08-14 16:50:27 UTC (rev 4559) @@ -290,6 +290,29 @@ } +/* Return the default socket name used by DirMngr. */ +const char * +dirmngr_socket_name (void) +{ +#ifdef HAVE_W32_SYSTEM + static char *name; + + if (!name) + { + const char *s1, *s2; + s1 = w32_rootdir (); + s2 = DIRSEP_S "S.dirmngr"; + name = xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (stpcpy (name, s1), s2); + } + return name; +#else /*!HAVE_W32_SYSTEM*/ + return "/var/run/dirmngr/socket"; +#endif /*!HAVE_W32_SYSTEM*/ +} + + + /* Return the file name of a helper tool. WHICH is one of the GNUPG_MODULE_NAME_foo constants. */ const char * Modified: trunk/common/util.h =================================================================== --- trunk/common/util.h 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/common/util.h 2007-08-14 16:50:27 UTC (rev 4559) @@ -178,6 +178,7 @@ const char *gnupg_libexecdir (void); const char *gnupg_libdir (void); const char *gnupg_datadir (void); +const char *dirmngr_socket_name (void); #define GNUPG_MODULE_NAME_AGENT 1 #define GNUPG_MODULE_NAME_PINENTRY 2 Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/doc/ChangeLog 2007-08-14 16:50:27 UTC (rev 4559) @@ -1,3 +1,15 @@ +2007-08-14 Werner Koch + + * glossary.texi (Glossary): Add a more items. + +2007-08-13 Werner Koch + + * yat2m.c (proc_texi_cmd): Do not put @samp content between two + newlines. + + * gpg-agent.texi (Agent Configuration): Explain the CM flag for + trustlist.txt. + 2007-08-09 Werner Koch * gpgsm.texi (Certificate Options): Describe --validation-model. Modified: trunk/doc/glossary.texi =================================================================== --- trunk/doc/glossary.texi 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/doc/glossary.texi 2007-08-14 16:50:27 UTC (rev 4559) @@ -12,6 +12,21 @@ @acronym{CRL} but used for @acronym{CA}s and not for end user certificates. + at item Chain model + Verification model for X.509 which uses the creation date of a +signature as the date the validation starts and in turn checks that each +certificate has been issued within the time frame, the issuing +certificate was valid. This allows the verification of signatures after +the the CA's certificate expired. The validation test also required an +online check of the certificate status. The chain model is required by +the German signature law. See also @emph{Shell model}. + + at item CMS + The @emph{Cryptographic Message Standard} describes a message +format for encryption and digital signing. It is closely related to the +X.509 certificate format. @acronym{CMS} was formerly known under the +name @code{PKCS#7} and is described by @code{RFC3369}. + @item CRL The @emph{Certificate Revocation List} is a list containing certificates revoked by the issuer. @@ -21,6 +36,12 @@ ask them to issue a new certificate. The data format of such a signing request is called PCKS#10. + at item OpenPGP + A data format used to build a PKI and to exchange encrypted or +signed messages. In contrast to X.509, OpenPGP also includes the +message format but does not explicilty demand a specific PKI. However +any kind of PKI may be build upon the OpenPGP protocol. + @item Keygrip This term is used by GnuPG to describe a 20 byte hash value used to identify a certain key without referencing to a concrete protocol. @@ -37,4 +58,15 @@ on a disk; the latter is often called a Soft-PSE. + at item Shell model +The standard model for validation of certificates under X.509. At the +time of the verification all certifciates must be valid and not expired. +See also @emph{Chain mode}. + + + at item X.509 +Description of a PKI used with CMS. It is for example +defined by @code{RFC3280}. + + @end table Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/doc/gpg-agent.texi 2007-08-14 16:50:27 UTC (rev 4559) @@ -493,31 +493,40 @@ even advisable to change the permissions to read-only so that this file can't be changed inadvertently. -It is possible to add further flags after the @code{S} for use by the -caller. The only flag currently defined is @code{relax} to relax -checking of some root certificate requirements. - As a special feature a line @code{include-default} will include a global list of trusted certificates (e.g. @file{/etc/gnupg/trustlist.txt}). This global list is also used if the local list is not available. +It is possible to add further flags after the @code{S} for use by the +caller: + + at table @code + at item relax +Relax checking of some root certificate requirements. + + at item cm +If validation of a certificate finally issued by a CA with this flag set +fails, try again using the chain validation model. + + at end table + @item sshcontrol - This file is used when support for the secure shell agent protocol has - been enabled (@pxref{option --enable-ssh-support}). Only keys present in - this file are used in the SSH protocol. The @command{ssh-add} tool y be - used to add new entries to this file; you may also add them manually. - Comment lines, indicated by a leading hash mark, as well as empty lines - are ignored. An entry starts with optional white spaces, followed by - the keygrip of the key given as 40 hex digits, optionally followed by - the caching TTL in seconds and another optional field for arbitrary - flags. A @code{!} may be prepended to the keygrip to disable this - entry. +This file is used when support for the secure shell agent protocol has +been enabled (@pxref{option --enable-ssh-support}). Only keys present +in this file are used in the SSH protocol. The @command{ssh-add} tool +y be used to add new entries to this file; you may also add them +manually. Comment lines, indicated by a leading hash mark, as well as +empty lines are ignored. An entry starts with optional white spaces, +followed by the keygrip of the key given as 40 hex digits, optionally +followed by the caching TTL in seconds and another optional field for +arbitrary flags. A @code{!} may be prepended to the keygrip to +disable this entry. - The follwoing example lists exactly one key. Note that keys available - through a OpenPGP smartcard in the active smartcard reader are implictly - added to this list; i.e. there is no need to list them. +The follwoing example lists exactly one key. Note that keys available +through a OpenPGP smartcard in the active smartcard reader are +implictly added to this list; i.e. there is no need to list them. @example # Key added on 2005-02-25 15:08:29 Modified: trunk/doc/gpgsm.texi =================================================================== --- trunk/doc/gpgsm.texi 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/doc/gpgsm.texi 2007-08-14 16:50:27 UTC (rev 4559) @@ -339,7 +339,8 @@ @opindex prefer-system-dirmngr If a system wide @command{dirmngr} is running in daemon mode, first try to connect to this one. Fallback to a pipe based server if this does -not work. +not work. Under Windows this option is ignored because the system dirmngr is +always used. @item --no-secmem-warning @opindex no-secmem-warning Modified: trunk/doc/yat2m.c =================================================================== --- trunk/doc/yat2m.c 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/doc/yat2m.c 2007-08-14 16:50:27 UTC (rev 4559) @@ -449,7 +449,7 @@ { "code", 0, "\\fB", "\\fR" }, { "sc", 0, "\\fB", "\\fR" }, { "var", 0, "\\fI", "\\fR" }, - { "samp", 0, "\n'", "'\n" }, + { "samp", 0, "'", "'" }, { "file", 0, "`\\fI","\\fR'" }, { "env", 0, "`\\fI","\\fR'" }, { "acronym", 0 }, Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/sm/ChangeLog 2007-08-14 16:50:27 UTC (rev 4559) @@ -1,3 +1,19 @@ +2007-08-14 Werner Koch + + * call-dirmngr.c (start_dirmngr): Use dirmngr_socket_name. change + the way infostr is xstrdupped. + + * gpgsm.c (main) [W32]: Make --prefer-system-dirmngr a dummy under + Windows. + +2007-08-13 Werner Koch + + * gpgsm.c (do_add_recipient): Add RECP_REQUIRED and make error + message depend on that. + (main): Add avriable RECP_REQUIRED, set ift for encryption + commands and pass it to do_add_recipient. + (our_pk_test_algo, our_cipher_test_algo, our_md_test_algo): Implement. + 2007-08-09 Werner Koch * gpgsm.c (main) [W32]: Enable CRL check by default. Modified: trunk/sm/call-dirmngr.c =================================================================== --- trunk/sm/call-dirmngr.c 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/sm/call-dirmngr.c 2007-08-14 16:50:27 UTC (rev 4559) @@ -34,8 +34,6 @@ #include "i18n.h" #include "keydb.h" -/* The name of the socket for a system daemon. */ -#define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket" struct membuf { size_t len; @@ -155,14 +153,23 @@ /* Note: if you change this to multiple connections, you also need to take care of the implicit option sending caching. */ +#ifdef HAVE_W32_SYSTEM + infostr = NULL; + opt.prefer_system_dirmngr = 1; +#else infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); - if (opt.prefer_system_dirmngr && !force_pipe_server - &&(!infostr || !*infostr)) +#endif /*HAVE_W32_SYSTEM*/ + if (infostr && !*infostr) + infostr = NULL; + else if (infostr) + infostr = xstrdup (infostr); + + if (opt.prefer_system_dirmngr && !force_pipe_server && !infostr) { - infostr = DEFAULT_SOCKET_NAME; + infostr = xstrdup (dirmngr_socket_name ()); try_default = 1; } - if (!infostr || !*infostr) + if (!infostr) { const char *pgmname; const char *argv[3]; @@ -206,8 +213,7 @@ int prot; int pid; - infostr = xstrdup (infostr); - if (!try_default && *infostr) + if (!try_default) { if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) { @@ -234,13 +240,20 @@ pid = -1; rc = assuan_socket_connect (&ctx, infostr, pid); +#ifdef HAVE_W32_SYSTEM + if (rc) + log_debug ("connecting dirmngr at `%s' failed\n", infostr); +#endif + xfree (infostr); +#ifndef HAVE_W32_SYSTEM if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED) { log_error (_("can't connect to the dirmngr - trying fall back\n")); force_pipe_server = 1; return start_dirmngr (); } +#endif /*!HAVE_W32_SYSTEM*/ } if (rc) Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2007-08-10 16:52:05 UTC (rev 4558) +++ trunk/sm/gpgsm.c 2007-08-14 16:50:27 UTC (rev 4559) @@ -491,25 +491,65 @@ static estream_t open_es_fwrite (const char *filename); static void run_protect_tool (int argc, char **argv); +/* Remove this if libgcrypt 1.3.0 is required. */ +#define MY_GCRY_PK_ECDSA 301 + static int our_pk_test_algo (int algo) { - return 1; + switch (algo) + { + case GCRY_PK_RSA: + case MY_GCRY_PK_ECDSA: + return gcry_pk_test_algo (algo); + default: + return 1; + } } static int our_cipher_test_algo (int algo) { - return 1; + switch (algo) + { + case GCRY_CIPHER_3DES: + case GCRY_CIPHER_AES128: + case GCRY_CIPHER_AES192: + case GCRY_CIPHER_AES256: + case GCRY_CIPHER_SERPENT128: + case GCRY_CIPHER_SERPENT192: + case GCRY_CIPHER_SERPENT256: + case 309 /*GCRY_CIPHER_SEED*/: + case 310 /*GCRY_CIPHER_CAMELLIA128*/: + case 311 /*GCRY_CIPHER_CAMELLIA192*/: + case 312 /*GCRY_CIPHER_CAMELLIA256*/: + return gcry_cipher_test_algo (algo); + default: + return 1; + } } + static int our_md_test_algo (int algo) { - return 1; + switch (algo) + { + case GCRY_MD_MD5: + case GCRY_MD_SHA1: + case GCRY_MD_RMD160: + case GCRY_MD_SHA256: + case GCRY_MD_SHA384: + case GCRY_MD_SHA512: + case 305 /*GCRY_MD_WHIRLPOOL*/: + return gcry_md_test_algo (algo); + default: + return 1; + } } + static const char * my_strusage( int level ) { @@ -571,12 +611,12 @@ gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */ } - for (i=1; i < 110; i++ ) + for (i=1; i < 400; i++ ) if (!chkf(i)) n += strlen(mapf(i)) + 2; list = xmalloc (21 + n); *list = 0; - for (p=NULL, i=1; i < 110; i++) + for (p=NULL, i=1; i < 400; i++) { if (!chkf(i)) { @@ -683,13 +723,15 @@ /* Helper to add recipients to a list. */ static void do_add_recipient (ctrl_t ctrl, const char *name, - certlist_t *recplist, int is_encrypt_to) + certlist_t *recplist, int is_encrypt_to, int recp_required) { int rc = gpgsm_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to); if (rc) { - log_error (_("can't encrypt to `%s': %s\n"), name, gpg_strerror (rc)); - gpgsm_status2 (ctrl, STATUS_INV_RECP, + if (recp_required) + { + log_error ("can't encrypt to `%s': %s\n", name, gpg_strerror (rc)); + gpgsm_status2 (ctrl, STATUS_INV_RECP, gpg_err_code (rc) == -1? "1": gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": @@ -701,6 +743,10 @@ gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8": "0", name, NULL); + } + else + log_info (_("NOTE: won't be able to encrypt to `%s': %s\n"), + name, gpg_strerror (rc)); } } @@ -747,6 +793,7 @@ certlist_t recplist = NULL; certlist_t signerlist = NULL; int do_not_setup_keys = 0; + int recp_required = 0; /*mtrace();*/ @@ -943,9 +990,13 @@ set_cmd (&cmd, pargs.r_opt); break; + case aEncr: + recp_required = 1; + set_cmd (&cmd, pargs.r_opt); + break; + case aSym: case aDecrypt: - case aEncr: case aSign: case aClearsign: case aVerify: @@ -1295,6 +1346,22 @@ opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.2"; else if (!strcmp (opt.def_cipher_algoid, "AES256") ) opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.42"; + else if (!strcmp (opt.def_cipher_algoid, "SERPENT") + || !strcmp (opt.def_cipher_algoid, "SERPENT128") ) + opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.2"; + else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") ) + opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.22"; + else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") ) + opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.42"; + else if (!strcmp (opt.def_cipher_algoid, "SEED") ) + opt.def_cipher_algoid = "1.2.410.200004.1.4"; + else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA") + || !strcmp (opt.def_cipher_algoid, "CAMELLIA128") ) + opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.2"; + else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA192") ) + opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.3"; + else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA256") ) + opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.4"; if (cmd != aGPGConfList) { @@ -1384,12 +1451,12 @@ complain about no (regular) recipients. */ for (sl = remusr; sl; sl = sl->next) if (!(sl->flags & 1)) - do_add_recipient (&ctrl, sl->d, &recplist, 0); + do_add_recipient (&ctrl, sl->d, &recplist, 0, recp_required); if (!opt.no_encrypt_to) { for (sl = remusr; sl; sl = sl->next) if ((sl->flags & 1)) - do_add_recipient (&ctrl, sl->d, &recplist, 1); + do_add_recipient (&ctrl, sl->d, &recplist, 1, recp_required); } } @@ -1428,8 +1495,10 @@ GC_OPT_FLAG_NONE ); printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE ); +#ifndef HAVE_W32_SYSTEM printf ("prefer-system-dirmngr:%lu:\n", GC_OPT_FLAG_NONE ); +#endif printf ("cipher-algo:%lu:\"3DES:\n", GC_OPT_FLAG_DEFAULT ); printf ("p12-charset:%lu:\n", From cvs at cvs.gnupg.org Tue Aug 14 19:40:57 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 14 Aug 2007 19:40:57 +0200 Subject: [svn] dirmngr - r262 - in trunk: . doc src Message-ID: Author: wk Date: 2007-08-14 19:40:27 +0200 (Tue, 14 Aug 2007) New Revision: 262 Modified: trunk/ChangeLog trunk/doc/yat2m.c trunk/src/ChangeLog trunk/src/get-path.c Log: Changed the default path for the socket. Updated yat2m. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-13 13:32:46 UTC (rev 261) +++ trunk/ChangeLog 2007-08-14 17:40:27 UTC (rev 262) @@ -1,3 +1,7 @@ +2007-08-14 Werner Koch + + * doc/yat2m.c: Updated from current GnuPG SVN. + 2007-08-12 Werner Koch * doc/Makefile.am (yat2m): Change the way this helper is build. Modified: trunk/doc/yat2m.c =================================================================== --- trunk/doc/yat2m.c 2007-08-13 13:32:46 UTC (rev 261) +++ trunk/doc/yat2m.c 2007-08-14 17:40:27 UTC (rev 262) @@ -4,7 +4,7 @@ * * This program 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -13,9 +13,7 @@ * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. + * along with this program; if not, see . */ /* @@ -105,11 +103,27 @@ static const char *opt_include; static int opt_store; +/* The only define we understand is -D gpgone. Thus we need a simple + boolean tro track it. */ +static int gpgone_defined; /* Flag to keep track whether any error occurred. */ static int any_error; +/* Object to keep macro definitions. */ +struct macro_s +{ + struct macro_s *next; + char *value; /* Malloced value. */ + char name[1]; +}; +typedef struct macro_s *macro_t; + +/* List of all defined macros. */ +static macro_t macrolist; + + /* Object to store one line of content. */ struct line_buffer_s { @@ -435,7 +449,7 @@ { "code", 0, "\\fB", "\\fR" }, { "sc", 0, "\\fB", "\\fR" }, { "var", 0, "\\fI", "\\fR" }, - { "samp", 0, "\n'", "'\n" }, + { "samp", 0, "'", "'" }, { "file", 0, "`\\fI","\\fR'" }, { "env", 0, "`\\fI","\\fR'" }, { "acronym", 0 }, @@ -456,7 +470,6 @@ { "opindex", 1 }, { "cpindex", 1 }, { "cindex", 1 }, - { "node", 1 }, { "noindent", 0 }, { "section", 1 }, { "chapter", 1 }, @@ -465,10 +478,10 @@ { "item", 2, ".TP\n.B " }, { "itemx", 2, ".TP\n.B " }, { "table", 3 }, + { "itemize", 3 }, + { "bullet", 0, "* " }, { "end", 4 }, { "quotation",1, ".RS\n\\fB" }, - { "ifset", 1 }, - { "ifclear", 1 }, { NULL } }; size_t n; @@ -523,11 +536,6 @@ { fputs ("\\fR\n.RE\n", fp); } - else if (n >= 5 && !memcmp (s, "ifset", 5) - && (!n || s[5] == ' ' || s[5] == '\t' || s[5] == '\n')) - { - fputs ("\\fR\n.RE\n", fp); - } /* Now throw away the entire line. */ s = memchr (rest, '\n', len); return s? (s-rest)+1 : len; @@ -555,8 +563,20 @@ } else { - inf ("texinfo command `%s' not supported (%.*s)", command, - ((s = memchr (rest, '\n', len)), (s? (s-rest) : len)), rest); + macro_t m; + + for (m = macrolist; m ; m = m->next) + if (!strcmp (m->name, command)) + break; + if (m) + { + proc_texi_buffer (fp, m->value, strlen (m->value), + table_level, eol_action); + ignore_args = 1; /* Parameterized macros are not yet supported. */ + } + else + inf ("texinfo command `%s' not supported (%.*s)", command, + ((s = memchr (rest, '\n', len)), (s? (s-rest) : len)), rest); } if (*rest == '{') @@ -658,6 +678,16 @@ else putc (*s, fp); } + + if (in_cmd > 1) + { + cmdbuf[cmdidx] = 0; + n = proc_texi_cmd (fp, cmdbuf, s, len, table_level, eol_action); + assert (n <= len); + s += n; len -= n; + s--; len++; + in_cmd = 0; + } } @@ -723,7 +753,7 @@ finish_page (void) { FILE *fp; - section_buffer_t sect; + section_buffer_t sect = NULL; int idx; const char *s; int i; @@ -812,10 +842,23 @@ { char *line; int lnr = 0; + /* Fixme: The follwing state variables don't carry over to include + files. */ int in_verbatim = 0; int skip_to_end = 0; /* Used to skip over menu entries. */ int skip_sect_line = 0; /* Skip after @mansect. */ + int ifset_nesting = 0; /* How often a ifset has been seen. */ + int ifclear_nesting = 0; /* How often a ifclear has been seen. */ + int in_gpgone = 0; /* Keep track of "@ifset gpgone" parts. */ + int not_in_gpgone = 0; /* Keep track of "@ifclear gpgone" parts. */ + int not_in_man = 0; /* Keep track of "@ifclear isman" parts. */ + /* Helper to define a macro. */ + char *macroname = NULL; + char *macrovalue = NULL; + size_t macrovaluesize = 0; + size_t macrovalueused = 0; + line = xmalloc (LINESIZE); while (fgets (line, LINESIZE, fp)) { @@ -826,12 +869,77 @@ lnr++; if (!n || line[n-1] != '\n') { - err ("%s:$d: trailing linefeed missing, line too long or " + err ("%s:%d: trailing linefeed missing, line too long or " "embedded Nul character", fname, lnr); break; } line[--n] = 0; + if (*line == '@') + { + for (p=line+1, n=1; *p && *p != ' ' && *p != '\t'; p++) + n++; + while (*p == ' ' || *p == '\t') + p++; + } + else + p = line; + + /* Take action on macro. */ + if (macroname) + { + if (n == 4 && !memcmp (line, "@end", 4) + && (line[4]==' '||line[4]=='\t'||!line[4]) + && !strncmp (p, "macro", 5) + && (p[5]==' '||p[5]=='\t'||!p[5])) + { + macro_t m; + + if (macrovalueused) + macrovalue[--macrovalueused] = 0; /* Kill the last LF. */ + macrovalue[macrovalueused] = 0; /* Terminate macro. */ + macrovalue = xrealloc (macrovalue, macrovalueused+1); + + for (m= macrolist; m; m = m->next) + if (!strcmp (m->name, macroname)) + break; + if (m) + free (m->value); + else + { + m = xcalloc (1, sizeof *m + strlen (macroname)); + strcpy (m->name, macroname); + m->next = macrolist; + macrolist = m; + } + m->value = macrovalue; + macrovalue = NULL; + free (macroname); + macroname = NULL; + } + else + { + if (macrovalueused + strlen (line) + 2 >= macrovaluesize) + { + macrovaluesize += strlen (line) + 256; + macrovalue = xrealloc (macrovalue, macrovaluesize); + } + strcpy (macrovalue+macrovalueused, line); + macrovalueused += strlen (line); + macrovalue[macrovalueused++] = '\n'; + } + continue; + } + + + if (n >= 5 && !memcmp (line, "@node", 5) + && (line[5]==' '||line[5]=='\t'||!line[5])) + { + /* Completey ignore @node lines. */ + continue; + } + + if (skip_sect_line) { skip_sect_line = 0; @@ -845,37 +953,116 @@ few macros used to control this as well as one @ifset command. Parts we know about are saved away into containers separate for each section. */ + + /* First process ifset/ifclear commands. */ if (*line == '@') { - for (p=line+1, n=1; *p && *p != ' ' && *p != '\t'; p++) - n++; - while (*p == ' ' || *p == '\t') - p++; + if (n == 6 && !memcmp (line, "@ifset", 6) + && (line[6]==' '||line[6]=='\t')) + { + ifset_nesting++; + if (!strncmp (p, "manverb", 7) && (p[7]==' '||p[7]=='\t'||!p[7])) + { + if (in_verbatim) + err ("%s:%d: nested \"@ifset manverb\"", fname, lnr); + else + in_verbatim = ifset_nesting; + } + else if (!strncmp (p, "gpgone", 6) + && (p[6]==' '||p[6]=='\t'||!p[6])) + { + if (in_gpgone) + err ("%s:%d: nested \"@ifset gpgone\"", fname, lnr); + else + in_gpgone = ifset_nesting; + } + continue; + } + else if (n == 4 && !memcmp (line, "@end", 4) + && (line[4]==' '||line[4]=='\t') + && !strncmp (p, "ifset", 5) + && (p[5]==' '||p[5]=='\t'||!p[5])) + { + if (in_verbatim && ifset_nesting == in_verbatim) + in_verbatim = 0; + if (in_gpgone && ifset_nesting == in_gpgone) + in_gpgone = 0; + + if (ifset_nesting) + ifset_nesting--; + else + err ("%s:%d: unbalanced \"@end ifset\"", fname, lnr); + continue; + } + else if (n == 8 && !memcmp (line, "@ifclear", 8) + && (line[8]==' '||line[8]=='\t')) + { + ifclear_nesting++; + + if (!strncmp (p, "gpgone", 6) + && (p[6]==' '||p[6]=='\t'||!p[6])) + { + if (not_in_gpgone) + err ("%s:%d: nested \"@ifclear gpgone\"", fname, lnr); + else + not_in_gpgone = ifclear_nesting; + } + + else if (!strncmp (p, "isman", 5) + && (p[5]==' '||p[5]=='\t'||!p[5])) + { + if (not_in_man) + err ("%s:%d: nested \"@ifclear isman\"", fname, lnr); + else + not_in_man = ifclear_nesting; + } + + continue; + } + else if (n == 4 && !memcmp (line, "@end", 4) + && (line[4]==' '||line[4]=='\t') + && !strncmp (p, "ifclear", 7) + && (p[7]==' '||p[7]=='\t'||!p[7])) + { + if (not_in_gpgone && ifclear_nesting == not_in_gpgone) + not_in_gpgone = 0; + if (not_in_man && ifclear_nesting == not_in_man) + not_in_man = 0; + + if (ifclear_nesting) + ifclear_nesting--; + else + err ("%s:%d: unbalanced \"@end ifclear\"", fname, lnr); + continue; + } + } + + /* Take action on ifset/ifclear. */ + if ( (in_gpgone && !gpgone_defined) + || (not_in_gpgone && gpgone_defined) + || not_in_man) + continue; + + /* Process commands. */ + if (*line == '@') + { if (skip_to_end && n == 4 && !memcmp (line, "@end", 4) && (line[4]==' '||line[4]=='\t'||!line[4])) { skip_to_end = 0; } - else if (n == 6 && !memcmp (line, "@ifset", 6) - && !strncmp (p, "manverb", 7) && (p[7]==' '||p[7]=='\t'||!p[7])) + else if (in_verbatim) { - if (in_verbatim) - err ("%s:%d: nested \"@ifset manverb\"", fname, lnr); - else - in_verbatim = 1; + got_line = 1; } - else if (in_verbatim && n == 4 && !memcmp (line, "@end", 4) - && !strncmp (p, "ifset", 5) - && (p[5]==' '||p[5]=='\t'||!p[5])) + else if (n == 6 && !memcmp (line, "@macro", 6)) { - in_verbatim = 0; + macroname = xstrdup (p); + macrovalue = xmalloc ((macrovaluesize = 1024)); + macrovalueused = 0; } - else if (in_verbatim) - { - got_line = 1; - } else if (n == 8 && !memcmp (line, "@manpage", 8)) { free (*section_name); @@ -919,11 +1106,6 @@ { skip_to_end = 1; } - else if (n == 8 && !memcmp (line, "@ifclear", 8) - && !strncmp (p, "isman", 5) && (p[5]==' '||p[5]=='\t'||!p[5])) - { - skip_to_end = 1; - } else if (n == 8 && !memcmp (line, "@include", 8) && (line[8]==' '||line[8]=='\t'||!line[8])) { @@ -952,6 +1134,11 @@ } free (incname); } + else if (n == 4 && !memcmp (line, "@bye", 4) + && (line[4]==' '||line[4]=='\t'||!line[4])) + { + break; + } else if (!skip_to_end) got_line = 1; } @@ -966,6 +1153,8 @@ } if (ferror (fp)) err ("%s:%d: read error: %s", fname, lnr, strerror (errno)); + free (macroname); + free (macrovalue); free (line); } @@ -975,6 +1164,14 @@ { char *section_name = NULL; /* Name of the current section or NULL if not in a section. */ + while (macrolist) + { + macro_t m = macrolist->next; + free (m->value); + free (m); + macrolist = m; + } + parse_file (fname, fp, §ion_name, 0); free (section_name); finish_page (); @@ -1013,7 +1210,8 @@ " --verbose enable extra informational output\n" " --debug enable additional debug output\n" " --help display this help and exit\n" - " -I DIR also search in include DIR\n\n" + " -I DIR also search in include DIR\n" + " -D gpgone the only useable define\n\n" "With no FILE, or when FILE is -, read standard input.\n\n" "Report bugs to ."); exit (0); @@ -1087,6 +1285,16 @@ argc--; argv++; } } + else if (!strcmp (*argv, "-D")) + { + argc--; argv++; + if (argc) + { + if (!strcmp (*argv, "gpgone")) + gpgone_defined = 1; + argc--; argv++; + } + } } if (argc > 1) Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-13 13:32:46 UTC (rev 261) +++ trunk/src/ChangeLog 2007-08-14 17:40:27 UTC (rev 262) @@ -1,3 +1,7 @@ +2007-08-14 Werner Koch + + * get-path.c (dirmngr_cachedir) [W32]: Use CSIDL_LOCAL_APPDATA. + 2007-08-13 Werner Koch * dirmngr.c (handle_connections): Use a timeout in the accept Modified: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-08-13 13:32:46 UTC (rev 261) +++ trunk/src/get-path.c 2007-08-14 17:40:27 UTC (rev 262) @@ -473,17 +473,28 @@ dirmngr_cachedir (void) { #ifdef HAVE_W32_SYSTEM - static char *name; + static const char *dir; - if (!name) + if (!dir) { - const char *s1, *s2; - s1 = w32_rootdir (); /* FIXME: /var in windows? */ - s2 = DIRSEP_S "cache" DIRSEP_S "dirmngr"; - name = xmalloc (strlen (s1) + strlen (s2) + 1); - strcpy (stpcpy (name, s1), s2); + char path[MAX_PATH]; + const char *s1; + + s1 = "\\GNU\\cache\\dirmngr"; + if (w32_shgetfolderpath (NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) + { + char *tmp = xmalloc (strlen (path) + strlen (s1) +1); + strcpy (stpcpy (tmp, path), s1); + dir = tmp; + + if (access (dir, F_OK)) + CreateDirectory (dir, NULL); + } + else + dir = "c:\\temp\\cache\\dirmngr"; } - return name; + return dir; #else /*!HAVE_W32_SYSTEM*/ return DIRMNGR_CACHEDIR; #endif /*!HAVE_W32_SYSTEM*/ From cvs at cvs.gnupg.org Thu Aug 16 12:26:26 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 12:26:26 +0200 Subject: [svn] w32pth - r12 - trunk Message-ID: Author: wk Date: 2007-08-16 12:25:57 +0200 (Thu, 16 Aug 2007) New Revision: 12 Modified: trunk/ChangeLog trunk/NEWS trunk/configure.ac trunk/w32-pth.c Log: About to release 2.0.1 Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-07-27 14:55:04 UTC (rev 11) +++ trunk/ChangeLog 2007-08-16 10:25:57 UTC (rev 12) @@ -1,3 +1,13 @@ +2007-08-16 Werner Koch + + Released 2.0.1. + + * configure.ac: Bump LT version to C0/A0/R1. + +2007-08-13 Werner Koch + + * w32-pth.c (pth_init): Allow setting of a debug file. + 2007-07-27 Marcus Brinkmann * w32-pth.c (pth_select): Reimplement in terms of pth_select_ev. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-07-27 14:55:04 UTC (rev 11) +++ trunk/NEWS 2007-08-16 10:25:57 UTC (rev 12) @@ -1,3 +1,9 @@ +Noteworthy changes in version 2.0.1 (2007-08-16) +------------------------------------------------ + + * Fixes. Better support for select. + + Noteworthy changes in version 2.0.0 (2007-07-05) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-07-27 14:55:04 UTC (rev 11) +++ trunk/configure.ac 2007-08-16 10:25:57 UTC (rev 12) @@ -26,7 +26,7 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.0.0]) +m4_define([my_version], [2.0.1]) m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ @@ -41,7 +41,7 @@ # Please remember to document interface changes in the NEWS file. W32PTH_LT_CURRENT=0 W32PTH_LT_AGE=0 -W32PTH_LT_REVISION=0 +W32PTH_LT_REVISION=1 #------------------- # If the API is changed in an incompatible way: increment the next counter. W32PTH_CONFIG_API_VERSION=1 Modified: trunk/w32-pth.c =================================================================== --- trunk/w32-pth.c 2007-07-27 14:55:04 UTC (rev 11) +++ trunk/w32-pth.c 2007-08-16 10:25:57 UTC (rev 12) @@ -61,6 +61,7 @@ /* Keeps the current debug level. Define marcos to test them. */ static int debug_level; +static FILE *dbgfp; #define DBG_ERROR (debug_level >= 1) #define DBG_INFO (debug_level >= 2) #define DBG_CALLS (debug_level >= 3) @@ -189,7 +190,7 @@ if (!h) { if (DBG_ERROR) - fprintf (stderr, "%s: CreateEvent failed: %s\n", + fprintf (dbgfp, "%s: CreateEvent failed: %s\n", log_get_prefix (NULL), w32_strerror (strerr, sizeof strerr)); return NULL; @@ -199,7 +200,7 @@ EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, 0 ) ) { if (DBG_ERROR) - fprintf (stderr, "%s: " + fprintf (dbgfp, "%s: " "setting synchronize for event object %p failed: %s\n", log_get_prefix (NULL), h, w32_strerror (strerr, sizeof strerr)); @@ -209,7 +210,7 @@ CloseHandle (h); if (DBG_INFO) { - fprintf (stderr, "%s: CreateEvent(%p) succeeded\n", + fprintf (dbgfp, "%s: CreateEvent(%p) succeeded\n", log_get_prefix (NULL), h2); } return h2; @@ -224,13 +225,13 @@ if (!SetEvent (h)) { if (DBG_ERROR) - fprintf (stderr, "%s: SetEvent(%p) failed: %s\n", + fprintf (dbgfp, "%s: SetEvent(%p) failed: %s\n", log_get_prefix (NULL), h, w32_strerror (strerr, sizeof strerr)); } else if (DBG_INFO) { - fprintf (stderr, "%s: SetEvent(%p) succeeded\n", + fprintf (dbgfp, "%s: SetEvent(%p) succeeded\n", log_get_prefix (NULL), h); } } @@ -243,13 +244,13 @@ if (!ResetEvent (h)) { if (DBG_ERROR) - fprintf (stderr, "%s: ResetEvent(%p) failed: %s\n", + fprintf (dbgfp, "%s: ResetEvent(%p) failed: %s\n", log_get_prefix (NULL), h, w32_strerror (strerr, sizeof strerr)); } else if (DBG_INFO) { - fprintf (stderr, "%s: ResetEvent(%p) succeeded\n", + fprintf (dbgfp, "%s: ResetEvent(%p) succeeded\n", log_get_prefix (NULL), h); } } @@ -272,14 +273,14 @@ if (!h) { if (DBG_ERROR) - fprintf (stderr, "%s: CreateWaitableTimer failed: %s\n", + fprintf (dbgfp, "%s: CreateWaitableTimer failed: %s\n", log_get_prefix (NULL), w32_strerror (strerr, sizeof strerr)); return NULL; } if (DBG_INFO) { - fprintf (stderr, "%s: CreateWaitableTimer(%p) succeeded\n", + fprintf (dbgfp, "%s: CreateWaitableTimer(%p) succeeded\n", log_get_prefix (NULL), h); } return h; @@ -290,14 +291,38 @@ pth_init (void) { WSADATA wsadat; - const char *s; - + const char *s, *s1, *s2; + char *p; + if (pth_initialized) return TRUE; - debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0; + s = getenv ("PTH_DEBUG"); + if (s) + { + debug_level = atoi (s); + s1 = strchr (s, ';'); + if (s1) + { + s1++; + if (!(s2 = strchr (s1, ';'))) + s2 = s1 + strlen (s1); + p = malloc (s2 - s1 + 1); + if (p) + { + memcpy (p, s1, s2-s1); + p[s2-s1] = 0; + dbgfp = fopen (p, "a"); + if (dbgfp) + setvbuf (dbgfp, NULL, _IOLBF, 0); + free (p); + } + } + } + if (!dbgfp) + dbgfp = stderr; if (debug_level) - fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); + fprintf (dbgfp, "%s: pth_init: called.\n", log_get_prefix (NULL)); if (WSAStartup (0x202, &wsadat)) return FALSE; @@ -339,7 +364,7 @@ /* Fixme: I am not sure whether the same thread my enter a critical section twice. */ if (DBG_CALLS) - fprintf (stderr, "%s: enter_pth (%s)\n", + fprintf (dbgfp, "%s: enter_pth (%s)\n", log_get_prefix (NULL), function? function:""); LeaveCriticalSection (&pth_shd); } @@ -350,7 +375,7 @@ { EnterCriticalSection (&pth_shd); if (DBG_CALLS) - fprintf (stderr, "%s: leave_pth (%s)\n", + fprintf (dbgfp, "%s: leave_pth (%s)\n", log_get_prefix (NULL), function? function:""); } @@ -417,7 +442,7 @@ char strerr[256]; if (DBG_ERROR) - fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", + fprintf (dbgfp, "%s: pth_read(%d) failed read from file: %s\n", log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); n = -1; @@ -458,7 +483,7 @@ if (!n) { if (DBG_ERROR) - fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", + fprintf (dbgfp, "%s: pth_write(%d) failed in write: %s\n", log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); n = -1; @@ -471,7 +496,7 @@ char strerr[256]; if (DBG_ERROR) - fprintf (stderr, "%s: pth_write(%d) failed in send: %s\n", + fprintf (dbgfp, "%s: pth_write(%d) failed in send: %s\n", log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); n = -1; @@ -488,14 +513,14 @@ if (!ev) { - fprintf (stderr, "show_event_ring(%s): No ring\n", text); + fprintf (dbgfp, "show_event_ring(%s): No ring\n", text); return; } r = ev; do { - fprintf (stderr, "show_event_ring(%s): type=%d r=%p prev=%p next=%p\n", + fprintf (dbgfp, "show_event_ring(%s): type=%d r=%p prev=%p next=%p\n", text, r->u_type, r, r->prev, r->next); } while (r=r->next, r != ev); @@ -717,7 +742,7 @@ char strerr[256]; if (DBG_ERROR) - fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", + fprintf (dbgfp, "%s: pth_release_mutex %p failed: %s\n", log_get_prefix (NULL), *mutex, w32_strerror (strerr, sizeof strerr)); rc = FALSE; @@ -749,7 +774,7 @@ char strerr[256]; if (DBG_ERROR) - fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", + fprintf (dbgfp, "%s: pth_mutex_acquire for %p failed: %s\n", log_get_prefix (NULL), *mutex, w32_strerror (strerr, sizeof strerr)); } @@ -762,7 +787,7 @@ default: if (DBG_ERROR) - fprintf (stderr, "%s: WaitForSingleObject returned unexpected " + fprintf (dbgfp, "%s: WaitForSingleObject returned unexpected " "code %d for mutex %p\n", log_get_prefix (NULL), code, *mutex); rc = FALSE; @@ -865,7 +890,7 @@ { hd->flags |= PTH_ATTR_JOINABLE; if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", + fprintf (dbgfp, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", log_get_prefix (NULL)); } break; @@ -877,7 +902,7 @@ hd->flags |= PTH_ATTR_STACK_SIZE; hd->stack_size = val; if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", + fprintf (dbgfp, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", log_get_prefix (NULL), val); } break; @@ -893,7 +918,7 @@ return FALSE; hd->flags |= PTH_ATTR_NAME; if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", + fprintf (dbgfp, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", log_get_prefix (NULL), hd->name); } break; @@ -939,14 +964,14 @@ FIXME: We should not use W32's thread handle directly but keep our own thread control structure. CTX may be used for that. */ if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", + fprintf (dbgfp, "%s: do_pth_spawn creating thread ...\n", log_get_prefix (NULL)); th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)launch_thread, ctx, CREATE_SUSPENDED, &tid); ctx->th = th; if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn created thread %p\n", + fprintf (dbgfp, "%s: do_pth_spawn created thread %p\n", log_get_prefix (NULL),th); if (!th) free (ctx); @@ -1084,7 +1109,7 @@ /* Fixme: We can keep only track of one signal at a time. */ set_event (pth_signo_ev); if (DBG_INFO) - fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); + fprintf (dbgfp, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); return TRUE; } @@ -1127,13 +1152,13 @@ if ((spec & (PTH_MODE_CHAIN|PTH_MODE_REUSE))) { if (DBG_ERROR) - fprintf (stderr, "%s: pth_event spec=%lu - not supported\n", + fprintf (dbgfp, "%s: pth_event spec=%lu - not supported\n", log_get_prefix (NULL), spec); return NULL; /* Not supported. */ } if (DBG_INFO) - fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); + fprintf (dbgfp, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); ev = calloc (1, sizeof *ev); if (!ev) @@ -1170,7 +1195,7 @@ /* The signal handler is disabled for now. */ rc = 0/*SetConsoleCtrlHandler (sig_handler, TRUE)*/; if (DBG_INFO) - fprintf (stderr, "%s: pth_event: sigs rc=%d\n", + fprintf (dbgfp, "%s: pth_event: sigs rc=%d\n", log_get_prefix (NULL), rc); } else if (spec & PTH_EVENT_FD) @@ -1180,7 +1205,7 @@ ev->u_type = PTH_EVENT_FD; ev->u.fd = va_arg (arg, int); if (DBG_INFO) - fprintf (stderr, "%s: pth_event: fd=%d\n", + fprintf (dbgfp, "%s: pth_event: fd=%d\n", log_get_prefix (NULL), ev->u.fd); } else if (spec & PTH_EVENT_TIME) @@ -1220,7 +1245,7 @@ if (WSAEventSelect (fdarray[i].fd, ev->hd, fdarray[i].netevents)) { if (DBG_ERROR) - fprintf (stderr, + fprintf (dbgfp, "%s: pth_event: WSAEventSelect(%d[%d]) failed: %s\n", log_get_prefix (NULL), i, fdarray[i].fd, wsa_strerror (strerr, sizeof strerr)); @@ -1311,7 +1336,7 @@ { n = select (fd+1, &r, &w, NULL, &tv); if (DBG_INFO) - fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", + fprintf (dbgfp, "%s: wait_for_fd=%d fd %d (ec=%d)\n", log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); if (n == -1) break; @@ -1516,13 +1541,13 @@ sa.nLength = sizeof sa; if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", + fprintf (dbgfp, "%s: spawn_helper_thread creating thread ...\n", log_get_prefix (NULL)); th = CreateThread (&sa, 32*1024, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", + fprintf (dbgfp, "%s: spawn_helper_thread created thread %p\n", log_get_prefix (NULL), th); return th; @@ -1537,7 +1562,7 @@ wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); if (DBG_INFO) - fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); + fprintf (dbgfp, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); set_event (ev->hd); ExitThread (0); return NULL; @@ -1564,7 +1589,7 @@ return -1; if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); + fprintf (dbgfp, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); /* Set all events to pending. */ r = ev; @@ -1586,7 +1611,7 @@ { case PTH_EVENT_SIGS: if (DBG_INFO) - fprintf (stderr, "pth_wait: add signal event\n"); + fprintf (dbgfp, "pth_wait: add signal event\n"); /* Register the global signal event. */ evarray[pos] = r; waitbuf[pos++] = pth_signo_ev; @@ -1594,7 +1619,7 @@ case PTH_EVENT_FD: if (DBG_INFO) - fprintf (stderr, "pth_wait: spawn wait_fd_thread\n"); + fprintf (dbgfp, "pth_wait: spawn wait_fd_thread\n"); evarray[pos] = r; waitbuf[pos++] = r->hd; threadlist[thlstidx++] = spawn_helper_thread (wait_fd_thread, r); @@ -1602,7 +1627,7 @@ case PTH_EVENT_TIME: if (DBG_INFO) - fprintf (stderr, "pth_wait: adding timer event\n"); + fprintf (dbgfp, "pth_wait: adding timer event\n"); { LARGE_INTEGER ll; @@ -1611,7 +1636,7 @@ if (!SetWaitableTimer (r->hd, &ll, 0, NULL, NULL, FALSE)) { if (DBG_ERROR) - fprintf (stderr,"%s: %s: SetWaitableTimer failed: %s\n", + fprintf (dbgfp,"%s: %s: SetWaitableTimer failed: %s\n", log_get_prefix (NULL), __func__, w32_strerror (strerr, sizeof strerr)); return -1; @@ -1623,14 +1648,14 @@ case PTH_EVENT_SELECT: if (DBG_INFO) - fprintf (stderr, "pth_wait: adding select event\n"); + fprintf (dbgfp, "pth_wait: adding select event\n"); evarray[pos] = r; waitbuf[pos++] = r->hd; break; case PTH_EVENT_MUTEX: if (DBG_ERROR) - fprintf (stderr, "pth_wait: ignoring mutex event.\n"); + fprintf (dbgfp, "pth_wait: ignoring mutex event.\n"); break; } r = r->next; @@ -1639,10 +1664,10 @@ if (DBG_INFO) { - fprintf (stderr, "%s: pth_wait: WFMO n=%d\n", + fprintf (dbgfp, "%s: pth_wait: WFMO n=%d\n", log_get_prefix (NULL), pos); for (i=0; i < pos; i++) - fprintf (stderr, "%s: pth_wait: %d=%p\n", + fprintf (dbgfp, "%s: pth_wait: %d=%p\n", log_get_prefix (NULL), i, waitbuf[i]); } n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); @@ -1653,7 +1678,7 @@ for (i=0; i < thlstidx; i++) CloseHandle (threadlist[i]); if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: WFMO returned %ld\n", + fprintf (dbgfp, "%s: pth_wait: WFMO returned %ld\n", log_get_prefix (NULL), n); if (n >= 0 && n < pos) @@ -1668,7 +1693,7 @@ r = evarray[idx]; if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: setting %d ev=%p\n", + fprintf (dbgfp, "%s: pth_wait: setting %d ev=%p\n", __func__, idx, r); r->status = PTH_STATUS_OCCURRED; count++; @@ -1704,7 +1729,7 @@ if (WSAEnumNetworkEvents (fdarray[i].fd, NULL, &ne)) { if (DBG_ERROR) - fprintf (stderr, + fprintf (dbgfp, "%s: pth_wait: " "WSAEnumNetworkEvents(%d[%d]) failed: %s\n", log_get_prefix (NULL), i, fdarray[i].fd, @@ -1737,7 +1762,7 @@ if (WSAEventSelect (fdarray[i].fd, NULL, 0)) { if (DBG_ERROR) - fprintf (stderr, + fprintf (dbgfp, "%s: pth_wait: WSAEventSelect(%d[%d]-clear)" " failed: %s\n", log_get_prefix (NULL), i, fdarray[i].fd, @@ -1749,7 +1774,7 @@ == SOCKET_ERROR) { if (DBG_ERROR) - fprintf (stderr, + fprintf (dbgfp, "%s: pth_wait: ioctlsocket(%d[%d])" " failed: %s\n", log_get_prefix (NULL), i, fdarray[i].fd, @@ -1770,7 +1795,7 @@ reset_event (evarray[idx]->hd); } if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: %d events have been signalled\n", + fprintf (dbgfp, "%s: pth_wait: %d events have been signalled\n", log_get_prefix (NULL), count); return count; } From cvs at cvs.gnupg.org Thu Aug 16 12:39:10 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 12:39:10 +0200 Subject: [svn] w32pth - r13 - tags Message-ID: Author: wk Date: 2007-08-16 12:38:40 +0200 (Thu, 16 Aug 2007) New Revision: 13 Added: tags/w32pth-2.0.1/ Log: Released! Copied: tags/w32pth-2.0.1 (from rev 12, trunk) From cvs at cvs.gnupg.org Thu Aug 16 12:40:10 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 12:40:10 +0200 Subject: [svn] w32pth - r14 - trunk Message-ID: Author: wk Date: 2007-08-16 12:39:42 +0200 (Thu, 16 Aug 2007) New Revision: 14 Modified: trunk/NEWS trunk/configure.ac Log: post release version number bump Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-16 10:38:40 UTC (rev 13) +++ trunk/NEWS 2007-08-16 10:39:42 UTC (rev 14) @@ -1,3 +1,7 @@ +Noteworthy changes in version 2.0.2 +------------------------------------------------ + + Noteworthy changes in version 2.0.1 (2007-08-16) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-16 10:38:40 UTC (rev 13) +++ trunk/configure.ac 2007-08-16 10:39:42 UTC (rev 14) @@ -26,8 +26,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.0.1]) -m4_define([my_issvn], [no]) +m4_define([my_version], [2.0.2]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) From cvs at cvs.gnupg.org Thu Aug 16 12:58:04 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 12:58:04 +0200 Subject: [svn] GnuPG - r4562 - trunk Message-ID: Author: wk Date: 2007-08-16 12:57:35 +0200 (Thu, 16 Aug 2007) New Revision: 4562 Modified: trunk/NEWS trunk/configure.ac Log: Post release version number bump Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-16 10:52:41 UTC (rev 4561) +++ trunk/NEWS 2007-08-16 10:57:35 UTC (rev 4562) @@ -1,3 +1,7 @@ +Noteworthy changes in version 2.0.7 +------------------------------------------------ + + Noteworthy changes in version 2.0.6 (2007-08-16) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-16 10:52:41 UTC (rev 4561) +++ trunk/configure.ac 2007-08-16 10:57:35 UTC (rev 4562) @@ -24,8 +24,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.0.6]) -m4_define([my_issvn], [no]) +m4_define([my_version], [2.0.7]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ From cvs at cvs.gnupg.org Thu Aug 16 12:53:11 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 12:53:11 +0200 Subject: [svn] GnuPG - r4561 - tags Message-ID: Author: wk Date: 2007-08-16 12:52:41 +0200 (Thu, 16 Aug 2007) New Revision: 4561 Added: tags/gnupg-2.0.6/ Log: Released Copied: tags/gnupg-2.0.6 (from rev 4560, trunk) From cvs at cvs.gnupg.org Thu Aug 16 14:19:13 2007 From: cvs at cvs.gnupg.org (svn author mo) Date: Thu, 16 Aug 2007 14:19:13 +0200 Subject: [svn] GnuPG - r4563 - branches Message-ID: Author: mo Date: 2007-08-16 14:18:44 +0200 (Thu, 16 Aug 2007) New Revision: 4563 Added: branches/GNUPG-TRUNK-MO-HACKS/ Log: Creating new branch for moritz' hacks Copied: branches/GNUPG-TRUNK-MO-HACKS (from rev 4562, trunk) From cvs at cvs.gnupg.org Thu Aug 16 14:44:47 2007 From: cvs at cvs.gnupg.org (svn author mo) Date: Thu, 16 Aug 2007 14:44:47 +0200 Subject: [svn] GnuPG - r4564 - branches/GNUPG-TRUNK-MO-HACKS/scd Message-ID: Author: mo Date: 2007-08-16 14:44:17 +0200 (Thu, 16 Aug 2007) New Revision: 4564 Added: branches/GNUPG-TRUNK-MO-HACKS/scd/NOTES-STATUSFD branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.c branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.h Modified: branches/GNUPG-TRUNK-MO-HACKS/scd/ChangeLog branches/GNUPG-TRUNK-MO-HACKS/scd/Makefile.am branches/GNUPG-TRUNK-MO-HACKS/scd/command.c Log: Implemented the STATUSFD mechanism. 2007-08-16 Moritz Schulte * command.c: Include "statusfd.h". (cmd_statusfd): New function. (register_commands): New entry for STATUSFD command. (update_reader_status_file): Call statusfd_event_card_inserted and statusfd_event_card_removed on events. (scd_command_handler): Pass flags=3 to assuan_init_socket_server_ext (enabling fd passing). * statusfd.c, statusfd.h: New files. * Makefile.am (scdaemon_SOURCES): Added statusfd.c, statusfd.h. * NOTES-STATUSFD: New file. Modified: branches/GNUPG-TRUNK-MO-HACKS/scd/ChangeLog =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/ChangeLog 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) @@ -1,3 +1,16 @@ +2007-08-16 Moritz Schulte + + * command.c: Include "statusfd.h". + (cmd_statusfd): New function. + (register_commands): New entry for STATUSFD command. + (update_reader_status_file): Call statusfd_event_card_inserted and + statusfd_event_card_removed on events. + (scd_command_handler): Pass flags=3 to + assuan_init_socket_server_ext (enabling fd passing). + * statusfd.c, statusfd.h: New files. + * Makefile.am (scdaemon_SOURCES): Added statusfd.c, statusfd.h. + * NOTES-STATUSFD: New file. + 2007-08-07 Werner Koch * tlv.c, tlv.h: Move to ../common/. Modified: branches/GNUPG-TRUNK-MO-HACKS/scd/Makefile.am =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/Makefile.am 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/Makefile.am 2007-08-16 12:44:17 UTC (rev 4564) @@ -38,6 +38,7 @@ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ + statusfd.c statusfd.h \ app.c app-common.h app-help.c $(card_apps) Added: branches/GNUPG-TRUNK-MO-HACKS/scd/NOTES-STATUSFD =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/NOTES-STATUSFD 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/NOTES-STATUSFD 2007-08-16 12:44:17 UTC (rev 4564) @@ -0,0 +1,36 @@ +Description of the statusfd mechanism: + +Applications can now ask scdaemon to be notified about certain events +(card inserted/removed) on a specified file descriptor. + +This is how it works: + +Run gpg-agent in daemon mode. +Figure out scdaemons socket: + + +moritz at pink:~/g10/hacks/gnupg-mo/build/scd$ gpg-connect-agent +SCD GETINFO socket_name +D /tmp/gpg-QZRVNr/S.scdaemon +OK + +Connect to scdaemon and register a status file descriptor: + +moritz at pink:~/g10/hacks/gnupg-mo/build/scd$ gpg-connect-agent -S /tmp/gpg-QZRVNr/S.scdaemon +/sendfd /tmp/scd-events w +STATUSFD +OK +moritz at pink:~/g10/hacks/gnupg-mo/build/scd$ + + +Watch the log file as you remove/insert the smartcard: + +moritz at pink:~/g10/hacks/gnupg-mo/build/scd$ tail -f /tmp/scd-events +CARD REMOVED +CARD INSERTED +CARD REMOVED +CARD INSERTED +^C +moritz at pink:~/g10/hacks/gnupg-mo/build/scd$ + +That's it for now. Modified: branches/GNUPG-TRUNK-MO-HACKS/scd/command.c =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/command.c 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/command.c 2007-08-16 12:44:17 UTC (rev 4564) @@ -40,6 +40,7 @@ #ifdef HAVE_LIBUSB #include "ccid-driver.h" #endif +#include "statusfd.h" /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */ #define MAXLEN_PIN 100 @@ -1649,9 +1650,37 @@ return rc; } +/* STATUSFD + */ +static int +cmd_statusfd (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc; + int fd; + /* FIXME, moritz, locking? */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_LOCKED); + rc = assuan_receivefd (ctx, &fd); + if (rc) + /* FIXME, moritz, proper error message for client? */ + goto leave; + rc = statusfd_register (fd); + + leave: + + if (rc) + close (fd); + + return rc; +} + + + + /* Tell the assuan library about our commands */ static int @@ -1683,6 +1712,7 @@ { "GETINFO", cmd_getinfo }, { "RESTART", cmd_restart }, { "APDU", cmd_apdu }, + { "STATUSFD", cmd_statusfd }, { NULL } }; int i, rc; @@ -1719,7 +1749,7 @@ } else { - rc = assuan_init_socket_server_ext (&ctx, fd, 2); + rc = assuan_init_socket_server_ext (&ctx, fd, 3); } if (rc) { @@ -1880,6 +1910,15 @@ log_info ("updating status of slot %d to 0x%04X\n", ss->slot, status); + { + /* Broadcast on statusfds. */ + + if ((! (ss->status & 2)) && (status & 2)) + statusfd_event_card_inserted (0); + if ((ss->status & 2) && (! (status & 2))) + statusfd_event_card_removed (0); + } + /* FIXME: Should this be IDX instead of ss->slot? This depends on how client sessions will associate the reader status with their session. */ Added: branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.c =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.c 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.c 2007-08-16 12:44:17 UTC (rev 4564) @@ -0,0 +1,139 @@ +/* statusfd.c - SCdaemon status fd handling + * Copyright (C) 2007 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 3 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, see . + */ + +/* AUTHOR: Moritz Schulte . */ + +#include +#include +#include +#include +#include +#include + +#include "scdaemon.h" +#include "statusfd.h" + +struct statusfd_s +{ + FILE *stream; + struct statusfd_s *next, **prevp; +}; + +typedef struct statusfd_s *statusfd_t; + +static statusfd_t statusfd_list; + + + +static int +statusfd_add (FILE *stream) +{ + statusfd_t statusfd_obj; + int rc; + + statusfd_obj = xtrymalloc (sizeof (*statusfd_obj)); + + if (statusfd_obj) + { + statusfd_obj->stream = stream; + statusfd_obj->next = statusfd_list; + statusfd_obj->prevp = &statusfd_list; + if (statusfd_list) + statusfd_list->prevp = &statusfd_obj->next; + statusfd_list = statusfd_obj; + rc = 0; + } + else + rc = gpg_error_from_syserror (); + + return rc; +} + +static void +statusfd_remove (statusfd_t statusfd) +{ + *statusfd->prevp = statusfd->next; + if (statusfd->next) + statusfd->next->prevp = statusfd->prevp; + + xfree (statusfd); +} + +static void +statusfd_broadcast (const char *fmt, ...) +{ + statusfd_t statusfd = statusfd_list; + statusfd_t statusfd_next; + int ret; + va_list ap; + + va_start (ap, fmt); + + while (statusfd) + { + ret = vfprintf (statusfd->stream, fmt, ap); + if (ret >= 0) + ret = fflush (statusfd->stream); + + if (ret < 0) + { + /* Error on this statusfd stream, remove it. */ + /* FIXME: only remove on certain errros? -moritz */ + + statusfd_next = statusfd->next; + statusfd_remove (statusfd); + statusfd = statusfd_next; + continue; + } + + statusfd = statusfd->next; + } + + va_end (ap); +} + +int +statusfd_register (int fd) +{ + FILE *stream; + int rc; + + stream = fdopen (fd, "a"); + if (! stream) + rc = gpg_error_from_syserror (); + else + rc = statusfd_add (stream); + + if (rc && stream) + fclose (stream); + + return rc; +} + +void +statusfd_event_card_inserted (int slot) +{ + statusfd_broadcast ("CARD INSERTED\n"); +} + +void +statusfd_event_card_removed (int slot) +{ + statusfd_broadcast ("CARD REMOVED\n"); +} Added: branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.h =================================================================== --- branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.h 2007-08-16 12:18:44 UTC (rev 4563) +++ branches/GNUPG-TRUNK-MO-HACKS/scd/statusfd.h 2007-08-16 12:44:17 UTC (rev 4564) @@ -0,0 +1,28 @@ +/* statusfd.h - SCdaemon status fd handling + * Copyright (C) 2007 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 3 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, see . + */ + + +#ifndef GNUPG_SCD_STATUSFD_H +#define GNUPG_SCD_STATUSFD_H + +int statusfd_register (int fd); +void statusfd_event_card_inserted (int slot); +void statusfd_event_card_removed (int slot); + +#endif From cvs at cvs.gnupg.org Thu Aug 16 15:46:04 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 15:46:04 +0200 Subject: [svn] dirmngr - r264 - tags Message-ID: Author: wk Date: 2007-08-16 15:45:35 +0200 (Thu, 16 Aug 2007) New Revision: 264 Added: tags/dirmngr-1.0.1/ Log: Released Copied: tags/dirmngr-1.0.1 (from rev 263, trunk) From cvs at cvs.gnupg.org Thu Aug 16 15:49:34 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 16 Aug 2007 15:49:34 +0200 Subject: [svn] dirmngr - r265 - trunk Message-ID: Author: wk Date: 2007-08-16 15:49:05 +0200 (Thu, 16 Aug 2007) New Revision: 265 Modified: trunk/NEWS trunk/configure.ac Log: Post release version number bump Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-16 13:45:35 UTC (rev 264) +++ trunk/NEWS 2007-08-16 13:49:05 UTC (rev 265) @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.0.2 +------------------------------------------------ + + Noteworthy changes in version 1.0.1 (2007-08-16) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-16 13:45:35 UTC (rev 264) +++ trunk/configure.ac 2007-08-16 13:49:05 UTC (rev 265) @@ -26,8 +26,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.0.1]) -m4_define([my_issvn], [no]) +m4_define([my_version], [1.0.2]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) From cvs at cvs.gnupg.org Mon Aug 20 18:12:41 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 20 Aug 2007 18:12:41 +0200 Subject: [svn] gpgme - r1245 - trunk/gpgme Message-ID: Author: marcus Date: 2007-08-20 18:12:07 +0200 (Mon, 20 Aug 2007) New Revision: 1245 Modified: trunk/gpgme/ChangeLog trunk/gpgme/gpgme.h Log: 2007-08-20 Marcus Brinkmann * gpgme.h: Move include of gpg-error.h out of extern "C". Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-08-07 15:21:50 UTC (rev 1244) +++ trunk/gpgme/ChangeLog 2007-08-20 16:12:07 UTC (rev 1245) @@ -1,3 +1,7 @@ +2007-08-20 Marcus Brinkmann + + * gpgme.h: Move include of gpg-error.h out of extern "C". + 2007-08-07 Werner Koch * gpgme.h (struct _gpgme_signature): Add member CHAIN_MODEL. Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-08-07 15:21:50 UTC (rev 1244) +++ trunk/gpgme/gpgme.h 2007-08-20 16:12:07 UTC (rev 1245) @@ -40,6 +40,8 @@ # include #endif +#include + #ifdef __cplusplus extern "C" { #if 0 /* just to make Emacs auto-indent happy */ @@ -47,7 +49,6 @@ #endif #endif /* __cplusplus */ -#include /* Check for compiler features. */ From cvs at cvs.gnupg.org Tue Aug 21 17:10:29 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 21 Aug 2007 17:10:29 +0200 Subject: [svn] gpgme - r1246 - trunk Message-ID: Author: marcus Date: 2007-08-21 17:09:59 +0200 (Tue, 21 Aug 2007) New Revision: 1246 Modified: trunk/ChangeLog trunk/configure.ac Log: 2007-08-21 Marcus Brinkmann * configure.ac (--enable-w32-glib): Use --enableval, not --withval. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-20 16:12:07 UTC (rev 1245) +++ trunk/ChangeLog 2007-08-21 15:09:59 UTC (rev 1246) @@ -1,3 +1,8 @@ +2007-08-21 Marcus Brinkmann + + * configure.ac (--enable-w32-glib): Use --enableval, not + --withval. + 2007-07-16 Marcus Brinkmann * assuan/assuan-socket.c (_assuan_close): Always use close(). Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-20 16:12:07 UTC (rev 1245) +++ trunk/configure.ac 2007-08-21 15:09:59 UTC (rev 1246) @@ -159,7 +159,7 @@ AM_PATH_GLIB_2_0 AC_ARG_ENABLE(w32-glib, AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), - build_w32_glib=$withval) + build_w32_glib=enableval) AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes) AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") From cvs at cvs.gnupg.org Wed Aug 22 00:03:36 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 00:03:36 +0200 Subject: [svn] GPGol - r173 - in trunk: po src Message-ID: Author: wk Date: 2007-08-22 00:03:05 +0200 (Wed, 22 Aug 2007) New Revision: 173 Modified: trunk/po/de.po trunk/po/sv.po trunk/src/ChangeLog trunk/src/w32-gettext.c Log: Portability fixed in the laguage codes Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-08-13 15:02:04 UTC (rev 172) +++ trunk/po/de.po 2007-08-21 22:03:05 UTC (rev 173) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol 0.9.4\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-08-03 18:07+0200\n" +"POT-Creation-Date: 2007-08-21 23:43+0200\n" "PO-Revision-Date: 2007-04-13 12:55+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" @@ -23,62 +23,62 @@ msgid "Select GPG Key Manager" msgstr "Das Schl?sselverwaltungsprogramm festlegen" -#: src/engine-gpgme.c:991 +#: src/engine-gpgme.c:1004 msgid "Fingerprint: " msgstr "Fingerabdruck: " -#: src/engine-gpgme.c:1048 +#: src/engine-gpgme.c:1061 msgid "This signature is valid\n" msgstr "Diese Unterschrift ist korrekt\n" -#: src/engine-gpgme.c:1050 +#: src/engine-gpgme.c:1063 msgid "signature state is \"green\"\n" msgstr "Status der Unterschrift ist \"gr?n\"\n" -#: src/engine-gpgme.c:1052 +#: src/engine-gpgme.c:1065 msgid "signature state is \"red\"\n" msgstr "Status der Unterschrift ist \"rot\"\n" -#: src/engine-gpgme.c:1056 +#: src/engine-gpgme.c:1069 msgid "Warning: One of the keys has been revoked\n" msgstr "Warnung: Einer der Schl?ssel wurde widerrufen\n" -#: src/engine-gpgme.c:1066 +#: src/engine-gpgme.c:1079 msgid "Warning: The key used to create the signature expired at: " msgstr "" "Warnung: Der Schl?ssel mit der diese Unterschrift erzeugt wurde verfiel am: " -#: src/engine-gpgme.c:1072 +#: src/engine-gpgme.c:1085 msgid "Warning: At least one certification key has expired\n" msgstr "" "Warnung: Mindestens einer der Zertifizierungsschl?ssel ist abgelaufen\n" -#: src/engine-gpgme.c:1078 +#: src/engine-gpgme.c:1091 msgid "Warning: The signature expired at: " msgstr "Die Unterschrift verfiel am: " -#: src/engine-gpgme.c:1084 +#: src/engine-gpgme.c:1097 msgid "Can't verify due to a missing key or certificate\n" msgstr "" "Aufrund eines fehlenden Schl?ssels ist eine ?berpr?fung nicht m?glich\n" -#: src/engine-gpgme.c:1088 +#: src/engine-gpgme.c:1101 msgid "The CRL is not available\n" msgstr "Die CRL ist nicht verf?gbar\n" -#: src/engine-gpgme.c:1094 +#: src/engine-gpgme.c:1107 msgid "Available CRL is too old\n" msgstr "Die vorhandene CRL ist zu alt\n" -#: src/engine-gpgme.c:1099 +#: src/engine-gpgme.c:1112 msgid "A policy requirement was not met\n" msgstr "Eine Richtlinie wurde nicht erf?llt\n" -#: src/engine-gpgme.c:1105 +#: src/engine-gpgme.c:1118 msgid "A system error occured" msgstr "Ein Systemfehler ist aufgetreten" -#: src/engine-gpgme.c:1142 +#: src/engine-gpgme.c:1155 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -86,12 +86,12 @@ "WARNUNG: Es gibt keinen Hinweis darauf, ob der Schl?ssel wirklich der Person " "geh?rt, die oben angezeigt ist\n" -#: src/engine-gpgme.c:1149 +#: src/engine-gpgme.c:1162 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" msgstr "" "WARNUNG: Der Schl?ssel geh?rt NICHT der Person die oben angezeigt ist\n" -#: src/engine-gpgme.c:1153 +#: src/engine-gpgme.c:1166 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -99,43 +99,43 @@ "WARNING: Es ist nicht sicher, da? der Schl?ssel der Person geh?rt, die oben " "angezeigt ist\n" -#: src/engine-gpgme.c:1186 +#: src/engine-gpgme.c:1199 msgid "Verification started at: " msgstr "?berpr?fung begann am: " -#: src/engine-gpgme.c:1191 +#: src/engine-gpgme.c:1204 msgid "Verification result for: " msgstr "Pr?fungsresultat f?r: " -#: src/engine-gpgme.c:1192 +#: src/engine-gpgme.c:1205 msgid "[unnamed part]" msgstr "[Unbenannter Teil]" -#: src/engine-gpgme.c:1210 src/engine-gpgme.c:1240 +#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253 msgid "Good signature from: " msgstr "Korrekte Unterschrift von: " -#: src/engine-gpgme.c:1217 +#: src/engine-gpgme.c:1230 msgid " aka: " msgstr " alias: " -#: src/engine-gpgme.c:1221 src/engine-gpgme.c:1243 +#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256 msgid " created: " msgstr " erzeugt: " -#: src/engine-gpgme.c:1230 +#: src/engine-gpgme.c:1243 msgid "*BAD* signature claimed to be from: " msgstr "*FALSCHE* Unterschrift, vorgeblich von: " -#: src/engine-gpgme.c:1253 +#: src/engine-gpgme.c:1266 msgid "Error checking signature" msgstr "Fehler beim Pr?fen der Unterschrift" -#: src/engine-gpgme.c:1269 +#: src/engine-gpgme.c:1282 msgid "*** Begin Notation (signature by: " msgstr "*** Anfang Notation (Unterschrift von: " -#: src/engine-gpgme.c:1289 +#: src/engine-gpgme.c:1302 msgid "*** End Notation ***\n" msgstr "*** Ende Notation ***\n" @@ -336,15 +336,15 @@ msgid "[PGP/MIME message]" msgstr "[PGP/MIME Nachricht]" -#: src/pgpmime.c:604 +#: src/pgpmime.c:605 msgid "[PGP/MIME message without plain text body]" msgstr "[PGP/MIME Nachricht ohne reinen Textk?rper]" -#: src/pgpmime.c:679 +#: src/pgpmime.c:680 msgid "[PGP/MIME signed message without a plain text body]" msgstr "[PGP/MIME signierte Nachricht ohne reinen Textk?rper]" -#: src/pgpmime.c:691 +#: src/pgpmime.c:692 msgid "[PGP/MIME signature]" msgstr "[PGP/MIME Signatur]" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-08-13 15:02:04 UTC (rev 172) +++ trunk/po/sv.po 2007-08-21 22:03:05 UTC (rev 173) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-08-03 18:07+0200\n" +"POT-Creation-Date: 2007-08-21 23:43+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -23,59 +23,59 @@ msgid "Select GPG Key Manager" msgstr "V?lj GPG-nyckelhanterare" -#: src/engine-gpgme.c:991 +#: src/engine-gpgme.c:1004 msgid "Fingerprint: " msgstr "Fingeravtryck: " -#: src/engine-gpgme.c:1048 +#: src/engine-gpgme.c:1061 msgid "This signature is valid\n" msgstr "Den h?r signaturen ?r giltig\n" -#: src/engine-gpgme.c:1050 +#: src/engine-gpgme.c:1063 msgid "signature state is \"green\"\n" msgstr "signaturens tillst?nd ?r \"gr?n\"\n" -#: src/engine-gpgme.c:1052 +#: src/engine-gpgme.c:1065 msgid "signature state is \"red\"\n" msgstr "signaturens tillst?nd ?r \"r?d\"\n" -#: src/engine-gpgme.c:1056 +#: src/engine-gpgme.c:1069 msgid "Warning: One of the keys has been revoked\n" msgstr "Varning: En av nycklarna har sp?rrats\n" -#: src/engine-gpgme.c:1066 +#: src/engine-gpgme.c:1079 msgid "Warning: The key used to create the signature expired at: " msgstr "Varning: Nyckeln som anv?ndes f?r att skapa signaturen gick ut den: " -#: src/engine-gpgme.c:1072 +#: src/engine-gpgme.c:1085 msgid "Warning: At least one certification key has expired\n" msgstr "Varning: ?tminstone en certifieringsnyckel har g?tt ut\n" -#: src/engine-gpgme.c:1078 +#: src/engine-gpgme.c:1091 msgid "Warning: The signature expired at: " msgstr "Varning: Signaturen gick ut den: " -#: src/engine-gpgme.c:1084 +#: src/engine-gpgme.c:1097 msgid "Can't verify due to a missing key or certificate\n" msgstr "Kan inte validera p? grund av en saknad nyckel eller certifikat\n" -#: src/engine-gpgme.c:1088 +#: src/engine-gpgme.c:1101 msgid "The CRL is not available\n" msgstr "Sp?rrlistan ?r inte tillg?nglig\n" -#: src/engine-gpgme.c:1094 +#: src/engine-gpgme.c:1107 msgid "Available CRL is too old\n" msgstr "Tillg?nglig sp?rrlista ?r f?r gammal\n" -#: src/engine-gpgme.c:1099 +#: src/engine-gpgme.c:1112 msgid "A policy requirement was not met\n" msgstr "Ett policykrav matchades inte\n" -#: src/engine-gpgme.c:1105 +#: src/engine-gpgme.c:1118 msgid "A system error occured" msgstr "Ett systemfel intr?ffade" -#: src/engine-gpgme.c:1142 +#: src/engine-gpgme.c:1155 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -83,11 +83,11 @@ "VARNING: Vi har INGA indikationer p? huruvida nyckeln tillh?r personen vars " "namn visas ovanf?r\n" -#: src/engine-gpgme.c:1149 +#: src/engine-gpgme.c:1162 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" msgstr "VARNING: Nyckeln TILLH?R INTE personen vars namn visas ovanf?r\n" -#: src/engine-gpgme.c:1153 +#: src/engine-gpgme.c:1166 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -95,43 +95,43 @@ "VARNING: Det ?r INTE s?kert att nyckeln tillh?r den person vars namn visas " "ovanf?r\n" -#: src/engine-gpgme.c:1186 +#: src/engine-gpgme.c:1199 msgid "Verification started at: " msgstr "Validering startad: " -#: src/engine-gpgme.c:1191 +#: src/engine-gpgme.c:1204 msgid "Verification result for: " msgstr "Valideringsresultat f?r: " -#: src/engine-gpgme.c:1192 +#: src/engine-gpgme.c:1205 msgid "[unnamed part]" msgstr "[ej namngiven del]" -#: src/engine-gpgme.c:1210 src/engine-gpgme.c:1240 +#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253 msgid "Good signature from: " msgstr "Korrekt signatur fr?n: " -#: src/engine-gpgme.c:1217 +#: src/engine-gpgme.c:1230 msgid " aka: " msgstr "?ven k?nd som:" -#: src/engine-gpgme.c:1221 src/engine-gpgme.c:1243 +#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256 msgid " created: " msgstr " skapad: " -#: src/engine-gpgme.c:1230 +#: src/engine-gpgme.c:1243 msgid "*BAD* signature claimed to be from: " msgstr "*FELAKTIG* signatur h?vdades komma fr?n: " -#: src/engine-gpgme.c:1253 +#: src/engine-gpgme.c:1266 msgid "Error checking signature" msgstr "Fel vid kontroll av signatur" -#: src/engine-gpgme.c:1269 +#: src/engine-gpgme.c:1282 msgid "*** Begin Notation (signature by: " msgstr "*** Notation start (signatur av: " -#: src/engine-gpgme.c:1289 +#: src/engine-gpgme.c:1302 msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" @@ -329,15 +329,15 @@ msgid "[PGP/MIME message]" msgstr "[PGP/MIME-meddelande]" -#: src/pgpmime.c:604 +#: src/pgpmime.c:605 msgid "[PGP/MIME message without plain text body]" msgstr "[PGP/MIME-meddelande utan vanlig meddelandetext]" -#: src/pgpmime.c:679 +#: src/pgpmime.c:680 msgid "[PGP/MIME signed message without a plain text body]" msgstr "[PGP/MIME-signerat meddelande utan vanlig meddelandetext]" -#: src/pgpmime.c:691 +#: src/pgpmime.c:692 msgid "[PGP/MIME signature]" msgstr "[PGP/MIME-signatur]" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-13 15:02:04 UTC (rev 172) +++ trunk/src/ChangeLog 2007-08-21 22:03:05 UTC (rev 173) @@ -1,3 +1,10 @@ +2007-08-21 Werner Koch + + * w32-gettext.c (SUBLANG_BENGALI_BANGLADESH): Fix to 2 as per MSDN. + (SUBLANG_PUNJABI_PAKISTAN): Remove as it is not in MSDN. + (SUBLANG_ROMANIAN_MOLDOVA): Remove as it is not in MSDN. + (SUBLANG_ROMANIAN_ROMANIA): Change to value 1 as per MSDN. + 2007-08-13 Marcus Brinkmann * Makefile.am (gpgol_SOURCES): Add common.h. Modified: trunk/src/w32-gettext.c =================================================================== --- trunk/src/w32-gettext.c 2007-08-13 15:02:04 UTC (rev 172) +++ trunk/src/w32-gettext.c 2007-08-21 22:03:05 UTC (rev 173) @@ -1,6 +1,6 @@ /* w32-gettext.h - A simple gettext implementation for Windows targets. Copyright (C) 1995,1996,1997,1999,2005 Free Software Foundation, Inc. - Copyright (C) 2005 g10 Code GmbH + Copyright (C) 2005, 2007 g10 Code GmbH This file is part of libgpg-error. @@ -521,10 +521,10 @@ # define SUBLANG_AZERI_CYRILLIC 0x02 # endif # ifndef SUBLANG_BENGALI_INDIA -# define SUBLANG_BENGALI_INDIA 0x00 +# define SUBLANG_BENGALI_INDIA 0x01 # endif # ifndef SUBLANG_BENGALI_BANGLADESH -# define SUBLANG_BENGALI_BANGLADESH 0x01 +# define SUBLANG_BENGALI_BANGLADESH 0x02 # endif # ifndef SUBLANG_CHINESE_MACAU # define SUBLANG_CHINESE_MACAU 0x05 @@ -617,17 +617,11 @@ # define SUBLANG_NEPALI_INDIA 0x02 # endif # ifndef SUBLANG_PUNJABI_INDIA -# define SUBLANG_PUNJABI_INDIA 0x00 +# define SUBLANG_PUNJABI_INDIA 0x01 # endif -# ifndef SUBLANG_PUNJABI_PAKISTAN -# define SUBLANG_PUNJABI_PAKISTAN 0x01 -# endif # ifndef SUBLANG_ROMANIAN_ROMANIA -# define SUBLANG_ROMANIAN_ROMANIA 0x00 +# define SUBLANG_ROMANIAN_ROMANIA 0x01 # endif -# ifndef SUBLANG_ROMANIAN_MOLDOVA -# define SUBLANG_ROMANIAN_MOLDOVA 0x01 -# endif # ifndef SUBLANG_SERBIAN_LATIN # define SUBLANG_SERBIAN_LATIN 0x02 # endif @@ -1055,7 +1049,6 @@ switch (sub) { case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ - case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */ } return "pa"; case LANG_RHAETO_ROMANCE: return "rm_CH"; @@ -1063,7 +1056,6 @@ switch (sub) { case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; - case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; } return "ro"; case LANG_RUSSIAN: From cvs at cvs.gnupg.org Wed Aug 22 11:11:37 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 11:11:37 +0200 Subject: [svn] gcry - r1260 - in trunk: . cipher Message-ID: Author: wk Date: 2007-08-22 11:11:06 +0200 (Wed, 22 Aug 2007) New Revision: 1260 Modified: trunk/ChangeLog trunk/README trunk/cipher/ChangeLog trunk/cipher/md.c trunk/cipher/rndw32.c trunk/configure.ac Log: Changed rndw32 to LGPL. Typo fixes. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/ChangeLog 2007-08-22 09:11:06 UTC (rev 1260) @@ -1,3 +1,11 @@ +2007-08-22 Werner Koch + + * configure.ac (USE_RNDW32): Unmark rndw32 as GPL. + +2007-08-08 Werner Koch + + * configure.ac: Use $host and not $target. + 2007-07-26 Werner Koch * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Fix a syntax error Modified: trunk/README =================================================================== --- trunk/README 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/README 2007-08-22 09:11:06 UTC (rev 1260) @@ -53,7 +53,6 @@ are: rndunix - Entropy gatherer for Unices without a /dev/random - rndw32 - Entropy gatherer for MS Windows gcryptrnd - The random number daemon. getrandom - A client for that daemon. Modified: trunk/cipher/ChangeLog =================================================================== --- trunk/cipher/ChangeLog 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/cipher/ChangeLog 2007-08-22 09:11:06 UTC (rev 1260) @@ -1,3 +1,7 @@ +2007-08-22 Werner Koch + + * rndw32.c: Switched tpo LGPL. + 2007-05-30 Werner Koch * camellia.h, camellia.c: Replace by new LGPL version and adjusted Modified: trunk/cipher/md.c =================================================================== --- trunk/cipher/md.c 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/cipher/md.c 2007-08-22 09:11:06 UTC (rev 1260) @@ -885,7 +885,7 @@ { /* return the first algorithm */ if (r && r->next) - log_debug("more than algorithm in md_read(0)\n"); + log_debug ("more than one algorithm in md_read(0)\n"); return r->digest->read( &r->context.c ); } else @@ -1133,7 +1133,7 @@ memcpy (buffer, asn, asnlen); *nbytes = asnlen; } - else if ((! buffer) && nbytes) + else if (!buffer && nbytes) *nbytes = asnlen; else { @@ -1200,7 +1200,7 @@ * Returns 1 when the handle works on secured memory * otherwise 0 is returned. There is no error return. * GCRYCTL_IS_ALGO_ENABLED: - * Returns 1 if the algo is enanled for that handle. + * Returns 1 if the algo is enabled for that handle. * The algo must be passed as the address of an int. */ gcry_error_t Modified: trunk/cipher/rndw32.c =================================================================== --- trunk/cipher/rndw32.c 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/cipher/rndw32.c 2007-08-22 09:11:06 UTC (rev 1260) @@ -34,15 +34,38 @@ * author, to allow them to be added to the * baseline version of the code. * - * ALTERNATIVELY, the code may be distributed under the terms of the GNU - * General Public License, version 2 or any later version published by the - * Free Software Foundation, in which case the provisions of the GNU GPL are - * required INSTEAD OF the above restrictions. + * ALTERNATIVELY, the code may be distributed under the terms of the + * GNU Lesser General Public License, version 2.1 or any later version + * published by the Free Software Foundation, in which case the + * provisions of the GNU LGPL are required INSTEAD OF the above + * restrictions. * - * Although not required under the terms of the GPL, it would still be nice if - * you could make any changes available to the author to allow a consistent - * code base to be maintained + * Although not required under the terms of the LGPL, it would still + * be nice if you could make any changes available to the author to + * allow a consistent code base to be maintained. ************************************************************************* + * The above alternative was changed from GPL to LGPL on 2007-08-22 with + * permission from Peter Gutmann: + *========== + From: pgut001 + Subject: Re: LGPL for the windows entropy gatherer + To: wk at gnupg.org + Date: Wed, 22 Aug 2007 03:05:42 +1200 + + Hi, + + >As of now libgcrypt is GPL under Windows due to that module and some people + >would really like to see it under LGPL too. Can you do such a license change + >to LGPL version 2? Note that LGPL give the user the option to relicense it + >under GPL, so the change would be pretty easy and backwar compatible. + + Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy + code as well, but Ian asked for LGPL as an option so as of the next release + I'll have LGPL in there. You can consider it to be retroactive, so your + current version will be LGPLd as well. + + Peter. + *========== */ #include @@ -481,7 +504,8 @@ pPerfData = gcry_realloc (pPerfData, cbPerfData); } else { - log_debug ( "rndw32: get performance data problem\n"); + log_debug ("rndw32: get performance data problem: ec=%ld\n", + status); break; } } Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-07-26 09:15:12 UTC (rev 1259) +++ trunk/configure.ac 2007-08-22 09:11:06 UTC (rev 1260) @@ -53,9 +53,9 @@ VERSION=$PACKAGE_VERSION AC_CONFIG_SRCDIR([src/libgcrypt.vers]) -AC_CANONICAL_TARGET() AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST AM_MAINTAINER_MODE AH_TOP([ @@ -156,8 +156,8 @@ print_egd_notice=no have_w32_system=no -# Setup some stuff depending on host/target. -case "${target}" in +# Setup some stuff depending on host. +case "${host}" in *-*-mingw32*) available_random_modules="w32" ac_cv_have_dev_random=no @@ -218,7 +218,7 @@ # A printable OS Name is sometimes useful. -case "${target}" in +case "${host}" in *-*-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; @@ -241,7 +241,7 @@ esac # Figure out the name of the random device -case "${target}" in +case "${host}" in *-openbsd*) # FIXME: Are these the best flags for OpenBSD? NAME_OF_DEV_RANDOM="/dev/srandom" @@ -641,7 +641,7 @@ # Try Linuxish random device. random_modules="linux" else - case "${target}" in + case "${host}" in *-*-mingw32*|*-*-cygwin*) # Windows random device. random_modules="w32" @@ -920,8 +920,7 @@ [Defined if the EGD based RNG should be used.]) LIST_MEMBER(w32, $random_modules) -test "$found" = "1" && GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo" \ - && gpl="$gpl rndw32" +test "$found" = "1" && GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo" AC_DEFINE_UNQUOTED(USE_RNDW32, $found, [Defined if the Windows specific RNG should be used.]) @@ -1010,5 +1009,5 @@ fi # Give some feedback -echo " Configured for: $PRINTABLE_OS_NAME ($target)" +echo " Configured for: $PRINTABLE_OS_NAME ($host)" echo From cvs at cvs.gnupg.org Wed Aug 22 11:53:28 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 11:53:28 +0200 Subject: [svn] gcry - r1261 - in trunk: . cipher src Message-ID: Author: wk Date: 2007-08-22 11:52:59 +0200 (Wed, 22 Aug 2007) New Revision: 1261 Modified: trunk/ChangeLog trunk/NEWS trunk/README trunk/cipher/ChangeLog trunk/cipher/rndunix.c trunk/configure.ac trunk/src/ChangeLog trunk/src/gcryptrnd.c trunk/src/getrandom.c Log: Made all library code LGPL. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/ChangeLog 2007-08-22 09:52:59 UTC (rev 1261) @@ -1,6 +1,7 @@ 2007-08-22 Werner Koch - * configure.ac (USE_RNDW32): Unmark rndw32 as GPL. + * README: Rewrite the license description. + * configure.ac (USE_RNDW32, USE_RNDUNIX): Unmark as GPL modules. 2007-08-08 Werner Koch Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/NEWS 2007-08-22 09:52:59 UTC (rev 1261) @@ -1,6 +1,10 @@ Noteworthy changes in version 1.3.1 ------------------------------------------------ + * The entire library is now under the LGPL. The helper programs and + the manual are under the GPL. Kudos to Peter Gutmann for giving + permissions to relicense the rndw32 and rndunix modules. + * The Camellia cipher is now under the LGPL and included by default. * Fixed a bug in the detection of symbol prefixes which inhibited the Modified: trunk/README =================================================================== --- trunk/README 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/README 2007-08-22 09:52:59 UTC (rev 1261) @@ -44,20 +44,13 @@ License ------- - Most of this library is distributed under the terms of the GNU - Lesser General Public License (LGPL); see the file COPYING.LIB for - the actual terms. However some parts are distributed under the - GNU General Public License (GPL) so if you configure Libgcrypt to - include these modules, you have to comply with the conditions of - the GPL as found in the file COPYING. The modules under the GPL - are: + The library is distributed under the terms of the GNU Lesser + General Public License (LGPL); see the file COPYING.LIB for the + actual terms. The helper programs (gcryptrnd and getrandom) as + well as the documentation are distributed under the terms of the + GNU General Public License (GPL); see the file COPYING for teh + actual terms. - rndunix - Entropy gatherer for Unices without a /dev/random - gcryptrnd - The random number daemon. - getrandom - A client for that daemon. - - The documentation is available under the terms of the GPL. - This library used to be available under the GPL - this was changed with version 1.1.7 with the rationale that there are now many free crypto libraries available and many of them come with capabilities Modified: trunk/cipher/ChangeLog =================================================================== --- trunk/cipher/ChangeLog 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/cipher/ChangeLog 2007-08-22 09:52:59 UTC (rev 1261) @@ -1,6 +1,6 @@ 2007-08-22 Werner Koch - * rndw32.c: Switched tpo LGPL. + * rndw32.c, rndunix.c: Switched to LGPL. 2007-05-30 Werner Koch Modified: trunk/cipher/rndunix.c =================================================================== --- trunk/cipher/rndunix.c 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/cipher/rndunix.c 2007-08-22 09:52:59 UTC (rev 1261) @@ -34,19 +34,56 @@ author, to allow them to be added to the baseline version of the code. - ALTERNATIVELY, the code may be distributed under the terms of the GNU - General Public License, version 2 or any later version published by the - Free Software Foundation, in which case the provisions of the GNU GPL are - required INSTEAD OF the above restrictions. + ALTERNATIVELY, the code may be distributed under the terms of the + GNU Lesser General Public License, version 2.1 or any later version + published by the Free Software Foundation, in which case the + provisions of the GNU LGPL are required INSTEAD OF the above + restrictions. - Although not required under the terms of the GPL, it would still be nice if - you could make any changes available to the author to allow a consistent - code base to be maintained */ + Although not required under the terms of the LGPL, it would still be + nice if you could make any changes available to the author to allow + a consistent code base to be maintained. */ +/************************************************************************* + The above alternative was changed from GPL to LGPL on 2007-08-22 with + permission from Peter Gutmann: + ========== + From: pgut001 + Subject: Re: LGPL for the windows entropy gatherer + To: wk at gnupg.org + Date: Wed, 22 Aug 2007 03:05:42 +1200 + + Hi, + + >As of now libgcrypt is GPL under Windows due to that module and some people + >would really like to see it under LGPL too. Can you do such a license change + >to LGPL version 2? Note that LGPL give the user the option to relicense it + >under GPL, so the change would be pretty easy and backwar compatible. + + Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy + code as well, but Ian asked for LGPL as an option so as of the next release + I'll have LGPL in there. You can consider it to be retroactive, so your + current version will be LGPLd as well. + + Peter. + ========== + From: pgut001 + Subject: Re: LGPL for the windows entropy gatherer + To: wk at gnupg.org + Date: Wed, 22 Aug 2007 20:50:08 +1200 + + >Would you mind to extend this also to the Unix entropy gatherer which is + >still used on systems without /dev/random and when EGD is not installed? That + >would be the last GPLed piece in Libgcrypt. + + Sure, it covers the entire entropy-gathering subsystem. + + Peter. + ========= +*/ +/* Fixme: We use plain mallocs here because it may be used as a module. + * Should be changed. */ -/* Fixme: We use plain mallocs here beucase it may be used as a module - * should be changed. */ - /* General includes */ #include Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/configure.ac 2007-08-22 09:52:59 UTC (rev 1261) @@ -906,8 +906,7 @@ LIST_MEMBER(unix, $random_modules) -test "$found" = "1" && GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo" \ - && gpl="$gpl rndunix" +test "$found" = "1" && GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo" AC_DEFINE_UNQUOTED(USE_RNDUNIX, $found, [Defined if the default Unix RNG should be used.]) if test "$found" = "1"; then Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/src/ChangeLog 2007-08-22 09:52:59 UTC (rev 1261) @@ -1,3 +1,8 @@ +2007-08-22 Werner Koch + + * getrandom.c (print_version): Use new standard license line. + * gcryptrnd.c (print_version): Ditto. + 2007-06-06 Werner Koch * gcrypt.h.in (GCRY_THREAD_OPTION_PTH_IMPL): Factror network Modified: trunk/src/gcryptrnd.c =================================================================== --- trunk/src/gcryptrnd.c 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/src/gcryptrnd.c 2007-08-22 09:52:59 UTC (rev 1261) @@ -216,9 +216,10 @@ { fputs (MYVERSION_LINE "\n" "Copyright (C) 2006 Free Software Foundation, Inc.\n" - "This program comes with ABSOLUTELY NO WARRANTY.\n" - "This is free software, and you are welcome to redistribute it\n" - "under certain conditions. See the file COPYING for details.\n", + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", stdout); if (with_help) Modified: trunk/src/getrandom.c =================================================================== --- trunk/src/getrandom.c 2007-08-22 09:11:06 UTC (rev 1260) +++ trunk/src/getrandom.c 2007-08-22 09:52:59 UTC (rev 1261) @@ -79,9 +79,10 @@ { fputs (MYVERSION_LINE "\n" "Copyright (C) 2006 Free Software Foundation, Inc.\n" - "This program comes with ABSOLUTELY NO WARRANTY.\n" - "This is free software, and you are welcome to redistribute it\n" - "under certain conditions. See the file COPYING for details.\n", + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", stdout); if (with_help) From cvs at cvs.gnupg.org Wed Aug 22 13:11:12 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 22 Aug 2007 13:11:12 +0200 Subject: [svn] gpgme - r1247 - trunk Message-ID: Author: marcus Date: 2007-08-22 13:10:42 +0200 (Wed, 22 Aug 2007) New Revision: 1247 Modified: trunk/configure.ac Log: Fix last change. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-21 15:09:59 UTC (rev 1246) +++ trunk/configure.ac 2007-08-22 11:10:42 UTC (rev 1247) @@ -159,7 +159,7 @@ AM_PATH_GLIB_2_0 AC_ARG_ENABLE(w32-glib, AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), - build_w32_glib=enableval) + build_w32_glib=$enableval) AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes) AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") From cvs at cvs.gnupg.org Wed Aug 22 12:55:41 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 12:55:41 +0200 Subject: [svn] GnuPG - r4565 - in trunk: . agent common g10 sm tools Message-ID: Author: wk Date: 2007-08-22 12:55:07 +0200 (Wed, 22 Aug 2007) New Revision: 4565 Modified: trunk/README.maint trunk/agent/ChangeLog trunk/agent/protect-tool.c trunk/common/ChangeLog trunk/common/Makefile.am trunk/common/estream-printf.c trunk/common/estream-printf.h trunk/common/estream.c trunk/common/estream.h trunk/common/exechelp.c trunk/common/sysutils.c trunk/common/sysutils.h trunk/g10/ChangeLog trunk/g10/misc.c trunk/sm/ChangeLog trunk/sm/certreqgen-ui.c trunk/sm/certreqgen.c trunk/sm/export.c trunk/sm/gpgsm.h trunk/sm/import.c trunk/sm/server.c trunk/tools/ChangeLog trunk/tools/gpgkey2ssh.c Log: Updated estream. More changes for Windows. Modified: trunk/README.maint =================================================================== --- trunk/README.maint 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/README.maint 2007-08-22 10:55:07 UTC (rev 4565) @@ -33,7 +33,7 @@ * Run configure as usual. * Run "make distcheck" * Build and test the new tarball (best on a different machine). - * [1.4 only] Build and test the W32 version. + * Build and test the W32 version. * Using the final test build run a "make -C doc online". * Sign the tarball * Get the previous tarball and run "mkdiff gnupg". Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/agent/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,3 +1,8 @@ +2007-08-22 Werner Koch + + * protect-tool.c (import_p12_file): Add hack to allow importing of + gnupg 2.0.4 generated files. + 2007-08-06 Werner Koch * trustlist.c (read_one_trustfile): Add flag "cm". Modified: trunk/agent/protect-tool.c =================================================================== --- trunk/agent/protect-tool.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/agent/protect-tool.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -638,7 +638,7 @@ { char *buf; unsigned char *result; - size_t buflen, resultlen; + size_t buflen, resultlen, buf_off; int i; int rc; gcry_mpi_t *kparms; @@ -654,7 +654,22 @@ if (!buf) return; - kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2, 0)), + /* GnuPG 2.0.4 accidently created binary P12 files with the string + "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data. + We fix that here. */ + if (buflen > 29 && !memcmp (buf, "The passphrase is ", 18)) + { + for (buf_off=18; buf_off < buflen && buf[buf_off] != '\n'; buf_off++) + ; + buf_off++; + if (buf_off < buflen && buf[buf_off] == '\n') + buf_off++; + } + else + buf_off = 0; + + kparms = p12_parse ((unsigned char*)buf+buf_off, buflen-buf_off, + (pw=get_passphrase (2, 0)), import_p12_cert_cb, NULL); release_passphrase (pw); xfree (buf); Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,3 +1,32 @@ +2007-08-22 Werner Koch + + Updated estream from libestream. + + * estream.c (mem_malloc, mem_realloc, mem_free): New. Use them + instead of the ES_MEM_foo. + * estream.c (estream_cookie_mem): Remove members DONT_FREE, + APPEND_ZERO, PTR and SIZE. Add MEMORY_LIMIT. Put GROW into a new + FLAGS struct. + (es_func_mem_create): Remove APPEND_ZERO, DONT_FREE, PTR and + SIZE. Add MEMORY_LIMIT. + (es_func_mem_write, es_func_mem_seek, es_func_mem_destroy): Revamp. + (es_open_memstream): Change API to just take a memory limit and a + mode argument. Rename to .. + (es_fopenmem): .. this. + (HAVE_W32_SYSTEM) [_WIN32]: Define if not defined. + (tmpfd) [W32]: Implement directly using the W32 API. + (es_fgets): Rewrite without using doreadline. + +2007-08-21 Werner Koch + + * sysutils.c (gnupg_tmpfile): New. + * t-sysutils.c: New. + * Makefile.am (module_tests): Add t-sysutils. + +2007-08-20 Werner Koch + + * exechelp.c [W32]: Redefine X_OK to F_OK. + 2007-08-16 Werner Koch * Makefile.am (t_convert_DEPENDENCIES): Remove Modified: trunk/common/Makefile.am =================================================================== --- trunk/common/Makefile.am 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/Makefile.am 2007-08-22 10:55:07 UTC (rev 4565) @@ -83,12 +83,12 @@ # # Module tests # -module_tests = t-convert t-gettime +module_tests = t-convert t-gettime t-sysutils t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) t_convert_LDADD = $(t_common_ldadd) t_gettime_LDADD = $(t_common_ldadd) +t_sysutils_LDADD = $(t_common_ldadd) - Modified: trunk/common/estream-printf.c =================================================================== --- trunk/common/estream-printf.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/estream-printf.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -5,7 +5,7 @@ * * Libestream 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 3 of the License, + * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Libestream is distributed in the hope that it will be useful, but @@ -15,8 +15,6 @@ * * You should have received a copy of the GNU General Public License * along with Libestream; if not, see . - * - * $Id: estream-printf.c 56 2007-05-15 18:38:43Z wk $ */ /* Required autoconf tests: Modified: trunk/common/estream-printf.h =================================================================== --- trunk/common/estream-printf.h 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/estream-printf.h 2007-08-22 10:55:07 UTC (rev 4565) @@ -5,7 +5,7 @@ * * Libestream 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 3 of the License, + * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Libestream is distributed in the hope that it will be useful, but @@ -15,8 +15,6 @@ * * You should have received a copy of the GNU General Public License * along with Libestream; if not, see . - * - * $Id: estream-printf.h 56 2007-05-15 18:38:43Z wk $ */ #ifndef ESTREAM_PRINTF_H Modified: trunk/common/estream.c =================================================================== --- trunk/common/estream.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/estream.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -5,7 +5,7 @@ * * Libestream 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 3 of the License, + * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Libestream is distributed in the hope that it will be useful, but @@ -25,6 +25,10 @@ # include #endif +#if defined(_WIN32) && !defined(HAVE_W32_SYSTEM) +# define HAVE_W32_SYSTEM 1 +#endif + #include #include #include @@ -37,10 +41,13 @@ #include #include #include +#ifdef HAVE_W32_SYSTEM +# include +#endif #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */ -#undef HAVE_PTH -#undef USE_GNU_PTH +# undef HAVE_PTH +# undef USE_GNU_PTH #endif #ifdef HAVE_PTH @@ -49,7 +56,7 @@ /* This is for the special hack to use estream.c in GnuPG. */ #ifdef GNUPG_MAJOR_VERSION -#include "../common/util.h" +# include "../common/util.h" #endif #ifndef HAVE_MKSTEMP @@ -74,13 +81,7 @@ typedef void *(*func_realloc_t) (void *mem, size_t size); typedef void (*func_free_t) (void *mem); -#ifdef HAVE_FOPENCOOKIE -typedef ssize_t my_funopen_hook_ret_t; -#else -typedef int my_funopen_hook_ret_t; -#endif - /* Buffer management layer. */ @@ -93,7 +94,6 @@ /* Macros. */ #define BUFFER_ROUND_TO_BLOCK(size, block_size) \ - (((size) + (block_size - 1)) / block_size) @@ -121,12 +121,6 @@ # define ESTREAM_MUTEX_INITIALIZE(mutex) (void) 0 #endif -/* Memory allocator functions. */ - -#define ES_MEM_ALLOC malloc -#define ES_MEM_REALLOC realloc -#define ES_MEM_FREE free - /* Primitive system I/O. */ #ifdef HAVE_PTH @@ -212,6 +206,9 @@ #define DIM(array) (sizeof (array) / sizeof (*array)) #endif +#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) + + /* Evaluate EXPRESSION, setting VARIABLE to the return code, if VARIABLE is zero. */ #define SET_UNLESS_NONZERO(variable, tmp_variable, expression) \ @@ -223,6 +220,33 @@ } \ while (0) + +/* Malloc wrappers to overcvome problems on some older OSes. */ +static void * +mem_alloc (size_t n) +{ + if (!n) + n++; + return malloc (n); +} + +static void * +mem_realloc (void *p, size_t n) +{ + if (!p) + return mem_alloc (n); + return realloc (p, n); +} + +static void +mem_free (void *p) +{ + if (p) + free (p); +} + + + /* * List manipulation. */ @@ -234,7 +258,7 @@ estream_list_t list_obj; int ret; - list_obj = ES_MEM_ALLOC (sizeof (*list_obj)); + list_obj = mem_alloc (sizeof (*list_obj)); if (! list_obj) ret = -1; else @@ -266,7 +290,7 @@ *list_obj->prev_cdr = list_obj->cdr; if (list_obj->cdr) list_obj->cdr->prev_cdr = list_obj->prev_cdr; - ES_MEM_FREE (list_obj); + mem_free (list_obj); break; } ESTREAM_LIST_UNLOCK; @@ -326,53 +350,49 @@ typedef struct estream_cookie_mem { unsigned int modeflags; /* Open flags. */ - unsigned char *memory; /* Data. */ - size_t memory_size; /* Size of MEMORY. */ + unsigned char *memory; /* Allocated data buffer. */ + size_t memory_size; /* Allocated size of memory. */ + size_t memory_limit; /* Maximum allowed allocation size or + 0 for no limit. */ size_t offset; /* Current offset in MEMORY. */ size_t data_len; /* Length of data in MEMORY. */ size_t block_size; /* Block size. */ - unsigned int grow: 1; /* MEMORY is allowed to grow. */ - unsigned int append_zero: 1; /* Append zero after data. */ - unsigned int dont_free: 1; /* Append zero after data. */ - char **ptr; - size_t *size; + struct { + unsigned int grow: 1; /* MEMORY is allowed to grow. */ + } flags; func_realloc_t func_realloc; func_free_t func_free; } *estream_cookie_mem_t; + /* Create function for memory objects. */ static int es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie, unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len, size_t block_size, unsigned int grow, - unsigned int append_zero, unsigned int dont_free, - char **ptr, size_t *size, func_realloc_t func_realloc, func_free_t func_free, - unsigned int modeflags) + unsigned int modeflags, + size_t memory_limit) { estream_cookie_mem_t mem_cookie; int err; - mem_cookie = ES_MEM_ALLOC (sizeof (*mem_cookie)); - if (! mem_cookie) + mem_cookie = mem_alloc (sizeof (*mem_cookie)); + if (!mem_cookie) err = -1; else { mem_cookie->modeflags = modeflags; mem_cookie->memory = data; mem_cookie->memory_size = data_n; + mem_cookie->memory_limit = memory_limit; mem_cookie->offset = 0; mem_cookie->data_len = data_len; mem_cookie->block_size = block_size; - mem_cookie->grow = grow ? 1 : 0; - mem_cookie->append_zero = append_zero ? 1 : 0; - mem_cookie->dont_free = dont_free ? 1 : 0; - mem_cookie->ptr = ptr; - mem_cookie->size = size; - mem_cookie->func_realloc = func_realloc ? func_realloc : ES_MEM_REALLOC; - mem_cookie->func_free = func_free ? func_free : ES_MEM_FREE; - mem_cookie->offset = 0; + mem_cookie->flags.grow = !!grow; + mem_cookie->func_realloc = func_realloc ? func_realloc : mem_realloc; + mem_cookie->func_free = func_free ? func_free : mem_free; *cookie = mem_cookie; err = 0; } @@ -380,6 +400,7 @@ return err; } + /* Read function for memory objects. */ static ssize_t es_func_mem_read (void *cookie, void *buffer, size_t size) @@ -397,115 +418,89 @@ } ret = size; - return ret; } + /* Write function for memory objects. */ static ssize_t es_func_mem_write (void *cookie, const void *buffer, size_t size) { estream_cookie_mem_t mem_cookie = cookie; - func_realloc_t func_realloc = mem_cookie->func_realloc; - unsigned char *memory_new; - size_t newsize; ssize_t ret; - int err; - if (size) + if (!size) + return 0; /* A flush is a NOP for memory objects. */ + + if (mem_cookie->modeflags & O_APPEND) { - /* Regular write. */ - - if (mem_cookie->modeflags & O_APPEND) - /* Append to data. */ - mem_cookie->offset = mem_cookie->data_len; + /* Append to data. */ + mem_cookie->offset = mem_cookie->data_len; + } - if (! mem_cookie->grow) - if (size > mem_cookie->memory_size - mem_cookie->offset) - size = mem_cookie->memory_size - mem_cookie->offset; + if (!mem_cookie->flags.grow) + { + /* We are not alloew to grow, thus limit the size to the left + space. FIXME: Does the grow flag an its semtics make sense + at all? */ + if (size > mem_cookie->memory_size - mem_cookie->offset) + size = mem_cookie->memory_size - mem_cookie->offset; + } - err = 0; - - while (size > (mem_cookie->memory_size - mem_cookie->offset)) - { - memory_new = (*func_realloc) (mem_cookie->memory, - mem_cookie->memory_size - + mem_cookie->block_size); - if (! memory_new) - { - err = -1; - break; - } - else - { - if (mem_cookie->memory != memory_new) - mem_cookie->memory = memory_new; - mem_cookie->memory_size += mem_cookie->block_size; - } - } - if (err) - goto out; - - if (size) - { - memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); - if (mem_cookie->offset + size > mem_cookie->data_len) - mem_cookie->data_len = mem_cookie->offset + size; - mem_cookie->offset += size; - } - } - else + if (size > (mem_cookie->memory_size - mem_cookie->offset)) { - /* Flush. */ - - err = 0; - if (mem_cookie->append_zero) - { - if (mem_cookie->data_len >= mem_cookie->memory_size) - { - newsize = BUFFER_ROUND_TO_BLOCK (mem_cookie->data_len + 1, - mem_cookie->block_size) - * mem_cookie->block_size; - - memory_new = (*func_realloc) (mem_cookie->memory, newsize); - if (! memory_new) - { - err = -1; - goto out; - } - - if (mem_cookie->memory != memory_new) - mem_cookie->memory = memory_new; - mem_cookie->memory_size = newsize; - } - - mem_cookie->memory[mem_cookie->data_len + 1] = 0; - } - - /* Return information to user if necessary. */ - if (mem_cookie->ptr) - *mem_cookie->ptr = (char *) mem_cookie->memory; - if (mem_cookie->size) - *mem_cookie->size = mem_cookie->data_len; + unsigned char *newbuf; + size_t newsize; + + newsize = mem_cookie->memory_size + mem_cookie->block_size; + + newsize = mem_cookie->offset + size; + if (newsize < mem_cookie->offset) + { + errno = EINVAL; + return -1; + } + newsize += mem_cookie->block_size - 1; + if (newsize < mem_cookie->offset) + { + errno = EINVAL; + return -1; + } + newsize /= mem_cookie->block_size; + newsize *= mem_cookie->block_size; + + if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit) + { + errno = ENOSPC; + return -1; + } + + newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); + if (!newbuf) + return -1; + + mem_cookie->memory = newbuf; + mem_cookie->memory_size = newsize; + + assert (!(size > (mem_cookie->memory_size - mem_cookie->offset))); } + + memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); + if (mem_cookie->offset + size > mem_cookie->data_len) + mem_cookie->data_len = mem_cookie->offset + size; + mem_cookie->offset += size; - out: - - if (err) - ret = -1; - else - ret = size; - + ret = size; return ret; } + /* Seek function for memory objects. */ static int es_func_mem_seek (void *cookie, off_t *offset, int whence) { estream_cookie_mem_t mem_cookie = cookie; off_t pos_new; - int err = 0; switch (whence) { @@ -522,69 +517,74 @@ break; default: - /* Never reached. */ - pos_new = 0; + errno = EINVAL; + return -1; } if (pos_new > mem_cookie->memory_size) { - /* Grow buffer if possible. */ + size_t newsize; + void *newbuf; - if (mem_cookie->grow) + if (!mem_cookie->flags.grow) { - func_realloc_t func_realloc = mem_cookie->func_realloc; - size_t newsize; - void *p; + errno = ENOSPC; + return -1; - newsize = BUFFER_ROUND_TO_BLOCK (pos_new, mem_cookie->block_size); - p = (*func_realloc) (mem_cookie->memory, newsize); - if (! p) - { - err = -1; - goto out; - } - else - { - if (mem_cookie->memory != p) - mem_cookie->memory = p; - mem_cookie->memory_size = newsize; - } - } - else - { - errno = EINVAL; - err = -1; - goto out; - } + } + + newsize = pos_new + mem_cookie->block_size - 1; + if (newsize < pos_new) + { + errno = EINVAL; + return -1; + } + newsize /= mem_cookie->block_size; + newsize *= mem_cookie->block_size; + if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit) + { + errno = ENOSPC; + return -1; + } + + newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize); + if (!newbuf) + return -1; + + mem_cookie->memory = newbuf; + mem_cookie->memory_size = newsize; } if (pos_new > mem_cookie->data_len) - /* Fill spare space with zeroes. */ - memset (mem_cookie->memory + mem_cookie->data_len, - 0, pos_new - mem_cookie->data_len); + { + /* Fill spare space with zeroes. */ + memset (mem_cookie->memory + mem_cookie->data_len, + 0, pos_new - mem_cookie->data_len); + mem_cookie->data_len = pos_new; + } mem_cookie->offset = pos_new; *offset = pos_new; - out: - - return err; + return 0; } + /* Destroy function for memory objects. */ static int es_func_mem_destroy (void *cookie) { estream_cookie_mem_t mem_cookie = cookie; - func_free_t func_free = mem_cookie->func_free; - if (! mem_cookie->dont_free) - (*func_free) (mem_cookie->memory); - ES_MEM_FREE (mem_cookie); - + if (cookie) + { + mem_cookie->func_free (mem_cookie->memory); + mem_free (mem_cookie); + } return 0; } + static es_cookie_io_functions_t estream_functions_mem = { es_func_mem_read, @@ -611,7 +611,7 @@ estream_cookie_fd_t fd_cookie; int err; - fd_cookie = ES_MEM_ALLOC (sizeof (*fd_cookie)); + fd_cookie = mem_alloc (sizeof (*fd_cookie)); if (! fd_cookie) err = -1; else @@ -690,7 +690,7 @@ if (fd_cookie) { err = fd_cookie->no_close? 0 : close (fd_cookie->fd); - ES_MEM_FREE (fd_cookie); + mem_free (fd_cookie); } else err = 0; @@ -726,7 +726,7 @@ estream_cookie_fp_t fp_cookie; int err; - fp_cookie = ES_MEM_ALLOC (sizeof *fp_cookie); + fp_cookie = mem_alloc (sizeof *fp_cookie); if (!fp_cookie) err = -1; else @@ -807,7 +807,7 @@ { fflush (fp_cookie->fp); err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp); - ES_MEM_FREE (fp_cookie); + mem_free (fp_cookie); } else err = 0; @@ -841,7 +841,7 @@ err = 0; fd = -1; - file_cookie = ES_MEM_ALLOC (sizeof (*file_cookie)); + file_cookie = mem_alloc (sizeof (*file_cookie)); if (! file_cookie) { err = -1; @@ -868,7 +868,7 @@ out: if (err) - ES_MEM_FREE (file_cookie); + mem_free (file_cookie); return err; } @@ -1149,14 +1149,14 @@ stream_new = NULL; stream_internal_new = NULL; - stream_new = ES_MEM_ALLOC (sizeof (*stream_new)); + stream_new = mem_alloc (sizeof (*stream_new)); if (! stream_new) { err = -1; goto out; } - stream_internal_new = ES_MEM_ALLOC (sizeof (*stream_internal_new)); + stream_internal_new = mem_alloc (sizeof (*stream_internal_new)); if (! stream_internal_new) { err = -1; @@ -1185,7 +1185,7 @@ if (stream_new) { es_deinitialize (stream_new); - ES_MEM_FREE (stream_new); + mem_free (stream_new); } } @@ -1202,8 +1202,8 @@ { es_list_remove (stream); err = es_deinitialize (stream); - ES_MEM_FREE (stream->intern); - ES_MEM_FREE (stream); + mem_free (stream->intern); + mem_free (stream); } return err; @@ -1694,8 +1694,8 @@ static int doreadline (estream_t ES__RESTRICT stream, size_t max_length, - char *ES__RESTRICT *ES__RESTRICT line, - size_t *ES__RESTRICT line_length) + char *ES__RESTRICT *ES__RESTRICT line, + size_t *ES__RESTRICT line_length) { size_t space_left; size_t line_size; @@ -1711,9 +1711,11 @@ line_stream = NULL; line_stream_cookie = NULL; - err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE, - 1, 0, 0, NULL, 0, ES_MEM_REALLOC, ES_MEM_FREE, - O_RDWR); + err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, + mem_realloc, mem_free, + O_RDWR, + 0); if (err) goto out; @@ -1779,7 +1781,7 @@ if (! *line) { - line_new = ES_MEM_ALLOC (line_size + 1); + line_new = mem_alloc (line_size + 1); if (! line_new) { err = -1; @@ -1810,7 +1812,7 @@ if (err) { if (! *line) - ES_MEM_FREE (line_new); + mem_free (line_new); stream->intern->indicators.err = 1; } @@ -1894,7 +1896,7 @@ if (stream->intern->deallocate_buffer) { stream->intern->deallocate_buffer = 0; - ES_MEM_FREE (stream->buffer); + mem_free (stream->buffer); stream->buffer = NULL; } @@ -1908,7 +1910,7 @@ buffer_new = buffer; else { - buffer_new = ES_MEM_ALLOC (size); + buffer_new = mem_alloc (size); if (! buffer_new) { err = -1; @@ -2034,8 +2036,8 @@ goto out; err = es_func_mem_create (&cookie, data, data_n, data_len, - BUFFER_BLOCK_SIZE, grow, 0, 0, - NULL, 0, func_realloc, func_free, modeflags); + BUFFER_BLOCK_SIZE, grow, + func_realloc, func_free, modeflags, 0); if (err) goto out; @@ -2052,37 +2054,33 @@ estream_t -es_open_memstream (char **ptr, size_t *size) +es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode) { unsigned int modeflags; - int create_called; - estream_t stream; - void *cookie; - int err; + estream_t stream = NULL; + void *cookie = NULL; - modeflags = O_RDWR; - create_called = 0; - stream = NULL; - cookie = 0; + /* Memory streams are always read/write. We use MODE only to get + the append flag. */ + if (es_convert_mode (mode, &modeflags)) + return NULL; + modeflags |= O_RDWR; + - err = es_func_mem_create (&cookie, NULL, 0, 0, - BUFFER_BLOCK_SIZE, 1, 1, 1, - ptr, size, ES_MEM_REALLOC, ES_MEM_FREE, modeflags); - if (err) - goto out; + if (es_func_mem_create (&cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, + mem_realloc, mem_free, modeflags, + memlimit)) + return NULL; - create_called = 1; - err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags); - - out: - - if (err && create_called) + if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags)) (*estream_functions_mem.func_close) (cookie); return stream; } + estream_t es_fopencookie (void *ES__RESTRICT cookie, const char *ES__RESTRICT mode, @@ -2613,22 +2611,31 @@ char * -es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream) +es_fgets (char *ES__RESTRICT buffer, int length, estream_t ES__RESTRICT stream) { - char *ret = NULL; - - if (n) + unsigned char *s = (unsigned char*)buffer; + int c; + + if (!length) + return NULL; + + c = EOF; + ESTREAM_LOCK (stream); + while (length > 1 && (c = es_getc_unlocked (stream)) != EOF && c != '\n') { - int err; - - ESTREAM_LOCK (stream); - err = doreadline (stream, n, &s, NULL); - ESTREAM_UNLOCK (stream); - if (! err) - ret = s; + *s++ = c; + length--; } - - return ret; + ESTREAM_UNLOCK (stream); + + if (c == EOF && s == (unsigned char*)buffer) + return NULL; /* Nothing read. */ + + if (c != EOF && length > 1) + *s++ = c; + + *s = 0; + return buffer; } @@ -2671,7 +2678,7 @@ void *p; - p = ES_MEM_REALLOC (*lineptr, line_n + 1); + p = mem_realloc (*lineptr, line_n + 1); if (! p) err = -1; else @@ -2687,7 +2694,7 @@ if (*n != line_n) *n = line_n; } - ES_MEM_FREE (line); + mem_free (line); } else { @@ -2747,7 +2754,7 @@ { /* No buffer given - allocate a new one. */ length = 256; - buffer = ES_MEM_ALLOC (length); + buffer = mem_alloc (length); *addr_of_buffer = buffer; if (!buffer) { @@ -2761,7 +2768,7 @@ if (length < 4) { - /* This should never happen. If it does, the fucntion has been + /* This should never happen. If it does, the function has been called with wrong arguments. */ errno = EINVAL; return -1; @@ -2788,11 +2795,11 @@ } length += 3; /* Adjust for the reserved bytes. */ length += length < 1024? 256 : 1024; - *addr_of_buffer = ES_MEM_REALLOC (buffer, length); + *addr_of_buffer = mem_realloc (buffer, length); if (!*addr_of_buffer) { int save_errno = errno; - ES_MEM_FREE (buffer); + mem_free (buffer); *length_of_buffer = *max_length = 0; ESTREAM_UNLOCK (stream); errno = save_errno; @@ -2820,8 +2827,7 @@ void es_free (void *a) { - if (a) - ES_MEM_FREE (a); + mem_free (a); } @@ -2870,9 +2876,66 @@ return ret; } + static int tmpfd (void) { +#ifdef HAVE_W32_SYSTEM + int attempts, n; + char buffer[MAX_PATH+9+12+1]; + char *name, *p; + HANDLE file; + int pid = GetCurrentProcessId (); + unsigned int value; + int i; + + n = GetTempPath (MAX_PATH+1, buffer); + if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH) + { + errno = ENOENT; + return -1; + } + p = buffer + strlen (buffer); + strcpy (p, "_estream"); + p += 8; + /* We try to create the directory but don't care about an error as + it may already exist and the CreateFile would throw an error + anyway. */ + CreateDirectory (buffer, NULL); + *p++ = '\\'; + name = p; + for (attempts=0; attempts < 10; attempts++) + { + p = name; + value = (GetTickCount () ^ ((pid<<16) & 0xffff0000)); + for (i=0; i < 8; i++) + { + *p++ = tohex (((value >> 28) & 0x0f)); + value <<= 4; + } + strcpy (p, ".tmp"); + file = CreateFile (buffer, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (file != INVALID_HANDLE_VALUE) + { + int fd = _open_osfhandle ((long)file, 0); + if (fd == -1) + { + CloseHandle (file); + return -1; + } + return fd; + } + Sleep (1); /* One ms as this is the granularity of GetTickCount. */ + } + errno = ENOENT; + return -1; +#else /*!HAVE_W32_SYSTEM*/ FILE *fp; int fp_fd; int fd; @@ -2893,6 +2956,7 @@ fclose (fp); return fd; +#endif /*!HAVE_W32_SYSTEM*/ } estream_t Modified: trunk/common/estream.h =================================================================== --- trunk/common/estream.h 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/estream.h 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,11 +1,11 @@ -/* estream.h - Extended stream I/O/ Library +/* estream.h - Extended stream I/O Library * Copyright (C) 2004, 2005, 2006, 2007 g10 Code GmbH * * This file is part of Libestream. * * Libestream 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 3 of the License, + * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Libestream is distributed in the hope that it will be useful, but @@ -41,7 +41,7 @@ #endif /*_ESTREAM_PREFIX*/ #define es_fopen _ESTREAM_PREFIX(es_fopen) #define es_mopen _ESTREAM_PREFIX(es_mopen) -#define es_open_memstream _ESTREAM_PREFIX(es_open_memstream) +#define es_fopenmem _ESTREAM_PREFIX(es_fopenmem) #define es_fdopen _ESTREAM_PREFIX(es_fdopen) #define es_fdopen_nc _ESTREAM_PREFIX(es_fdopen_nc) #define es_fpopen _ESTREAM_PREFIX(es_fpopen) @@ -198,7 +198,7 @@ void *(*func_realloc) (void *mem, size_t size), void (*func_free) (void *mem), const char *ES__RESTRICT mode); -estream_t es_open_memstream (char **ptr, size_t *size); +estream_t es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode); estream_t es_fdopen (int filedes, const char *mode); estream_t es_fdopen_nc (int filedes, const char *mode); estream_t es_fpopen (FILE *fp, const char *mode); Modified: trunk/common/exechelp.c =================================================================== --- trunk/common/exechelp.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/exechelp.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -64,7 +64,15 @@ #pragma weak pth_waitpid #endif +#ifdef HAVE_W32_SYSTEM +/* It seems Vista doesn't grok X_OK and so fails access() tests. + Previous versions interpreted X_OK as F_OK anyway, so we'll just + use F_OK directly. */ +#undef X_OK +#define X_OK F_OK +#endif /* HAVE_W32_SYSTEM */ + #ifdef HAVE_W32_SYSTEM /* We assume that a HANDLE can be represented by an int which should be true for all i386 systems (HANDLE is defined as void *) and Modified: trunk/common/sysutils.c =================================================================== --- trunk/common/sysutils.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/sysutils.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,5 +1,6 @@ /* sysutils.c - system helpers - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -53,6 +54,9 @@ #include "sysutils.h" +#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) + + #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 #warning using trap_unaligned static int @@ -298,7 +302,7 @@ } /* This is the same as translate_sys2libc_fd but takes an integer - which is assumet to be such an system handle. */ + which is assumed to be such an system handle. */ int translate_sys2libc_fd_int (int fd, int for_write) { @@ -311,3 +315,85 @@ return fd; #endif } + + + +/* Replacement for tmpfile(). This is required because the tmpfile + function of Windows' runtime library is broken, insecure, ignores + TMPDIR and so on. In addition we create a file with an inheritable + handle. */ +FILE * +gnupg_tmpfile (void) +{ +#ifdef HAVE_W32_SYSTEM + int attempts, n; + char buffer[MAX_PATH+7+12+1]; + char *name, *p; + HANDLE file; + int pid = GetCurrentProcessId (); + unsigned int value; + int i; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = TRUE; + + n = GetTempPath (MAX_PATH+1, buffer); + if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH) + { + errno = ENOENT; + return NULL; + } + p = buffer + strlen (buffer); + p = stpcpy (p, "_gnupg"); + /* We try to create the directory but don't care about an error as + it may already exist and the CreateFile would throw an error + anyway. */ + CreateDirectory (buffer, NULL); + *p++ = '\\'; + name = p; + for (attempts=0; attempts < 10; attempts++) + { + p = name; + value = (GetTickCount () ^ ((pid<<16) & 0xffff0000)); + for (i=0; i < 8; i++) + { + *p++ = tohex (((value >> 28) & 0x0f)); + value <<= 4; + } + strcpy (p, ".tmp"); + file = CreateFile (buffer, + GENERIC_READ | GENERIC_WRITE, + 0, + &sec_attr, + CREATE_NEW, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (file != INVALID_HANDLE_VALUE) + { + FILE *fp; + int fd = _open_osfhandle ((long)file, 0); + if (fd == -1) + { + CloseHandle (file); + return NULL; + } + fp = fdopen (fd, "w+b"); + if (!fp) + { + int save = errno; + close (fd); + errno = save; + return NULL; + } + return fp; + } + Sleep (1); /* One ms as this is the granularity of GetTickCount. */ + } + errno = ENOENT; + return NULL; +#else /*!HAVE_W32_SYSTEM*/ + return tmpfile (); +#endif /*!HAVE_W32_SYSTEM*/ +} Modified: trunk/common/sysutils.h =================================================================== --- trunk/common/sysutils.h 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/common/sysutils.h 2007-08-22 10:55:07 UTC (rev 4565) @@ -41,6 +41,7 @@ void gnupg_sleep (unsigned int seconds); int translate_sys2libc_fd (gnupg_fd_t fd, int for_write); int translate_sys2libc_fd_int (int fd, int for_write); +FILE *gnupg_tmpfile (void); #ifdef HAVE_W32_SYSTEM Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/g10/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,3 +1,8 @@ +2007-08-21 Werner Koch + + * misc.c (openpgp_md_test_algo): Remove rfc2440bis hash algorithms. + (openpgp_cipher_test_algo): Likewise for algos 5 and 6. + 2007-08-02 Werner Koch * gpg.c: Include gc-opt-flags.h and remove their definition here. Modified: trunk/g10/misc.c =================================================================== --- trunk/g10/misc.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/g10/misc.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,6 +1,6 @@ /* misc.c - miscellaneous functions * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005, 2006 Free Software Foundation, Inc. + * 2005, 2006, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -331,7 +331,8 @@ int openpgp_cipher_test_algo( int algo ) { - if ( algo < 0 || algo > 110 ) + /* 5 and 6 are marked reserved by rfc2440bis. */ + if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 ) return gpg_error (GPG_ERR_CIPHER_ALGO); return gcry_cipher_test_algo (algo); } @@ -396,8 +397,9 @@ /* Note: If the list of actual supported OpenPGP algorithms changes, make sure that our hard coded values at print_status_begin_signing() gets updated. */ - - if (algo < 0 || algo > 110) + /* 4, 5, 6, 7 are defined by rfc2440 but will be removed from the + next revision of the standard. */ + if (algo < 0 || algo > 110 || (algo >= 4 && algo <= 7)) return gpg_error (GPG_ERR_DIGEST_ALGO); return gcry_md_test_algo (algo); } Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,3 +1,20 @@ +2007-08-22 Werner Koch + + * certreqgen-ui.c (gpgsm_gencertreq_tty): Use es_fopenmem. + +2007-08-21 Werner Koch + + * import.c (parse_p12): Use gnupg_tmpfile. + * export.c (export_p12): Ditto. + +2007-08-20 Werner Koch + + * certreqgen.c (read_parameters): Change FP to an estream_t. + (gpgsm_genkey): Replace in_fd and in_stream by a estream_t. + * server.c (cmd_genkey): Adjust for that. + * certreqgen-ui.c (gpgsm_gencertreq_tty): Use es_open_memstream + instead of a temporary file. + 2007-08-14 Werner Koch * call-dirmngr.c (start_dirmngr): Use dirmngr_socket_name. change Modified: trunk/sm/certreqgen-ui.c =================================================================== --- trunk/sm/certreqgen-ui.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/certreqgen-ui.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -97,7 +97,7 @@ gpg_error_t err; char *answer; int selection; - FILE *fp = NULL; + estream_t fp = NULL; int method; char *keytype; char *keygrip = NULL; @@ -278,20 +278,20 @@ goto leave; /* Now create a parameter file and generate the key. */ - fp = tmpfile (); + fp = es_fopenmem (0, "w+"); if (!fp) { log_error (_("error creating temporary file: %s\n"), strerror (errno)); goto leave; } - fputs (result, fp); - rewind (fp); + es_fputs (result, fp); + es_rewind (fp); tty_printf (_("Now creating certificate request. " "This may take a while ...\n")); { int save_pem = ctrl->create_pem; ctrl->create_pem = 1; /* Force creation of PEM. */ - err = gpgsm_genkey (ctrl, -1, fp, output_fp); + err = gpgsm_genkey (ctrl, fp, output_fp); ctrl->create_pem = save_pem; } if (!err) @@ -302,8 +302,7 @@ mem_error: log_error (_("resource problem: out or core\n")); leave: - if (fp) - fclose (fp); + es_fclose (fp); xfree (keytype); xfree (subject_name); xfree (keygrip); Modified: trunk/sm/certreqgen.c =================================================================== --- trunk/sm/certreqgen.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/certreqgen.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -247,7 +247,7 @@ /* Read the certificate generation parameters from FP and generate (all) certificate requests. */ static int -read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer) +read_parameters (ctrl_t ctrl, estream_t fp, ksba_writer_t writer) { static struct { const char *name; @@ -275,7 +275,7 @@ err = NULL; para = NULL; - while (fgets (line, DIM(line)-1, fp) ) + while (es_fgets (line, DIM(line)-1, fp) ) { char *keyword, *value; @@ -391,7 +391,7 @@ log_error ("line %d: %s\n", outctrl.lnr, err); rc = gpg_error (GPG_ERR_GENERAL); } - else if (ferror(fp)) + else if (es_ferror(fp)) { log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) ); rc = gpg_error (GPG_ERR_GENERAL); @@ -829,27 +829,15 @@ -/* Create a new key by reading the parameters from in_fd or in_stream. - Multiple keys may be created */ +/* Create a new key by reading the parameters from IN_FP. Multiple + keys may be created */ int -gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *in_stream, FILE *out_fp) +gpgsm_genkey (ctrl_t ctrl, estream_t in_stream, FILE *out_fp) { int rc; - FILE *in_fp; Base64Context b64writer = NULL; ksba_writer_t writer; - if (in_stream) - in_fp = in_stream; - else - in_fp = fdopen (dup (in_fd), "rb"); - if (!in_fp) - { - gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); - log_error ("fdopen() failed: %s\n", strerror (errno)); - return tmperr; - } - ctrl->pem_name = "CERTIFICATE REQUEST"; rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer); if (rc) @@ -858,7 +846,7 @@ goto leave; } - rc = read_parameters (ctrl, in_fp, writer); + rc = read_parameters (ctrl, in_stream, writer); if (rc) { log_error ("error creating certificate request: %s <%s>\n", @@ -878,8 +866,6 @@ leave: gpgsm_destroy_writer (b64writer); - if (!in_stream) - fclose (in_fp); return rc; } Modified: trunk/sm/export.c =================================================================== --- trunk/sm/export.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/export.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -32,6 +32,7 @@ #include "keydb.h" #include "exechelp.h" #include "i18n.h" +#include "sysutils.h" @@ -606,7 +607,7 @@ else pgmname = opt.protect_tool_program; - infp = tmpfile (); + infp = gnupg_tmpfile (); if (!infp) { err = gpg_error_from_syserror (); @@ -622,7 +623,7 @@ goto cleanup; } - outfp = tmpfile (); + outfp = gnupg_tmpfile (); if (!outfp) { err = gpg_error_from_syserror (); Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/gpgsm.h 2007-08-22 10:55:07 UTC (rev 4565) @@ -325,7 +325,7 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- certreqgen.c --*/ -int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *in_stream, FILE *out_fp); +int gpgsm_genkey (ctrl_t ctrl, estream_t in_stream, FILE *out_fp); /*-- certreqgen-ui.c --*/ void gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *out_fp); Modified: trunk/sm/import.c =================================================================== --- trunk/sm/import.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/import.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -33,6 +33,7 @@ #include "keydb.h" #include "exechelp.h" #include "i18n.h" +#include "sysutils.h" struct stats_s { unsigned long count; @@ -517,7 +518,7 @@ gpg-protect-tool will anyway parse the entire pkcs#12 message in memory, we simply use tempfiles here and pass them to the gpg-protect-tool. */ - tmpfp = tmpfile (); + tmpfp = gnupg_tmpfile (); if (!tmpfp) { err = gpg_error_from_syserror (); @@ -542,7 +543,7 @@ goto cleanup; } - certfp = tmpfile (); + certfp = gnupg_tmpfile (); if (!certfp) { err = gpg_error_from_syserror (); Modified: trunk/sm/server.c =================================================================== --- trunk/sm/server.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/sm/server.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -863,6 +863,7 @@ int inp_fd, out_fd; FILE *out_fp; int rc; + estream_t in_stream; inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0); if (inp_fd == -1) @@ -871,10 +872,17 @@ if (out_fd == -1) return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); + in_stream = es_fdopen_nc (inp_fd, "r"); + if (!in_stream) + return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen failed"); + out_fp = fdopen ( dup(out_fd), "w"); if (!out_fp) - return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed"); - rc = gpgsm_genkey (ctrl, inp_fd, NULL, out_fp); + { + es_fclose (in_stream); + return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed"); + } + rc = gpgsm_genkey (ctrl, in_stream, out_fp); fclose (out_fp); /* close and reset the fds */ Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/tools/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) @@ -1,3 +1,7 @@ +2007-08-21 Werner Koch + + * gpgkey2ssh.c (key_to_blob): Use gnupg_tmpfile(). + 2007-08-02 Werner Koch * gpgconf-comp.c: Factor the public GC_OPT_FLAG constants out and Modified: trunk/tools/gpgkey2ssh.c =================================================================== --- trunk/tools/gpgkey2ssh.c 2007-08-16 12:44:17 UTC (rev 4564) +++ trunk/tools/gpgkey2ssh.c 2007-08-22 10:55:07 UTC (rev 4565) @@ -184,7 +184,7 @@ int ret; pkdbuf_t *pkd; - stream = tmpfile (); + stream = gnupg_tmpfile (); assert (stream); identifier_n = strlen (identifier); From cvs at cvs.gnupg.org Wed Aug 22 19:30:11 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 22 Aug 2007 19:30:11 +0200 Subject: [svn] gpgme - r1248 - trunk/gpgme Message-ID: Author: marcus Date: 2007-08-22 19:29:41 +0200 (Wed, 22 Aug 2007) New Revision: 1248 Modified: trunk/gpgme/ChangeLog trunk/gpgme/w32-io.c Log: 2007-08-22 Marcus Brinkmann * w32-io.c (_gpgme_io_write): Return early if COUNT is zero. (writer): Remove superfluous check. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-08-22 11:10:42 UTC (rev 1247) +++ trunk/gpgme/ChangeLog 2007-08-22 17:29:41 UTC (rev 1248) @@ -1,3 +1,8 @@ +2007-08-22 Marcus Brinkmann + + * w32-io.c (_gpgme_io_write): Return early if COUNT is zero. + (writer): Remove superfluous check. + 2007-08-20 Marcus Brinkmann * gpgme.h: Move include of gpg-error.h out of extern "C". Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-08-22 11:10:42 UTC (rev 1247) +++ trunk/gpgme/w32-io.c 2007-08-22 17:29:41 UTC (rev 1248) @@ -531,20 +531,22 @@ UNLOCK (ctx->mutex); TRACE_LOG1 ("writing %d bytes", ctx->nbytes); - if (ctx->nbytes - && !WriteFile (ctx->file_hd, ctx->buffer, - ctx->nbytes, &nwritten, NULL)) - { - ctx->error_code = (int) GetLastError (); - ctx->error = 1; - TRACE_LOG1 ("write error: ec=%d", ctx->error_code); - break; - } - TRACE_LOG1 ("wrote %d bytes", (int) nwritten); + /* Note that CTX->nbytes is not zero at this point, because + _gpgme_io_write always writes at least 1 byte before waking + us up, unless CTX->stop_me is true, which we catch above. */ + if (!WriteFile (ctx->file_hd, ctx->buffer, + ctx->nbytes, &nwritten, NULL)) + { + ctx->error_code = (int) GetLastError (); + ctx->error = 1; + TRACE_LOG1 ("write error: ec=%d", ctx->error_code); + break; + } + TRACE_LOG1 ("wrote %d bytes", (int) nwritten); - LOCK (ctx->mutex); - ctx->nbytes -= nwritten; - UNLOCK (ctx->mutex); + LOCK (ctx->mutex); + ctx->nbytes -= nwritten; + UNLOCK (ctx->mutex); } /* Indicate that we have an error. */ if (!SetEvent (ctx->is_empty)) @@ -724,6 +726,9 @@ "buffer=%p, count=%u", buffer, count); TRACE_LOGBUF (buffer, count); + if (count == 0) + return TRACE_SYS (0); + ctx = find_writer (fd, 1); if (!ctx) return TRACE_SYSRES (-1); From cvs at cvs.gnupg.org Wed Aug 22 19:44:08 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 19:44:08 +0200 Subject: [svn] gcry - r1262 - trunk/src Message-ID: Author: wk Date: 2007-08-22 19:43:39 +0200 (Wed, 22 Aug 2007) New Revision: 1262 Added: trunk/src/dumpsexp.c Modified: trunk/src/ChangeLog trunk/src/Makefile.am Log: Add new debug tool for S-expressions. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-22 09:52:59 UTC (rev 1261) +++ trunk/src/ChangeLog 2007-08-22 17:43:39 UTC (rev 1262) @@ -1,5 +1,8 @@ 2007-08-22 Werner Koch + * dumpsexp.c: New. + * Makefile.am (bin_PROGRAMS): Install it. + * getrandom.c (print_version): Use new standard license line. * gcryptrnd.c (print_version): Ditto. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-22 09:52:59 UTC (rev 1261) +++ trunk/src/Makefile.am 2007-08-22 17:43:39 UTC (rev 1262) @@ -28,11 +28,13 @@ include_HEADERS = gcrypt.h gcrypt-module.h lib_LTLIBRARIES = libgcrypt.la +bin_PROGRAMS = dumpsexp if USE_RANDOM_DAEMON sbin_PROGRAMS = gcryptrnd -bin_PROGRAMS = getrandom +bin_PROGRAMS += getrandom endif USE_RANDOM_DAEMON + if HAVE_LD_VERSION_SCRIPT libgcrypt_version_script_cmd = -Wl,--version-script=$(srcdir)/libgcrypt.vers else @@ -92,6 +94,9 @@ @LTLIBOBJS@ @GPG_ERROR_LIBS@ +dumpsexp_SOURCES = dumpsexp.c +dumpsexp_LDADD = + if USE_RANDOM_DAEMON gcryptrnd_SOURCES = gcryptrnd.c gcryptrnd_CFLAGS = $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS) Added: trunk/src/dumpsexp.c =================================================================== --- trunk/src/dumpsexp.c 2007-08-22 09:52:59 UTC (rev 1261) +++ trunk/src/dumpsexp.c 2007-08-22 17:43:39 UTC (rev 1262) @@ -0,0 +1,560 @@ +/* dumpsexp.c - Dump S-expressions. + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * Getrandom 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. + * + * Getrandom 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PGM "dumpsexp" +#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION +#define BUGREPORT_LINE "\nReport bugs to .\n" + + +static int verbose; /* Verbose mode. */ +static int decimal; /* Print addresses in decimal. */ + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2007 Free Software Foundation, Inc.\n" + "License GPLv2+: GNU GPL version 2 or later " + "\n" + "This is free software: you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] [file]\n" + "Debug tool for S-expressions\n" + "\n" + " --verbose Show what we are doing\n" + " --version Print version of the program and exit\n" + " --help Display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + +static int +print_usage (void) +{ + fputs ("usage: " PGM " [OPTIONS] NBYTES\n", stderr); + fputs (" (use --help to display options)\n", stderr); + exit (1); +} + + +#define digit_p(a) ((a) >= '0' && (a) <= '9') +#define octdigit_p(a) ((a) >= '0' && (a) <= '7') +#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \ + || ((a) >= 'a' && (a) <= 'z')) +#define hexdigit_p(a) (digit_p (a) \ + || ((a) >= 'A' && (a) <= 'F') \ + || ((a) >= 'a' && (a) <= 'f')) + + +/* Return true if P points to a byte containing a whitespace according + to the S-expressions definition. */ +static inline int +whitespace_p (int c) +{ + switch (c) + { + case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1; + default: return 0; + } +} + +static void +logit (const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + fputs (PGM ": ", stderr); + vfprintf (stderr, format, arg_ptr); + putc ('\n', stderr); + va_end (arg_ptr); +} + +/* The raw data buffer and its current length */ +static unsigned char databuffer[16]; +static int databufferlen; +/* The number of bytes in databuffer which should be skipped at a flush. */ +static int skipdatabufferlen; +/* The number of raw bytes printed on the last line. */ +static int nbytesprinted; +/* The file offset of the current data buffer . */ +static unsigned long databufferoffset; + +/* Flush the raw data buffer. */ +static void +flushdatabuffer (void) +{ + int i; + + if (!databufferlen) + return; + nbytesprinted = 0; + if (decimal) + printf ("%08lu ", databufferoffset); + else + printf ("%08lx ", databufferoffset); + for (i=0; i < databufferlen; i++) + { + if (i == 8) + putchar (' '); + if (i < skipdatabufferlen) + fputs (" ", stdout); + else + { + printf (" %02x", databuffer[i]); + databufferoffset++; + } + nbytesprinted++; + } + for (; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + fputs (" ", stdout); + } + fputs (" |", stdout); + for (i=0; i < databufferlen; i++) + { + if (i < skipdatabufferlen) + putchar (' '); + else if (databuffer[i] >= ' ' && databuffer[i] <= '~' + && databuffer[i] != '|') + putchar (databuffer[i]); + else + putchar ('.'); + } + putchar ('|'); + putchar ('\n'); + databufferlen = 0; + skipdatabufferlen = 0; +} + + +/* Add C to the raw data buffer and flush as needed. */ +static void +addrawdata (int c) +{ + if ( databufferlen >= sizeof databuffer ) + flushdatabuffer (); + databuffer[databufferlen++] = c; +} + + +static void +printcursor (int both) +{ + int i; + + flushdatabuffer (); + printf ("%8s ", ""); + for (i=0; i < sizeof (databuffer); i++) + { + if (i == 8) + putchar (' '); + if (i+1 == nbytesprinted) + { + fputs (" ^ ", stdout); + if (!both) + break; + } + else + fputs (" ", stdout); + } + if (both) + { + fputs (" ", stdout); + for (i=0; i < nbytesprinted-1; i++) + putchar (' '); + putchar ('^'); + } + databufferlen = skipdatabufferlen = nbytesprinted; +} + +static void +printerr (const char *text) +{ + printcursor (1); + printf ("\n Error: %s\n", text); +} + +static void +printctl (const char *text) +{ + if (verbose) + { + printcursor (0); + printf ("%s\n", text); + } +} + +static void +printchr (int c) +{ +} + +static void +printhex (int c) +{ +} + + + + +static int +parse_and_print (FILE *fp) +{ + static const char tokenchars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-./_:*+="; + int c; + int level = 0; + int tokenc = 0; + int hexcount = 0; + int disphint = 0; + unsigned long datalen = 0; + char quote_buf[10]; + int quote_idx = 0; + enum + { + INIT_STATE = 0, IN_NUMBER, PRE_DATA, IN_DATA, IN_STRING, + IN_ESCAPE, IN_OCT_ESC, IN_HEX_ESC, + CR_ESC, LF_ESC, IN_HEXFMT, IN_BASE64 + } + state = INIT_STATE; + + + while ((c = getc (fp)) != EOF ) + { + addrawdata (c); + switch (state) + { + case INIT_STATE: + if (tokenc) + { + if (strchr (tokenchars, c)) + { + printchr (c); + continue; + } + tokenc = 0; + } + parse_init_state: + if (c == '(') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("open"); + level++; + } + else if (c == ')') + { + if (disphint) + { + printerr ("unmatched display hint"); + disphint = 0; + } + printctl ("close"); + level--; + } + else if (c == '\"') + { + state = IN_STRING; + printctl ("beginstring"); + } + else if (c == '#') + { + state = IN_HEXFMT; + hexcount = 0; + printctl ("beginhex"); + } + else if (c == '|') + { + state = IN_BASE64; + printctl ("beginbase64"); + } + else if (c == '[') + { + if (disphint) + printerr ("nested display hint"); + disphint = c; + } + else if (c == ']') + { + if (!disphint) + printerr ("no open display hint"); + disphint = 0; + } + else if (c >= '0' && c <= '9') + { + if (c == '0') + printerr ("zero prefixed length"); + state = IN_NUMBER; + datalen = (c - '0'); + } + else if (strchr (tokenchars, c)) + { + printchr (c); + tokenc = c; + } + else if (whitespace_p (c)) + ; + else if (c == '{') + { + printerr ("rescanning is not supported"); + } + else if (c == '&' || c == '\\') + { + printerr ("reserved punctuation detected"); + } + else + { + printerr ("bad character detected"); + } + break; + + case IN_NUMBER: + if (digit_p (c)) + { + unsigned long tmp = datalen * 10 + (c - '0'); + if (tmp < datalen) + { + printerr ("overflow in data length"); + state = INIT_STATE; + datalen = 0; + } + else + datalen = tmp; + } + else if (c == ':') + { + if (!datalen) + { + printerr ("no data length"); + state = INIT_STATE; + } + else + state = PRE_DATA; + } + else if (c == '\"' || c == '#' || c == '|' ) + { + /* We ignore the optional length and divert to the init + state parser code. */ + goto parse_init_state; + } + else + printerr ("invalid length specification"); + break; + + case PRE_DATA: + state = IN_DATA; + printctl ("begindata"); + case IN_DATA: + if (datalen) + { + printhex (c); + datalen--; + } + if (!datalen) + { + state = INIT_STATE; + printctl ("enddata"); + } + break; + + case IN_STRING: + if (c == '\"') + { + printctl ("endstring"); + state = INIT_STATE; + } + else if (c == '\\') + state = IN_ESCAPE; + else + printchr (c); + break; + + case IN_ESCAPE: + switch (c) + { + case 'b': case 't': case 'v': case 'n': case 'f': + case 'r': case '"': case '\'': case '\\': + printhex (c); + state = IN_STRING; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + state = IN_OCT_ESC; + quote_idx = 0; + quote_buf[quote_idx++] = c; + break; + + case 'x': + state = IN_HEX_ESC; + quote_idx = 0; + break; + + case '\r': + state = CR_ESC; + break; + + case '\n': + state = LF_ESC; + break; + + default: + printerr ("invalid escape sequence"); + state = IN_STRING; + break; + } + + case IN_OCT_ESC: + state = IN_STRING; + break; + case IN_HEX_ESC: + state = IN_STRING; + break; + case CR_ESC: + state = IN_STRING; + break; + case LF_ESC: + state = IN_STRING; + break; + + case IN_HEXFMT: + if (hexdigit_p (c)) + { + printchr (c); + hexcount++; + } + else if (c == '#') + { + if ((hexcount & 1)) + printerr ("odd number of hex digits"); + printctl ("endhex"); + state = INIT_STATE; + } + else if (!whitespace_p (c)) + printerr ("bad hex character"); + break; + + case IN_BASE64: + if (c == '|') + { + printctl ("endbase64"); + state = INIT_STATE; + } + else + printchr (c); + break; + + default: + logit ("invalid state %d detected", state); + exit (1); + } + } + flushdatabuffer (); + if (ferror (fp)) + { + logit ("error reading input: %s\n", strerror (errno)); + return -1; + } + return 0; +} + + + +int +main (int argc, char **argv) +{ + int rc; + + if (argc) + { + argc--; argv++; + } + while (argc && **argv == '-' && (*argv)[1] == '-') + { + if (!(*argv)[2]) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--verbose")) + { + argc--; argv++; + verbose = 1; + } + else if (!strcmp (*argv, "--decimal")) + { + argc--; argv++; + decimal = 1; + } + else + print_usage (); + } + + if (!argc) + { + rc = parse_and_print (stdin); + } + else + { + for (; argc; argc--) + { + FILE *fp = fopen (*argv, "rb"); + if (!fp) + { + logit ("can't open `%s': %s\n", *argv, strerror (errno)); + rc = 1; + } + else + { + if ( parse_and_print (fp) ) + rc = 1; + fclose (fp); + } + } + } + + + return !rc; +} + From cvs at cvs.gnupg.org Wed Aug 22 22:37:03 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 22 Aug 2007 22:37:03 +0200 Subject: [svn] GnuPG - r4566 - in trunk: agent jnlib sm Message-ID: Author: wk Date: 2007-08-22 22:36:33 +0200 (Wed, 22 Aug 2007) New Revision: 4566 Modified: trunk/agent/ChangeLog trunk/agent/findkey.c trunk/jnlib/logging.h trunk/sm/ChangeLog trunk/sm/certreqgen.c Log: Fixed creation of private keys under W32. Minor code cleanups. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) +++ trunk/agent/ChangeLog 2007-08-22 20:36:33 UTC (rev 4566) @@ -1,5 +1,8 @@ 2007-08-22 Werner Koch + * findkey.c (O_BINARY): Make sure it is defined. + (agent_write_private_key): Use O_BINARY + * protect-tool.c (import_p12_file): Add hack to allow importing of gnupg 2.0.4 generated files. Modified: trunk/agent/findkey.c =================================================================== --- trunk/agent/findkey.c 2007-08-22 10:55:07 UTC (rev 4565) +++ trunk/agent/findkey.c 2007-08-22 20:36:33 UTC (rev 4566) @@ -32,6 +32,10 @@ #include "agent.h" +#ifndef O_BINARY +#define O_BINARY 0 +#endif + /* Helper to pass data to the check callback of the unprotect function. */ struct try_unprotect_arg_s { const unsigned char *protected_key; @@ -70,8 +74,8 @@ POSIX (GNU provides the "x" opentype for fopen, however, this is not portable). Thus, we use the more flexible open function and then use fdopen to obtain a stream. */ - fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY) - : (O_CREAT | O_EXCL | O_WRONLY), + fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY | O_BINARY) + : (O_CREAT | O_EXCL | O_WRONLY | O_BINARY), S_IRUSR | S_IWUSR #ifndef HAVE_W32_SYSTEM | S_IRGRP Modified: trunk/jnlib/logging.h =================================================================== --- trunk/jnlib/logging.h 2007-08-22 10:55:07 UTC (rev 4565) +++ trunk/jnlib/logging.h 2007-08-22 20:36:33 UTC (rev 4566) @@ -71,6 +71,11 @@ void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); + +/* Print a hexdump of BUFFER. With TEXT passes as NULL print just the + raw dump, with TEXT being an empty string, print a trailing + linefeed, otherwise print an entire debug line with TEXT followed + by the hexdump and a final LF. */ void log_printhex (const char *text, const void *buffer, size_t length); Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-22 10:55:07 UTC (rev 4565) +++ trunk/sm/ChangeLog 2007-08-22 20:36:33 UTC (rev 4566) @@ -1,5 +1,7 @@ 2007-08-22 Werner Koch + * certreqgen.c (create_request): Replace open coding by bin2hex. + * certreqgen-ui.c (gpgsm_gencertreq_tty): Use es_fopenmem. 2007-08-21 Werner Koch Modified: trunk/sm/certreqgen.c =================================================================== --- trunk/sm/certreqgen.c 2007-08-22 10:55:07 UTC (rev 4565) +++ trunk/sm/certreqgen.c 2007-08-22 20:36:33 UTC (rev 4566) @@ -1,5 +1,5 @@ /* certreqgen.c - Generate a key and a certification request - * Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -786,8 +786,7 @@ goto leave; } gcry_sexp_release (s_pkey); - for (n=0; n < 20; n++) - sprintf (hexgrip+n*2, "%02X", grip[n]); + bin2hex (grip, 20, hexgrip); if (carddirect) rc = gpgsm_scd_pksign (ctrl, carddirect, NULL, From cvs at cvs.gnupg.org Thu Aug 23 09:29:44 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 09:29:44 +0200 Subject: [svn] gcry - r1263 - in trunk: . cipher doc src Message-ID: Author: wk Date: 2007-08-23 09:29:14 +0200 (Thu, 23 Aug 2007) New Revision: 1263 Modified: trunk/TODO trunk/cipher/ChangeLog trunk/cipher/random.c trunk/doc/gcrypt.texi trunk/src/dumpsexp.c Log: Use extra counter to check random pool filling. Updated the documentation. Typo and comment fixes. Modified: trunk/TODO =================================================================== --- trunk/TODO 2007-08-22 17:43:39 UTC (rev 1262) +++ trunk/TODO 2007-08-23 07:29:14 UTC (rev 1263) @@ -26,6 +26,8 @@ the asymmetric ciphers could be changed for convenient interaction with the ac interface (i.e. by using ac's `data sets') and the pk interface could be changed to be a wrapper for the ac interface. + ==> It is unlikely that we will do that. The AC interafce turned + out to be more complicated than the regular one. * cipher/pubkey.c and pubkey implementaions. Don't rely on the secure memory based wiping function but add an @@ -34,19 +36,6 @@ * update/improve documentation ** it's outdated for e.g. gcry_pk_algo_info. ** document algorithm capabilities -** Explain seed files and correlation - Multiple instances of the applications sharing the same random seed - file can be started in parallel, in which case they will read out - the same pool and then race for updating it (the last update - overwrites earlier updates). They will differentiate only by the - weak entropy that is added in read_seed_file based on the PID and - clock, and up to 16 bytes of weak random non-blockingly. The - consequence is that the output of these different instances is - correlated to some extent. In the perfect scenario, the attacker - can control (or at least guess) the PID and clock of the - application, and drain the system's entropy pool to reduce the "up - to 16 bytes" above to 0. Then the dependencies of the inital states - of the pools are completely known. ** Init requirements for random The documentation says in "Controlling the library" that some functions can only be used at initialization time, but it does not @@ -72,7 +61,7 @@ * Use builtin bit functions of gcc 3.4 -* Consider using a daemon to maintaint he random pool +* Consider using a daemon to maintain the random pool [Partly done] The down side of this is that we can't assume that the random has has always been stored in "secure memory". And we rely on that sniffing of Unix domain sockets is not possible. We can @@ -102,18 +91,6 @@ * gcryptrnd.c Requires a test for pth [done] as well as some other tests. -* random.c - If add_randomness is invoked before the pool is filled, but with a - weak source of entropy, for example the fast random poll, which - may happen from other parts of gcrypt, then the pool is filled - partially with weak random, defeating the purpose of pool_filled - and the "source > 1" check in add_randomness. - - Suggestion: Count initial filling bytes with source > 1 in - add_randomness seperately from the pool_writepos cursor. Only set - pool_filled if really POOLSIZE bytes with source > 1 have been - added. - * secmem.c Check whether the memory block is valid before releasing it and print a diagnosic, like glibc does. Modified: trunk/cipher/ChangeLog =================================================================== --- trunk/cipher/ChangeLog 2007-08-22 17:43:39 UTC (rev 1262) +++ trunk/cipher/ChangeLog 2007-08-23 07:29:14 UTC (rev 1263) @@ -1,3 +1,8 @@ +2007-08-23 Werner Koch + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + 2007-08-22 Werner Koch * rndw32.c, rndunix.c: Switched to LGPL. Modified: trunk/cipher/random.c =================================================================== --- trunk/cipher/random.c 2007-08-22 17:43:39 UTC (rev 1262) +++ trunk/cipher/random.c 2007-08-23 07:29:14 UTC (rev 1263) @@ -112,10 +112,14 @@ static size_t pool_readpos; /* This flag is set to true as soon as the pool has been completely - filles. This may happen either by rerading a seed file or by - adding enough entropy. */ + filled the first time. This may happen either by rereading a seed + file or by adding enough entropy. */ static int pool_filled; +/* This counter is used to track whether the initial seeding has been + done with enough bytes from a reliable entropy source. */ +static size_t pool_filled_counter; + /* If random of level GCRY_VERY_STRONG_RANDOM has been requested we have stricter requirements on what kind of entropy is in the pool. In particular POOL_FILLED is not sufficient. Thus we add some @@ -133,7 +137,7 @@ static int just_mixed; /* The name of the seed file or NULL if no seed file has been defined. - The seed file needs to be regsitered at initialiation time. we + The seed file needs to be regsitered at initialiation time. We keep a malloced copy here. */ static char *seed_file_name; @@ -742,8 +746,21 @@ } -/* Read in a seed form the random_seed file - and return true if this was successful. */ +/* Read in a seed from the random_seed file and return true if this + was successful. + + Note: Multiple instances of applications sharing the same random + seed file can be started in parallel, in which case they will read + out the same pool and then race for updating it (the last update + overwrites earlier updates). They will differentiate only by the + weak entropy that is added in read_seed_file based on the PID and + clock, and up to 16 bytes of weak random non-blockingly. The + consequence is that the output of these different instances is + correlated to some extent. In the perfect scenario, the attacker + can control (or at least guess) the PID and clock of the + application, and drain the system's entropy pool to reduce the "up + to 16 bytes" above to 0. Then the dependencies of the inital + states of the pools are completely known. */ static int read_seed_file (void) { @@ -837,7 +854,7 @@ /* And read a few bytes from our entropy source. By using a level * of 0 this will not block and might not return anything with some * entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read to much as we + * /dev/urandom and return some stuff - Do not read too much as we * want to be friendly to the scare system entropy resource. */ read_random_source ( RANDOM_ORIGIN_INIT, 16, GCRY_WEAK_RANDOM ); @@ -927,7 +944,7 @@ /* Read random out of the pool. This function is the core of the public random functions. Note that Level GCRY_WEAK_RANDOM is not - anymore handled special and in fact is an alias in teh API for + anymore handled special and in fact is an alias in the API for level GCRY_STRONG_RANDOM. Must be called with the pool already locked. */ static void @@ -1059,8 +1076,8 @@ /* We need to detect whether a fork has happened. A fork might have an identical pool and thus the child and the parent could emit the very same random number. This test here is to detect forks - in a multi-threaded process. It does not work with all trhead - implementaions in particualr not with pthreads. However it is + in a multi-threaded process. It does not work with all thread + implementations in particular not with pthreads. However it is good enough for GNU Pth. */ if ( getpid () != my_pid2 ) { @@ -1091,8 +1108,16 @@ rndpool[pool_writepos++] ^= *p++; if (pool_writepos >= POOLSIZE ) { - if (origin >= RANDOM_ORIGIN_SLOWPOLL) - pool_filled = 1; + /* It is possible that we are invoked before the pool is + filled using an unreliable origin of entropy, for example + the fast random poll. To avoid flagging the pool as + filled in this case, we track the initial filling state + separately. See also the remarks about the seed file. */ + if (origin >= RANDOM_ORIGIN_SLOWPOLL && !pool_filled) + { + if (++pool_filled_counter >= POOLSIZE) + pool_filled = 1; + } pool_writepos = 0; mix_pool(rndpool); rndstats.mixrnd++; just_mixed = !length; Modified: trunk/doc/gcrypt.texi =================================================================== --- trunk/doc/gcrypt.texi 2007-08-22 17:43:39 UTC (rev 1262) +++ trunk/doc/gcrypt.texi 2007-08-23 07:29:14 UTC (rev 1263) @@ -570,14 +570,29 @@ This command specifies the file, which is to be used as seed file for the PRNG. If the seed file is registered prior to initialization of the PRNG, the seed file's content (if it exists and seems to be valid) is -feed into the PRNG pool. After the seed file has been registered, the +fed into the PRNG pool. After the seed file has been registered, the PRNG can be signalled to write out the PRNG pool's content into the seed file with the following command. + @item GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none Write out the PRNG pool's content into the registered seed file. +Multiple instances of the applications sharing the same random seed file +can be started in parallel, in which case they will read out the same +pool and then race for updating it (the last update overwrites earlier +updates). They will differentiate only by the weak entropy that is +added in read_seed_file based on the PID and clock, and up to 16 bytes +of weak random non-blockingly. The consequence is that the output of +these different instances is correlated to some extent. In the perfect +scenario, the attacker can control (or at least guess) the PID and clock +of the application, and drain the system's entropy pool to reduce the +"up to 16 bytes" above to 0. Then the dependencies of the inital states +of the pools are completely known. Note that this is not an issue if +random of @code{GCRY_VERY_STRONG_RANDOM} quality is requested as in this +case enough extra entropy gets mixed. + @item GCRYCTL_SET_VERBOSITY @@ -1241,6 +1256,12 @@ @item GCRY_CIPHER_SEED A 128 bit cipher as described by RFC4269. + at item GCRY_CIPHER_CAMELLIA128 + at itemx GCRY_CIPHER_CAMELLIA192 + at itemx GCRY_CIPHER_CAMELLIA256 +The Camellia cipher by NTT. See + at uref{http://info.isl.ntt.co.jp/@/crypt/@/eng/@/camellia/@/specifications.html}. + @end table @node Cipher modules Modified: trunk/src/dumpsexp.c =================================================================== --- trunk/src/dumpsexp.c 2007-08-22 17:43:39 UTC (rev 1262) +++ trunk/src/dumpsexp.c 2007-08-23 07:29:14 UTC (rev 1263) @@ -32,6 +32,7 @@ static int verbose; /* Verbose mode. */ static int decimal; /* Print addresses in decimal. */ +static int assume_hex; /* Assume input is hexencoded. */ static void print_version (int with_help) @@ -49,6 +50,8 @@ "Usage: " PGM " [OPTIONS] [file]\n" "Debug tool for S-expressions\n" "\n" + " --decimal Print offsetc using decimal notation\n" + " --assume-hex Assume input is a hex dump\n" " --verbose Show what we are doing\n" " --version Print version of the program and exit\n" " --help Display this help and exit\n" @@ -66,13 +69,16 @@ } -#define digit_p(a) ((a) >= '0' && (a) <= '9') +#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') +#define digit_p(a) ((a) >= '0' && (a) <= '9') #define octdigit_p(a) ((a) >= '0' && (a) <= '7') #define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \ || ((a) >= 'a' && (a) <= 'z')) #define hexdigit_p(a) (digit_p (a) \ || ((a) >= 'A' && (a) <= 'F') \ || ((a) >= 'a' && (a) <= 'f')) +#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \ + (a) <= 'F'? ((a)-'A'+10):((a)-'a'+10)) /* Return true if P points to a byte containing a whitespace according @@ -109,6 +115,46 @@ /* The file offset of the current data buffer . */ static unsigned long databufferoffset; + + +static int +my_getc (FILE *fp) +{ + int c1, c2; + + if (!assume_hex) + return getc (fp); + + while ( (c1=getc (fp)) != EOF && space_p (c1) ) + ; + if (c1 == EOF) + return EOF; + + if (!hexdigit_p (c1)) + { + logit ("non hex-digit encountered\n"); + return EOF; + } + + while ( (c2=getc (fp)) != EOF && space_p (c2) ) + ; + if (c2 == EOF) + { + logit ("error reading second hex nibble\n"); + return EOF; + } + if (!hexdigit_p (c2)) + { + logit ("second hex nibble is not a hex-digit\n"); + return EOF; + } + return xtoi_1 (c1) * 16 + xtoi_1 (c2); +} + + + + + /* Flush the raw data buffer. */ static void flushdatabuffer (void) @@ -229,6 +275,8 @@ + + static int parse_and_print (FILE *fp) { @@ -253,7 +301,7 @@ state = INIT_STATE; - while ((c = getc (fp)) != EOF ) + while ((c = my_getc (fp)) != EOF ) { addrawdata (c); switch (state) @@ -527,6 +575,11 @@ argc--; argv++; decimal = 1; } + else if (!strcmp (*argv, "--assume-hex")) + { + argc--; argv++; + assume_hex = 1; + } else print_usage (); } From cvs at cvs.gnupg.org Thu Aug 23 10:40:40 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 10:40:40 +0200 Subject: [svn] GnuPG - r4567 - trunk/common Message-ID: Author: wk Date: 2007-08-23 10:40:11 +0200 (Thu, 23 Aug 2007) New Revision: 4567 Added: trunk/common/t-sysutils.c Log: Add missing file Added: trunk/common/t-sysutils.c =================================================================== --- trunk/common/t-sysutils.c 2007-08-22 20:36:33 UTC (rev 4566) +++ trunk/common/t-sysutils.c 2007-08-23 08:40:11 UTC (rev 4567) @@ -0,0 +1,85 @@ +/* t-sysutils.c - Module test for sysutils.c + * Copyright (C) 2007 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 3 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, see . + */ + +#include +#include +#include + +#include "util.h" +#include "sysutils.h" + +#define pass() do { ; } while(0) +#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ + __FILE__,__LINE__, (a)); \ + errcount++; \ + } while(0) + +static int verbose; +static int errcount; + + +static void +test_gnupg_tmpfile (void) +{ + FILE *fparr[10]; + int fparridx; + int idx; + FILE *fp; + char buffer[100]; + +#define ASTRING "fooooooooooooooo\n" /* Needs to be shorter than BUFFER. */ + + for (fparridx=0; fparridx < DIM (fparr); fparridx++) + { + fp = gnupg_tmpfile (); + fparr[fparridx] = fp; + if (!fp) + fail (fparridx); + else + { + fputs ( ASTRING, fp); + rewind (fp); + if (!fgets (buffer, sizeof (buffer), fp)) + fail (fparridx); + if (strcmp (buffer, ASTRING)) + fail (fparridx); + if (fgets (buffer, sizeof (buffer), fp)) + fail (fparridx); + } + } + for (idx=0; idx < fparridx; idx++) + { + if (fparr[idx]) + fclose (fparr[idx]); + } +} + + + +int +main (int argc, char **argv) +{ + if (argc > 1 && !strcmp (argv[1], "--verbose")) + verbose = 1; + + test_gnupg_tmpfile (); + + return !!errcount; +} + From cvs at cvs.gnupg.org Thu Aug 23 11:56:46 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 11:56:46 +0200 Subject: [svn] dirmngr - r266 - in trunk: . doc doc/examples doc/examples/extra-certs doc/examples/trusted-certs Message-ID: Author: wk Date: 2007-08-23 11:56:16 +0200 (Thu, 23 Aug 2007) New Revision: 266 Added: trunk/doc/examples/ trunk/doc/examples/Makefile.am trunk/doc/examples/README trunk/doc/examples/bnetza-10r-ocsp.signer trunk/doc/examples/dirmngr.conf trunk/doc/examples/extra-certs/ trunk/doc/examples/extra-certs/bnetza-10r-ocsp-1.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-10.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-11.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-12.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-2.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-3.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-4.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-5.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-6.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-7.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-8.crt trunk/doc/examples/extra-certs/bnetza-10r-ocsp-9.crt trunk/doc/examples/trusted-certs/ trunk/doc/examples/trusted-certs/README trunk/doc/examples/trusted-certs/bnetza-10r-ca.crt Modified: trunk/ChangeLog trunk/configure.ac trunk/doc/Makefile.am Log: Add example files Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/ChangeLog 2007-08-23 09:56:16 UTC (rev 266) @@ -1,3 +1,8 @@ +2007-08-23 Werner Koch + + * doc/Makefile.am (SUBDIRS): New. + * doc/examples/: New. + 2007-08-16 Werner Koch Release 1.0.1. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/configure.ac 2007-08-23 09:56:16 UTC (rev 266) @@ -458,6 +458,7 @@ jnlib/Makefile src/Makefile doc/Makefile +doc/examples/Makefile tests/Makefile ]) AC_OUTPUT Modified: trunk/doc/Makefile.am =================================================================== --- trunk/doc/Makefile.am 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/Makefile.am 2007-08-23 09:56:16 UTC (rev 266) @@ -21,6 +21,8 @@ EXTRA_DIST = internals.texi see-also-note.texi yat2m.c +SUBDIRS = . examples + AM_MAKEFINFOFLAGS = -I $(srcdir) --css-include=/dev/null YAT2M_OPTIONS = -I $(srcdir) \ Added: trunk/doc/examples/Makefile.am =================================================================== --- trunk/doc/examples/Makefile.am 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/examples/Makefile.am 2007-08-23 09:56:16 UTC (rev 266) @@ -0,0 +1,19 @@ + +EXTRA_DIST = README dirmngr.conf bnetza-10r-ocsp.signer + +EXTRA_DIST += trusted-certs/README \ + trusted-certs/bnetza-10r-ca.crt + +EXTRA_DIST += extra-certs/bnetza-10r-ocsp-1.crt \ + extra-certs/bnetza-10r-ocsp-2.crt \ + extra-certs/bnetza-10r-ocsp-3.crt \ + extra-certs/bnetza-10r-ocsp-4.crt \ + extra-certs/bnetza-10r-ocsp-5.crt \ + extra-certs/bnetza-10r-ocsp-6.crt \ + extra-certs/bnetza-10r-ocsp-7.crt \ + extra-certs/bnetza-10r-ocsp-8.crt \ + extra-certs/bnetza-10r-ocsp-9.crt \ + extra-certs/bnetza-10r-ocsp-10.crt \ + extra-certs/bnetza-10r-ocsp-11.crt \ + extra-certs/bnetza-10r-ocsp-12.crt + Added: trunk/doc/examples/README =================================================================== --- trunk/doc/examples/README 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/examples/README 2007-08-23 09:56:16 UTC (rev 266) @@ -0,0 +1,13 @@ +Files in this directory: + + +dirmngr.conf A sample configuration file. + +bnetza-10r-ocsp.signer OCSP signer certificate fingerprints of the + Bundesnetzagentur. Valid until 2007-12-31. + +trusted-certs/ A directory with trusted root certificates. + +extra-certs/ A directory with other useful certificates; + they are usually installed at + /var/lib/dirmngr/extra-certs/ . Added: trunk/doc/examples/bnetza-10r-ocsp.signer =================================================================== --- trunk/doc/examples/bnetza-10r-ocsp.signer 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/examples/bnetza-10r-ocsp.signer 2007-08-23 09:56:16 UTC (rev 266) @@ -0,0 +1,34 @@ +# bnetza-10r-ocsp.signer -*- generic -*- +# List of all OCSP certificates used by the Bundesnetzagentur. +# This file may be used with --ocsp-signer to allow for multiple +# response signer certificates. Use these lines in dirmngr.conf: +# +# ocsp-responder http://ocsp.nrca-ds.de:8080/ocsp-ocspresponder +# ocsp-signer bnetza-10r-ocsp.txt +# + +#31/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +EB:DD:B3:DE:07:9B:6E:DE:F3:C9:54:63:E8:23:4E:D2:04:3B:B2:F5 +#35/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +4A:28:12:05:6F:9C:07:73:69:10:4F:2F:F5:A2:22:43:16:ED:85:2F +#36/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +8A:38:F4:9B:7F:16:1F:EC:CA:E5:F2:F5:03:63:EA:B7:98:62:3E:B9 +#37/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +1A:22:01:3F:FA:64:2F:F1:1B:D3:80:F7:44:B4:20:5C:1E:56:15:60 +#38/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +C5:4C:2E:53:F2:E6:7B:67:D7:F9:9E:22:CE:4E:F0:DC:93:81:E6:6E +#39/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +8A:7B:96:5C:B3:BA:6F:F3:D4:E2:82:CD:44:8A:79:83:35:21:68:32 +#3E/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +40:BA:29:69:C6:4E:51:B5:74:B4:FF:88:1E:0D:C1:1A:AD:FC:42:BB +#3F/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +A8:C1:BD:8E:54:C3:A5:25:C9:5D:A6:7D:1F:04:D2:5D:4F:9E:04:97 +#32/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +FE:EA:3D:E1:E5:FD:04:EA:FA:95:A1:1D:AE:BA:7E:55:12:FE:76:56 +#40/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +60:3F:6A:4D:A4:40:6F:EF:23:6D:24:03:22:60:F3:93:8E:5D:C5:48 +#41/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +95:76:1A:20:5C:5D:84:79:D5:F0:DC:53:E1:61:1B:9D:97:30:D6:58 +#33/CN=10R-CA 1:PN,O=Bundesnetzagentur,C=DE +6F:02:77:58:3F:F1:C2:8E:9F:98:E0:D4:B3:BE:36:37:C6:83:2C:BD + Added: trunk/doc/examples/dirmngr.conf =================================================================== --- trunk/doc/examples/dirmngr.conf 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/examples/dirmngr.conf 2007-08-23 09:56:16 UTC (rev 266) @@ -0,0 +1,12 @@ +# Sample configuration file for dirmngr + +log-file /var/log/dirmngr/dirmngr.log + +allow-ocsp + +ocsp-responder http://ocsp.nrca-ds.de:8080/ocsp-ocspresponder +ocsp-signer bnetza-10r-ocsp.txt +ocsp-current-period 86400 + + + Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-1.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-1.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-10.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-10.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-11.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-11.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-12.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-12.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-2.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-2.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-3.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-3.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-4.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-4.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-5.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-5.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-6.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-6.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-7.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-7.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-8.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-8.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-9.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/extra-certs/bnetza-10r-ocsp-9.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/doc/examples/trusted-certs/README =================================================================== --- trunk/doc/examples/trusted-certs/README 2007-08-16 13:49:05 UTC (rev 265) +++ trunk/doc/examples/trusted-certs/README 2007-08-23 09:56:16 UTC (rev 266) @@ -0,0 +1,4 @@ +These certificates are trusted and thus make up an anchor for a certificate +chain. Note that only DER encoded certificates with the suffix ".crt" are +used. They are loded at dirmngr startup. + Added: trunk/doc/examples/trusted-certs/bnetza-10r-ca.crt =================================================================== (Binary files differ) Property changes on: trunk/doc/examples/trusted-certs/bnetza-10r-ca.crt ___________________________________________________________________ Name: svn:mime-type + application/octet-stream From cvs at cvs.gnupg.org Thu Aug 23 12:14:23 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 12:14:23 +0200 Subject: [svn] GpgEX - r1 - / Message-ID: Author: wk Date: 2007-08-23 12:13:55 +0200 (Thu, 23 Aug 2007) New Revision: 1 Added: branches/ tags/ trunk/ Log: New repository From cvs at cvs.gnupg.org Thu Aug 23 19:47:09 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 19:47:09 +0200 Subject: [svn] gpg-error - r197 - trunk/po Message-ID: Author: wk Date: 2007-08-23 19:46:39 +0200 (Thu, 23 Aug 2007) New Revision: 197 Modified: trunk/po/ChangeLog trunk/po/de.po Log: Typo fix Modified: trunk/po/ChangeLog =================================================================== --- trunk/po/ChangeLog 2007-08-03 09:01:33 UTC (rev 196) +++ trunk/po/ChangeLog 2007-08-23 17:46:39 UTC (rev 197) @@ -1,3 +1,7 @@ +2007-08-23 Werner Koch + + * de.po: Typo fix [bug#828]. + 2007-02-26 Werner Koch * sv.po: Update from Daniel. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-08-03 09:01:33 UTC (rev 196) +++ trunk/po/de.po 2007-08-23 17:46:39 UTC (rev 197) @@ -8,7 +8,7 @@ "Project-Id-Version: libgpg-error-1.4\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" "POT-Creation-Date: 2006-11-30 15:57+0100\n" -"PO-Revision-Date: 2006-09-14 15:11+0200\n" +"PO-Revision-Date: 2007-08-23 19:40+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: none\n" "MIME-Version: 1.0\n" @@ -197,7 +197,7 @@ #: src/err-codes.h:55 msgid "Not found" -msgstr "Nich gefunden" +msgstr "Nicht gefunden" #: src/err-codes.h:56 msgid "Value not found" From cvs at cvs.gnupg.org Thu Aug 23 19:41:52 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 23 Aug 2007 19:41:52 +0200 Subject: [svn] GnuPG - r4568 - in trunk: kbx sm Message-ID: Author: wk Date: 2007-08-23 19:41:22 +0200 (Thu, 23 Aug 2007) New Revision: 4568 Modified: trunk/kbx/ChangeLog trunk/kbx/kbxutil.c trunk/kbx/keybox-defs.h trunk/kbx/keybox-dump.c trunk/sm/ChangeLog trunk/sm/certlist.c trunk/sm/export.c trunk/sm/gpgsm.h Log: Add new features to kbxutil. Fixed bug 829 (can't encrypt if duplicated certs are in the keybox) Modified: trunk/kbx/ChangeLog =================================================================== --- trunk/kbx/ChangeLog 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/kbx/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,3 +1,12 @@ +2007-08-23 Werner Koch + + * kbxutil.c: New commands --find-dups and --cut. New options + --from an --to. + * keybox-dump.c (hash_blob_rawdata): New. + (_keybox_dump_find_dups): New. + (open_file): Factor some code out to this. + (_keybox_dump_cut_records): New. + 2007-06-26 Werner Koch * kbxutil.c: Include init.h Modified: trunk/kbx/kbxutil.c =================================================================== --- trunk/kbx/kbxutil.c 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/kbx/kbxutil.c 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,5 +1,5 @@ /* kbxutil.c - The Keybox utility - * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include #include #include +#include #include #define JNLIB_NEED_LOG_LOGV @@ -52,12 +53,15 @@ aFindByUid, aStats, aImportOpenPGP, + aFindDups, + aCut, oDebug, oDebugAll, oNoArmor, - + oFrom, + oTo, aTest }; @@ -71,9 +75,13 @@ /* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */ { aStats, "stats", 0, "show key statistics" }, { aImportOpenPGP, "import-openpgp", 0, "import OpenPGP keyblocks"}, + { aFindDups, "find-dups", 0, "find duplicates" }, + { aCut, "cut", 0, "export records" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, + { oFrom, "from", 4, "|N|first record to export" }, + { oTo, "to", 4, "|N|last record to export" }, /* { oArmor, "armor", 0, N_("create ascii armored output")}, */ /* { oArmor, "armour", 0, "@" }, */ /* { oOutput, "output", 2, N_("use as output file")}, */ @@ -402,6 +410,7 @@ { ARGPARSE_ARGS pargs; enum cmd_and_opt_values cmd = 0; + unsigned long from = 0, to = ULONG_MAX; set_strusage( my_strusage ); gcry_control (GCRYCTL_DISABLE_SECMEM); @@ -452,14 +461,24 @@ case aFindByUid: case aStats: case aImportOpenPGP: + case aFindDups: + case aCut: cmd = pargs.r_opt; break; + case oFrom: from = pargs.r.ret_ulong; break; + case oTo: to = pargs.r.ret_ulong; break; + default: pargs.err = 2; break; } } + + if (to < from) + log_error ("record number of \"--to\" is lower than \"--from\" one\n"); + + if (log_get_errorcount(0) ) myexit(2); @@ -483,6 +502,26 @@ _keybox_dump_file (*argv, 1, stdout); } } + else if (cmd == aFindDups ) + { + if (!argc) + _keybox_dump_find_dups (NULL, 0, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_find_dups (*argv, 0, stdout); + } + } + else if (cmd == aCut ) + { + if (!argc) + _keybox_dump_cut_records (NULL, from, to, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_cut_records (*argv, from, to, stdout); + } + } else if (cmd == aImportOpenPGP) { if (!argc) Modified: trunk/kbx/keybox-defs.h =================================================================== --- trunk/kbx/keybox-defs.h 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/kbx/keybox-defs.h 2007-08-23 17:41:22 UTC (rev 4568) @@ -169,6 +169,9 @@ /*-- keybox-dump.c --*/ int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp); +int _keybox_dump_find_dups (const char *filename, int print_them, FILE *outfp); +int _keybox_dump_cut_records (const char *filename, unsigned long from, + unsigned long to, FILE *outfp); /*-- keybox-util.c --*/ @@ -186,7 +189,7 @@ #define DIM(v) (sizeof(v)/sizeof((v)[0])) #define DIMof(type,member) DIM(((type *)0)->member) #ifndef STR - #define STR(v) #v +# define STR(v) #v #endif #define STR2(v) STR(v) Modified: trunk/kbx/keybox-dump.c =================================================================== --- trunk/kbx/keybox-dump.c 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/kbx/keybox-dump.c 2007-08-23 17:41:22 UTC (rev 4568) @@ -24,7 +24,12 @@ #include #include "keybox-defs.h" +#include +/* Argg, we can't include ../common/util.h */ +char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf); + + static ulong get32 (const byte *buffer) { @@ -183,6 +188,9 @@ fprintf( fp, "Data-Offset: %lu\n", rawdata_off ); fprintf( fp, "Data-Length: %lu\n", rawdata_len ); + if (rawdata_off > length || rawdata_len > length + || rawdata_off+rawdata_off > length) + fprintf (fp, "[Error: raw data larger than blob]\n"); nkeys = get16 (buffer + 16); fprintf (fp, "Key-Count: %lu\n", nkeys ); @@ -322,6 +330,53 @@ } +/* Compute the SHA_1 checksum of teh rawdata in BLOB and aput it into + DIGEST. */ +static int +hash_blob_rawdata (KEYBOXBLOB blob, unsigned char *digest) +{ + const unsigned char *buffer; + size_t n, length; + int type; + ulong rawdata_off, rawdata_len; + + buffer = _keybox_get_blob_image (blob, &length); + + if (length < 32) + return -1; + n = get32 (buffer); + if (n < length) + length = n; /* Blob larger than length in header - ignore the rest. */ + + type = buffer[4]; + switch (type) + { + case BLOBTYPE_PGP: + case BLOBTYPE_X509: + break; + + case BLOBTYPE_EMPTY: + case BLOBTYPE_HEADER: + default: + memset (digest, 0, 20); + return 0; + } + + if (length < 40) + return -1; + + rawdata_off = get32 (buffer + 8); + rawdata_len = get32 (buffer + 12); + + if (rawdata_off > length || rawdata_len > length + || rawdata_off+rawdata_off > length) + return -1; /* Out of bounds. */ + + gcry_md_hash_buffer (GCRY_MD_SHA1, digest, buffer+rawdata_off, rawdata_len); + return 0; +} + + struct file_stats_s { unsigned long too_short_blobs; @@ -401,6 +456,29 @@ +static FILE * +open_file (const char **filename, FILE *outfp) +{ + FILE *fp; + + if (!*filename) + { + *filename = "-"; + fp = stdin; + } + else + fp = fopen (*filename, "rb"); + if (!fp) + { + int save_errno = errno; + fprintf (outfp, "can't open `%s': %s\n", *filename, strerror(errno)); + errno = save_errno; + } + return fp; +} + + + int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp) { @@ -412,19 +490,8 @@ memset (&stats, 0, sizeof stats); - if (!filename) - { - filename = "-"; - fp = stdin; - } - else - fp = fopen (filename, "rb"); - if (!fp) - { - gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); - fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno)); - return tmperr; - } + if (!(fp = open_file (&filename, outfp))) + return gpg_error_from_syserror (); while ( !(rc = _keybox_read_blob (&blob, fp)) ) { @@ -481,3 +548,150 @@ return rc; } + + + +struct dupitem_s +{ + unsigned long recno; + unsigned char digest[20]; +}; + + +static int +cmp_dupitems (const void *arg_a, const void *arg_b) +{ + struct dupitem_s *a = (struct dupitem_s *)arg_a; + struct dupitem_s *b = (struct dupitem_s *)arg_b; + + return memcmp (a->digest, b->digest, 20); +} + + +int +_keybox_dump_find_dups (const char *filename, int print_them, FILE *outfp) +{ + FILE *fp; + KEYBOXBLOB blob; + int rc; + unsigned long recno = 0; + unsigned char zerodigest[20]; + struct dupitem_s *dupitems; + size_t dupitems_size, dupitems_count, lastn, n; + char fprbuf[3*20+1]; + + memset (zerodigest, 0, sizeof zerodigest); + + if (!(fp = open_file (&filename, outfp))) + return gpg_error_from_syserror (); + + dupitems_size = 1000; + dupitems = malloc (dupitems_size * sizeof *dupitems); + if (!dupitems) + { + gpg_error_t tmperr = gpg_error_from_syserror (); + fprintf (outfp, "error allocating array for `%s': %s\n", + filename, strerror(errno)); + return tmperr; + } + dupitems_count = 0; + + while ( !(rc = _keybox_read_blob (&blob, fp)) ) + { + unsigned char digest[20]; + + if (hash_blob_rawdata (blob, digest)) + fprintf (outfp, "error in blob %ld of `%s'\n", recno, filename); + else if (memcmp (digest, zerodigest, 20)) + { + if (dupitems_count >= dupitems_size) + { + struct dupitem_s *tmp; + + dupitems_size += 1000; + tmp = realloc (dupitems, dupitems_size * sizeof *dupitems); + if (!tmp) + { + gpg_error_t tmperr = gpg_error_from_syserror (); + fprintf (outfp, "error reallocating array for `%s': %s\n", + filename, strerror(errno)); + free (dupitems); + return tmperr; + } + dupitems = tmp; + } + dupitems[dupitems_count].recno = recno; + memcpy (dupitems[dupitems_count].digest, digest, 20); + dupitems_count++; + } + _keybox_release_blob (blob); + recno++; + } + if (rc == -1) + rc = 0; + if (rc) + fprintf (outfp, "error reading `%s': %s\n", filename, gpg_strerror (rc)); + if (fp != stdin) + fclose (fp); + + qsort (dupitems, dupitems_count, sizeof *dupitems, cmp_dupitems); + + for (lastn=0, n=1; n < dupitems_count; lastn=n, n++) + { + if (!memcmp (dupitems[lastn].digest, dupitems[n].digest, 20)) + { + bin2hexcolon (dupitems[lastn].digest, 20, fprbuf); + fprintf (outfp, "fpr=%s recno=%lu", fprbuf, dupitems[lastn].recno); + do + fprintf (outfp, " %lu", dupitems[n].recno); + while (++n < dupitems_count + && !memcmp (dupitems[lastn].digest, dupitems[n].digest, 20)); + putc ('\n', outfp); + n--; + } + } + + free (dupitems); + + return rc; +} + + +/* Print records with record numbers FROM to TO to OUTFP. */ +int +_keybox_dump_cut_records (const char *filename, unsigned long from, + unsigned long to, FILE *outfp) +{ + FILE *fp; + KEYBOXBLOB blob; + int rc; + unsigned long recno = 0; + + if (!(fp = open_file (&filename, stderr))) + return gpg_error_from_syserror (); + + while ( !(rc = _keybox_read_blob (&blob, fp)) ) + { + if (recno > to) + break; /* Ready. */ + if (recno >= from) + { + if ((rc = _keybox_write_blob (blob, outfp))) + { + fprintf (stderr, "error writing output: %s\n", + gpg_strerror (rc)); + goto leave; + } + } + _keybox_release_blob (blob); + recno++; + } + if (rc == -1) + rc = 0; + if (rc) + fprintf (stderr, "error reading `%s': %s\n", filename, gpg_strerror (rc)); + leave: + if (fp != stdin) + fclose (fp); + return rc; +} Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/sm/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,3 +1,11 @@ +2007-08-23 Werner Koch + + * certlist.c (gpgsm_certs_identical_p): New. + (gpgsm_add_to_certlist): Ignore duplicate certificates in + ambigious name detection. + (gpgsm_find_cert): Ditto. + * export.c (gpgsm_p12_export): Ditto. + 2007-08-22 Werner Koch * certreqgen.c (create_request): Replace open coding by bin2hex. Modified: trunk/sm/certlist.c =================================================================== --- trunk/sm/certlist.c 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/sm/certlist.c 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,5 +1,5 @@ /* certlist.c - build list of certificates - * Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -225,6 +225,25 @@ return tmp; } + +/* Return true if CERT_A is the same as CERT_B. */ +int +gpgsm_certs_identical_p (ksba_cert_t cert_a, ksba_cert_t cert_b) +{ + const unsigned char *img_a, *img_b; + size_t len_a, len_b; + + img_a = ksba_cert_get_image (cert_a, &len_a); + if (img_a) + { + img_b = ksba_cert_get_image (cert_b, &len_b); + if (img_b && len_a == len_b && !memcmp (img_a, img_b, len_a)) + return 1; /* Identical. */ + } + return 0; +} + + /* Return true if CERT is already contained in CERTLIST. */ static int is_cert_in_certlist (ksba_cert_t cert, certlist_t certlist) @@ -330,6 +349,8 @@ if (!rc) { + certlist_t dup_certs = NULL; + next_ambigious: rc = keydb_search (kh, &desc, 1); if (rc == -1) @@ -337,23 +358,45 @@ else if (!rc) { ksba_cert_t cert2 = NULL; + + /* If this is the first possible duplicate, add thye orginal + certificate to our list of duplicates. */ + if (!dup_certs) + gpgsm_add_cert_to_certlist (ctrl, cert, &dup_certs, 0); /* We have to ignore ambigious names as long as - there only fault is a bad key usage */ + there only fault is a bad key usage. This is + required to support encryption and signing + certifciates of the same subject. + + Further we ignore them if they are due to an + identical certificate (which may happen if a + certificate is accidential duplicated in the + keybox). */ if (!keydb_get_cert (kh, &cert2)) { int tmp = (same_subject_issuer (subject, issuer, cert2) && ((gpg_err_code ( secret? gpgsm_cert_use_sign_p (cert2) - : gpgsm_cert_use_encrypt_p (cert2) + : gpgsm_cert_use_encrypt_p (cert2) ) ) == GPG_ERR_WRONG_KEY_USAGE)); + if (tmp) + gpgsm_add_cert_to_certlist (ctrl, cert2, + &dup_certs, 0); + else + { + if (is_cert_in_certlist (cert2, dup_certs)) + tmp = 1; + } + ksba_cert_release (cert2); if (tmp) goto next_ambigious; } rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); } + gpgsm_release_certlist (dup_certs); } xfree (subject); xfree (issuer); @@ -464,13 +507,27 @@ won't lead to ambiguous names. */ if (!rc && !keyid) { + next_ambiguous: rc = keydb_search (kh, &desc, 1); if (rc == -1) rc = 0; else { if (!rc) - rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + { + ksba_cert_t cert2 = NULL; + + if (!keydb_get_cert (kh, &cert2)) + { + if (gpgsm_certs_identical_p (*r_cert, cert2)) + { + ksba_cert_release (cert2); + goto next_ambiguous; + } + ksba_cert_release (cert2); + } + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } ksba_cert_release (*r_cert); *r_cert = NULL; } Modified: trunk/sm/export.c =================================================================== --- trunk/sm/export.c 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/sm/export.c 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,5 +1,5 @@ -/* export.c - * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* export.c - Export certificates and private keys. + * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -379,10 +379,24 @@ log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc)); goto leave; } - + + next_ambiguous: rc = keydb_search (hd, desc, 1); if (!rc) - rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + { + ksba_cert_t cert2 = NULL; + + if (!keydb_get_cert (hd, &cert2)) + { + if (gpgsm_certs_identical_p (cert, cert2)) + { + ksba_cert_release (cert2); + goto next_ambiguous; + } + ksba_cert_release (cert2); + } + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) rc = 0; if (rc) Modified: trunk/sm/gpgsm.h =================================================================== --- trunk/sm/gpgsm.h 2007-08-23 08:40:11 UTC (rev 4567) +++ trunk/sm/gpgsm.h 2007-08-23 17:41:22 UTC (rev 4568) @@ -1,5 +1,5 @@ /* gpgsm.h - Global definitions for GpgSM - * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -287,6 +287,7 @@ int gpgsm_cert_use_decrypt_p (ksba_cert_t cert); int gpgsm_cert_use_cert_p (ksba_cert_t cert); int gpgsm_cert_use_ocsp_p (ksba_cert_t cert); +int gpgsm_certs_identical_p (ksba_cert_t cert_a, ksba_cert_t cert_b); int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, certlist_t *listaddr, int is_encrypt_to); int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, From cvs at cvs.gnupg.org Fri Aug 24 07:49:56 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 24 Aug 2007 07:49:56 +0200 Subject: [svn] assuan - r248 - in trunk: . doc src Message-ID: Author: wk Date: 2007-08-24 07:49:26 +0200 (Fri, 24 Aug 2007) New Revision: 248 Modified: trunk/COPYING.LIB trunk/ChangeLog trunk/Makefile.am trunk/NEWS trunk/README trunk/configure.ac trunk/doc/ChangeLog trunk/doc/assuan.texi trunk/doc/lgpl.texi trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/assuan-buffer.c trunk/src/assuan-client.c trunk/src/assuan-connect.c trunk/src/assuan-handler.c trunk/src/assuan-inquire.c trunk/src/assuan-io-pth.c trunk/src/assuan-io.c trunk/src/assuan-listen.c trunk/src/assuan-logging.c trunk/src/assuan-pipe-connect.c trunk/src/assuan-pipe-server.c trunk/src/assuan-socket-connect.c trunk/src/assuan-socket-server.c trunk/src/assuan-socket.c trunk/src/assuan-uds.c trunk/src/assuan-util.c trunk/src/assuan.h trunk/src/funopen.c trunk/src/isascii.c trunk/src/memrchr.c trunk/src/mkerrors trunk/src/putc_unlocked.c trunk/src/setenv.c trunk/src/stpcpy.c Log: Preparing 1.0.3 Modified: trunk/COPYING.LIB =================================================================== --- trunk/COPYING.LIB 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/COPYING.LIB 2007-08-24 05:49:26 UTC (rev 248) @@ -1,165 +1,510 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. + Preamble - 0. Additional Definitions. + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. - 1. Exception to Section 3 of the GNU GPL. + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. - 2. Conveying Modified Versions. + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. - 3. Object Code Incorporating Material from Library Header Files. + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. - b) Accompany the object code with a copy of the GNU GPL and this license - document. + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) - 4. Combined Works. + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. + a) The modified work must itself be a software library. - d) Do one of the following: + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) - 5. Combined Libraries. +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. - 6. Revised Versions of the GNU Lesser General Public License. + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/ChangeLog 2007-08-24 05:49:26 UTC (rev 248) @@ -1,3 +1,11 @@ +2007-08-24 Werner Koch + + Released 1.0.3. + + Switched license of the library code back to LGPLv2.1. See NEWS. + + * COPYING.LIB: Replaced by LPGLv2.1 + 2007-07-05 Werner Koch Released 1.0.2. @@ -261,5 +269,14 @@ * tests: New directory. + Copyright 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/Makefile.am 2007-08-24 05:49:26 UTC (rev 248) @@ -1,4 +1,23 @@ +# Assuan top level Makefile +# Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc. +# +# This file is part of Assuan. +# +# Assuan is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Assuan 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . +## Process this file with automake to produce Makefile.in + ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/NEWS 2007-08-24 05:49:26 UTC (rev 248) @@ -2,11 +2,20 @@ ------------------------------------------------ * New type assuan_fd_t and constant ASSUAN_INVALID_FD for better W32 - support. it does not change teh semantics under Unix. Under W32 + support. It does not change the semantics under Unix. Under W32 all file descriptors are now guaranteed to be system handles. + * New functions assuan_process_done and assuan_inquire_ext to support + external event loops. -Noteworthy changes in version 1.0.2 (2007-07-05 + * Changed the license of the library code back to LGPLv2.1 to support + a bunch of GPLv2(only) software which does not allow the use of + LGPLv3. Note that this is only a temporary change and authors of + GPLv2(only) software are asked to switch to GPLv3 or to add an + exception which allow the use of LPGLv3 software. + + +Noteworthy changes in version 1.0.2 (2007-07-05) ------------------------------------------------ * Changed license to LGPLv3. @@ -174,7 +183,7 @@ * Initial release as a standalone library. - Copyright 2003, 2004, 2006 Free Software Foundation, Inc. + Copyright 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without Modified: trunk/README =================================================================== --- trunk/README 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/README 2007-08-24 05:49:26 UTC (rev 248) @@ -9,7 +9,7 @@ It is currently not intended to be used as a shared library. See COPYING.LIB on how to share, modify and distribute the software -itself and COPYING for the documentation. +itself (LGPLv2.1+) and COPYING for the documentation (GPLv3+). Please send bug report to the gnupg-devel mailing list or enter them into the gnupg bug tracker at http://bugs.g10code.com using the Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/configure.ac 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ # # Assuan is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 3 of +# published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Assuan is distributed in the hope that it will be useful, but @@ -25,7 +25,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [1.0.3]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/doc/ChangeLog 2007-08-24 05:49:26 UTC (rev 248) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + * lgpl.texi: Replace by LGPLv2.1 version. + 2007-08-09 Marcus Brinkmann * assuan.texi (External I/O Loop): New chapter. @@ -45,7 +49,7 @@ * assuan.texi: Imported from newpg. - Copyright 2003, 2007 Free Software Foundation, Inc. + Copyright 2003, 2006, 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/doc/assuan.texi 2007-08-24 05:49:26 UTC (rev 248) @@ -3,7 +3,7 @@ @setfilename assuan.info @macro copyrightnotice -Copyright @copyright{} 2002, 2003, 2006 Free Software Foundation, Inc. +Copyright @copyright{} 2002, 2003, 2006, 2007 Free Software Foundation, Inc. @end macro @macro permissionnotice Permission is granted to copy, distribute and/or modify this document @@ -85,7 +85,8 @@ @title Developing with Assuan @subtitle Version @value{VERSION} @subtitle @value{UPDATED} - at author Werner Koch @code{(wk@@gnupg.org)} + at author by Werner Koch and Marcus Brinkmann + at author @code{@{wk,mb@}@@g10code.com} @page @vskip 0pt plus 1filll Modified: trunk/doc/lgpl.texi =================================================================== --- trunk/doc/lgpl.texi 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/doc/lgpl.texi 2007-08-24 05:49:26 UTC (rev 248) @@ -1,192 +1,565 @@ @node Library Copying + at appendix GNU LESSER GENERAL PUBLIC LICENSE - at unnumbered GNU Lesser General Public License - at center Version 3, 29 June 2007 + at cindex LGPL, Lesser General Public License + at center Version 2.1, February 1999 - at c This file is intended to be included in another file. - @display -Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} +Copyright @copyright{} 1991, 1999 Free Software Foundation, Inc. +59 Temple Place -- Suite 330, Boston, MA 02110-1301, USA -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts +as the successor of the GNU Library Public License, version 2, hence the +version number 2.1.] @end display + at appendixsubsec Preamble -This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software---to make sure the software is free for all its users. - at enumerate 0 - at item Additional Definitions. + This license, the Lesser General Public License, applies to some +specially designated software---typically libraries---of the Free +Software Foundation and other authors who decide to use it. You can use +it too, but we suggest you first think carefully about whether this +license or the ordinary General Public License is the better strategy to +use in any particular case, based on the explanations below. - As used herein, ``this License'' refers to version 3 of the GNU Lesser -General Public License, and the ``GNU GPL'' refers to version 3 of the GNU -General Public License. + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of it +in new free programs; and that you are informed that you can do these +things. - ``The Library'' refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. - An ``Application'' is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. - A ``Combined Work'' is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the ``Linked -Version''. + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. - The ``Minimal Corresponding Source'' for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. - The ``Corresponding Application Code'' for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. - at item Exception to Section 3 of the GNU GPL. + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. - at item Conveying Modified Versions. + We call this license the @dfn{Lesser} General Public License because it +does @emph{Less} to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +``work based on the library'' and a ``work that uses the library''. The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + at iftex + at appendixsubsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + at end iftex + at ifinfo + at center GNU LESSER GENERAL PUBLIC LICENSE + at center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + at end ifinfo + + at enumerate 0 + at item +This License Agreement applies to any software library or other program +which contains a notice placed by the copyright holder or other +authorized party saying it may be distributed under the terms of this +Lesser General Public License (also called ``this License''). Each +licensee is addressed as ``you''. + + A ``library'' means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The ``Library'', below, refers to any such software library or work +which has been distributed under these terms. A ``work based on the +Library'' means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term ``modification''.) + + ``Source code'' for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + at item +You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + at item +You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + @enumerate a - at item - under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or + at item +The modified work must itself be a software library. - at item - under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. + at item +You must cause the files modified to carry prominent notices +stating that you changed the files and the date of any change. + + at item +You must cause the whole of the work to be licensed at no +charge to all third parties under the terms of this License. + + at item +If a facility in the modified Library refers to a function or a +table of data to be supplied by an application program that uses +the facility, other than as an argument passed when the facility +is invoked, then you must make a good faith effort to ensure that, +in the event an application does not supply such function or +table, the facility still operates, and performs whatever part of +its purpose remains meaningful. + +(For example, a function in a library to compute square roots has +a purpose that is entirely well-defined independent of the +application. Therefore, Subsection 2d requires that any +application-supplied function or table used by this function must +be optional: if the application does not supply it, the square +root function must still compute square roots.) @end enumerate - at item Object Code Incorporating Material from Library Header Files. +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + at item +You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + at item +You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + at item +A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a ``work that uses the Library''. Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a ``work that uses the Library'' with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a ``work that uses the +library''. The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a ``work that uses the Library'' uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + at item +As an exception to the Sections above, you may also combine or +link a ``work that uses the Library'' with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + @enumerate a @item - Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. +Accompany the work with the complete corresponding +machine-readable source code for the Library including whatever +changes were used in the work (which must be distributed under +Sections 1 and 2 above); and, if the work is an executable linked +with the Library, with the complete machine-readable ``work that +uses the Library'', as object code and/or source code, so that the +user can modify the Library and then relink to produce a modified +executable containing the modified Library. (It is understood +that the user who changes the contents of definitions files in the +Library will not necessarily be able to recompile the application +to use the modified definitions.) + @item - Accompany the object code with a copy of the GNU GPL and this license - document. +Use a suitable shared library mechanism for linking with the Library. A +suitable mechanism is one that (1) uses at run time a copy of the +library already present on the user's computer system, rather than +copying library functions into the executable, and (2) will operate +properly with a modified version of the library, if the user installs +one, as long as the modified version is interface-compatible with the +version that the work was made with. + + at item +Accompany the work with a written offer, valid for at +least three years, to give the same user the materials +specified in Subsection 6a, above, for a charge no more +than the cost of performing this distribution. + + at item +If distribution of the work is made by offering access to copy +from a designated place, offer equivalent access to copy the above +specified materials from the same place. + + at item +Verify that the user has already received a copy of these +materials or that you have already sent this user a copy. @end enumerate - at item Combined Works. + For an executable, the required form of the ``work that uses the +Library'' must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies the +executable. - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + at item +You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + @enumerate a @item - Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. +Accompany the combined library with a copy of the same work +based on the Library, uncombined with any other library +facilities. This must be distributed under the terms of the +Sections above. + @item - Accompany the Combined Work with a copy of the GNU GPL and this license - document. +Give prominent notice with the combined library of the fact +that part of it is a work based on the Library, and explaining +where to find the accompanying uncombined form of the same work. + at end enumerate + @item - For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. +You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + @item - Do one of the following: +You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. - at enumerate 0 @item - Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. +Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + @item - Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - at end enumerate +If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + @item - Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - at end enumerate +If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. - at item Combined Libraries. + at item +The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +``any later version'', you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. - at enumerate a @item - Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. +If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + at iftex + at heading NO WARRANTY + at end iftex + at ifinfo + at center NO WARRANTY + at end ifinfo + @item - Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. +BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + at item +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. @end enumerate - at item Revised Versions of the GNU Lesser General Public License. + at iftex + at heading END OF TERMS AND CONDITIONS + at end iftex + at ifinfo + at center END OF TERMS AND CONDITIONS + at end ifinfo - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. + at page + at appendixsubsec How to Apply These Terms to Your New Libraries - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License ``or any later version'' -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +``copyright'' line and a pointer to where the full notice is found. - at end enumerate + at smallexample + at var{one line to give the library's name and an idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at +your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301, +USA. + at end smallexample + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a ``copyright disclaimer'' for the library, if +necessary. Here is a sample; alter the names: + + at smallexample +Yoyodyne, Inc., hereby disclaims all copyright interest in the library +`Frob' (a library for tweaking knobs) written by James Random Hacker. + + at var{signature of Ty Coon}, 1 April 1990 +Ty Coon, President of Vice + at end smallexample + +That's all there is to it! Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/ChangeLog 2007-08-24 05:49:26 UTC (rev 248) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + Switched license to back to LGPLv2.1. + 2007-08-09 Marcus Brinkmann * assuan.h (assuan_process_done, assuan_inquire_ext): New @@ -1102,7 +1106,7 @@ * assuan-defs.h: Add space in the context for this. - Copyright 2001, 2002, 2006 Free Software Foundation, Inc. + Copyright 2001, 2002, 2006, 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/Makefile.am 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ # # Assuan is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 3 of +# published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-buffer.c =================================================================== --- trunk/src/assuan-buffer.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-buffer.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-client.c =================================================================== --- trunk/src/assuan-client.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-client.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-connect.c =================================================================== --- trunk/src/assuan-connect.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-connect.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-handler.c 2007-08-24 05:49:26 UTC (rev 248) @@ -1,11 +1,11 @@ /* assuan-handler.c - dispatch commands - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-inquire.c =================================================================== --- trunk/src/assuan-inquire.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-inquire.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-io-pth.c =================================================================== --- trunk/src/assuan-io-pth.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-io-pth.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-io.c =================================================================== --- trunk/src/assuan-io.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-io.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-listen.c =================================================================== --- trunk/src/assuan-listen.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-listen.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-logging.c =================================================================== --- trunk/src/assuan-logging.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-logging.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-pipe-connect.c =================================================================== --- trunk/src/assuan-pipe-connect.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-pipe-connect.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-pipe-server.c =================================================================== --- trunk/src/assuan-pipe-server.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-pipe-server.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-socket-connect.c =================================================================== --- trunk/src/assuan-socket-connect.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-socket-connect.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-socket-server.c =================================================================== --- trunk/src/assuan-socket-server.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-socket-server.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-socket.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-uds.c =================================================================== --- trunk/src/assuan-uds.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-uds.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan-util.c =================================================================== --- trunk/src/assuan-util.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan-util.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/assuan.h 2007-08-24 05:49:26 UTC (rev 248) @@ -1,11 +1,11 @@ /* assuan.c - Definitions for the Assuan IPC library - * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but @@ -325,7 +325,7 @@ process. */ ASSUAN_NO_WAITPID = 1, /* This flag indicates whether Assuan logging is in confidential - mode. Use assuan_{begin,end}_condidential tochange the + mode. Use assuan_{begin,end}_condidential to change the mode. */ ASSUAN_CONFIDENTIAL = 2 } @@ -342,7 +342,7 @@ /* Because we use system handles and not libc low level file descriptors on W32, we need to declare them as HANDLE (which actually is a plain pointer). This is required to eventually - support 64 bits Windows systems. */ + support 64 bit Windows systems. */ #ifdef _WIN32 typedef void * assuan_fd_t; #define ASSUAN_INVALID_FD ((void*)(-1)) Modified: trunk/src/funopen.c =================================================================== --- trunk/src/funopen.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/funopen.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/isascii.c =================================================================== --- trunk/src/isascii.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/isascii.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/memrchr.c =================================================================== --- trunk/src/memrchr.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/memrchr.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/mkerrors =================================================================== --- trunk/src/mkerrors 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/mkerrors 2007-08-24 05:49:26 UTC (rev 248) @@ -7,7 +7,7 @@ # # Assuan is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 3 of +# published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/putc_unlocked.c =================================================================== --- trunk/src/putc_unlocked.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/putc_unlocked.c 2007-08-24 05:49:26 UTC (rev 248) @@ -5,7 +5,7 @@ * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 3 of + * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but Modified: trunk/src/setenv.c =================================================================== --- trunk/src/setenv.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/setenv.c 2007-08-24 05:49:26 UTC (rev 248) @@ -4,7 +4,7 @@ The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. + version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of Modified: trunk/src/stpcpy.c =================================================================== --- trunk/src/stpcpy.c 2007-08-09 10:44:02 UTC (rev 247) +++ trunk/src/stpcpy.c 2007-08-24 05:49:26 UTC (rev 248) @@ -4,7 +4,7 @@ The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. + version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of From cvs at cvs.gnupg.org Fri Aug 24 07:51:51 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 24 Aug 2007 07:51:51 +0200 Subject: [svn] assuan - r249 - trunk Message-ID: Author: wk Date: 2007-08-24 07:51:23 +0200 (Fri, 24 Aug 2007) New Revision: 249 Modified: trunk/NEWS Log: Preparing 1.0.3 Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-24 05:49:26 UTC (rev 248) +++ trunk/NEWS 2007-08-24 05:51:23 UTC (rev 249) @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.0.3 +Noteworthy changes in version 1.0.3 (2007-08-24) ------------------------------------------------ * New type assuan_fd_t and constant ASSUAN_INVALID_FD for better W32 From cvs at cvs.gnupg.org Fri Aug 24 08:00:19 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 24 Aug 2007 08:00:19 +0200 Subject: [svn] assuan - r250 - tags Message-ID: Author: wk Date: 2007-08-24 07:59:50 +0200 (Fri, 24 Aug 2007) New Revision: 250 Added: tags/libassuan-1.0.3/ Log: Tagged release Copied: tags/libassuan-1.0.3 (from rev 249, trunk) From cvs at cvs.gnupg.org Fri Aug 24 11:52:30 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 24 Aug 2007 11:52:30 +0200 Subject: [svn] GnuPG - r4570 - in branches/STABLE-BRANCH-1-4: . g10 include po util Message-ID: Author: wk Date: 2007-08-24 11:51:58 +0200 (Fri, 24 Aug 2007) New Revision: 4570 Modified: branches/STABLE-BRANCH-1-4/NEWS branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/keyring.c branches/STABLE-BRANCH-1-4/include/ChangeLog branches/STABLE-BRANCH-1-4/include/util.h branches/STABLE-BRANCH-1-4/po/de.glo branches/STABLE-BRANCH-1-4/util/ChangeLog branches/STABLE-BRANCH-1-4/util/fileutil.c Log: Improved detection of ketrings specified several times. Modified: branches/STABLE-BRANCH-1-4/NEWS =================================================================== --- branches/STABLE-BRANCH-1-4/NEWS 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/NEWS 2007-08-24 09:51:58 UTC (rev 4570) @@ -3,8 +3,9 @@ * Changed the license to GPLv3. + * Improved detection of keyrings specified multiple times. + * Minor bug fixes. - Noteworthy changes in version 1.4.7 (2007-03-05) ------------------------------------------------ Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) @@ -1,3 +1,8 @@ +2007-08-24 Werner Koch + + * keyring.c (keyring_register_filename): Use same_file_p. + Suggested by Kurt Fitzner. + 2007-07-19 David Shaw * gpg.c (main): Fix typo. Noted by John Clizbe. Modified: branches/STABLE-BRANCH-1-4/g10/keyring.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/keyring.c 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/g10/keyring.c 2007-08-24 09:51:58 UTC (rev 4570) @@ -207,7 +207,7 @@ for (kr=kr_names; kr; kr = kr->next) { - if ( !compare_filenames (kr->fname, fname) ) + if (same_file_p (kr->fname, fname) ) { *ptr=kr; return 0; /* already registered */ Modified: branches/STABLE-BRANCH-1-4/include/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/include/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/include/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + * util.h (same_file_p): Add prototype. + 2007-06-13 David Shaw * cipher.h (CIPHER_ALGO_CAMELLIA): Add Camellia define. Modified: branches/STABLE-BRANCH-1-4/include/util.h =================================================================== --- branches/STABLE-BRANCH-1-4/include/util.h 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/include/util.h 2007-08-24 09:51:58 UTC (rev 4570) @@ -143,6 +143,7 @@ char * make_dirname(const char *filepath); char *make_filename( const char *first_part, ... ); int compare_filenames( const char *a, const char *b ); +int same_file_p (const char *name1, const char *name2); const char *print_fname_stdin( const char *s ); const char *print_fname_stdout( const char *s ); int is_file_compressed(const char *s, int *r_status); Modified: branches/STABLE-BRANCH-1-4/po/de.glo =================================================================== --- branches/STABLE-BRANCH-1-4/po/de.glo 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/po/de.glo 2007-08-24 09:51:58 UTC (rev 4570) @@ -143,7 +143,7 @@ packet Paket packet type Pakettyp parse -zerlegen -passphrase Mantra +passphrase Passphrase -# Mantra permission [file] Zugriffsrechte Photo-ID Foto-ID policy Richtlinie Modified: branches/STABLE-BRANCH-1-4/util/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/util/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/util/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) @@ -1,3 +1,9 @@ +2007-08-24 Werner Koch + + * fileutil.c (same_file_p): New. Taken from SVN trunk. + (compare_filenames) [HAVE_DRIVE_LETTERS]: Take drive letters and + backslashes in account. + 2007-04-16 David Shaw * strgutil.c (ascii_toupper, ascii_tolower, ascii_strcasecmp, Modified: branches/STABLE-BRANCH-1-4/util/fileutil.c =================================================================== --- branches/STABLE-BRANCH-1-4/util/fileutil.c 2007-08-24 09:34:39 UTC (rev 4569) +++ branches/STABLE-BRANCH-1-4/util/fileutil.c 2007-08-24 09:51:58 UTC (rev 4570) @@ -1,5 +1,5 @@ /* fileutil.c - file utilities - * Copyright (C) 1998, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,17 @@ #ifdef HAVE_PWD_H #include #endif +#include +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include +#else /*!HAVE_W32_SYSTEM*/ +# include +# include +# include +#endif /*!HAVE_W32_SYSTEM*/ + + #include "util.h" #include "memory.h" #include "ttyio.h" @@ -194,32 +205,87 @@ } +/* Compare whether the filenames are identical. This is a + special version of strcmp() taking the semantics of filenames in + account. Note that this function works only on the supplied names + without considereing any context like the current directory. See + also same_file_p(). */ int -compare_filenames( const char *a, const char *b ) +compare_filenames (const char *a, const char *b) { - /* ? check whether this is an absolute filename and - * resolve symlinks? - */ -#ifndef __riscos__ -#ifdef HAVE_DRIVE_LETTERS - return ascii_strcasecmp(a,b); -#else - return strcmp(a,b); +#ifdef __riscos__ + int c = 0; + char *abuf, *bbuf; + + abuf = riscos_gstrans(a); + bbuf = riscos_gstrans(b); + c = ascii_strcasecmp (abuf, bbuf); + xfree(abuf); + xfree(bbuf); + + return c; +#elif defined (HAVE_DRIVE_LETTERS) + for ( ; *a && *b; a++, b++ ) + { + if (*a != *b + && (toupper (*(const unsigned char*)a) + != toupper (*(const unsigned char*)b) ) + && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))) + break; + } + if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) + return 0; + else + return (toupper (*(const unsigned char*)a) + - toupper (*(const unsigned char*)b)); +#else /*!HAVE_DRIVE_LETTERS*/ + return strcmp (a,b); #endif -#else /* __riscos__ */ - int c = 0; - char *abuf, *bbuf; +} - abuf = riscos_gstrans(a); - bbuf = riscos_gstrans(b); - - c = ascii_strcasecmp (abuf, bbuf); - - xfree(abuf); - xfree(bbuf); - - return c; -#endif /* __riscos__ */ +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int +same_file_p (const char *name1, const char *name2) +{ + int yes; + + /* First try a shortcut. */ + if (!compare_filenames (name1, name2)) + yes = 1; + else + { +#ifdef HAVE_W32_SYSTEM + HANDLE file1, file2; + BY_HANDLE_FILE_INFORMATION info1, info2; + + file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + yes = (GetFileInformationByHandle (file1, &info1) + && GetFileInformationByHandle (file2, &info2) + && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow); + CloseHandle (file2); + } + CloseHandle (file1); + } +#else /*!HAVE_W32_SYSTEM*/ + struct stat info1, info2; + + yes = (!stat (name1, &info1) && !stat (name2, &info2) + && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino); +#endif /*!HAVE_W32_SYSTEM*/ + } + return yes; } From cvs at cvs.gnupg.org Fri Aug 24 11:35:09 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 24 Aug 2007 11:35:09 +0200 Subject: [svn] GnuPG - r4569 - in trunk: . doc g10 jnlib kbx tests/samplekeys Message-ID: Author: wk Date: 2007-08-24 11:34:39 +0200 (Fri, 24 Aug 2007) New Revision: 4569 Added: trunk/tests/samplekeys/gte.pem Modified: trunk/NEWS trunk/doc/ChangeLog trunk/doc/debugging.texi trunk/doc/gpg-agent.texi trunk/g10/ChangeLog trunk/g10/keyring.c trunk/jnlib/ChangeLog trunk/jnlib/mischelp.c trunk/jnlib/mischelp.h trunk/jnlib/stringhelp.c trunk/kbx/ChangeLog trunk/kbx/keybox-init.c trunk/tests/samplekeys/README Log: tryu harder to ignore duplicate specified keyrings and -boxes. Documentation updates. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/NEWS 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,7 +1,12 @@ Noteworthy changes in version 2.0.7 ------------------------------------------------ + * Fixed encryption problem if duplicate certificates are in the + keybox. + * Made it work on Windows Vista. + + Noteworthy changes in version 2.0.6 (2007-08-16) ------------------------------------------------ Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/doc/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,3 +1,8 @@ +2007-08-24 Werner Koch + + * debugging.texi (Common Problems): Add "A root certifciate does + not validate." + 2007-08-14 Werner Koch * glossary.texi (Glossary): Add a more items. Modified: trunk/doc/debugging.texi =================================================================== --- trunk/doc/debugging.texi 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/doc/debugging.texi 2007-08-24 09:34:39 UTC (rev 4569) @@ -77,10 +77,17 @@ provided by @command{gpgsm} or @command{gpg}. 81 certifcates are stored in a standard way and directly available from @command{gpgsm}. + at noindent +To find duplicated certificates and keyblocks in a keybox file (this +should not occur but sometimes things go wrong), run it using + at samp{kbxutil --find-dups ~/.gnupg/pubring.kbx} + + + @node Common Problems @section Commonly Seen Problems @@ -165,6 +172,18 @@ or other purposes and don't have a corresponding certificate. + at item A root certificate does not verify + +A common problem is that the root certificate misses the required +basicConstrains attribute and thus @command{gpgsm} rejects this +certificate. An error message indicating ``no value'' is a sign for +such a certificate. You may use the @code{relax} flag in + at file{trustlist.txt} to accept the certificate anyway. Note that the +fingerprint and this flag may only be added manually to + at file{trustlist.txt}. + + + @end itemize Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/doc/gpg-agent.texi 2007-08-24 09:34:39 UTC (rev 4569) @@ -502,7 +502,9 @@ @table @code @item relax -Relax checking of some root certificate requirements. +Relax checking of some root certificate requirements. This is for +example required if the certificate is missing the basicConstraints +attribute (despite that it is a MUST for CA certificates). @item cm If validation of a certificate finally issued by a CA with this flag set Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/g10/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + * keyring.c (keyring_register_filename): Use same_file_p(). + 2007-08-21 Werner Koch * misc.c (openpgp_md_test_algo): Remove rfc2440bis hash algorithms. Modified: trunk/g10/keyring.c =================================================================== --- trunk/g10/keyring.c 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/g10/keyring.c 2007-08-24 09:34:39 UTC (rev 4569) @@ -206,10 +206,10 @@ for (kr=kr_names; kr; kr = kr->next) { - if ( !compare_filenames (kr->fname, fname) ) + if (same_file_p (kr->fname, fname)) { *ptr=kr; - return 0; /* already registered */ + return 0; /* Already registered. */ } } Modified: trunk/jnlib/ChangeLog =================================================================== --- trunk/jnlib/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/jnlib/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,3 +1,9 @@ +2007-08-24 Werner Koch + + * mischelp.c (same_file_p): New. + (libjnlib_dummy_mischelp_func): Remove as we now always have one + function. + 2007-08-09 Werner Koch * argparse.c (show_help): Expand the @EMAIL@ macro in the package Modified: trunk/jnlib/mischelp.c =================================================================== --- trunk/jnlib/mischelp.c 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/jnlib/mischelp.c 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,5 +1,5 @@ /* mischelp.c - Miscellaneous helper functions - * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. * * This file is part of JNLIB. * @@ -21,16 +21,63 @@ #include #include #include +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include +#else /*!HAVE_W32_SYSTEM*/ +# include +# include +# include +#endif /*!HAVE_W32_SYSTEM*/ #include "libjnlib-config.h" +#include "stringhelp.h" #include "mischelp.h" -/* A dummy function to prevent an empty compilation unit. Some - compilers bail out in this case. */ -time_t -libjnlib_dummy_mischelp_func (void) + +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int +same_file_p (const char *name1, const char *name2) { - return time (NULL); + int yes; + + /* First try a shortcut. */ + if (!compare_filenames (name1, name2)) + yes = 1; + else + { +#ifdef HAVE_W32_SYSTEM + HANDLE file1, file2; + BY_HANDLE_FILE_INFORMATION info1, info2; + + file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + yes = (GetFileInformationByHandle (file1, &info1) + && GetFileInformationByHandle (file2, &info2) + && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow); + CloseHandle (file2); + } + CloseHandle (file1); + } +#else /*!HAVE_W32_SYSTEM*/ + struct stat info1, info2; + + yes = (!stat (name1, &info1) && !stat (name2, &info2) + && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino); +#endif /*!HAVE_W32_SYSTEM*/ + } + return yes; } Modified: trunk/jnlib/mischelp.h =================================================================== --- trunk/jnlib/mischelp.h 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/jnlib/mischelp.h 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,6 +1,6 @@ /* mischelp.h - Miscellaneous helper macros and functions * Copyright (C) 1999, 2000, 2001, 2002, 2003, - * 2006 Free Software Foundation, Inc. + * 2006, 2007 Free Software Foundation, Inc. * * This file is part of JNLIB. * @@ -22,6 +22,11 @@ #define LIBJNLIB_MISCHHELP_H +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int same_file_p (const char *name1, const char *name2); + + #ifndef HAVE_TIMEGM #include time_t timegm (struct tm *tm); Modified: trunk/jnlib/stringhelp.c =================================================================== --- trunk/jnlib/stringhelp.c 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/jnlib/stringhelp.c 2007-08-24 09:34:39 UTC (rev 4569) @@ -338,11 +338,14 @@ } +/* Compare whether the filenames are identical. This is a + specialversion of strcmp() taking the semantics of filenames in + account. Note that this function works only on the supplied names + without considereing any context like the current directory. See + also same_file_p(). */ int compare_filenames (const char *a, const char *b) { - /* ? check whether this is an absolute filename and resolve - symlinks? */ #ifdef HAVE_DRIVE_LETTERS for ( ; *a && *b; a++, b++ ) { Modified: trunk/kbx/ChangeLog =================================================================== --- trunk/kbx/ChangeLog 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/kbx/ChangeLog 2007-08-24 09:34:39 UTC (rev 4569) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + * keybox-init.c (keybox_register_file): Use same_file_p. + 2007-08-23 Werner Koch * kbxutil.c: New commands --find-dups and --cut. New options Modified: trunk/kbx/keybox-init.c =================================================================== --- trunk/kbx/keybox-init.c 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/kbx/keybox-init.c 2007-08-24 09:34:39 UTC (rev 4569) @@ -24,10 +24,9 @@ #include #include +#include "../jnlib/mischelp.h" #include "keybox-defs.h" -#define compare_filenames strcmp - static KB_NAME kb_names; @@ -42,8 +41,8 @@ for (kr=kb_names; kr; kr = kr->next) { - if ( !compare_filenames (kr->fname, fname) ) - return NULL; /* already registered */ + if (same_file_p (kr->fname, fname) ) + return NULL; /* Already registered. */ } kr = xtrymalloc (sizeof *kr + strlen (fname)); Modified: trunk/tests/samplekeys/README =================================================================== --- trunk/tests/samplekeys/README 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/tests/samplekeys/README 2007-08-24 09:34:39 UTC (rev 4569) @@ -13,5 +13,8 @@ webdeca.der trust.web.de CA certificate [2004-02-17] +gte.pem GTE CyberTrust Global Root + + Added: trunk/tests/samplekeys/gte.pem =================================================================== --- trunk/tests/samplekeys/gte.pem 2007-08-23 17:41:22 UTC (rev 4568) +++ trunk/tests/samplekeys/gte.pem 2007-08-24 09:34:39 UTC (rev 4569) @@ -0,0 +1,19 @@ +Issuer ...: /CN=GTE CyberTrust Global Root/OU=GTE CyberTrust Solutions, Inc./O=GTE Corporation/C=US +Serial ...: 01A5 +Subject ..: /CN=GTE CyberTrust Global Root/OU=GTE CyberTrust Solutions, Inc./O=GTE Corporation/C=US + +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- From cvs at cvs.gnupg.org Mon Aug 27 20:11:00 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 27 Aug 2007 20:11:00 +0200 Subject: [svn] GnuPG - r4571 - in trunk: . agent common doc doc/examples g10 jnlib sm tools Message-ID: Author: wk Date: 2007-08-27 20:10:27 +0200 (Mon, 27 Aug 2007) New Revision: 4571 Added: trunk/doc/examples/pwpattern.list trunk/tools/gpg-check-pattern.c Modified: trunk/ChangeLog trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/call-pinentry.c trunk/agent/genkey.c trunk/agent/gpg-agent.c trunk/agent/trustlist.c trunk/autogen.sh trunk/common/ChangeLog trunk/common/exechelp.c trunk/common/exechelp.h trunk/common/homedir.c trunk/common/util.h trunk/configure.ac trunk/doc/ChangeLog trunk/doc/Makefile.am trunk/doc/gpg-agent.texi trunk/g10/ChangeLog trunk/g10/trustdb.c trunk/jnlib/stringhelp.c trunk/sm/ChangeLog trunk/sm/Makefile.am trunk/tools/ChangeLog trunk/tools/Makefile.am trunk/tools/gpgconf-comp.c Log: Implemented more gpg-agen options to support certain passphrase policies. New tool gpg-check-pattern. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,10 @@ +2007-08-27 Werner Koch + + * configure.ac: Remove remaining support for internal regex. + Define DISABLE_REGEX automake conditional. Add option + --with-regex. + * autogen.sh [--build-w32]: Remove --disable-regex. Use --with-regex. + 2007-08-16 Werner Koch Released 2.0.6. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/NEWS 2007-08-27 18:10:27 UTC (rev 4571) @@ -4,9 +4,13 @@ * Fixed encryption problem if duplicate certificates are in the keybox. - * Made it work on Windows Vista. + * Made it work on Windows Vista. Note that the entire Windows port + is still considered Beta. + * Add new options min-passphrase-nonalpha, check-passphrase-pattern + and enforce-passphrase-constraints to gpg-agent. + Noteworthy changes in version 2.0.6 (2007-08-16) ------------------------------------------------ Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,22 @@ +2007-08-27 Werner Koch + + * gpg-agent.c: Add options --min-passphrase-nonalpha, + --check-passphrase-pattern and --enforce-passphrase-constraints. + (MIN_PASSPHRASE_NONALPHA): Init nonalpha option to 1. + (main): Declare options for gpgconf. + * agent.h (struct): Add members MIN_PASSPHRASE_NONALPHA, + ENFORCE_PASSPHRASE_CONSTRAINTS and CHECK_PASSPHRASE_PATTERN. + * genkey.c (nonalpha_charcount): New. + (check_passphrase_pattern): New. + (check_passphrase_constraints): Implement. Factor some code out... + (take_this_one_anyway, take_this_one_anyway2): .. New. + + * call-pinentry.c (agent_show_message): New. + (agent_askpin): We better reset the pin buffer before asking. + + * trustlist.c (insert_colons): New. + (agent_marktrusted): Pretty print the fpr. + 2007-08-22 Werner Koch * findkey.c (O_BINARY): Make sure it is defined. Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/agent.h 2007-08-27 18:10:27 UTC (rev 4571) @@ -80,9 +80,16 @@ unsigned long max_cache_ttl; /* Default. */ unsigned long max_cache_ttl_ssh; /* for SSH. */ + /* Flag disallowin bypassing of the warning. */ + int enforce_passphrase_constraints; /* The require minmum length of a passphrase. */ unsigned int min_passphrase_len; + /* The minimum number of non-alpha characters in a passphrase. */ + unsigned int min_passphrase_nonalpha; + /* File name with a patternfile or NULL if not enabled. */ + const char *check_passphrase_pattern; + int running_detached; /* We are running detached from the tty. */ int ignore_cache_for_signing; @@ -227,6 +234,7 @@ const char *errtext); int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, const char *cancel); +int agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn); int agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn); void agent_popup_message_stop (ctrl_t ctrl); Modified: trunk/agent/call-pinentry.c =================================================================== --- trunk/agent/call-pinentry.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/call-pinentry.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -213,7 +213,9 @@ #endif if (fflush (NULL)) { +#ifndef HAVE_W32_SYSTEM gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); +#endif log_error ("error flushing pending output: %s\n", strerror (errno)); /* At least Windows XP fails here with EBADF. According to docs and Wine an fflush(NULL) is the same as _flushall. However @@ -476,6 +478,7 @@ { memset (&parm, 0, sizeof parm); parm.size = pininfo->max_length; + *pininfo->pin = 0; /* Reset the PIN. */ parm.buffer = (unsigned char*)pininfo->pin; if (errtext) @@ -671,6 +674,55 @@ } + +/* Pop up the PINentry, display the text DESC and a button with the + text OK_BTN (which may be NULL to use the default of "OK") and waut + for the user to hit this button. The return value is not + relevant. */ +int +agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + + rc = start_pinentry (ctrl); + if (rc) + return rc; + + if (desc) + snprintf (line, DIM(line)-1, "SETDESC %s", desc); + else + snprintf (line, DIM(line)-1, "RESET"); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + /* Most pinentries out in the wild return the old Assuan error code + for canceled which gets translated to an assuan Cancel error and + not to the code for a user cancel. Fix this here. */ + if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) + rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); + + if (rc) + return unlock_pinentry (rc); + + if (ok_btn) + { + snprintf (line, DIM(line)-1, "SETOK %s", ok_btn); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, + NULL, NULL, NULL); + if (rc) + return unlock_pinentry (rc); + } + + rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL, + NULL, NULL, NULL); + if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) + rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); + + return unlock_pinentry (rc); +} + + /* The thread running the popup message. */ static void * popup_message_thread (void *arg) Modified: trunk/agent/genkey.c =================================================================== --- trunk/agent/genkey.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/genkey.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -27,6 +27,8 @@ #include "agent.h" #include "i18n.h" +#include "exechelp.h" +#include "sysutils.h" static int store_key (gcry_sexp_t private, const char *passphrase, int force) @@ -70,6 +72,100 @@ } +/* Count the number of non-alpha characters in S. Control characters + and non-ascii characters are not considered. */ +static size_t +nonalpha_count (const char *s) +{ + size_t n; + + for (n=0; *s; s++) + if (isascii (*s) && ( isdigit (*s) || ispunct (*s) )) + n++; + + return n; +} + + +/* Check PW against a list of pattern. Return 0 if PW does not match + these pattern. */ +static int +check_passphrase_pattern (ctrl_t ctrl, const char *pw) +{ + gpg_error_t err = 0; + const char *pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CHECK_PATTERN); + FILE *infp; + const char *argv[10]; + pid_t pid; + int result, i; + + infp = gnupg_tmpfile (); + if (!infp) + { + err = gpg_error_from_syserror (); + log_error (_("error creating temporary file: %s\n"), strerror (errno)); + return 1; /* Error - assume password should not be used. */ + } + + if (fwrite (pw, strlen (pw), 1, infp) != 1) + { + err = gpg_error_from_syserror (); + log_error (_("error writing to temporary file: %s\n"), + strerror (errno)); + fclose (infp); + return 1; /* Error - assume password should not be used. */ + } + rewind (infp); + + i = 0; + argv[i++] = "--null"; + argv[i++] = "--", + argv[i++] = opt.check_passphrase_pattern, + argv[i] = NULL; + assert (i < sizeof argv); + + if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid)) + result = 1; /* Execute error - assume password should no be used. */ + else if (gnupg_wait_process (pgmname, pid)) + result = 1; /* Helper returned an error - probably a match. */ + else + result = 0; /* Success; i.e. no match. */ + + /* Overwrite our temporary file. */ + rewind (infp); + for (i=((strlen (pw)+99)/100)*100; i > 0; i--) + putc ('\xff', infp); + fflush (infp); + fclose (infp); + return result; +} + + +static int +take_this_one_anyway2 (ctrl_t ctrl, const char *desc, const char *anyway_btn) +{ + gpg_error_t err; + + if (opt.enforce_passphrase_constraints) + { + err = agent_show_message (ctrl, desc, _("Enter new passphrase")); + if (!err) + err = gpg_error (GPG_ERR_CANCELED); + } + else + err = agent_get_confirmation (ctrl, desc, + anyway_btn, _("Enter new passphrase")); + return err; +} + + +static int +take_this_one_anyway (ctrl_t ctrl, const char *desc) +{ + return take_this_one_anyway2 (ctrl, desc, _("Take this one anyway")); +} + + /* Check whether the passphrase PW is suitable. Returns 0 if the passphrase is suitable and true if it is not and the user should be asked to provide a different one. */ @@ -78,7 +174,8 @@ { gpg_error_t err; unsigned int minlen = opt.min_passphrase_len; - + unsigned int minnonalpha = opt.min_passphrase_nonalpha; + if (!pw) pw = ""; @@ -93,25 +190,60 @@ "be at least %u characters long.", minlen), minlen ); if (!desc) return gpg_error_from_syserror (); - - err = agent_get_confirmation (ctrl, desc, - _("Take this one anyway"), - _("Enter new passphrase")); + err = take_this_one_anyway (ctrl, desc); xfree (desc); if (err) return err; } + if (nonalpha_count (pw) < minnonalpha ) + { + char *desc = xtryasprintf + ( ngettext ("Warning: You have entered a passphrase that%%0A" + "is obviously not secure. A passphrase should%%0A" + "contain at least %u digit or special character.", + "Warning: You have entered a passphrase that%%0A" + "is obviously not secure. A passphrase should%%0A" + "contain at least %u digits or special characters.", + minnonalpha), minnonalpha ); + if (!desc) + return gpg_error_from_syserror (); + err = take_this_one_anyway (ctrl, desc); + xfree (desc); + if (err) + return err; + } + + /* If configured check the passphrase against a list of know words + and pattern. The actual test is done by an external program. + The warning message is generic to give the user no hint on how to + circumvent this list. */ + if (*pw && opt.check_passphrase_pattern && + check_passphrase_pattern (ctrl, pw)) + { + const char *desc = + /* */ _("Warning: You have entered a passphrase that%0A" + "is obviously not secure. A passphrase may not%0A" + "be a known term or match certain pattern."); + + err = take_this_one_anyway (ctrl, desc); + if (err) + return err; + } + + /* The final check is to warn about an empty passphrase. */ if (!*pw) { - const char *desc = _("You have not entered a passphrase - " - "this is in general a bad idea!%0A" - "Please confirm that you do not want to " - "have any protection on your key."); + const char *desc = (opt.enforce_passphrase_constraints? + _("You have not entered a passphrase!%0A" + "An empty passphrase is not allowed.") : + _("You have not entered a passphrase - " + "this is in general a bad idea!%0A" + "Please confirm that you do not want to " + "have any protection on your key.")); - err = agent_get_confirmation (ctrl, desc, - _("Yes, protection is not needed"), - _("Enter new passphrase")); + err = take_this_one_anyway2 (ctrl, desc, + _("Yes, protection is not needed")); if (err) return err; } Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/gpg-agent.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -88,7 +88,10 @@ oDefCacheTTLSSH, oMaxCacheTTL, oMaxCacheTTLSSH, + oEnforcePassphraseConstraints, oMinPassphraseLen, + oMinPassphraseNonalpha, + oCheckPassphrasePattern, oUseStandardSocket, oNoUseStandardSocket, @@ -149,7 +152,12 @@ { oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" }, { oMaxCacheTTL, "max-cache-ttl", 4, "@" }, { oMaxCacheTTLSSH, "max-cache-ttl-ssh", 4, "@" }, + + { oEnforcePassphraseConstraints, "enforce-passphrase-constraints", 0, "@"}, { oMinPassphraseLen, "min-passphrase-len", 4, "@" }, + { oMinPassphraseNonalpha, "min-passphrase-nonalpha", 4, "@" }, + { oCheckPassphrasePattern, "check-passphrase-pattern", 2, "@" }, + { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, { oAllowMarkTrusted, "allow-mark-trusted", 0, @@ -168,6 +176,7 @@ #define MAX_CACHE_TTL (120*60) /* 2 hours */ #define MAX_CACHE_TTL_SSH (120*60) /* 2 hours */ #define MIN_PASSPHRASE_LEN (8) +#define MIN_PASSPHRASE_NONALPHA (1) /* The timer tick used for housekeeping stuff. For Windows we use a longer period as the SetWaitableTimer seems to signal earlier than @@ -362,7 +371,10 @@ opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH; opt.max_cache_ttl = MAX_CACHE_TTL; opt.max_cache_ttl_ssh = MAX_CACHE_TTL_SSH; + opt.enforce_passphrase_constraints = 0; opt.min_passphrase_len = MIN_PASSPHRASE_LEN; + opt.min_passphrase_nonalpha = MIN_PASSPHRASE_NONALPHA; + opt.check_passphrase_pattern = NULL; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; opt.disable_scdaemon = 0; @@ -402,7 +414,16 @@ case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break; + case oEnforcePassphraseConstraints: + opt.enforce_passphrase_constraints=1; + break; case oMinPassphraseLen: opt.min_passphrase_len = pargs->r.ret_ulong; break; + case oMinPassphraseNonalpha: + opt.min_passphrase_nonalpha = pargs->r.ret_ulong; + break; + case oCheckPassphrasePattern: + opt.check_passphrase_pattern = pargs->r.ret_str; + break; case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; @@ -723,8 +744,15 @@ GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL ); printf ("max-cache-ttl-ssh:%lu:%d:\n", GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MAX_CACHE_TTL_SSH ); + printf ("enforce-passphrase-constraints:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("min-passphrase-len:%lu:%d:\n", GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, MIN_PASSPHRASE_LEN ); + printf ("min-passphrase-nonalpha:%lu:%d:\n", + GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, + MIN_PASSPHRASE_NONALPHA); + printf ("check-passphrase-pattern:%lu:\n", + GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME); printf ("no-grab:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("ignore-cache-for-signing:%lu:\n", Modified: trunk/agent/trustlist.c =================================================================== --- trunk/agent/trustlist.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/agent/trustlist.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -455,13 +455,40 @@ } +/* Create a copy of string with colons inserted after each two bytes. + Caller needs to release the string. In case of a memory failure, + NULL is returned. */ +static char * +insert_colons (const char *string) +{ + char *buffer, *p; + size_t n = strlen (string); + + p = buffer = xtrymalloc ( n + (n+2)/3 + 1 ); + if (!buffer) + return NULL; + while (*string) + { + *p++ = *string++; + if (*string) + { + *p++ = *string++; + if (*string) + *p++ = ':'; + } + } + *p = 0; + + return buffer; +} + + /* Insert the given fpr into our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'. - This function does first check whether that key has alreay been put + This function does first check whether that key has already been put into the trustdb and returns success in this case. Before a FPR - actually gets inserted, the user is asked by means of the pin-entry - whether this is actual wants he want to do. -*/ + actually gets inserted, the user is asked by means of the Pinentry + whether this is actual wants he want to do. */ gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag) { @@ -469,7 +496,9 @@ char *desc; char *fname; FILE *fp; + char *fprformatted; + /* Check whether we are at all allowed to modify the trustlist. This is useful so that the trustlist may be a symlink to a global trustlist with only admin priviliges to modify it. Of course @@ -494,6 +523,9 @@ return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Insert a new one. */ + fprformatted = insert_colons (fpr); + if (!fprformatted) + return out_of_core (); if (asprintf (&desc, /* TRANSLATORS: This prompt is shown by the Pinentry and has one special property: A "%%0A" is used by @@ -503,12 +535,15 @@ plain % sign, you need to encode it as "%%25". The second "%s" gets replaced by a hexdecimal fingerprint string whereas the first one receives - the name as store in the certificate. */ + the name as stored in the certificate. */ _("Please verify that the certificate identified as:%%0A" " \"%s\"%%0A" "has the fingerprint:%%0A" - " %s"), name, fpr) < 0 ) - return out_of_core (); + " %s"), name, fprformatted) < 0 ) + { + xfree (fprformatted); + return out_of_core (); + } /* TRANSLATORS: "Correct" is the label of a button and intended to be hit if the fingerprint matches the one of the CA. The other @@ -519,8 +554,11 @@ gpgsm may stop asking further questions. We won't do this for the second question of course. */ if (err) - return (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED ? - gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED) : err); + { + xfree (fprformatted); + return (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED ? + gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED) : err); + } @@ -537,12 +575,18 @@ " \"%s\"%%0A" "to correctly certify user certificates?"), name) < 0 ) - return out_of_core (); + { + xfree (fprformatted); + return out_of_core (); + } err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No")); free (desc); if (err) - return err; + { + xfree (fprformatted); + return err; + } /* Now check again to avoid duplicates. We take the lock to make sure that nobody else plays with our file. Frankly we don't work @@ -552,6 +596,7 @@ if (!agent_istrusted (ctrl, fpr)) { unlock_trusttable (); + xfree (fprformatted); return 0; } @@ -566,6 +611,7 @@ log_error ("can't create `%s': %s\n", fname, gpg_strerror (err)); xfree (fname); unlock_trusttable (); + xfree (fprformatted); return err; } fputs (headerblurb, fp); @@ -578,13 +624,14 @@ log_error ("can't open `%s': %s\n", fname, gpg_strerror (err)); xfree (fname); unlock_trusttable (); + xfree (fprformatted); return err; } /* Append the key. */ fputs ("\n# ", fp); print_sanitized_string (fp, name, 0); - fprintf (fp, "\n%s %c\n", fpr, flag); + fprintf (fp, "\n%s %c\n", fprformatted, flag); if (ferror (fp)) err = gpg_error_from_syserror (); @@ -595,6 +642,7 @@ agent_reload_trustlist (); xfree (fname); unlock_trusttable (); + xfree (fprformatted); return err; } Modified: trunk/autogen.sh =================================================================== --- trunk/autogen.sh 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/autogen.sh 2007-08-27 18:10:27 UTC (rev 4571) @@ -91,9 +91,9 @@ --with-libgcrypt-prefix=${w32root} \ --with-libassuan-prefix=${w32root} \ --with-zlib=${w32root} \ + --with-regex=${w32root} \ --with-pth-prefix=${w32root} \ - --without-included-gettext \ - --disable-regex "$@" + --without-included-gettext "$@" rc=$? exit $rc fi Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/common/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,12 @@ +2007-08-27 Werner Koch + + * util.h (GNUPG_MODULE_NAME_CHECK_PATTERN): New. + * homedir.c (gnupg_module_name): Add it. + * exechelp.c (w32_fd_or_null) [W32]: New. + (gnupg_spawn_process_fd): New. + (gnupg_wait_process) [W32]: Close the handle after if the process has + returned. + 2007-08-22 Werner Koch Updated estream from libestream. Modified: trunk/common/exechelp.c =================================================================== --- trunk/common/exechelp.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/common/exechelp.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,5 +1,5 @@ /* exechelp.c - fork and exec helpers - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -191,6 +191,23 @@ #endif /*HAVE_W32_SYSTEM*/ +#ifdef HAVE_W32_SYSTEM +static HANDLE +w32_open_null (int for_write) +{ + HANDLE hfile; + + hfile = CreateFile ("nul", + for_write? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hfile == INVALID_HANDLE_VALUE) + log_debug ("can't open `nul': %s\n", w32_strerror (-1)); + return hfile; +} +#endif /*HAVE_W32_SYSTEM*/ + + #ifndef HAVE_W32_SYSTEM /* The exec core used right after the fork. This will never return. */ static void @@ -257,9 +274,9 @@ stdin, write the output to OUTFILE, return a new stream in STATUSFILE for stderr and the pid of the process in PID. The arguments for the process are expected in the NULL terminated array - ARGV. The program name itself should not be included there. if + ARGV. The program name itself should not be included there. If PREEXEC is not NULL, that function will be called right before the - exec. + exec. Calling gnupg_wait_process is required. Returns 0 on success or an error code. */ gpg_error_t @@ -439,6 +456,119 @@ } + +/* Simplified version of gnupg_spawn_process. This function forks and + then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout + and ERRFD to stderr (any of them may be -1 to connect them to + /dev/null). The arguments for the process are expected in the NULL + terminated array ARGV. The program name itself should not be + included there. Calling gnupg_wait_process is required. + + Returns 0 on success or an error code. */ +gpg_error_t +gnupg_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, pid_t *pid) +{ +#ifdef HAVE_W32_SYSTEM + gpg_error_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; + STARTUPINFO si; + char *cmdline; + int i; + HANDLE stdhd[3]; + + /* Setup return values. */ + *pid = (pid_t)(-1); + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + stdhd[0] = infd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE; + stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; + stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; + si.hStdInput = infd == -1? stdhd[0] : (void*)_get_osfhandle (infd); + si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd); + si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); + + log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); + if (!CreateProcess (pgmname, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED), + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + err = gpg_error (GPG_ERR_GENERAL); + } + else + err = 0; + xfree (cmdline); + for (i=0; i < 3; i++) + if (stdhd[i] != INVALID_HANDLE_VALUE) + CloseHandle (stdhd[i]); + if (err) + return err; + + log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + /* Process has been created suspended; resume it now. */ + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + + *pid = handle_to_pid (pi.hProcess); + return 0; + +#else /* !HAVE_W32_SYSTEM */ + gpg_error_t err; + +#ifdef USE_GNU_PTH + *pid = pth_fork? pth_fork () : fork (); +#else + *pid = fork (); +#endif + if (*pid == (pid_t)(-1)) + { + err = gpg_error_from_syserror (); + log_error (_("error forking process: %s\n"), strerror (errno)); + return err; + } + + if (!*pid) + { + gcry_control (GCRYCTL_TERM_SECMEM); + /* Run child. */ + do_exec (pgmname, argv, infd, outfd, errfd, NULL); + /*NOTREACHED*/ + } + + return 0; +#endif /* !HAVE_W32_SYSTEM */ +} + + /* Wait for the process identified by PID to terminate. PGMNAME should be the same as suplieed to the spawn fucntion and is only used for diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for @@ -483,6 +613,7 @@ } else ec = 0; + CloseHandle (proc); break; default: Modified: trunk/common/exechelp.h =================================================================== --- trunk/common/exechelp.h 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/common/exechelp.h 2007-08-27 18:10:27 UTC (rev 4571) @@ -28,16 +28,31 @@ arguments for the process are expected in the NULL terminated array ARGV. The program name itself should not be included there. if PREEXEC is not NULL, that function will be called right before the - exec. Returns 0 on success or an error code. */ + exec. Calling gnupg_wait_process is required. Returns 0 on + success or an error code. */ gpg_error_t gnupg_spawn_process (const char *pgmname, const char *argv[], FILE *infile, FILE *outfile, void (*preexec)(void), FILE **statusfile, pid_t *pid); + +/* Simplified version of gnupg_spawn_process. This function forks and + then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout + and ERRFD to stderr (any of them may be -1 to connect them to + /dev/null). The arguments for the process are expected in the NULL + terminated array ARGV. The program name itself should not be + included there. Calling gnupg_wait_process is required. Returns 0 + on success or an error code. */ +gpg_error_t gnupg_spawn_process_fd (const char *pgmname, + const char *argv[], + int infd, int outfd, int errfd, + pid_t *pid); + + /* Wait for the process identified by PID to terminate. PGMNAME should - be the same as suplieed to the spawn fucntion and is only used for - diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for - any failures of the spawned program or other error codes.*/ + be the same as supplied to the spawn fucntion and is only used for + diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL + for any failures of the spawned program or other error codes.*/ gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid); Modified: trunk/common/homedir.c =================================================================== --- trunk/common/homedir.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/common/homedir.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -369,6 +369,9 @@ X(libexecdir, "gpg-protect-tool"); #endif + case GNUPG_MODULE_NAME_CHECK_PATTERN: + X(libexecdir, "gpg-check-pattern"); + default: BUG (); } Modified: trunk/common/util.h =================================================================== --- trunk/common/util.h 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/common/util.h 2007-08-27 18:10:27 UTC (rev 4571) @@ -185,6 +185,7 @@ #define GNUPG_MODULE_NAME_SCDAEMON 3 #define GNUPG_MODULE_NAME_DIRMNGR 4 #define GNUPG_MODULE_NAME_PROTECT_TOOL 5 +#define GNUPG_MODULE_NAME_CHECK_PATTERN 6 const char *gnupg_module_name (int which); Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/configure.ac 2007-08-27 18:10:27 UTC (rev 4571) @@ -1025,7 +1025,6 @@ # # Sanity check regex. Tests adapted from mutt. -# FIXME: We should use the the regex from gnulib # AC_MSG_CHECKING([whether regular expression support is requested]) AC_ARG_ENABLE(regex, @@ -1035,20 +1034,28 @@ AC_MSG_RESULT($use_regex) if test "$use_regex" = yes ; then - AC_MSG_CHECKING([whether the included regex lib is requested]) - AC_ARG_WITH(included-regex, - [ --with-included-regex use the included GNU regex library], - [gnupg_cv_included_regex="$withval"],[gnupg_cv_included_regex=no]) - AC_MSG_RESULT($gnupg_cv_included_regex) + _cppflags="${CPPFLAGS}" + _ldflags="${LDFLAGS}" + AC_ARG_WITH(regex, + AC_HELP_STRING([--with-regex=DIR],[look for regex in DIR]), + [ + if test -d "$withval" ; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + ],withval="") - if test $gnupg_cv_included_regex = no ; then - # Does the system have regex functions at all? - AC_CHECK_FUNC(regcomp,gnupg_cv_included_regex=no, - gnupg_cv_included_regex=yes) - fi + # Does the system have regex functions at all? + AC_SEARCH_LIBS([regcomp], [regex]) + AC_CHECK_FUNC(regcomp, gnupg_cv_have_regex=yes, gnupg_cv_have_regex=no) - if test $gnupg_cv_included_regex = no ; then - AC_CACHE_CHECK([whether your system's regexp library is broken], + if test $gnupg_cv_have_regex = no; then + use_regex=no + else + if test x"$cross_compiling" = xyes; then + AC_MSG_WARN([cross compiling; assuming regexp libray is not broken]) + else + AC_CACHE_CHECK([whether your system's regexp library is broken], [gnupg_cv_regex_broken], AC_TRY_RUN([ #include @@ -1056,23 +1063,23 @@ main() { regex_t blah ; regmatch_t p; p.rm_eo = p.rm_eo; return regcomp(&blah, "foo.*bar", REG_NOSUB) || regexec (&blah, "foobar", 0, NULL, 0); }], gnupg_cv_regex_broken=no, gnupg_cv_regex_broken=yes, gnupg_cv_regex_broken=yes)) - if test $gnupg_cv_regex_broken = yes ; then - AC_MSG_WARN(your regex is broken - using the included GNU regex instead.) - gnupg_cv_included_regex=yes - fi + if test $gnupg_cv_regex_broken = yes; then + AC_MSG_WARN([your regex is broken - disabling regex use]) + use_regex=no + fi + fi fi + CPPFLAGS="${_cppflags}" + LDFLAGS="${_ldflags}" +fi - if test $gnupg_cv_included_regex = yes; then - AC_DEFINE(USE_INTERNAL_REGEX,1,[ Define if you want to use the included regex lib ]) - fi -else - AC_DEFINE(DISABLE_REGEX,1,[ Define to disable regular expression support ]) +if test "$use_regex" != yes ; then + AC_DEFINE(DISABLE_REGEX,1, [Define to disable regular expression support]) fi +AM_CONDITIONAL(DISABLE_REGEX, test x"$use_regex" != xyes) -AM_CONDITIONAL(USE_INTERNAL_REGEX, test x"$gnupg_cv_included_regex" = xyes) - # # Do we have zlib? Must do it here because Solaris failed # when compiling a conftest (due to the "-lz" from LIBS). @@ -1397,6 +1404,12 @@ Default scdaemon: $show_gnupg_scdaemon_pgm Default dirmngr: $show_gnupg_dirmngr_pgm - PKITS based tests: $run_pkits_tests + PKITS based tests: $run_pkits_tests" +if test x"$use_regex" != xyes ; then +echo " + Warning: No regular expression support available. + OpenPGP trust signatures won't work. + gpg-check-pattern will not be build. " +fi Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/doc/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,7 @@ +2007-08-27 Werner Koch + + * examples/pwpattern.list: New. + 2007-08-24 Werner Koch * debugging.texi (Common Problems): Add "A root certifciate does Modified: trunk/doc/Makefile.am =================================================================== --- trunk/doc/Makefile.am 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/doc/Makefile.am 2007-08-27 18:10:27 UTC (rev 4571) @@ -18,7 +18,7 @@ ## Process this file with automake to produce Makefile.in examples = examples/README examples/scd-event examples/trustlist.txt \ - examples/gpgconf.conf + examples/gpgconf.conf examples/pwpattern.list EXTRA_DIST = DETAILS HACKING TRANSLATE OpenPGP KEYSERVER samplekeys.asc \ gnupg-logo.eps gnupg-logo.pdf gnupg-logo.png \ Added: trunk/doc/examples/pwpattern.list =================================================================== --- trunk/doc/examples/pwpattern.list 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/doc/examples/pwpattern.list 2007-08-27 18:10:27 UTC (rev 4571) @@ -0,0 +1,48 @@ +# pwpattern.list -*- default-generic -*- +# +# This is an example for a pattern file as used by gpg-check-pattern. +# The file is line based with comment lines beginning on the *first* +# position with a '#'. Empty lines and lines with just spaces are +# ignored. The other lines may be verbatim patterns and match as they +# are (trailing spaces are ignored) or extended regular expressions +# indicated by a / in the first column and terminated by another / or +# end of line. All comparisons are case insensitive. + +# Reject the usual metavariables. Usual not required because +# gpg-agent can be used to reject all passphrases shorter than 8 +# charactes. +foo +bar +baz + +# As well as very common passwords. Note that gpg-agent can be used +# to reject them due to missing non-alpha characters. +password +passwort +passphrase +mantra +test +abc +egal + +# German number plates. +/^[A-Z]{1,3}[ ]*-[ ]*[A-Z]{1,2}[ ]*[0-9]+/ + +# Dates (very limited, only ISO dates). */ +/^[012][0-9][0-9][0-9]-[012][0-9]-[0123][0-9]$/ + +# Arbitrary strings +the quick brown fox jumps over the lazy dogs back +no-password +no password + +12345678 +123456789 +1234567890 +87654321 +987654321 +0987654321 +qwertyuiop +qwertzuiop +asdfghjkl +zxcvbnm Modified: trunk/doc/gpg-agent.texi =================================================================== --- trunk/doc/gpg-agent.texi 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/doc/gpg-agent.texi 2007-08-27 18:10:27 UTC (rev 4571) @@ -334,11 +334,38 @@ seconds. After this time a cache entry will get expired even if it has been accessed recently. The default are 2 hours (7200 seconds). + at item --enforce-passphrase-constraints + at opindex enforce-passphrase-constraints +Enforce the passphrase constraints by not allowing the user to bypass +them using the ``Take it anyway'' button. + @item --min-passphrase-len @var{n} @opindex min-passphrase-len Set the minimal length of a passphrase. When entering a new passphrase shorter than this value a warning will be displayed. Defaults to 8. + at item --min-passphrase-nonalpha @var{n} + at opindex min-passphrase-nonalpha +Set the minimal number of digits or special characters required in a +passphrase. When entering a new passphrase with less than this number +of digits or special characters a warning will be displayed. Defaults +to 1. + + at item --check-passphrase-pattern @var{file} + at opindex check-passphrase-pattern +Check the passphrase against the pattern given in @var{file}. When +entering a new passphrase matching one of these pattern a warning will +be displayed. @var{file} should be an absolute filename. The default is +not to use any pattern file. + +Security note: It is known that checking a passphrase against a list of +pattern or even against a complete dictionary is not very effective to +enforce good passphrases. Users will soon figure up ways to bypass such +a policy. A better policy is to educate users on good security +behavior and optional to run a passphrase cracker regularly on all +users passphrases t catch the very simple ones. + + @item --pinentry-program @var{filename} @opindex pinentry-program Use program @var{filename} as the PIN entry. The default is installation Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/g10/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,7 @@ +2007-08-27 Werner Koch + + * trustdb.c (USE_INTERNAL_REGEX): Remove support. + 2007-08-24 Werner Koch * keyring.c (keyring_register_filename): Use same_file_p(). Modified: trunk/g10/trustdb.c =================================================================== --- trunk/g10/trustdb.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/g10/trustdb.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -26,11 +26,7 @@ #ifndef DISABLE_REGEX #include -#ifdef USE_INTERNAL_REGEX -#include "_regex.h" -#else #include -#endif #endif /* !DISABLE_REGEX */ #include "gpg.h" Modified: trunk/jnlib/stringhelp.c =================================================================== --- trunk/jnlib/stringhelp.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/jnlib/stringhelp.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -339,7 +339,7 @@ /* Compare whether the filenames are identical. This is a - specialversion of strcmp() taking the semantics of filenames in + special version of strcmp() taking the semantics of filenames in account. Note that this function works only on the supplied names without considereing any context like the current directory. See also same_file_p(). */ Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/sm/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,7 @@ +2007-08-24 Werner Koch + + * Makefile.am (common_libs): Swap libkeybox and jnlib. + 2007-08-23 Werner Koch * certlist.c (gpgsm_certs_identical_p): New. Modified: trunk/sm/Makefile.am =================================================================== --- trunk/sm/Makefile.am 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/sm/Makefile.am 2007-08-27 18:10:27 UTC (rev 4571) @@ -52,7 +52,7 @@ qualified.c -common_libs = $(libcommon) ../jnlib/libjnlib.a ../kbx/libkeybox.a \ +common_libs = $(libcommon) ../kbx/libkeybox.a ../jnlib/libjnlib.a \ ../gl/libgnu.a gpgsm_LDADD = $(common_libs) ../common/libgpgrl.a \ Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/tools/ChangeLog 2007-08-27 18:10:27 UTC (rev 4571) @@ -1,3 +1,15 @@ +2007-08-27 Werner Koch + + * gpg-check-pattern.c: New + * Makefile.am (libexec_PROGRAMS): Add unless DISABLE_REGEX. + +2007-08-24 Werner Koch + + * gpgconf-comp.c : Add options --check-passphrase-pattern, + --min-passphrase-nonalpha and --enforce-passphrase-constraints and + move them into a new "passphrase policy" group. + (gc_component) [W32]: Enable dirmngr. + 2007-08-21 Werner Koch * gpgkey2ssh.c (key_to_blob): Use gnupg_tmpfile(). Modified: trunk/tools/Makefile.am =================================================================== --- trunk/tools/Makefile.am 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/tools/Makefile.am 2007-08-27 18:10:27 UTC (rev 4571) @@ -46,6 +46,10 @@ bin_PROGRAMS += watchgnupg gpgparsemail endif +if !DISABLE_REGEX +libexec_PROGRAMS = gpg-check-pattern +endif + noinst_PROGRAMS = clean-sat mk-tdata make-dns-cert gpgsplit common_libs = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a @@ -86,6 +90,13 @@ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) +if !DISABLE_REGEX +gpg_check_pattern_SOURCES = gpg-check-pattern.c +gpg_check_pattern_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) +gpg_check_pattern_LDADD = $(common_libs) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS) +endif + # Make sure that all libs are build before we use them. This is # important for things like make -j2. $(PROGRAMS): $(common_libs) $(pwquery_libs) Added: trunk/tools/gpg-check-pattern.c =================================================================== --- trunk/tools/gpg-check-pattern.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/tools/gpg-check-pattern.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -0,0 +1,504 @@ +/* gpg-check-pattern.c - A tool to check passphrases against pattern. + * Copyright (C) 2007 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 3 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, see . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LOCALE_H +# include +#endif +#ifdef HAVE_LANGINFO_CODESET +# include +#endif +#ifdef HAVE_DOSISH_SYSTEM +# include /* for setmode() */ +#endif +#include +#include +#include +#include + + +#define JNLIB_NEED_LOG_LOGV +#include "util.h" +#include "i18n.h" +#include "sysutils.h" + + +enum cmd_and_opt_values +{ aNull = 0, + oVerbose = 'v', + oArmor = 'a', + oPassphrase = 'P', + + oProtect = 'p', + oUnprotect = 'u', + oNull = '0', + + oNoVerbose = 500, + oCheck, + + oHomedir +}; + + +/* The list of commands and options. */ +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oVerbose, "verbose", 0, "verbose" }, + + { oHomedir, "homedir", 2, "@" }, + { oCheck, "check", 0, "run only a syntax check on the patternfile" }, + { oNull, "null", 0, "input is expected to be null delimited" }, + + {0} +}; + + +/* Global options are accessed through the usual OPT structure. */ +static struct +{ + int verbose; + const char *homedir; + int checkonly; + int null; +} opt; + + +enum { + PAT_NULL, /* Indicates end of the array. */ + PAT_STRING, /* The pattern is a simple string. */ + PAT_REGEX /* The pattern is an extended regualr expression. */ +}; + + +/* An object to decibe an item of our pattern table. */ +struct pattern_s +{ + int type; + unsigned int lineno; /* Line number of the pattern file. */ + union { + struct { + const char *string; /* Pointer to the actual string (nul termnated). */ + size_t length; /* The length of this string (strlen). */ + } s; /*PAT_STRING*/ + struct { + /* We allocate the regex_t because this type is larger than what + we need for PAT_STRING and we expect only a few regex in a + patternfile. It would be a waste of core to have so many + unused stuff in the table. */ + regex_t *regex; + } r; /*PAT_REGEX*/ + } u; +}; +typedef struct pattern_s pattern_t; + + + +/*** Local prototypes ***/ +static char *read_file (const char *fname, size_t *r_length); +static pattern_t *parse_pattern_file (char *data, size_t datalen); +static void process (FILE *fp, pattern_t *patarray); + + + + +/* Info function for usage(). */ +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-check-pattern (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: + p = _("Usage: gpg-check-pattern [options] patternfile (-h for help)\n"); + break; + case 41: + p = _("Syntax: gpg-check-pattern [options] patternfile\n" + "Check a passphrase given on stdin against the patternfile\n"); + break; + + default: p = NULL; + } + return p; +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + char *raw_pattern; + size_t raw_pattern_length; + pattern_t *patternarray; + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + log_set_prefix ("gpg-check-pattern", 1); + + /* Make sure that our subsystems are ready. */ + init_common_subsystems (); + + i18n_init (); + + /* We need Libgcrypt for hashing. */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal ( _("%s is too old (need %s, have %s)\n"), "libgcrypt", + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + setup_libgcrypt_logging (); + gcry_control (GCRYCTL_INIT_SECMEM, 4096, 0); + + opt.homedir = default_homedir (); + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* (do not remove the args) */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oHomedir: opt.homedir = pargs.r.ret_str; break; + case oCheck: opt.checkonly = 1; break; + case oNull: opt.null = 1; break; + + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit (2); + + if (argc != 1) + usage (1); + + /* We read the entire pattern file into our memory and parse it + using a separate function. This allows us to eventual do the + reading while running setuid so that the pattern file can be + hidden from regular users. I am not sure whether this makes + sense, but lets be prepared for it. */ + raw_pattern = read_file (*argv, &raw_pattern_length); + if (!raw_pattern) + exit (2); + + patternarray = parse_pattern_file (raw_pattern, raw_pattern_length); + if (!patternarray) + exit (1); + if (opt.checkonly) + return 0; + +#ifdef HAVE_DOSISH_SYSTEM + setmode (fileno (stdin) , O_BINARY ); +#endif + process (stdin, patternarray); + + return log_get_errorcount(0)? 1 : 0; +} + + + +/* Read a file FNAME into a buffer and return that malloced buffer. + Caller must free the buffer. On error NULL is returned, on success + the valid length of the buffer is stored at R_LENGTH. The returned + buffer is guarnteed to be nul terminated. */ +static char * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + char *buf; + size_t buflen; + + if (!strcmp (fname, "-")) + { + size_t nread, bufsize = 0; + + fp = stdin; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(fp) , O_BINARY ); +#endif + buf = NULL; + buflen = 0; +#define NCHUNK 8192 + do + { + bufsize += NCHUNK; + if (!buf) + buf = xmalloc (bufsize+1); + else + buf = xrealloc (buf, bufsize+1); + + nread = fread (buf+buflen, 1, NCHUNK, fp); + if (nread < NCHUNK && ferror (fp)) + { + log_error ("error reading `[stdin]': %s\n", strerror (errno)); + xfree (buf); + return NULL; + } + buflen += nread; + } + while (nread == NCHUNK); +#undef NCHUNK + + } + else + { + struct stat st; + + fp = fopen (fname, "rb"); + if (!fp) + { + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + xfree (buf); + return NULL; + } + fclose (fp); + } + buf[buflen] = 0; + *r_length = buflen; + return buf; +} + + + +static char * +get_regerror (int errcode, regex_t *compiled) +{ + size_t length = regerror (errcode, compiled, NULL, 0); + char *buffer = xmalloc (length); + regerror (errcode, compiled, buffer, length); + return buffer; +} + +/* Parse the pattern given in the memory aread DATA/DATALEN and return + a new pattern array. The end of the array is indicated by a NULL + entry. On error an error message is printed and the fucntion + returns NULL. Note that the function modifies DATA and assumes + that data is nul terminated (even if this is one byte past + DATALEN). */ +static pattern_t * +parse_pattern_file (char *data, size_t datalen) +{ + char *p, *p2; + size_t n; + pattern_t *array; + size_t arraysize, arrayidx; + unsigned int lineno = 0; + + /* Estimate the number of entries by counting the non-comment lines. */ + arraysize = 0; + p = data; + for (n = datalen; n && (p2 = memchr (p, '\n', n)); p2++, n -= p2 - p, p = p2) + if (*p != '#') + arraysize++; + arraysize += 2; /* For the terminating NULL and a last line w/o a LF. */ + + array = xcalloc (arraysize, sizeof *array); + arrayidx = 0; + + /* Loop over all lines. */ + while (datalen && data) + { + lineno++; + p = data; + p2 = data = memchr (p, '\n', datalen); + if (p2) + { + *data++ = 0; + datalen -= data - p; + } + else + p2 = p + datalen; + assert (!*p2); + p2--; + while (isascii (*p) && isspace (*p)) + p++; + if (*p == '#') + continue; + while (p2 > p && isascii (*p2) && isspace (*p2)) + *p2-- = 0; + if (!*p) + continue; + assert (arrayidx < arraysize); + array[arrayidx].lineno = lineno; + if (*p == '/') + { + int rerr; + + p++; + array[arrayidx].type = PAT_REGEX; + if (*p && p[strlen(p)-1] == '/') + p[strlen(p)-1] = 0; /* Remove optional delimiter. */ + array[arrayidx].u.r.regex = xcalloc (1, sizeof (regex_t)); + rerr = regcomp (array[arrayidx].u.r.regex, p, + REG_ICASE|REG_NOSUB|REG_EXTENDED); + if (rerr) + { + char *rerrbuf = get_regerror (rerr, array[arrayidx].u.r.regex); + log_error ("invalid r.e. at line %u: %s\n", lineno, rerrbuf); + xfree (rerrbuf); + if (!opt.checkonly) + exit (1); + } + } + else + { + array[arrayidx].type = PAT_STRING; + array[arrayidx].u.s.string = p; + array[arrayidx].u.s.length = strlen (p); + } + arrayidx++; + } + assert (arrayidx < arraysize); + array[arrayidx].type = PAT_NULL; + + return array; +} + + +/* Check whether string macthes any of the pattern in PATARRAY and + returns the matching pattern item or NULL. */ +static pattern_t * +match_p (const char *string, pattern_t *patarray) +{ + pattern_t *pat; + + if (!*string) + { + if (opt.verbose) + log_info ("zero length input line - ignored\n"); + return NULL; + } + + for (pat = patarray; pat->type != PAT_NULL; pat++) + { + if (pat->type == PAT_STRING) + { + if (!strcasecmp (pat->u.s.string, string)) + return pat; + } + else if (pat->type == PAT_REGEX) + { + int rerr; + + rerr = regexec (pat->u.r.regex, string, 0, NULL, 0); + if (!rerr) + return pat; + else if (rerr != REG_NOMATCH) + { + char *rerrbuf = get_regerror (rerr, pat->u.r.regex); + log_error ("matching r.e. failed: %s\n", rerrbuf); + xfree (rerrbuf); + return pat; /* Better indicate a match on error. */ + } + } + else + BUG (); + } + return NULL; +} + + +/* Actual processing of the input. This fucntion does not return an + error code but exits as soon as a match has been found. */ +static void +process (FILE *fp, pattern_t *patarray) +{ + char buffer[2048]; + size_t idx; + int c; + unsigned long lineno = 0; + pattern_t *pat; + + idx = 0; + c = 0; + while (idx < sizeof buffer -1 && c != EOF ) + { + if ((c = getc (fp)) != EOF) + buffer[idx] = c; + if ((c == '\n' && !opt.null) || (!c && opt.null) || c == EOF) + { + lineno++; + if (!opt.null) + { + while (idx && isascii (buffer[idx-1]) && isspace (buffer[idx-1])) + idx--; + } + buffer[idx] = 0; + pat = match_p (buffer, patarray); + if (pat) + { + if (opt.verbose) + log_error ("input line %lu matches pattern at line %u" + " - rejected\n", + lineno, pat->lineno); + exit (1); + } + idx = 0; + } + else + idx++; + } + if (c != EOF) + { + log_error ("input line %lu too long - rejected\n", lineno+1); + exit (1); + } + if (ferror (fp)) + { + log_error ("input read error at line %lu: %s - rejected\n", + lineno+1, strerror (errno)); + exit (1); + } + if (opt.verbose) + log_info ("no input line matches the pattern - accepted\n"); +} + Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-08-24 09:51:58 UTC (rev 4570) +++ trunk/tools/gpgconf-comp.c 2007-08-27 18:10:27 UTC (rev 4571) @@ -505,14 +505,30 @@ { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "allow clients to mark keys as \"trusted\"", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, - { "min-passphrase-len", GC_OPT_FLAG_RUNTIME, - GC_LEVEL_EXPERT, "gnupg", - N_("|N|set minimal required length for new passphrases to N"), - GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "Passphrase policy", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", N_("Options enforcing a passphrase policy") }, + { "enforce-passphrases-constraints", GC_OPT_FLAG_RUNTIME, + GC_LEVEL_EXPERT, "gnupg", + N_("do not allow to bypass the passphrase policy"), + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "min-passphrase-len", GC_OPT_FLAG_RUNTIME, + GC_LEVEL_ADVANCED, "gnupg", + N_("|N|set minimal required length for new passphrases to N"), + GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME, + GC_LEVEL_EXPERT, "gnupg", + N_("|N|require at least N non-alpha characters for a new passphrase"), + GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME, + GC_LEVEL_EXPERT, + "gnupg", N_("|FILE|check new passphrases against pattern in FILE"), + GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, + GC_OPTION_NULL }; @@ -915,9 +931,7 @@ { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, -#ifndef HAVE_W32_SYSTEM { "dirmngr", NULL, "Directory Manager", gc_options_dirmngr } -#endif }; From cvs at cvs.gnupg.org Tue Aug 28 01:43:50 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 28 Aug 2007 01:43:50 +0200 Subject: [svn] GpgEX - r3 - in trunk: . src Message-ID: Author: marcus Date: 2007-08-28 01:43:19 +0200 (Tue, 28 Aug 2007) New Revision: 3 Modified: trunk/README trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/gpgex-class.cc trunk/src/gpgex-factory.cc trunk/src/gpgex.cc trunk/src/gpgex.def trunk/src/gpgex.h trunk/src/main.cc trunk/src/main.h Log: 2007-08-28 Marcus Brinkmann * Makefile.am (gpgex_LDADD): Add -lole32. * gpgex.def: Rename functions to not carry the @NR thingie. * main.h: Many TRACE macros added. (DEBUG_INIT, DEBUG_CONTEXT_MENU, STRINGIFY, GUID_FMT, GUID_ARG): New macros. (_gpgex_debug): New prototype. * main.cc: Include , and . Add debugging traces. (debug_lock, debug_flags, debug_file): New statics. (get_debug_file, debug_init, debug_deinit): New static functions. (_gpgex_debug): New function. (DllMain): Call debug_init. (DllRegisterServer, DllUnregisterServer): Call SHChangeNotify. * gpgex.h: Include and . Use std::vector and std::string namespaces. (class gpgex_t): New member filenames, and new method reset. * gpgex.cc: Include , , and use std::vector and std::string namespaces. Add debugging traces. (gpgex_t::reset): New function. (gpgex_t::Initialize): Implement dummy function. (gpgex_t::QueryContextMenu): Implement dummy function. (gpgex_t::GetCommandString): Implement dummy function. (gpgex_t::InvokeCommand): Implement dummy function. * gpgex-factory.cc: Add debugging traces. * gpgex-class.cc (gpgex_class::init): Implement registration of shell extension. (gpgex_class::deinit): Implement corresponding unregistration. Modified: trunk/README =================================================================== --- trunk/README 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/README 2007-08-27 23:43:19 UTC (rev 3) @@ -4,4 +4,25 @@ This package contains GpgEX, the GNU Privacy Guard extensions for the Windows Explorer shell. -FIXME: Add more info. +Debugging +========= + +A debug file path can be specified with the registry value "GpgEX +Debug File" in the HKLM\Software\GNU\GnuPG key. To this file logging +information is appended. Also see: + +http://msdn2.microsoft.com/en-us/library/aa969286.aspx + + +BUGS +==== + +* DllRegisterServer does not correctly figure out the DLL path name + (it catches regsvr32.exe instead). Thus the DLL path is hard coded + to "C:\\gpgex.dll" for now. You can change it in the registry by + locating + "HKCR\CLSID\{CCD955E4-5C16-4A33-AFDA-A8947A94946B}\InprocServer32" + and changing the default value of that key. + +* DllMain is not invoked for some reason, so i18n is not initialized + and debugging output is done inefficiently. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/ChangeLog 2007-08-27 23:43:19 UTC (rev 3) @@ -1,3 +1,33 @@ +2007-08-28 Marcus Brinkmann + + * Makefile.am (gpgex_LDADD): Add -lole32. + * gpgex.def: Rename functions to not carry the @NR thingie. + * main.h: Many TRACE macros added. + (DEBUG_INIT, DEBUG_CONTEXT_MENU, STRINGIFY, GUID_FMT, GUID_ARG): + New macros. + (_gpgex_debug): New prototype. + * main.cc: Include , and . Add + debugging traces. + (debug_lock, debug_flags, debug_file): New statics. + (get_debug_file, debug_init, debug_deinit): New static functions. + (_gpgex_debug): New function. + (DllMain): Call debug_init. + (DllRegisterServer, DllUnregisterServer): Call SHChangeNotify. + * gpgex.h: Include and . Use std::vector and + std::string namespaces. + (class gpgex_t): New member filenames, and new method reset. + * gpgex.cc: Include , , and use + std::vector and std::string namespaces. Add debugging traces. + (gpgex_t::reset): New function. + (gpgex_t::Initialize): Implement dummy function. + (gpgex_t::QueryContextMenu): Implement dummy function. + (gpgex_t::GetCommandString): Implement dummy function. + (gpgex_t::InvokeCommand): Implement dummy function. + * gpgex-factory.cc: Add debugging traces. + * gpgex-class.cc (gpgex_class::init): Implement registration of + shell extension. + (gpgex_class::deinit): Implement corresponding unregistration. + 2007-08-23 Marcus Brinkmann * Initial commit. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/Makefile.am 2007-08-27 23:43:19 UTC (rev 3) @@ -29,8 +29,8 @@ #gpgex_LDADD = $(srcdir)/gpgex.def \ # -L . -lshell32 -lgdi32 -lcomdlg32 \ -# -lole32 -loleaut32 -lws2_32 -ladvapi32 -gpgex_LDADD = $(srcdir)/gpgex.def -L . -lshell32 -lws2_32 -luuid +# -loleaut32 -lws2_32 -ladvapi32 +gpgex_LDADD = $(srcdir)/gpgex.def -L . -lshell32 -lws2_32 -lole32 -luuid resource.o: versioninfo.rc Modified: trunk/src/gpgex-class.cc =================================================================== --- trunk/src/gpgex-class.cc 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/gpgex-class.cc 2007-08-27 23:43:19 UTC (rev 3) @@ -50,9 +50,9 @@ /* FIXME: Error handling? */ + /* Set a key for our CLSID. */ strcpy (key, "CLSID\\{" CLSID_GPGEX_STR "}"); RegCreateKey (HKEY_CLASSES_ROOT, key, &key_handle); - /* The default value is a human readable name for the class. */ strcpy (value, "GpgEX"); RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); @@ -61,13 +61,37 @@ /* The InprocServer32 key holds the path to the server component. */ strcpy (key, "CLSID\\{" CLSID_GPGEX_STR "}\\InprocServer32"); RegCreateKey (HKEY_CLASSES_ROOT, key, &key_handle); - + /* FIXME: We get regsvr32.exe here instead gpgex.dll. */ +#if 0 result = GetModuleFileName (gpgex_server::instance, value, MAX_PATH); +#endif + strcpy (value, "C:\\gpgex.dll"); RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); + /* We also need a threading model. */ + strcpy (key, "ThreadingModel"); + strcpy (value, "Apartment"); + RegSetValueEx (key_handle, key, 0, REG_SZ, + (BYTE *) value, strlen (value) + 1); RegCloseKey (key_handle); - /* FIXME: Now add the required registry keys for the context menu - triggers. */ + strcpy (key, "*\\ShellEx\\ContextMenuHandlers\\GpgEX"); + RegCreateKey (HKEY_CLASSES_ROOT, key, &key_handle); + /* The default value is the CLSID for the class. */ + strcpy (value, "{" CLSID_GPGEX_STR "}"); + RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); + RegCloseKey (key_handle); + +#if 0 + /* We also have to approve the shell extension for Windows NT. */ + strcpy (key, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); + RegCreateKey (HKEY_LOCAL_MACHINE, key, &key_handle); + /* The key is the CLSID, the value can be anything. */ + strcpy (key, "{" CLSID_GPGEX_STR "}"); + strcpy (value, "GpgEX"); + RegSetValueEx (key_handle, key, 0, REG_SZ, + (BYTE *) value, strlen (value) + 1); + RegCloseKey (key_handle); +#endif } @@ -77,9 +101,15 @@ { /* FIXME: Error handling? */ - /* FIXME: Unregister the required registry keys for the context menu - triggers. */ +#if 0 + RegDeleteValue (HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows\\CurrentVersion" + "\\Shell Extensions\\Approved", "{" CLSID_GPGEX_STR "}"); +#endif + RegDeleteKey (HKEY_CLASSES_ROOT, + "*\\ShellEx\\ContextMenuHandlers\\GpgEX"); + /* Delete registry keys in reverse order. */ RegDeleteKey (HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_GPGEX_STR "}\\InprocServer32"); Modified: trunk/src/gpgex-factory.cc =================================================================== --- trunk/src/gpgex-factory.cc 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/gpgex-factory.cc 2007-08-27 23:43:19 UTC (rev 3) @@ -35,8 +35,12 @@ STDMETHODIMP gpgex_factory_t::QueryInterface (REFIID riid, void **ppv) { +#define _TRACE_BEG12(a,b,c,d,e,f) TRACE_BEG12 (a,b,c,d,e,f) + _TRACE_BEG12 (DEBUG_INIT, "gpgex_factory_t::QueryInterface", this, + "riid=" GUID_FMT ", ppv=%p", GUID_ARG (riid), ppv); + if (ppv == NULL) - return E_INVALIDARG; + return TRACE_RES (E_INVALIDARG); /* Be nice to broken software. */ *ppv = NULL; @@ -48,20 +52,22 @@ else if (riid == IID_IClassFactory) *ppv = static_cast (this); else - return E_NOINTERFACE; + return TRACE_RES (E_NOINTERFACE); /* We have to acquire a reference to the returned object. We lost the type information, but we know that all object classes inherit from IUnknown, which is good enough. */ reinterpret_cast(*ppv)->AddRef (); - return S_OK; + return TRACE_RES (S_OK); } STDMETHODIMP_(ULONG) gpgex_factory_t::AddRef (void) { + (void) TRACE (DEBUG_INIT, "gpgex_factory_t::AddRef", this); + /* This factory is a singleton and therefore no reference counting is needed. */ return 1; @@ -71,6 +77,8 @@ STDMETHODIMP_(ULONG) gpgex_factory_t::Release (void) { + (void) TRACE (DEBUG_INIT, "gpgex_factory_t::Release", this); + /* This factory is a singleton and therefore no reference counting is needed. */ return 1; @@ -85,28 +93,36 @@ { HRESULT result; +#define _TRACE_BEG13(a,b,c,d,e,f,g) TRACE_BEG13 (a,b,c,d,e,f,g) + _TRACE_BEG13 (DEBUG_INIT, "gpgex_factory_t::CreateInstance", this, + "punkOuter=%lu, riid=" GUID_FMT ", ppv=%p", + punkOuter, GUID_ARG (riid), ppv); + /* Be nice to broken software. */ *ppv = NULL; /* Aggregation is not supported. */ if (punkOuter) - return CLASS_E_NOAGGREGATION; + return TRACE_RES (CLASS_E_NOAGGREGATION); gpgex_t *gpgex = new gpgex_t; if (!gpgex) - return E_OUTOFMEMORY; + return TRACE_RES (E_OUTOFMEMORY); result = gpgex->QueryInterface (riid, ppv); if (FAILED (result)) delete gpgex; - return result; + return TRACE_RES (result); } STDMETHODIMP gpgex_factory_t::LockServer (BOOL fLock) { + (void) TRACE1 (DEBUG_INIT, "gpgex_factory_t::LockServer", this, + "fLock=%s", fLock ? "true" : "false"); + /* Locking the singleton gpgex factory object acquires a reference for the server component. */ if (fLock) Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/gpgex.cc 2007-08-27 23:43:19 UTC (rev 3) @@ -22,6 +22,13 @@ #include #endif +#include +#include +#include + +using std::vector; +using std::string; + #include #include "main.h" @@ -29,11 +36,23 @@ #include "gpgex.h" +/* Reset the instance between operations. */ +void +gpgex_t::reset (void) +{ + this->filenames.clear (); +} + + STDMETHODIMP gpgex_t::QueryInterface (REFIID riid, void **ppv) { +#define _TRACE_BEG12(a,b,c,d,e,f) TRACE_BEG12(a,b,c,d,e,f) + _TRACE_BEG12 (DEBUG_INIT, "gpgex_t::QueryInterface", this, + "riid=" GUID_FMT ", ppv=%p", GUID_ARG (riid), ppv); + if (ppv == NULL) - return E_INVALIDARG; + return TRACE_RES (E_INVALIDARG); /* Be nice to broken software. */ *ppv = NULL; @@ -57,20 +76,23 @@ *ppv = static_cast (this); #endif else - return E_NOINTERFACE; + return TRACE_RES (E_NOINTERFACE); /* We have to acquire a reference to the returned object. We lost the type information, but we know that all object classes inherit from IUnknown, which is good enough. */ reinterpret_cast(*ppv)->AddRef (); - return S_OK; + return TRACE_RES (S_OK); } STDMETHODIMP_(ULONG) gpgex_t::AddRef (void) { + (void) TRACE1 (DEBUG_INIT, "gpgex_t::AddRef", this, + "new_refcount=%i", this->refcount + 1); + return InterlockedIncrement (&this->refcount); } @@ -80,6 +102,9 @@ { LONG count; + (void) TRACE1 (DEBUG_INIT, "gpgex_t::Release", this, + "new_refcount=%i", this->refcount - 1); + count = InterlockedDecrement (&this->refcount); if (count == 0) delete this; @@ -94,36 +119,181 @@ gpgex_t::Initialize (LPCITEMIDLIST pIDFolder, IDataObject *pDataObj, HKEY hRegKey) { - /* FIXME */ - return S_OK; + HRESULT err = S_OK; + + TRACE_BEG3 (DEBUG_INIT, "gpgex_t::Initialize", this, + "pIDFolder=%p, pDataObj=%p, hRegKey=%p", + pIDFolder, pDataObj, hRegKey); + + /* This function is called for the Shortcut (context menu), + Drag-and-Drop, and Property Sheet extensions. */ + + this->reset (); + + try + { + if (pDataObj) + { + /* The data object contains a drop item which we extract. */ + FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + STGMEDIUM medium; + UINT count; + + if (SUCCEEDED (pDataObj->GetData (&fe, &medium))) + { + HDROP drop = (HDROP) GlobalLock (medium.hGlobal); + unsigned int i; + + /* Now that we have the drop item, we can extract the + file names. */ + count = DragQueryFile (drop, (UINT) -1, NULL, 0); + if (count == 0) + throw std::invalid_argument ("no filenames"); + + try + { + for (i = 0; i < count; i++) + { + char filename[MAX_PATH]; + UINT len; + len = DragQueryFile (drop, i, + filename, sizeof (filename) - 1); + if (len == 0) + throw std::invalid_argument ("zero-length filename"); + + this->filenames.push_back (filename); + } + } + catch (...) + { + GlobalUnlock (medium.hGlobal); + ReleaseStgMedium (&medium); + throw; + } + + GlobalUnlock (medium.hGlobal); + ReleaseStgMedium (&medium); + } + } + } + catch (std::bad_alloc) + { + err = E_OUTOFMEMORY; + } + catch (std::invalid_argument &e) + { + (VOID) TRACE_LOG1 ("exception: E_INVALIDARG: %s", e.what ()); + err = E_INVALIDARG; + } + catch (...) + { + err = E_UNEXPECTED; + } + + if (err != S_OK) + this->reset (); + + return TRACE_RES (err); } /* IContextMenu methods. */ +/* The argument HMENU contains the context menu, and INDEXMENU points + to the first index where we can add items. IDCMDFIRST and + IDCMDLAST is the range of command ID values which we can use. */ STDMETHODIMP gpgex_t::QueryContextMenu (HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { - /* FIXME */ - return S_OK; + UINT next_cmd = idCmdFirst; + + TRACE_BEG5 (DEBUG_CONTEXT_MENU, "gpgex_t::QueryContextMenu", this, + "hMenu=%p, indexMenu=%u, idCmdFirst=%u, idCmdLast=%u, uFlags=%x", + hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + + /* If the flags include CMF_DEFAULTONLY then nothing should be done. */ + if (! (uFlags & CMF_DEFAULTONLY)) + { + BOOL res; + + res = InsertMenu (hMenu, indexMenu, MF_BYPOSITION, + next_cmd++, _("GpgEX Test Item")); + if (! res) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + } + + /* We should return a HRESULT that indicates success and the offset + to the next free command ID after the last one we used, relative + to idCmdFirst. In other words: max_used - idCmdFirst + 1. */ + return TRACE_RES (MAKE_HRESULT (SEVERITY_SUCCESS, FACILITY_NULL, + next_cmd - idCmdFirst)); } +/* Get a verb or help text for the command IDCOMMAND (which is the + offset to IDCMDFIRST of QueryContextMenu, ie zero based). UFLAGS + has GCS_HELPTEXT set if the help-text is requested (otherwise a + verb is requested). If UFLAGS has the GCS_UNICODE bit set, we need + to return a wide character string. */ + STDMETHODIMP gpgex_t::GetCommandString (UINT idCommand, UINT uFlags, LPUINT lpReserved, LPSTR pszName, UINT uMaxNameLen) { - /* FIXME */ - return S_OK; + TRACE_BEG5 (DEBUG_CONTEXT_MENU, "gpgex_t::GetCommandString", this, + "idCommand=%u, uFlags=%x, lpReserved=%lu, pszName=%p, " + "uMaxNameLen=%u", + idCommand, uFlags, lpReserved, pszName, uMaxNameLen); + + if (idCommand != 0) + return TRACE_RES (E_INVALIDARG); + + if (! (uFlags & GCS_HELPTEXT)) + return TRACE_RES (E_INVALIDARG); + + if (uFlags & GCS_UNICODE) + lstrcpynW ((LPWSTR) pszName, L"GpgEX help string (unicode)", uMaxNameLen); + else + lstrcpynA (pszName, "GpgEX help string (ASCII)", uMaxNameLen); + + return TRACE_RES (S_OK); } STDMETHODIMP gpgex_t::InvokeCommand (LPCMINVOKECOMMANDINFO lpcmi) { - /* FIXME */ - return S_OK; + TRACE_BEG1 (DEBUG_CONTEXT_MENU, "gpgex_t::GetCommandString", this, + "lpcmi=%p", lpcmi); + + /* If lpVerb really points to a string, ignore this function call + and bail out. */ + if (HIWORD (lpcmi->lpVerb) != 0) + return TRACE_RES (E_INVALIDARG); + + /* Get the command index, which is the offset to IDCMDFIRST of + QueryContextMenu, ie zero based). */ + switch (LOWORD (lpcmi->lpVerb)) + { + case 0: + { + string msg; + unsigned int i; + + msg = "The selected files were:\n\n"; + for (i = 0; i < this->filenames.size (); i++) + msg = msg + this->filenames[i] + '\n'; + + MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); + } + break; + + default: + return TRACE_RES (E_INVALIDARG); + } + + return TRACE_RES (S_OK); } Modified: trunk/src/gpgex.def =================================================================== --- trunk/src/gpgex.def 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/gpgex.def 2007-08-27 23:43:19 UTC (rev 3) @@ -2,8 +2,8 @@ DESCRIPTION 'GpgEX - GPG Shell Extensions' EXPORTS - DllMain at 12 @1 PRIVATE - DllCanUnloadNow at 0 @2 PRIVATE - DllGetClassObject at 12 @3 PRIVATE - DllRegisterServer at 0 @4 PRIVATE - DllUnregisterServer at 0 @5 PRIVATE + DllMain = DllMain at 12 @1 PRIVATE + DllRegisterServer = DllRegisterServer at 0 @2 PRIVATE + DllUnregisterServer = DllUnregisterServer at 0 @3 PRIVATE + DllCanUnloadNow = DllCanUnloadNow at 0 @4 PRIVATE + DllGetClassObject = DllGetClassObject at 12 @5 PRIVATE Modified: trunk/src/gpgex.h =================================================================== --- trunk/src/gpgex.h 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/gpgex.h 2007-08-27 23:43:19 UTC (rev 3) @@ -21,6 +21,12 @@ #ifndef GPGEX_H #define GPGEX_H +#include +#include + +using std::vector; +using std::string; + #include #include @@ -74,6 +80,9 @@ /* Per-object reference count. */ LONG refcount; + /* Support for IShellExtInit. */ + vector filenames; + /* Support for the context menu. */ public: @@ -90,6 +99,9 @@ gpgex_server::release (); } + /* Reset the instance between operations. */ + void reset (void); + public: /* IUnknown methods. */ STDMETHODIMP QueryInterface (REFIID riid, void **ppv); Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/main.cc 2007-08-27 23:43:19 UTC (rev 3) @@ -21,7 +21,10 @@ #include #endif +#include +#include #include +#include #include "registry.h" #include "gpgex-class.h" @@ -104,22 +107,120 @@ textdomain (PACKAGE_GT); } + +static CRITICAL_SECTION debug_lock; +/* No flags on means no debugging. */ +static unsigned int debug_flags = 0; + +static FILE *debug_file; + + +/* Get the filename of the debug file, if any. */ +static char * +get_debug_file (void) +{ + return read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + "GpgEX Debug File"); +} + + +static void +debug_init (void) +{ + char *filename; + + /* FIXME: Sanity check due to DllMain not running. */ + if (debug_file) + return; + + InitializeCriticalSection (&debug_lock); + + filename = get_debug_file (); + if (!filename) + return; + + debug_file = fopen (filename, "a"); + if (!debug_file) + return; + + /* FIXME: Make this configurable eventually. */ + debug_flags = DEBUG_INIT | DEBUG_CONTEXT_MENU; +} + + +static void +debug_deinit (void) +{ + if (debug_file) + fclose (debug_file); +} + + +/* Log the formatted string FORMAT at debug level LEVEL or higher. */ +void +_gpgex_debug (unsigned int flags, const char *format, ...) +{ + va_list arg_ptr; + int saved_errno; + + saved_errno = errno; + +#if 1 + /* FIXME: WTF. */ + debug_init (); +#endif + + if (! (debug_flags & flags)) + return; + + va_start (arg_ptr, format); + EnterCriticalSection (&debug_lock); + vfprintf (debug_file, format, arg_ptr); + va_end (arg_ptr); + if (format && *format && format[strlen (format) - 1] != '\n') + putc ('\n', debug_file); + LeaveCriticalSection (&debug_lock); + fflush (debug_file); + +#if 1 + /* FIXME */ + fclose (debug_file); + debug_file = NULL; +#endif + + errno = saved_errno; +} + + /* Entry point called by DLL loader. */ int WINAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) { + /* FIXME: It seems this is never called!!! */ +#if 0 + TRACE2 (DEBUG_INIT, "DllMain", hinst, + "reason=%i, reserved=%p", reason, reserved); +#endif + if (reason == DLL_PROCESS_ATTACH) { gpgex_server::instance = hinst; - /* FIXME: Initialize subsystems. */ - /* Early initializations of our subsystems. */ i18n_init (); + + debug_init (); + + (void) TRACE0 (DEBUG_INIT, "DllMain", hinst, + "reason=DLL_PROCESS_ATTACH"); } else if (reason == DLL_PROCESS_DETACH) { + (void) TRACE0 (DEBUG_INIT, "DllMain", hinst, + "reason=DLL_PROCESS_DETACH"); + + debug_deinit (); } return TRUE; @@ -133,6 +234,7 @@ STDAPI DllCanUnloadNow (void) { + (void) TRACE (DEBUG_INIT, "DllCanUnloadNow", gpgex_server::refcount); return (gpgex_server::refcount == 0 ? S_OK : S_FALSE); } @@ -143,8 +245,15 @@ STDAPI DllRegisterServer (void) { + /* FIXME: This is wrong!!! The module path will point to + regsvr32.exe. */ + gpgex_server::instance = GetModuleHandle (NULL); + gpgex_class::init (); + /* Notify the shell about the change. */ + SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + return S_OK; } @@ -155,6 +264,9 @@ { gpgex_class::deinit (); + /* Notify the shell about the change. */ + SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + return S_OK; } @@ -166,12 +278,20 @@ STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID *ppv) { + /* We have to evaluate the arguments first. */ +#define _TRACE_BEG22(a,b,c,d,e,f) TRACE_BEG22(a,b,c,d,e,f) + _TRACE_BEG22 (DEBUG_INIT, "DllGetClassObject", ppv, + "rclsid=" GUID_FMT ", riid=" GUID_FMT, + GUID_ARG (rclsid), GUID_ARG (riid)); + if (rclsid == CLSID_gpgex) - return gpgex_factory.QueryInterface (riid, ppv); + { + HRESULT err = gpgex_factory.QueryInterface (riid, ppv); + return TRACE_RES (err); + } /* Be nice to broken software. */ *ppv = NULL; - return CLASS_E_CLASSNOTAVAILABLE; - return 0; + return TRACE_RES (CLASS_E_CLASSNOTAVAILABLE); } Modified: trunk/src/main.h =================================================================== --- trunk/src/main.h 2007-08-23 10:43:51 UTC (rev 2) +++ trunk/src/main.h 2007-08-27 23:43:19 UTC (rev 3) @@ -60,4 +60,162 @@ } }; + +#define DEBUG_INIT 1 +#define DEBUG_CONTEXT_MENU 2 + +#define STRINGIFY(v) #v + +#define GUID_FMT "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" +#define GUID_ARG(x) (x).Data1, (x).Data2, (x).Data3, (x).Data4[0], \ + (x).Data4[1], (x).Data4[2], (x).Data4[3], (x).Data4[4], \ + (x).Data4[5], (x).Data4[6], (x).Data4[7] + +/* Log the formatted string FORMAT in categories FLAGS. */ +void _gpgex_debug (unsigned int flags, const char *format, ...); + +#define _TRACE(lvl, name, tag) \ + int _gpgex_trace_level = lvl; \ + const char *const _gpgex_trace_func = name; \ + const char *const _gpgex_trace_tagname = STRINGIFY (tag); \ + void *_gpgex_trace_tag = (void *) tag + +#define TRACE_BEG(lvl, name, tag) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag) +#define TRACE_BEG0(lvl, name, tag, fmt) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag) +#define TRACE_BEG1(lvl, name, tag, fmt, arg1) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1) +#define TRACE_BEG2(lvl, name, tag, fmt, arg1, arg2) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2) +#define TRACE_BEG3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3) +#define TRACE_BEG4(lvl, name, tag, fmt, arg1, arg2, arg3, arg4) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4) +#define TRACE_BEG5(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5) +#define TRACE_BEG12(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12) +#define TRACE_BEG13(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ + arg13) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12, arg13) +#define TRACE_BEG22(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ + arg13, arg14, arg15, arg16, arg17, arg18, arg19, \ + arg20, arg21, arg22) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, \ + arg15, arg16, arg17, arg18, arg19, arg20, arg21, \ + arg22) + +#define TRACE(lvl, name, tag) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call\n", \ + name, STRINGIFY (tag), (void *) tag), 0) +#define TRACE0(lvl, name, tag, fmt) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag), 0) +#define TRACE1(lvl, name, tag, fmt, arg1) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1), 0) +#define TRACE2(lvl, name, tag, fmt, arg1, arg2) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2), 0) +#define TRACE3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2, \ + arg3), 0) +#define TRACE6(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2, arg3, \ + arg4, arg5, arg6), 0) + +#define TRACE_RES(err) \ + err == S_OK ? (TRACE_SUC ()) : \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): %s: ec=%x\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, \ + SUCCEEDED (err) ? "leave" : "error", \ + err), (err)) + +#define TRACE_SUC() \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_SUC0(fmt) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_SUC1(fmt, arg1) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1), 0) +#define TRACE_SUC2(fmt, arg1, arg2) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2), 0) +#define TRACE_SUC5(fmt, arg1, arg2, arg3, arg4, arg5) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5), 0) + +#define TRACE_LOG(fmt) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_LOG1(fmt, arg1) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1), 0) +#define TRACE_LOG2(fmt, arg1, arg2) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2), 0) +#define TRACE_LOG3(fmt, arg1, arg2, arg3) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3), 0) +#define TRACE_LOG4(fmt, arg1, arg2, arg3, arg4) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4), 0) +#define TRACE_LOG6(fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, \ + arg6), 0) + #endif From cvs at cvs.gnupg.org Tue Aug 28 14:00:58 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 28 Aug 2007 14:00:58 +0200 Subject: [svn] GpgEX - r4 - trunk/src Message-ID: Author: marcus Date: 2007-08-28 14:00:29 +0200 (Tue, 28 Aug 2007) New Revision: 4 Modified: trunk/src/ChangeLog trunk/src/gpgex-class.h trunk/src/main.cc Log: 2007-08-28 Marcus Brinkmann * main.cc (DllMain): Change return type to "STADPI" to get an extern "C" declaration. (_gpgex_debug): Remove lazy initialization cruft. DllMain is called now, and initialization works properly. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-27 23:43:19 UTC (rev 3) +++ trunk/src/ChangeLog 2007-08-28 12:00:29 UTC (rev 4) @@ -1,5 +1,10 @@ 2007-08-28 Marcus Brinkmann + * main.cc (DllMain): Change return type to "STADPI" to get an + extern "C" declaration. + (_gpgex_debug): Remove lazy initialization cruft. DllMain is + called now, and initialization works properly. + * Makefile.am (gpgex_LDADD): Add -lole32. * gpgex.def: Rename functions to not carry the @NR thingie. * main.h: Many TRACE macros added. Modified: trunk/src/gpgex-class.h =================================================================== --- trunk/src/gpgex-class.h 2007-08-27 23:43:19 UTC (rev 3) +++ trunk/src/gpgex-class.h 2007-08-28 12:00:29 UTC (rev 4) @@ -19,7 +19,7 @@ 02110-1301, USA. */ #ifndef GPGEX_CLASS_H -#define GPGEX_CLASS_H +#define GPGEX_CLASS_H 1 #include Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-08-27 23:43:19 UTC (rev 3) +++ trunk/src/main.cc 2007-08-28 12:00:29 UTC (rev 4) @@ -130,7 +130,7 @@ { char *filename; - /* FIXME: Sanity check due to DllMain not running. */ + /* Sanity check. */ if (debug_file) return; @@ -153,7 +153,10 @@ debug_deinit (void) { if (debug_file) - fclose (debug_file); + { + fclose (debug_file); + debug_file = NULL; + } } @@ -166,11 +169,6 @@ saved_errno = errno; -#if 1 - /* FIXME: WTF. */ - debug_init (); -#endif - if (! (debug_flags & flags)) return; @@ -183,26 +181,14 @@ LeaveCriticalSection (&debug_lock); fflush (debug_file); -#if 1 - /* FIXME */ - fclose (debug_file); - debug_file = NULL; -#endif - errno = saved_errno; } /* Entry point called by DLL loader. */ -int WINAPI +STDAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) { - /* FIXME: It seems this is never called!!! */ -#if 0 - TRACE2 (DEBUG_INIT, "DllMain", hinst, - "reason=%i, reserved=%p", reason, reserved); -#endif - if (reason == DLL_PROCESS_ATTACH) { gpgex_server::instance = hinst; From cvs at cvs.gnupg.org Tue Aug 28 14:12:43 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 28 Aug 2007 14:12:43 +0200 Subject: [svn] GpgEX - r5 - in trunk: . src Message-ID: Author: marcus Date: 2007-08-28 14:12:14 +0200 (Tue, 28 Aug 2007) New Revision: 5 Modified: trunk/README trunk/src/ChangeLog trunk/src/gpgex-class.cc trunk/src/main.cc Log: 2007-08-28 Marcus Brinkmann * main.cc (DllRegisterServer): Do not trash gpgex_server::instance. * gpgex-class.cc (gpgex_class::init): Now that DllMain loads, we can access the DLL file name. Modified: trunk/README =================================================================== --- trunk/README 2007-08-28 12:00:29 UTC (rev 4) +++ trunk/README 2007-08-28 12:12:14 UTC (rev 5) @@ -12,17 +12,3 @@ information is appended. Also see: http://msdn2.microsoft.com/en-us/library/aa969286.aspx - - -BUGS -==== - -* DllRegisterServer does not correctly figure out the DLL path name - (it catches regsvr32.exe instead). Thus the DLL path is hard coded - to "C:\\gpgex.dll" for now. You can change it in the registry by - locating - "HKCR\CLSID\{CCD955E4-5C16-4A33-AFDA-A8947A94946B}\InprocServer32" - and changing the default value of that key. - -* DllMain is not invoked for some reason, so i18n is not initialized - and debugging output is done inefficiently. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-28 12:00:29 UTC (rev 4) +++ trunk/src/ChangeLog 2007-08-28 12:12:14 UTC (rev 5) @@ -1,5 +1,9 @@ 2007-08-28 Marcus Brinkmann + * main.cc (DllRegisterServer): Do not trash gpgex_server::instance. + * gpgex-class.cc (gpgex_class::init): Now that DllMain loads, we + can access the DLL file name. + * main.cc (DllMain): Change return type to "STADPI" to get an extern "C" declaration. (_gpgex_debug): Remove lazy initialization cruft. DllMain is Modified: trunk/src/gpgex-class.cc =================================================================== --- trunk/src/gpgex-class.cc 2007-08-28 12:00:29 UTC (rev 4) +++ trunk/src/gpgex-class.cc 2007-08-28 12:12:14 UTC (rev 5) @@ -61,11 +61,7 @@ /* The InprocServer32 key holds the path to the server component. */ strcpy (key, "CLSID\\{" CLSID_GPGEX_STR "}\\InprocServer32"); RegCreateKey (HKEY_CLASSES_ROOT, key, &key_handle); - /* FIXME: We get regsvr32.exe here instead gpgex.dll. */ -#if 0 result = GetModuleFileName (gpgex_server::instance, value, MAX_PATH); -#endif - strcpy (value, "C:\\gpgex.dll"); RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); /* We also need a threading model. */ strcpy (key, "ThreadingModel"); Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-08-28 12:00:29 UTC (rev 4) +++ trunk/src/main.cc 2007-08-28 12:12:14 UTC (rev 5) @@ -231,10 +231,6 @@ STDAPI DllRegisterServer (void) { - /* FIXME: This is wrong!!! The module path will point to - regsvr32.exe. */ - gpgex_server::instance = GetModuleHandle (NULL); - gpgex_class::init (); /* Notify the shell about the change. */ From cvs at cvs.gnupg.org Wed Aug 29 11:52:07 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 29 Aug 2007 11:52:07 +0200 Subject: [svn] GnuPG - r4573 - in trunk: . agent common doc doc/examples sm tools Message-ID: Author: wk Date: 2007-08-29 11:51:37 +0200 (Wed, 29 Aug 2007) New Revision: 4573 Modified: trunk/NEWS trunk/agent/genkey.c trunk/common/ChangeLog trunk/common/exechelp.c trunk/common/exechelp.h trunk/common/homedir.c trunk/common/util.h trunk/doc/ChangeLog trunk/doc/examples/gpgconf.conf trunk/doc/tools.texi trunk/sm/export.c trunk/sm/import.c trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c trunk/tools/gpgconf.c trunk/tools/gpgconf.h trunk/tools/no-libgcrypt.c Log: New command --check-programs for gpgconf. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/NEWS 2007-08-29 09:51:37 UTC (rev 4573) @@ -11,7 +11,11 @@ enforce-passphrase-constraints and max-passphrase-days to gpg-agent. + * Add command --check-components to gpgconf. Gpgconf now uses the + installed versions of the programs and does not anymore search via + PATH for them. + Noteworthy changes in version 2.0.6 (2007-08-16) ------------------------------------------------ Modified: trunk/agent/genkey.c =================================================================== --- trunk/agent/genkey.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/agent/genkey.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -126,7 +126,7 @@ if (gnupg_spawn_process_fd (pgmname, argv, fileno (infp), -1, -1, &pid)) result = 1; /* Execute error - assume password should no be used. */ - else if (gnupg_wait_process (pgmname, pid)) + else if (gnupg_wait_process (pgmname, pid, NULL)) result = 1; /* Helper returned an error - probably a match. */ else result = 0; /* Success; i.e. no match. */ Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/common/ChangeLog 2007-08-29 09:51:37 UTC (rev 4573) @@ -1,3 +1,11 @@ +2007-08-29 Werner Koch + + * exechelp.c (gnupg_wait_process): Add arg EXITCODE. Changed all + callers. + + * util.h (GNUPG_MODULE_NAME_GPGSM, GNUPG_MODULE_NAME_GPG): New. + * homedir.c (gnupg_module_name): Add them + 2007-08-28 Werner Koch * gettime.c (check_isotime, add_isotime): New. Orginally written Modified: trunk/common/exechelp.c =================================================================== --- trunk/common/exechelp.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/common/exechelp.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -570,11 +570,13 @@ /* Wait for the process identified by PID to terminate. PGMNAME should - be the same as suplieed to the spawn fucntion and is only used for - diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for - any failures of the spawned program or other error codes.*/ + be the same as supplied to the spawn function and is only used for + diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL + for any failures of the spawned program or other error codes. If + EXITCODE is not NULL the exit code of the process is stored at this + address or -1 if it could not be retrieved. */ gpg_error_t -gnupg_wait_process (const char *pgmname, pid_t pid) +gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode) { gpg_err_code_t ec; @@ -583,6 +585,9 @@ int code; DWORD exc; + if (exitcode) + *exitcode = -1; + if (pid == (pid_t)(-1)) return gpg_error (GPG_ERR_INV_VALUE); @@ -609,10 +614,16 @@ { log_error (_("error running `%s': exit status %d\n"), pgmname, (int)exc ); + if (exitcode) + *exitcode = (int)exc; ec = GPG_ERR_GENERAL; } else - ec = 0; + { + if (exitcode) + *exitcode = 0; + ec = 0; + } CloseHandle (proc); break; @@ -626,6 +637,9 @@ #else /* !HAVE_W32_SYSTEM */ int i, status; + if (exitcode) + *exitcode = -1; + if (pid == (pid_t)(-1)) return gpg_error (GPG_ERR_INV_VALUE); @@ -650,6 +664,8 @@ { log_error (_("error running `%s': exit status %d\n"), pgmname, WEXITSTATUS (status)); + if (exitcode) + *exitcode = WEXITSTATUS (status); ec = GPG_ERR_GENERAL; } else if (!WIFEXITED (status)) @@ -658,11 +674,14 @@ ec = GPG_ERR_GENERAL; } else - ec = 0; + { + if (exitcode) + *exitcode = 0; + ec = 0; + } #endif /* !HAVE_W32_SYSTEM */ return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); - } Modified: trunk/common/exechelp.h =================================================================== --- trunk/common/exechelp.h 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/common/exechelp.h 2007-08-29 09:51:37 UTC (rev 4573) @@ -52,8 +52,10 @@ /* Wait for the process identified by PID to terminate. PGMNAME should be the same as supplied to the spawn fucntion and is only used for diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL - for any failures of the spawned program or other error codes.*/ -gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid); + for any failures of the spawned program or other error codes. If + EXITCODE is not NULL the exit code of the process is stored at this + address or -1 if it could not be retrieved. */ +gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode); /* Spawn a new process and immediatley detach from it. The name of Modified: trunk/common/homedir.c =================================================================== --- trunk/common/homedir.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/common/homedir.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -372,6 +372,12 @@ case GNUPG_MODULE_NAME_CHECK_PATTERN: X(libexecdir, "gpg-check-pattern"); + case GNUPG_MODULE_NAME_GPGSM: + X(bindir, "gpgsm"); + + case GNUPG_MODULE_NAME_GPG: + X(bindir, "gpg2"); + default: BUG (); } Modified: trunk/common/util.h =================================================================== --- trunk/common/util.h 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/common/util.h 2007-08-29 09:51:37 UTC (rev 4573) @@ -182,12 +182,16 @@ const char *gnupg_datadir (void); const char *dirmngr_socket_name (void); +/* All module names. We also include gpg and gpgsm for the sake for + gpgconf. */ #define GNUPG_MODULE_NAME_AGENT 1 #define GNUPG_MODULE_NAME_PINENTRY 2 #define GNUPG_MODULE_NAME_SCDAEMON 3 #define GNUPG_MODULE_NAME_DIRMNGR 4 #define GNUPG_MODULE_NAME_PROTECT_TOOL 5 #define GNUPG_MODULE_NAME_CHECK_PATTERN 6 +#define GNUPG_MODULE_NAME_GPGSM 7 +#define GNUPG_MODULE_NAME_GPG 8 const char *gnupg_module_name (int which); Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/doc/ChangeLog 2007-08-29 09:51:37 UTC (rev 4573) @@ -1,3 +1,7 @@ +2007-08-29 Werner Koch + + * tools.texi (Checking programs): New. + 2007-08-27 Werner Koch * examples/pwpattern.list: New. Modified: trunk/doc/examples/gpgconf.conf =================================================================== --- trunk/doc/examples/gpgconf.conf 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/doc/examples/gpgconf.conf 2007-08-29 09:51:37 UTC (rev 4573) @@ -34,7 +34,14 @@ # :staff gpg-agent allow-mark-trusted [change] # gpg-agent min-passphrase-len 6 # -# * gpg-agent min-passphrase-len [no-change] 12 +# * gpg-agent min-passphrase-len [no-change] 8 +# gpg-agent min-passphrase-nonalpha [no-change] 1 +# gpg-agent max-passphrase-days [no-change] 700 +# gpg-agent enable-passphrase-history [no-change] +# gpg-agent enforce-passphrase-policy [default] +# gpg-agent enforce-passphrase-policy [no-change] +# gpg-agent max-cache-ttl [no-change] 10800 +# gpg-agent max-cache-ttl-ssh [no-change] 10800 # gpg-agent allow-mark-trusted [default] # gpg-agent allow-mark-trusted [no-change] # gpgsm enable-ocsp @@ -46,7 +53,7 @@ # to 6. All other users are not allowed to change # "min-passphrase-len" and "allow-mark-trusted". When "gpgconf # --apply-defaults" is used for them, "min-passphrase-len" is set to -# 12, "allow-mark-trusted" deleted from the config file and +# 8, "allow-mark-trusted" deleted from the config file and # "enable-ocsp" is put into the config file of gpgsm. The latter may # be changed by any user. #------------------------------------------------------------------- Modified: trunk/doc/tools.texi =================================================================== --- trunk/doc/tools.texi 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/doc/tools.texi 2007-08-29 09:51:37 UTC (rev 4573) @@ -200,6 +200,7 @@ * Invoking gpgconf:: List of all commands and options. * Format conventions:: Formatting conventions relevant for all commands. * Listing components:: List all gpgconf components. +* Checking programs:: Check all programs know to gpgconf. * Listing options:: List all options of a component. * Changing options:: Changing options of a component. * Files used by gpgconf:: What files are used by gpgconf. @@ -218,6 +219,9 @@ List all components. This is the default command used if none is specified. + at item --check-programs +List all available backend programs and test whether they are runnable. + @item --list-options @var{component} List all options of the component @var{component}. @@ -335,6 +339,14 @@ the verbose option is used). You should ignore everything in the field that follows the number. + at item @w{boolean value} +Some fields contain a @emph{boolean value}. This is a number with +either the value 0 or 1. The number may be followed by a space, +followed by a human readable description of that value (if the verbose +option is used). You should ignore everything in the field that follows +the number; checking just the first character is sufficient in this +case. + @item option Some fields contain an @emph{option} argument. The format of an option argument depends on the type of the option and on some flags: @@ -436,6 +448,62 @@ @end example + + at node Checking programs + at subsection Checking programs + +The command @code{--check-programs} is similar to + at code{--list-components} but works on backend programs and not on +components. It runs each program to test wether it is installed and +runnable. This also includes a syntax check of all config file options +of the program. + +The command argument @code{--check-programs} lists all available +programs, one per line. The format of each line is: + + at code{@var{name}:@var{description}:@var{program name}:@var{available}:@var{config okay}:} + + at table @var + at item name +This field contains a name tag of the program which is identical to the +name of the component. The name tag is to be used @emph{verbatim}. It +is thus not in any escaped format. + + at item description +The @emph{string} in this field contains a human-readable description +of the component. It can be displayed to the user of the GUI for +informational purposes. It is @emph{percent-escaped} and + at emph{localized}. + + at item program name +The @emph{string} in this field contains the absolute name of the +program's file. It can be used to unambiguously invoke that program. +It is @emph{percent-escaped}. + + at item available +The @emph{boolean value} in this field indicates whether the program is +installed and runnable. + + at item config okay +The @emph{boolean value} in this field indicates whether the program's +config file is syntactically okay. + + at end table + + at noindent +In the following example the @command{dirmngr} is not runnable and the +configuration file of @command{scdaemon} is not okay. + + at example +$ gpgconf --check-programs +gpg:GPG for OpenPGP:/usr/local/bin/gpg2:1:1: +gpg-agent:GPG Agent:/usr/local/bin/gpg-agent:1:1: +scdaemon:Smartcard Daemon:/usr/local/bin/scdaemon:1:0: +gpgsm:GPG for S/MIME:/usr/local/bin/gpgsm:1:1: +dirmngr:Directory Manager:/usr/local/bin/dirmngr:0:0: + at end example + + @node Listing options @subsection Listing options Modified: trunk/sm/export.c =================================================================== --- trunk/sm/export.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/sm/export.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -713,7 +713,7 @@ fclose (fp); if (pid != -1) { - if (!gnupg_wait_process (pgmname, pid)) + if (!gnupg_wait_process (pgmname, pid, NULL)) child_err = 0; } if (!err) Modified: trunk/sm/import.c =================================================================== --- trunk/sm/import.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/sm/import.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -635,7 +635,7 @@ fclose (fp); if (pid != -1) { - if (!gnupg_wait_process (pgmname, pid)) + if (!gnupg_wait_process (pgmname, pid, NULL)) child_err = 0; } if (!err) Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/tools/ChangeLog 2007-08-29 09:51:37 UTC (rev 4573) @@ -1,3 +1,12 @@ +2007-08-29 Werner Koch + + * gpgconf.c: New comamnd --check-programs. + * gpgconf-comp.c (gc_component_check_programs): New. + (gc_backend): Add member MODULE_NAME and add these module names. + (retrieve_options_from_program): Use module name so that we use an + absolute file name and don't rely on $PATH. + * no-libgcrypt.c (gcry_control): New. + 2007-08-28 Werner Koch * gpgconf-comp.c : Add options --max-passphrase-days @@ -713,7 +722,7 @@ * watchgnupg.c: New. - Copyright 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/tools/gpgconf-comp.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -43,6 +43,7 @@ #define JNLIB_NEED_LOG_LOGV #include "util.h" #include "i18n.h" +#include "exechelp.h" #include "gc-opt-flags.h" #include "gpgconf.h" @@ -153,6 +154,12 @@ GPGConf. In this case, PROGRAM is NULL. */ char *program; + /* The module name (GNUPG_MODULE_NAME_foo) as defined by + ../common/util.h. This value is used to get the actual installed + path of the program. 0 is used if no backedn program is + available. */ + char module_name; + /* The runtime change callback. */ void (*runtime_change) (void); @@ -168,14 +175,18 @@ } gc_backend[GC_BACKEND_NR] = { { NULL }, /* GC_BACKEND_ANY dummy entry. */ - { "GnuPG", GPGNAME, NULL, "gpgconf-gpg.conf" }, - { "GPGSM", "gpgsm", NULL, "gpgconf-gpgsm.conf" }, - { "GPG Agent", "gpg-agent", gpg_agent_runtime_change, - "gpgconf-gpg-agent.conf" }, - { "SCDaemon", "scdaemon", NULL, "gpgconf-scdaemon.conf" }, - { "DirMngr", "dirmngr", NULL, "gpgconf-dirmngr.conf" }, - { "DirMngr LDAP Server List", NULL, NULL, "ldapserverlist-file", - "LDAP Server" }, + { "GnuPG", GPGNAME, GNUPG_MODULE_NAME_GPG, + NULL, "gpgconf-gpg.conf" }, + { "GPGSM", "gpgsm", GNUPG_MODULE_NAME_GPGSM, + NULL, "gpgconf-gpgsm.conf" }, + { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, + gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" }, + { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON, + NULL, "gpgconf-scdaemon.conf" }, + { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR, + NULL, "gpgconf-dirmngr.conf" }, + { "DirMngr LDAP Server List", NULL, 0, + NULL, "ldapserverlist-file", "LDAP Server" }, }; @@ -1129,7 +1140,82 @@ } } + +/* Check all components that are available. */ +void +gc_component_check_programs (FILE *out) +{ + gc_component_t component; + unsigned int result; + int backend_seen[GC_BACKEND_NR]; + gc_backend_t backend; + gc_option_t *option; + const char *desc; + const char *pgmname; + const char *argv[2]; + pid_t pid; + int exitcode; + + for (component = 0; component < GC_COMPONENT_NR; component++) + { + if (!gc_component[component].options) + continue; + + for (backend = 0; backend < GC_BACKEND_NR; backend++) + backend_seen[backend] = 0; + + option = gc_component[component].options; + for (; option && option->name; option++) + { + if ((option->flags & GC_OPT_FLAG_GROUP)) + continue; + backend = option->backend; + if (backend_seen[backend]) + continue; + backend_seen[backend] = 1; + assert (backend != GC_BACKEND_ANY); + if (!gc_backend[backend].program) + continue; + if (!gc_backend[backend].module_name) + continue; + + pgmname = gnupg_module_name (gc_backend[backend].module_name); + argv[0] = "--gpgconf-test"; + argv[1] = NULL; + + /* Note that under Windows the spawn fucntion returns an + error if the progrom could not be executed whereas under + Unix the wait function returns an error. */ + result = 0; + if (gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid)) + result |= 1; /* Program could not be run. */ + else if (gnupg_wait_process (pgmname, pid, &exitcode)) + { + if (exitcode == -1) + result |= 1; /* Program could not be run or it + terminated abnormally. */ + result |= 2; /* Program returned an error. */ + } + + /* If the program could not be run, we can't tell whether + the config file is good. */ + if ((result&1)) + result |= 2; + + desc = gc_component[component].desc; + desc = my_dgettext (gc_component[component].desc_domain, desc); + fprintf (out, "%s:%s:", + gc_component[component].name, my_percent_escape (desc)); + fputs (my_percent_escape (pgmname), out); + fprintf (out, ":%d:%d:\n", !(result & 1), !(result & 2)); + break; /* Loop over options of this component */ + } + } +} + + + /* Find the component with the name NAME. Returns -1 if not found. */ int @@ -1362,7 +1448,10 @@ FILE *config; char *config_pathname; - cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program); + cmd_line = xasprintf ("%s --gpgconf-list", + gc_backend[backend].module_name ? + gnupg_module_name (gc_backend[backend].module_name) : + gc_backend[backend].program ); config = popen (cmd_line, "r"); if (!config) @@ -1663,6 +1752,8 @@ while (process_all && ++component < GC_COMPONENT_NR); } + + /* Perform a simple validity check based on the type. Return in NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of Modified: trunk/tools/gpgconf.c =================================================================== --- trunk/tools/gpgconf.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/tools/gpgconf.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -1,5 +1,5 @@ /* gpgconf.c - Configuration utility for GnuPG - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,6 +40,7 @@ oHomedir, aListComponents, + aCheckPrograms, aListOptions, aChangeOptions, aApplyDefaults, @@ -54,6 +55,7 @@ { 300, NULL, 0, N_("@Commands:\n ") }, { aListComponents, "list-components", 256, N_("list all components") }, + { aCheckPrograms, "check-programs", 256, N_("check all programs") }, { aListOptions, "list-options", 256, N_("|COMPONENT|list options") }, { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") }, { aApplyDefaults, "apply-defaults", 256, @@ -137,6 +139,7 @@ case oNoVerbose: opt.verbose = 0; break; case aListComponents: + case aCheckPrograms: case aListOptions: case aChangeOptions: case aApplyDefaults: @@ -161,6 +164,11 @@ gc_component_list_components (stdout); break; + case aCheckPrograms: + /* Check all programs. */ + gc_component_check_programs (stdout); + break; + case aListOptions: case aChangeOptions: if (!fname) Modified: trunk/tools/gpgconf.h =================================================================== --- trunk/tools/gpgconf.h 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/tools/gpgconf.h 2007-08-29 09:51:37 UTC (rev 4573) @@ -40,6 +40,9 @@ /* List all components that are available. */ void gc_component_list_components (FILE *out); +/* List all programs along with their status. */ +void gc_component_check_programs (FILE *out); + /* Find the component with the name NAME. Returns -1 if not found. */ int gc_component_find (const char *name); Modified: trunk/tools/no-libgcrypt.c =================================================================== --- trunk/tools/no-libgcrypt.c 2007-08-28 17:48:13 UTC (rev 4572) +++ trunk/tools/no-libgcrypt.c 2007-08-29 09:51:37 UTC (rev 4573) @@ -102,3 +102,12 @@ if (a) free (a); } + + +/* We need this dummy because exechelp.c uses gcry_control to + terminate the secure memeory. */ +gcry_error_t +gcry_control (enum gcry_ctl_cmds CMD, ...) +{ + return 0; +} From cvs at cvs.gnupg.org Thu Aug 30 17:42:16 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 30 Aug 2007 17:42:16 +0200 Subject: [svn] GpgEX - r6 - trunk/src Message-ID: Author: marcus Date: 2007-08-30 17:41:44 +0200 (Thu, 30 Aug 2007) New Revision: 6 Modified: trunk/src/ChangeLog trunk/src/gpgex-class.cc Log: 2007-08-30 Marcus Brinkmann * gpgex-class.cc (gpgex_class::init): Also register the shell extension for directories. (gpgex_class::deinit): Unregister shell extension for directories. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-28 12:12:14 UTC (rev 5) +++ trunk/src/ChangeLog 2007-08-30 15:41:44 UTC (rev 6) @@ -1,3 +1,9 @@ +2007-08-30 Marcus Brinkmann + + * gpgex-class.cc (gpgex_class::init): Also register the shell + extension for directories. + (gpgex_class::deinit): Unregister shell extension for directories. + 2007-08-28 Marcus Brinkmann * main.cc (DllRegisterServer): Do not trash gpgex_server::instance. Modified: trunk/src/gpgex-class.cc =================================================================== --- trunk/src/gpgex-class.cc 2007-08-28 12:12:14 UTC (rev 5) +++ trunk/src/gpgex-class.cc 2007-08-30 15:41:44 UTC (rev 6) @@ -77,6 +77,13 @@ RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); RegCloseKey (key_handle); + strcpy (key, "Directory\\ShellEx\\ContextMenuHandlers\\GpgEX"); + RegCreateKey (HKEY_CLASSES_ROOT, key, &key_handle); + /* The default value is the CLSID for the class. */ + strcpy (value, "{" CLSID_GPGEX_STR "}"); + RegSetValueEx (key_handle, 0, 0, REG_SZ, (BYTE *) value, strlen (value) + 1); + RegCloseKey (key_handle); + #if 0 /* We also have to approve the shell extension for Windows NT. */ strcpy (key, "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); @@ -104,6 +111,8 @@ #endif RegDeleteKey (HKEY_CLASSES_ROOT, + "Directory\\ShellEx\\ContextMenuHandlers\\GpgEX"); + RegDeleteKey (HKEY_CLASSES_ROOT, "*\\ShellEx\\ContextMenuHandlers\\GpgEX"); /* Delete registry keys in reverse order. */ From cvs at cvs.gnupg.org Thu Aug 30 17:49:10 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 30 Aug 2007 17:49:10 +0200 Subject: [svn] GpgEX - r7 - trunk/src Message-ID: Author: marcus Date: 2007-08-30 17:48:38 +0200 (Thu, 30 Aug 2007) New Revision: 7 Modified: trunk/src/ChangeLog trunk/src/gpgex.cc trunk/src/gpgex.h Log: 2007-08-30 Marcus Brinkmann * gpgex.h (ID_CMD_HELP, ID_CMD_VERIFY_DECRYPT) (ID_CMD_SIGN_ENCRYPT, ID_CMD_IMPORT, ID_CMD_MAX) (ID_CMD_STR_HELP, ID_CMD_STR_VERIFY_DECRYPT) (ID_CMD_STR_SIGN_ENCRYPT, ID_CMD_STR_IMPORT): New macros. (class gpgex_t): New member ALL_FILES_GPG. * gpgex.cc (gpgex_t::reset): Initialize THIS->all_files_gpg. (gpgex_t::Initialize): Check ending of added files. (gpgex_t::QueryContextMenu): Create a more involved dummy menu. (gpgex_t::InvokeCommand): Show different commands being invoked. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-30 15:41:44 UTC (rev 6) +++ trunk/src/ChangeLog 2007-08-30 15:48:38 UTC (rev 7) @@ -1,5 +1,15 @@ 2007-08-30 Marcus Brinkmann + * gpgex.h (ID_CMD_HELP, ID_CMD_VERIFY_DECRYPT) + (ID_CMD_SIGN_ENCRYPT, ID_CMD_IMPORT, ID_CMD_MAX) + (ID_CMD_STR_HELP, ID_CMD_STR_VERIFY_DECRYPT) + (ID_CMD_STR_SIGN_ENCRYPT, ID_CMD_STR_IMPORT): New macros. + (class gpgex_t): New member ALL_FILES_GPG. + * gpgex.cc (gpgex_t::reset): Initialize THIS->all_files_gpg. + (gpgex_t::Initialize): Check ending of added files. + (gpgex_t::QueryContextMenu): Create a more involved dummy menu. + (gpgex_t::InvokeCommand): Show different commands being invoked. + * gpgex-class.cc (gpgex_class::init): Also register the shell extension for directories. (gpgex_class::deinit): Unregister shell extension for directories. Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-08-30 15:41:44 UTC (rev 6) +++ trunk/src/gpgex.cc 2007-08-30 15:48:38 UTC (rev 7) @@ -41,6 +41,7 @@ gpgex_t::reset (void) { this->filenames.clear (); + this->all_files_gpg = TRUE; } @@ -161,6 +162,23 @@ if (len == 0) throw std::invalid_argument ("zero-length filename"); + /* Take a look at the ending. */ + char *ending = strrchr (filename, '.'); + if (ending) + { + BOOL gpg = false; + + ending++; + if (! strcasecmp (ending, "gpg") + || ! strcasecmp (ending, "pgp") + || ! strcasecmp (ending, "asc") + || ! strcasecmp (ending, "sig")) + gpg = true; + + if (gpg == false) + this->all_files_gpg = FALSE; + } + this->filenames.push_back (filename); } } @@ -206,28 +224,90 @@ gpgex_t::QueryContextMenu (HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { - UINT next_cmd = idCmdFirst; + BOOL res; TRACE_BEG5 (DEBUG_CONTEXT_MENU, "gpgex_t::QueryContextMenu", this, "hMenu=%p, indexMenu=%u, idCmdFirst=%u, idCmdLast=%u, uFlags=%x", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + /* FIXME: Do something if idCmdLast - idCmdFirst + 1 is not big + enough. */ + /* If the flags include CMF_DEFAULTONLY then nothing should be done. */ - if (! (uFlags & CMF_DEFAULTONLY)) + if (uFlags & CMF_DEFAULTONLY) + return TRACE_RES (MAKE_HRESULT (SEVERITY_SUCCESS, FACILITY_NULL, 0)); + + /* Windows puts a separator after our entries, but not before. */ + /* FIXME: Check error. */ + res = InsertMenu (hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL); + if (! res) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + + /* First we add the file-specific menus. */ + if (this->all_files_gpg) { - BOOL res; - - res = InsertMenu (hMenu, indexMenu, MF_BYPOSITION, - next_cmd++, _("GpgEX Test Item")); + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_VERIFY_DECRYPT, + ID_CMD_STR_VERIFY_DECRYPT); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); } + else + { + /* FIXME: Check error. */ + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_SIGN_ENCRYPT, + ID_CMD_STR_SIGN_ENCRYPT); + if (! res) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + } + /* Now generate and add the generic command popup menu. */ + HMENU popup; + UINT idx = 0; + + /* FIXME: Check error. */ + popup = CreatePopupMenu (); + if (popup == NULL) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING | MF_POPUP, + (UINT) popup, _("More GpgEX options")); + if (!res) + { + DWORD last_error = GetLastError (); + DestroyMenu (popup); + return TRACE_RES (HRESULT_FROM_WIN32 (last_error)); + } + + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_VERIFY_DECRYPT, + ID_CMD_STR_VERIFY_DECRYPT); + // idx - 1!!! + // res = SetMenuItemBitmaps (hPopup, idx - 1, MF_BYPOSITION, + // MenuVerifyDecryptBitmap, MenuVerifyDecryptBitmap); + + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_SIGN_ENCRYPT, + ID_CMD_STR_SIGN_ENCRYPT); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_IMPORT, ID_CMD_STR_IMPORT); + if (res) + res = InsertMenu (hMenu, idx++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_HELP, ID_CMD_STR_HELP); + + if (! res) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + /* We should return a HRESULT that indicates success and the offset to the next free command ID after the last one we used, relative to idCmdFirst. In other words: max_used - idCmdFirst + 1. */ return TRACE_RES (MAKE_HRESULT (SEVERITY_SUCCESS, FACILITY_NULL, - next_cmd - idCmdFirst)); + ID_CMD_MAX + 1)); } @@ -264,6 +344,8 @@ STDMETHODIMP gpgex_t::InvokeCommand (LPCMINVOKECOMMANDINFO lpcmi) { + string cmd; + TRACE_BEG1 (DEBUG_CONTEXT_MENU, "gpgex_t::GetCommandString", this, "lpcmi=%p", lpcmi); @@ -276,23 +358,34 @@ QueryContextMenu, ie zero based). */ switch (LOWORD (lpcmi->lpVerb)) { - case 0: - { - string msg; - unsigned int i; - - msg = "The selected files were:\n\n"; - for (i = 0; i < this->filenames.size (); i++) - msg = msg + this->filenames[i] + '\n'; - - MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); - } + case ID_CMD_HELP: + cmd = "HELP"; break; - + case ID_CMD_VERIFY_DECRYPT: + cmd = "VERIFY_DECRYPT"; + break; + case ID_CMD_SIGN_ENCRYPT: + cmd = "SIGN_ENCRYPT"; + break; + case ID_CMD_IMPORT: + cmd = "IMPORT"; + break; default: return TRACE_RES (E_INVALIDARG); + break; } + /* FIXME: Need to send commands to Kleopatra. */ + + string msg; + unsigned int i; + + msg = "Invoked " + cmd + "on files:\n\n"; + for (i = 0; i < this->filenames.size (); i++) + msg = msg + this->filenames[i] + '\n'; + + MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); + return TRACE_RES (S_OK); } Modified: trunk/src/gpgex.h =================================================================== --- trunk/src/gpgex.h 2007-08-30 15:41:44 UTC (rev 6) +++ trunk/src/gpgex.h 2007-08-30 15:48:38 UTC (rev 7) @@ -30,6 +30,19 @@ #include #include +/* For context menus. */ +#define ID_CMD_HELP 0 +#define ID_CMD_VERIFY_DECRYPT 1 +#define ID_CMD_SIGN_ENCRYPT 2 +#define ID_CMD_IMPORT 3 +#define ID_CMD_MAX 3 + +#define ID_CMD_STR_HELP _("Help on GpgEX") +#define ID_CMD_STR_VERIFY_DECRYPT _("Decrypt and verify") +#define ID_CMD_STR_SIGN_ENCRYPT _("Sign and encrypt") +#define ID_CMD_STR_IMPORT _("Import keys") + + /* Our shell extension interface. We use multiple inheritance to achieve polymorphy. @@ -83,6 +96,9 @@ /* Support for IShellExtInit. */ vector filenames; + /* TRUE if all files in filenames are directly related to GPG. */ + BOOL all_files_gpg; + /* Support for the context menu. */ public: From cvs at cvs.gnupg.org Fri Aug 31 10:25:22 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 31 Aug 2007 10:25:22 +0200 Subject: [svn] GnuPG - r4575 - in trunk: doc tools Message-ID: Author: wk Date: 2007-08-31 10:24:52 +0200 (Fri, 31 Aug 2007) New Revision: 4575 Modified: trunk/doc/tools.texi trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Make gpgconf --list-components also print the name of the executable program. Modified: trunk/doc/tools.texi =================================================================== --- trunk/doc/tools.texi 2007-08-29 16:59:20 UTC (rev 4574) +++ trunk/doc/tools.texi 2007-08-31 08:24:52 UTC (rev 4575) @@ -421,7 +421,7 @@ The command argument @code{--list-components} lists all available components, one per line. The format of each line is: - at code{@var{name}:@var{description}} + at code{@var{name}:@var{description}:@var{pgmname}:} @table @var @item name @@ -435,16 +435,21 @@ of the component. It can be displayed to the user of the GUI for informational purposes. It is @emph{percent-escaped} and @emph{localized}. + + at item pgmname +The @emph{string} in this field contains the absolute name of the +program's file. It can be used to unambiguously invoke that program. +It is @emph{percent-escaped}. @end table Example: @example $ gpgconf --list-components -gpg:GPG for OpenPGP -gpg-agent:GPG Agent -scdaemon:Smartcard Daemon -gpgsm:GPG for S/MIME -dirmngr:Directory Manager +gpg:GPG for OpenPGP:/usr/local/bin/gpg2: +gpg-agent:GPG Agent:/usr/local/bin/gpg-agent: +scdaemon:Smartcard Daemon:/usr/local/bin/scdaemon: +gpgsm:GPG for S/MIME:/usr/local/bin/gpgsm: +dirmngr:Directory Manager:/usr/local/bin/dirmngr: @end example Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-08-29 16:59:20 UTC (rev 4574) +++ trunk/tools/ChangeLog 2007-08-31 08:24:52 UTC (rev 4575) @@ -1,3 +1,8 @@ +2007-08-31 Werner Koch + + * gpgconf-comp.c (gc_component_list_components): List the programs + names. + 2007-08-29 Werner Koch * gpgconf.c: New command --check-programs. Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-08-29 16:59:20 UTC (rev 4574) +++ trunk/tools/gpgconf-comp.c 2007-08-31 08:24:52 UTC (rev 4575) @@ -1142,16 +1142,43 @@ void gc_component_list_components (FILE *out) { - gc_component_t idx; + gc_component_t component; + gc_option_t *option; + gc_backend_t backend; + int backend_seen[GC_BACKEND_NR]; + const char *desc; + const char *pgmname; - for (idx = 0; idx < GC_COMPONENT_NR; idx++) + for (component = 0; component < GC_COMPONENT_NR; component++) { - if (gc_component[idx].options) + option = gc_component[component].options; + if (option) { - const char *desc = gc_component[idx].desc; - desc = my_dgettext (gc_component[idx].desc_domain, desc); - fprintf (out, "%s:%s\n", - gc_component[idx].name, my_percent_escape (desc)); + for (backend = 0; backend < GC_BACKEND_NR; backend++) + backend_seen[backend] = 0; + + pgmname = ""; + for (; option && option->name; option++) + { + if ((option->flags & GC_OPT_FLAG_GROUP)) + continue; + backend = option->backend; + if (backend_seen[backend]) + continue; + backend_seen[backend] = 1; + assert (backend != GC_BACKEND_ANY); + if (gc_backend[backend].program + && !gc_backend[backend].module_name) + continue; + pgmname = gnupg_module_name (gc_backend[backend].module_name); + break; + } + + desc = gc_component[component].desc; + desc = my_dgettext (gc_component[component].desc_domain, desc); + fprintf (out, "%s:%s:", + gc_component[component].name, my_percent_escape (desc)); + fprintf (out, "%s:\n", my_percent_escape (pgmname)); } } }