diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | doc/gcrypt.texi | 25 | ||||
-rw-r--r-- | src/g10lib.h | 5 | ||||
-rw-r--r-- | src/gcrypt.h.in | 1 | ||||
-rw-r--r-- | src/global.c | 217 | ||||
-rw-r--r-- | src/libgcrypt.def | 2 | ||||
-rw-r--r-- | src/libgcrypt.vers | 2 | ||||
-rw-r--r-- | src/misc.c | 12 | ||||
-rw-r--r-- | src/visibility.c | 6 | ||||
-rw-r--r-- | src/visibility.h | 2 | ||||
-rw-r--r-- | tests/version.c | 49 |
11 files changed, 248 insertions, 74 deletions
@@ -67,6 +67,7 @@ Noteworthy changes in version 1.8.0 (unreleased) [C21/A1/R_] * Interface changes relative to the 1.7.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GCRYCTL_REINIT_SYSCALL_CLAMP NEW macro. + gcry_get_config NEW function. gcry_md_info DEPRECATED. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 26dd6c3d..cab1318d 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -824,7 +824,8 @@ proper random device. This command dumps information pertaining to the configuration of the library to the given stream. If NULL is given for @var{stream}, the log system is used. This command may be used before the initialization has -been finished but not before a @code{gcry_check_version}. +been finished but not before a @code{gcry_check_version}. Note that +the macro @code{estream_t} can be used instead of @code{gpgrt_stream_t}. @item GCRYCTL_OPERATIONAL_P; Arguments: none This command returns true if the library is in an operational state. @@ -5233,6 +5234,7 @@ wrong. * Memory allocation:: Functions related with memory allocation. * Context management:: Functions related with context management. * Buffer description:: A data type to describe buffers. +* Config reporting:: How to return Libgcrypt's configuration. @end menu @@ -5317,6 +5319,27 @@ of this structure are: @end table @end deftp +@node Config reporting +@section How to return Libgcrypt's configuration. + +Although @code{GCRYCTL_PRINT_CONFIG} can be used to print +configuration options, it is sometimes necessary to check them in a +program. This can be accomplished by using this function: + +@deftypefun {char *} gcry_get_config @ + (@w{int @var{mode}}, @ + @w{const char *@var{what}}) + +This function returns a malloced string with colon delimited configure +options. With a value of 0 for @var{mode} this string resembles the +output of @code{GCRYCTL_PRINT_CONFIG}. However, if @var{what} is not +NULL, only the line where the first field (e.g. "cpu-arch") matches +@var{what} is returned. + +Other values than 0 for @var{mode} are not defined. The caller shall +free the string using @code{gcry_free}. On error NULL is returned and +ERRNO is set; if a value for WHAT is unknow ERRNO will be set to 0. +@end deftypefun @c ********************************************************** diff --git a/src/g10lib.h b/src/g10lib.h index ec8aab56..961b5154 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -109,6 +109,8 @@ void _gcry_pre_syscall (void); void _gcry_post_syscall (void); int _gcry_get_debug_flag (unsigned int mask); +char *_gcry_get_config (int mode, const char *what); + /* Malloc functions and common wrapper macros. */ void *_gcry_malloc (size_t n) _GCRY_GCC_ATTR_MALLOC; void *_gcry_calloc (size_t n, size_t m) _GCRY_GCC_ATTR_MALLOC; @@ -163,8 +165,6 @@ void _gcry_log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); void _gcry_log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); void _gcry_log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); -int _gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) - JNLIB_GCC_A_PRINTF(2,3); void _gcry_log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printf ( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); void _gcry_log_printhex (const char *text, const void *buffer, size_t length); @@ -174,6 +174,7 @@ void _gcry_log_printsxp (const char *text, gcry_sexp_t sexp); void _gcry_set_log_verbosity( int level ); int _gcry_log_verbosity( int level ); + #ifdef JNLIB_GCC_M_FUNCTION #define BUG() _gcry_bug( __FILE__ , __LINE__, __FUNCTION__ ) #define gcry_assert(expr) (LIKELY(expr)? (void)0 \ diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 210ea2fd..8d20c83b 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1691,6 +1691,7 @@ void gcry_log_debugpnt (const char *text, gcry_mpi_point_t point, gcry_ctx_t ctx); void gcry_log_debugsxp (const char *text, gcry_sexp_t sexp); +char *gcry_get_config (int mode, const char *what); /* Log levels used by the internal logging facility. */ enum gcry_log_levels diff --git a/src/global.c b/src/global.c index 0796a945..4e2e274a 100644 --- a/src/global.c +++ b/src/global.c @@ -2,7 +2,7 @@ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 * 2004, 2005, 2006, 2008, 2011, * 2012 Free Software Foundation, Inc. - * Copyright (C) 2013, 2014 g10 Code GmbH + * Copyright (C) 2013, 2014, 2017 g10 Code GmbH * * This file is part of Libgcrypt. * @@ -273,91 +273,181 @@ _gcry_check_version (const char *req_version) static void -print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp) +print_config (const char *what, gpgrt_stream_t fp) { - unsigned int hwfeatures, afeature; int i; const char *s; - fnc (fp, "version:%s:%x:%s:%x:\n", - VERSION, GCRYPT_VERSION_NUMBER, - GPGRT_VERSION, GPGRT_VERSION_NUMBER); - fnc (fp, "cc:%d:%s:\n", + if (!what || !strcmp (what, "version")) + { + gpgrt_fprintf (fp, "version:%s:%x:%s:%x:\n", + VERSION, GCRYPT_VERSION_NUMBER, + GPGRT_VERSION, GPGRT_VERSION_NUMBER); + } + if (!what || !strcmp (what, "cc")) + { + gpgrt_fprintf (fp, "cc:%d:%s:\n", #if GPGRT_VERSION_NUMBER >= 0x011b00 /* 1.27 */ - GPGRT_GCC_VERSION + GPGRT_GCC_VERSION #else - _GPG_ERR_GCC_VERSION /* Due to a bug in gpg-error.h. */ + _GPG_ERR_GCC_VERSION /* Due to a bug in gpg-error.h. */ #endif - , + , #ifdef __clang__ - "clang:" __VERSION__ + "clang:" __VERSION__ #elif __GNUC__ - "gcc:" __VERSION__ + "gcc:" __VERSION__ #else - ":" + ":" #endif - ); + ); + } - fnc (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS); - fnc (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS); - fnc (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS); - fnc (fp, "rnd-mod:" + if (!what || !strcmp (what, "ciphers")) + gpgrt_fprintf (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS); + if (!what || !strcmp (what, "pubkeys")) + gpgrt_fprintf (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS); + if (!what || !strcmp (what, "digests")) + gpgrt_fprintf (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS); + + if (!what || !strcmp (what, "rnd-mod")) + { + gpgrt_fprintf (fp, "rnd-mod:" #if USE_RNDEGD - "egd:" + "egd:" #endif #if USE_RNDLINUX - "linux:" + "linux:" #endif #if USE_RNDUNIX - "unix:" + "unix:" #endif #if USE_RNDW32 - "w32:" + "w32:" #endif - "\n"); - fnc (fp, "cpu-arch:" + "\n"); + } + + if (!what || !strcmp (what, "cpu-arch")) + { + gpgrt_fprintf (fp, "cpu-arch:" #if defined(HAVE_CPU_ARCH_X86) - "x86" + "x86" #elif defined(HAVE_CPU_ARCH_ALPHA) - "alpha" + "alpha" #elif defined(HAVE_CPU_ARCH_SPARC) - "sparc" + "sparc" #elif defined(HAVE_CPU_ARCH_MIPS) - "mips" + "mips" #elif defined(HAVE_CPU_ARCH_M68K) - "m68k" + "m68k" #elif defined(HAVE_CPU_ARCH_PPC) - "ppc" + "ppc" #elif defined(HAVE_CPU_ARCH_ARM) - "arm" + "arm" #endif - ":\n"); - fnc (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ()); - hwfeatures = _gcry_get_hw_features (); - fnc (fp, "hwflist:"); - for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++) - if ((hwfeatures & afeature)) - fnc (fp, "%s:", s); - fnc (fp, "\n"); - /* We use y/n instead of 1/0 for the simple reason that Emacsen's - compile error parser would accidentally flag that line when printed - during "make check" as an error. */ - fnc (fp, "fips-mode:%c:%c:\n", - fips_mode ()? 'y':'n', - _gcry_enforced_fips_mode ()? 'y':'n' ); - /* The currently used RNG type. */ - { - i = _gcry_get_rng_type (0); - switch (i) - { - case GCRY_RNG_TYPE_STANDARD: s = "standard"; break; - case GCRY_RNG_TYPE_FIPS: s = "fips"; break; - case GCRY_RNG_TYPE_SYSTEM: s = "system"; break; - default: BUG (); - } - fnc (fp, "rng-type:%s:%d:\n", s, i); - } + ":\n"); + } + + if (!what || !strcmp (what, "mpi-asm")) + gpgrt_fprintf (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ()); + + if (!what || !strcmp (what, "hwflist")) + { + unsigned int hwfeatures, afeature; + + hwfeatures = _gcry_get_hw_features (); + gpgrt_fprintf (fp, "hwflist:"); + for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++) + if ((hwfeatures & afeature)) + gpgrt_fprintf (fp, "%s:", s); + gpgrt_fprintf (fp, "\n"); + } + + if (!what || !strcmp (what, "fips-mode")) + { + /* We use y/n instead of 1/0 for the stupid reason that + * Emacsen's compile error parser would accidentally flag that + * line when printed during "make check" as an error. */ + gpgrt_fprintf (fp, "fips-mode:%c:%c:\n", + fips_mode ()? 'y':'n', + _gcry_enforced_fips_mode ()? 'y':'n' ); + } + + if (!what || !strcmp (what, "rng-type")) + { + /* The currently used RNG type. */ + unsigned int jver; + int active; + + i = _gcry_get_rng_type (0); + switch (i) + { + case GCRY_RNG_TYPE_STANDARD: s = "standard"; break; + case GCRY_RNG_TYPE_FIPS: s = "fips"; break; + case GCRY_RNG_TYPE_SYSTEM: s = "system"; break; + default: BUG (); + } + jver = _gcry_rndjent_get_version (&active); + gpgrt_fprintf (fp, "rng-type:%s:%d:%u:%d:\n", s, i, jver, active); + } +} + + +/* With a MODE of 0 return a malloced string with configured features. + * In that case a WHAT of NULL returns everything in the same way + * GCRYCTL_PRINT_CONFIG would do. With a specific WHAT string only + * the requested feature is returned (w/o the trailing LF. On error + * NULL is returned. */ +char * +_gcry_get_config (int mode, const char *what) +{ + gpgrt_stream_t fp; + int save_errno; + void *data; + char *p; + + if (mode) + { + gpg_err_set_errno (EINVAL); + return NULL; + } + + fp = gpgrt_fopenmem (0, "w+b,samethread"); + if (!fp) + return NULL; + + print_config (what, fp); + if (gpgrt_ferror (fp)) + { + save_errno = errno; + gpgrt_fclose (fp); + gpg_err_set_errno (save_errno); + return NULL; + } + + gpgrt_rewind (fp); + if (gpgrt_fclose_snatch (fp, &data, NULL)) + { + save_errno = errno; + gpgrt_fclose (fp); + gpg_err_set_errno (save_errno); + return NULL; + } + + if (!data) + { + /* Nothing was printed (unknown value for WHAT). This is okay, + * so clear ERRNO to indicate this. */ + gpg_err_set_errno (0); + return NULL; + } + + /* Strip trailing LF. */ + if (what && (p = strchr (data, '\n'))) + *p = 0; + return data; } @@ -549,12 +639,21 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr) /* This command dumps information pertaining to the configuration of libgcrypt to the given stream. It may be used before the initialization has been finished but not - before a gcry_version_check. */ + before a gcry_version_check. See also gcry_get_config. */ case GCRYCTL_PRINT_CONFIG: { FILE *fp = va_arg (arg_ptr, FILE *); + char *tmpstr; _gcry_set_preferred_rng_type (0); - print_config (fp?fprintf:_gcry_log_info_with_dummy_fp, fp); + tmpstr = _gcry_get_config (0, NULL); + if (tmpstr) + { + if (fp) + fputs (tmpstr, fp); + else + log_info ("%s", tmpstr); + xfree (tmpstr); + } } break; diff --git a/src/libgcrypt.def b/src/libgcrypt.def index 067cb843..c4a9eacc 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -282,4 +282,6 @@ EXPORTS gcry_mpi_ec_decode_point @246 + gcry_get_config @247 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 785b8ed2..1d2d150a 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -111,6 +111,8 @@ GCRYPT_1.6 { gcry_log_debug; gcry_log_debughex; gcry_log_debugmpi; gcry_log_debugpnt; gcry_log_debugsxp; + gcry_get_config; + _gcry_mpi_get_const; gcry_ctx_release; @@ -198,18 +198,6 @@ _gcry_log_info( const char *fmt, ... ) va_end(arg_ptr); } -int -_gcry_log_info_with_dummy_fp (FILE *fp, const char *fmt, ... ) -{ - va_list arg_ptr; - - (void)fp; - va_start( arg_ptr, fmt ) ; - _gcry_logv( GCRY_LOG_INFO, fmt, arg_ptr ); - va_end(arg_ptr); - return 0; -} - void _gcry_log_error( const char *fmt, ... ) { diff --git a/src/visibility.c b/src/visibility.c index 3abbd379..7bf3d57b 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1435,6 +1435,12 @@ gcry_log_debugsxp (const char *text, gcry_sexp_t sexp) _gcry_log_printsxp (text, sexp); } +char * +gcry_get_config (int mode, const char *what) +{ + return _gcry_get_config (mode, what); +} + void gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data) { diff --git a/src/visibility.h b/src/visibility.h index 7ecd75e3..d28993a8 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -279,6 +279,8 @@ MARK_VISIBLEX (gcry_log_debugmpi) MARK_VISIBLEX (gcry_log_debugpnt) MARK_VISIBLEX (gcry_log_debugsxp) +MARK_VISIBLEX (gcry_get_config) + /* Functions used to implement macros. */ MARK_VISIBLEX (_gcry_mpi_get_const) diff --git a/tests/version.c b/tests/version.c index baf984ec..6a01610d 100644 --- a/tests/version.c +++ b/tests/version.c @@ -32,12 +32,58 @@ #include <stdlib.h> #include <string.h> #include <stdarg.h> +#include <errno.h> #include "../src/gcrypt-int.h" #define PGM "version" #include "t-common.h" +static void +test_get_config (void) +{ + char *string; + + string = gcry_get_config (0, NULL); + if (!string) + fail ("gcry_get_config does not return anything: %s\n", + gpg_strerror (gpg_error_from_syserror ())); + else if ( !strchr (string, '\n') ) + fail ("gcry_get_config(0, NULL) did not return multiple lines\n"); + + xfree (string); + string = gcry_get_config (0, "version"); + if (!string) + fail ("gcry_get_config(\"version\") returned NULL: %s\n", + gpg_strerror (gpg_error_from_syserror ())); + else if ( strchr (string, '\n') ) + fail ("gcry_get_config(\"version\") returned more than one line\n"); + else if ( strncmp (string, "version:", 8) ) + fail ("gcry_get_config(\"version\") returned wrong line\n"); + + /* Test an item which is not the first. */ + xfree (string); + string = gcry_get_config (0, "cpu-arch"); + if (!string) + fail ("gcry_get_config(\"cpu-arch\") returned NULL: %s\n", + gpg_strerror (gpg_error_from_syserror ())); + else if ( strchr (string, '\n') ) + fail ("gcry_get_config(\"cpu-arch\") returned more than one line\n"); + else if ( strncmp (string, "cpu-arch:", 9) ) + fail ("gcry_get_config(\"cpu-arch\") returned wrong line\n"); + + /* Test that an unknown item return sthe correct error. */ + xfree (string); + string = gcry_get_config (0, "no-such-item"); + if (string) + fail ("gcry_get_config(\"no-such-item\") returned something\n"); + else if (errno) + fail ("gcry_get_config(\"no-such-item\") returned wrong error: %s\n", + gpg_strerror (gpg_error_from_syserror ())); + + xfree (string); +} + int main (int argc, char **argv) @@ -96,5 +142,8 @@ main (int argc, char **argv) xgcry_control (GCRYCTL_PRINT_CONFIG, NULL); + test_get_config (); + + return 0; } |