diff options
author | Werner Koch <wk@gnupg.org> | 2011-01-24 12:24:11 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2011-01-24 12:24:11 +0100 |
commit | c5e8a4c0fdde7f4aef2163a3710483c87bdf3161 (patch) | |
tree | ae9da511231485f5c8ba8faeb3e7db3b971fe8ff | |
parent | Fix regression introduced by "editing only change". (diff) | |
parent | Remove keyserver/ from the build system. (diff) | |
download | gnupg2-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.tar.xz gnupg2-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.zip |
Merge branch 'master' into ECC-INTEGRATION-2-1
49 files changed, 3536 insertions, 1629 deletions
@@ -1,3 +1,13 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + * configure.ac (AC_CONFIG_FILES): Remove keyserver/. + +2011-01-19 Werner Koch <wk@g10code.com> + + * configure.ac: Add new option --enable-gpg2-is-gpg. + (NAME_OF_INSTALLED_GPG): New ac_define. + * autogen.sh [--build-w32ce]: Use --enable-gpg2-is-gpg. + 2011-01-21 Werner Koch <wk@g10code.com> * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. @@ -21,7 +31,7 @@ 2010-11-17 Werner Koch <wk@g10code.com> - * configure.ac (ENABLE_CARD_SUPPORT): Define. + * configure.ac (ENABLE_CARD_SUPPORT): Define. 2010-10-27 Werner Koch <wk@g10code.com> diff --git a/Makefile.am b/Makefile.am index c5c2a01db..e2ad6d100 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,7 @@ endif if BUILD_GPG gpg = g10 if !HAVE_W32CE_SYSTEM -keyserver = keyserver +keyserver = endif else gpg = @@ -17,6 +17,9 @@ Noteworthy changes in version 2.1.0beta2 (unreleased) * Fixed TTY management for pinentries and session variable update problem. + * Dirmngr has taken over the function of the keyserver helpers. Thus + we now have a specified direct interface to keyservers via Dirmngr. + Noteworthy changes in version 2.1.0beta1 (2010-10-26) ----------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index 4b0712c8d..7dace3aef 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2011-01-19 Werner Koch <wk@g10code.com> + + * trustlist.c (read_one_trustfile): Also chop an CR. + 2011-01-21 Werner Koch <wk@g10code.com> * pksign.c (do_encode_dsa): Compare MDLEN to bytes. diff --git a/agent/trustlist.c b/agent/trustlist.c index 791df9682..d56598245 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -139,8 +139,9 @@ read_one_trustfile (const char *fname, int allow_include, while (es_fgets (line, DIM(line)-1, fp)) { lnr++; - - if (!*line || line[strlen(line)-1] != '\n') + + n = strlen (line); + if (!n || line[n-1] != '\n') { /* Eat until end of line. */ while ( (c=es_getc (fp)) != EOF && c != '\n') @@ -151,7 +152,9 @@ read_one_trustfile (const char *fname, int allow_include, fname, lnr, gpg_strerror (err)); continue; } - line[strlen(line)-1] = 0; /* Chop the LF. */ + line[--n] = 0; /* Chop the LF. */ + if (n && line[n-1] == '\r') + line[--n] = 0; /* Chop an optional CR. */ /* Allow for empty lines and spaces */ for (p=line; spacep (p); p++) diff --git a/autogen.sh b/autogen.sh index 72e5fee2c..d05415507 100755 --- a/autogen.sh +++ b/autogen.sh @@ -104,7 +104,8 @@ if [ "$myhost" = "w32" ]; then [ -z "$w32root" ] && w32root="$HOME/w32ce_root" toolprefixes="$w32ce_toolprefixes arm-mingw32ce" extraoptions="--enable-dirmngr-auto-start --disable-scdaemon " - extraoptions="$extraoptions --disable-zip $w32ce_extraoptions" + extraoptions="$extraoptions --disable-zip --enable-gpg2-is-gpg" + extraoptions="$extraoptions $w32ce_extraoptions" ;; *) [ -z "$w32root" ] && w32root="$HOME/w32root" diff --git a/common/ChangeLog b/common/ChangeLog index 6a6f6e071..61f6b292b 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,55 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + Fix bug#1313. + + * http.c (my_select): New. Define to pth_select if building with Pth. + (start_server, write_server, cookie_read, cookie_write): Use it. + (my_connect): New. Define to pth_connect if building with Pth. + (connect_server): Use it. + (my_accept): New. Define to pth_accept if building with Pth. + (start_server): Use it. + +2011-01-20 Werner Koch <wk@g10code.com> + + * util.h (struct b64state): Add field LASTERR. + * b64enc.c (enc_start, b64enc_write, b64enc_finish): Handle + LASTERR. This is to make sure that we don't leak strduped data. + * b64dec.c (b64dec_start, b64dec_proc, b64dec_finish): Ditto. + + * http.c (escape_data): New. + (insert_escapes): Implement using escape_data. + (http_escape_data): New. + +2011-01-19 Werner Koch <wk@g10code.com> + + * homedir.c (gnupg_module_name): Use NAME_OF_INSTALLED_GPG instead + of "gpg2". + +2011-01-18 Werner Koch <wk@g10code.com> + + * iobuf.c (file_es_filter_ctx_t): New. + (file_es_filter): New. + (iobuf_esopen): New. + + * membuf.c (clear_membuf, peek_membuf): New. + + * util.h (GPG_ERR_NO_KEYSERVER): New. + + * keyserver.h (keyserver_spec): Move from ../g10/options.h to here. + + * http.c (do_parse_uri): Add arg NO_SCHEME_CHECK. Change all + callers. Support HKP and HKPS. + (_http_parse_uri): Do proper error management. + * http.h (parsed_uri_s): Add field IS_HTTP. + (http_parse_uri): Support NO_SCHEME_CHECK arg. + + * estream.c (es_func_mem_write): Fix computation of NEWSIZE. + +2011-01-10 Werner Koch <wk@g10code.com> + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + 2011-01-10 Werner Koch <wk@g10code.com> * session-env.c (update_var): Fix same value detection. Fixes diff --git a/common/b64dec.c b/common/b64dec.c index af223aef2..137dd7216 100644 --- a/common/b64dec.c +++ b/common/b64dec.c @@ -1,5 +1,5 @@ /* b64dec.c - Simple Base64 decoder. - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -72,16 +72,19 @@ b64dec_start (struct b64state *state, const char *title) if (title) { if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' ')) - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - - state->title = xtrystrdup (title); - if (!state->title) - return gpg_error_from_syserror (); - state->idx = s_init; + state->lasterr = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + else + { + state->title = xtrystrdup (title); + if (!state->title) + state->lasterr = gpg_error_from_syserror (); + else + state->idx = s_init; + } } else state->idx = s_b64_0; - return 0; + return state->lasterr; } @@ -96,12 +99,18 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length, int pos = state->quad_count; char *d, *s; + if (state->lasterr) + return state->lasterr; + if (state->stop_seen) { *r_nbytes = 0; - return gpg_error (GPG_ERR_EOF); + state->lasterr = gpg_error (GPG_ERR_EOF); + xfree (state->title); + state->title = NULL; + return state->lasterr; } - + for (s=d=buffer; length && !state->stop_seen; length--, s++) { switch (ds) @@ -210,6 +219,9 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length, gpg_error_t b64dec_finish (struct b64state *state) { + if (state->lasterr) + return state->lasterr; + xfree (state->title); state->title = NULL; return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0; diff --git a/common/b64enc.c b/common/b64enc.c index 1e277f4cb..5d616198e 100644 --- a/common/b64enc.c +++ b/common/b64enc.c @@ -1,5 +1,6 @@ /* b64enc.c - Simple Base64 encoder. - * Copyright (C) 2001, 2003, 2004, 2008, 2010 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2008, 2010, + * 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -143,6 +144,7 @@ enc_start (struct b64state *state, FILE *fp, estream_t stream, memset (state, 0, sizeof *state); state->fp = fp; state->stream = stream; + state->lasterr = 0; if (title && !*title) state->flags |= B64ENC_NO_LINEFEEDS; else if (title) @@ -154,9 +156,9 @@ enc_start (struct b64state *state, FILE *fp, estream_t stream, } state->title = xtrystrdup (title); if (!state->title) - return gpg_error_from_syserror (); + state->lasterr = gpg_error_from_syserror (); } - return 0; + return state->lasterr; } @@ -203,6 +205,8 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) int idx, quad_count; const unsigned char *p; + if (state->lasterr) + return state->lasterr; if (!nbytes) { @@ -285,7 +289,13 @@ b64enc_write (struct b64state *state, const void *buffer, size_t nbytes) return 0; write_error: - return gpg_error_from_syserror (); + state->lasterr = gpg_error_from_syserror (); + if (state->title) + { + xfree (state->title); + state->title = NULL; + } + return state->lasterr; } @@ -297,6 +307,9 @@ b64enc_finish (struct b64state *state) int idx, quad_count; char tmp[4]; + if (state->lasterr) + return state->lasterr; + if (!(state->flags & B64ENC_DID_HEADER)) goto cleanup; @@ -404,6 +417,7 @@ b64enc_finish (struct b64state *state) } state->fp = NULL; state->stream = NULL; + state->lasterr = err; return err; } diff --git a/common/estream.c b/common/estream.c index bc25452ed..416aa8376 100644 --- a/common/estream.c +++ b/common/estream.c @@ -641,7 +641,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size) if (!mem_cookie->memory_size) newsize = size; /* Not yet allocated. */ else - newsize = mem_cookie->memory_size + (nleft - size); + newsize = mem_cookie->memory_size + (size - nleft); if (newsize < mem_cookie->offset) { _set_errno (EINVAL); diff --git a/common/homedir.c b/common/homedir.c index a6364f8b5..3d31bd376 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -528,7 +528,7 @@ gnupg_module_name (int which) X(bindir, "gpgsm"); case GNUPG_MODULE_NAME_GPG: - X(bindir, "gpg2"); + X(bindir, NAME_OF_INSTALLED_GPG); case GNUPG_MODULE_NAME_CONNECT_AGENT: X(bindir, "gpg-connect-agent"); diff --git a/common/http.c b/common/http.c index 1d84051a2..b50b6b8ad 100644 --- a/common/http.c +++ b/common/http.c @@ -1,6 +1,6 @@ /* http.c - HTTP protocol handler - * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, - * 2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010, + * 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -105,6 +105,16 @@ struct srventry #endif/*!USE_DNS_SRV*/ +#ifdef HAVE_PTH +# define my_select(a,b,c,d,e) pth_select ((a), (b), (c), (d), (e)) +# define my_connect(a,b,c) pth_connect ((a), (b), (c)) +# define my_accept(a,b,c) pth_accept ((a), (b), (c)) +#else +# define my_select(a,b,c,d,e) select ((a), (b), (c), (d), (e)) +# define my_connect(a,b,c) connect ((a), (b), (c)) +# define my_accept(a,b,c) accept ((a), (b), (c)) +#endif + #ifdef HAVE_W32_SYSTEM #define sock_close(a) closesocket(a) #else @@ -138,7 +148,8 @@ typedef unsigned long longcounter_t; typedef void * gnutls_session_t; #endif -static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part); +static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part, + int no_scheme_check); static int remove_escapes (char *string); static int insert_escapes (char *buffer, const char *string, const char *special); @@ -356,7 +367,7 @@ _http_open (http_t *r_hd, http_req_t reqtype, const char *url, hd->flags = flags; hd->tls_context = tls_context; - err = _http_parse_uri (&hd->uri, url, errsource); + err = _http_parse_uri (&hd->uri, url, 0, errsource); if (!err) err = send_request (hd, auth, proxy, srvtag, headers, errsource); @@ -368,7 +379,6 @@ _http_open (http_t *r_hd, http_req_t reqtype, const char *url, es_fclose (hd->fp_read); if (hd->fp_write) es_fclose (hd->fp_write); - http_release_parsed_uri (hd->uri); xfree (hd); } else @@ -511,18 +521,27 @@ http_get_status_code (http_t hd) /* * Parse an URI and put the result into the newly allocated RET_URI. - * The caller must always use release_parsed_uri() to releases the - * resources (even on error). + * On success the caller must use release_parsed_uri() to releases the + * resources. If NO_SCHEME_CHECK is set, the function tries to parse + * the URL in the same way it would do for an HTTP style URI. */ gpg_error_t -_http_parse_uri (parsed_uri_t * ret_uri, const char *uri, - gpg_err_source_t errsource) +_http_parse_uri (parsed_uri_t *ret_uri, const char *uri, + int no_scheme_check, gpg_err_source_t errsource) { + gpg_err_code_t ec; + *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri)); if (!*ret_uri) return gpg_err_make (errsource, gpg_err_code_from_syserror ()); strcpy ((*ret_uri)->buffer, uri); - return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0)); + ec = do_parse_uri (*ret_uri, 0, no_scheme_check); + if (ec) + { + xfree (*ret_uri); + *ret_uri = NULL; + } + return gpg_err_make (errsource, ec); } void @@ -543,7 +562,7 @@ http_release_parsed_uri (parsed_uri_t uri) static gpg_err_code_t -do_parse_uri (parsed_uri_t uri, int only_local_part) +do_parse_uri (parsed_uri_t uri, int only_local_part, int no_scheme_check) { uri_tuple_t *tail; char *p, *p2, *p3, *pp; @@ -557,6 +576,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part) uri->port = 0; uri->params = uri->query = NULL; uri->use_tls = 0; + uri->is_http = 0; /* A quick validity check. */ if (strspn (p, VALID_URI_CHARS) != n) @@ -572,15 +592,24 @@ do_parse_uri (parsed_uri_t uri, int only_local_part) *pp = tolower (*(unsigned char*)pp); uri->scheme = p; if (!strcmp (uri->scheme, "http")) - uri->port = 80; + { + uri->port = 80; + uri->is_http = 1; + } + else if (!strcmp (uri->scheme, "hkp")) + { + uri->port = 11371; + uri->is_http = 1; + } #ifdef HTTP_USE_GNUTLS - else if (!strcmp (uri->scheme, "https")) + else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")) { uri->port = 443; + uri->is_http = 1; uri->use_tls = 1; } #endif - else + else if (!no_scheme_check) return GPG_ERR_INV_URI; /* Unsupported scheme */ p = p2; @@ -723,14 +752,14 @@ remove_escapes (char *string) } -static int -insert_escapes (char *buffer, const char *string, - const char *special) +static size_t +escape_data (char *buffer, const void *data, size_t datalen, + const char *special) { - const unsigned char *s = (const unsigned char*)string; - int n = 0; + const unsigned char *s; + size_t n = 0; - for (; *s; s++) + for (s = data; datalen; s++, datalen--) { if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s)) { @@ -752,6 +781,14 @@ insert_escapes (char *buffer, const char *string, } +static int +insert_escapes (char *buffer, const char *string, + const char *special) +{ + return escape_data (buffer, string, strlen (string), special); +} + + /* Allocate a new string from STRING using standard HTTP escaping as well as escaping of characters given in SPECIALS. A common pattern for SPECIALS is "%;?&=". However it depends on the needs, for @@ -773,6 +810,27 @@ http_escape_string (const char *string, const char *specials) return buf; } +/* Allocate a new string from {DATA,DATALEN} using standard HTTP + escaping as well as escaping of characters given in SPECIALS. A + common pattern for SPECIALS is "%;?&=". However it depends on the + needs, for example "+" and "/: often needs to be escaped too. + Returns NULL on failure and sets ERRNO. */ +char * +http_escape_data (const void *data, size_t datalen, const char *specials) +{ + int n; + char *buf; + + n = escape_data (NULL, data, datalen, specials); + buf = xtrymalloc (n+1); + if (buf) + { + escape_data (buf, data, datalen, specials); + buf[n] = 0; + } + return buf; +} + static uri_tuple_t @@ -852,12 +910,11 @@ send_request (http_t hd, const char *auth, if (proxy) http_proxy = proxy; - err = _http_parse_uri (&uri, http_proxy, errsource); + err = _http_parse_uri (&uri, http_proxy, 0, errsource); if (err) { log_error ("invalid HTTP proxy (%s): %s\n", http_proxy, gpg_strerror (err)); - http_release_parsed_uri (uri); return gpg_err_make (errsource, GPG_ERR_CONFIGURATION); } @@ -1374,14 +1431,14 @@ start_server () FD_ZERO (&rfds); FD_SET (fd, &rfds); - if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0) + if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0) continue; /* ignore any errors */ if (!FD_ISSET (fd, &rfds)) continue; addrlen = sizeof peer; - client = accept (fd, (struct sockaddr *) &peer, &addrlen); + client = my_accept (fd, (struct sockaddr *) &peer, &addrlen); if (client == -1) continue; /* oops */ @@ -1451,7 +1508,7 @@ connect_server (const char *server, unsigned short port, addr.sin_port = htons(port); memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr)); - if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) ) + if (!my_connect (sock,(struct sockaddr *)&addr,sizeof(addr)) ) return sock; sock_close(sock); return -1; @@ -1519,7 +1576,7 @@ connect_server (const char *server, unsigned short port, return -1; } - if (connect (sock, ai->ai_addr, ai->ai_addrlen)) + if (my_connect (sock, ai->ai_addr, ai->ai_addrlen)) last_errno = errno; else connected = 1; @@ -1573,7 +1630,7 @@ connect_server (const char *server, unsigned short port, for (i = 0; host->h_addr_list[i] && !connected; i++) { memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length); - if (connect (sock, (struct sockaddr *) &addr, sizeof (addr))) + if (my_connect (sock, (struct sockaddr *) &addr, sizeof (addr))) last_errno = errno; else { @@ -1613,7 +1670,6 @@ write_server (int sock, const char *data, size_t length) int nleft; int nwritten; - /* FIXME: We would better use pth I/O functions. */ nleft = length; while (nleft > 0) { @@ -1640,7 +1696,7 @@ write_server (int sock, const char *data, size_t length) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); continue; } log_info ("network write failed: %s\n", strerror (errno)); @@ -1686,7 +1742,7 @@ cookie_read (void *cookie, void *buffer, size_t size) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); goto again; } if (nread == GNUTLS_E_REHANDSHAKE) @@ -1748,7 +1804,7 @@ cookie_write (void *cookie, const void *buffer, size_t size) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); continue; } log_info ("TLS network write failed: %s\n", @@ -1882,11 +1938,10 @@ main (int argc, char **argv) http_register_tls_callback (verify_callback); #endif /*HTTP_USE_GNUTLS*/ - rc = http_parse_uri (&uri, *argv); + rc = http_parse_uri (&uri, *argv, 0); if (rc) { log_error ("`%s': %s\n", *argv, gpg_strerror (rc)); - http_release_parsed_uri (uri); return 1; } diff --git a/common/http.h b/common/http.h index ac9cb1513..7eecbc004 100644 --- a/common/http.h +++ b/common/http.h @@ -23,7 +23,8 @@ #include <gpg-error.h> #include "../common/estream.h" -struct uri_tuple_s { +struct uri_tuple_s +{ struct uri_tuple_s *next; const char *name; /* A pointer into name. */ char *value; /* A pointer to value (a Nul is always appended). */ @@ -36,8 +37,9 @@ typedef struct uri_tuple_s *uri_tuple_t; struct parsed_uri_s { /* All these pointers point into BUFFER; most stuff is not escaped. */ - char *scheme; /* Pointer to the scheme string (lowercase). */ - int use_tls; /* Whether TLS should be used. */ + char *scheme; /* Pointer to the scheme string (always lowercase). */ + unsigned int is_http:1; /* This is a HTTP style URI. */ + unsigned int use_tls:1; /* Whether TLS should be used. */ char *auth; /* username/password for basic auth */ char *host; /* Host (converted to lowercase). */ unsigned short port; /* Port (always set if the host is set). */ @@ -71,9 +73,9 @@ typedef struct http_context_s *http_t; void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int)); gpg_error_t _http_parse_uri (parsed_uri_t *ret_uri, const char *uri, - gpg_err_source_t errsource); -#define http_parse_uri(a,b) \ - _http_parse_uri ((a), (b), GPG_ERR_SOURCE_DEFAULT) + int no_scheme_check, gpg_err_source_t errsource); +#define http_parse_uri(a,b,c) \ + _http_parse_uri ((a), (b), (c), GPG_ERR_SOURCE_DEFAULT) void http_release_parsed_uri (parsed_uri_t uri); @@ -115,6 +117,7 @@ unsigned int http_get_status_code (http_t hd); const char *http_get_header (http_t hd, const char *name); char *http_escape_string (const char *string, const char *specials); +char *http_escape_data (const void *data, size_t datalen, const char *specials); #endif /*GNUPG_COMMON_HTTP_H*/ diff --git a/common/iobuf.c b/common/iobuf.c index b9bed3218..9813d3da6 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1,6 +1,6 @@ /* iobuf.c - File Handling for OpenPGP. * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008, - * 2009, 2010 Free Software Foundation, Inc. + * 2009, 2010, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -78,6 +78,17 @@ typedef struct char fname[1]; /* Name of the file. */ } file_filter_ctx_t; +/* The context used by the estream filter. */ +typedef struct +{ + estream_t fp; /* Open estream handle. */ + int keep_open; + int no_cache; + int eof_seen; + int print_only_name; /* Flags indicating that fname is not a real file. */ + char fname[1]; /* Name of the file. */ +} file_es_filter_ctx_t; + /* Object to control the "close cache". */ struct close_cache_s @@ -577,6 +588,96 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf, } +/* Similar to file_filter but using the estream system. */ +static int +file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf, + size_t * ret_len) +{ + file_es_filter_ctx_t *a = opaque; + estream_t f = a->fp; + size_t size = *ret_len; + size_t nbytes = 0; + int rc = 0; + + (void)chain; /* Not used. */ + + if (control == IOBUFCTRL_UNDERFLOW) + { + assert (size); /* We need a buffer. */ + if (a->eof_seen) + { + rc = -1; + *ret_len = 0; + } + else + { + nbytes = 0; + rc = es_read (f, buf, size, &nbytes); + if (rc == -1) + { /* error */ + rc = gpg_error_from_syserror (); + log_error ("%s: read error: %s\n", a->fname, strerror (errno)); + } + else if (!nbytes) + { /* eof */ + a->eof_seen = 1; + rc = -1; + } + *ret_len = nbytes; + } + } + else if (control == IOBUFCTRL_FLUSH) + { + if (size) + { + byte *p = buf; + size_t nwritten; + + nbytes = size; + do + { + nwritten = 0; + if (es_write (f, p, nbytes, &nwritten)) + { + rc = gpg_error_from_syserror (); + log_error ("%s: write error: %s\n", + a->fname, strerror (errno)); + break; + } + p += nwritten; + nbytes -= nwritten; + } + while (nbytes); + nbytes = p - buf; + } + *ret_len = nbytes; + } + else if (control == IOBUFCTRL_INIT) + { + a->eof_seen = 0; + a->no_cache = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "estream_filter"; + } + else if (control == IOBUFCTRL_FREE) + { + if (f != es_stdin && f != es_stdout) + { + if (DBG_IOBUF) + log_debug ("%s: es_fclose %p\n", a->fname, f); + if (!a->keep_open) + es_fclose (f); + } + f = NULL; + xfree (a); /* We can free our context now. */ + } + + return rc; +} + + #ifdef HAVE_W32_SYSTEM /* Because network sockets are special objects under Lose32 we have to use a dedicated filter for them. */ @@ -1258,6 +1359,30 @@ iobuf_fdopen_nc (int fd, const char *mode) iobuf_t +iobuf_esopen (estream_t estream, const char *mode, int keep_open) +{ + iobuf_t a; + file_es_filter_ctx_t *fcx; + size_t len; + + a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, IOBUF_BUFFER_SIZE); + fcx = xtrymalloc (sizeof *fcx + 30); + fcx->fp = estream; + fcx->print_only_name = 1; + fcx->keep_open = keep_open; + sprintf (fcx->fname, "[fd %p]", estream); + a->filter = file_es_filter; + a->filter_ov = fcx; + file_es_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: esopen%s `%s'\n", + a->no, a->subno, keep_open? "_nc":"", fcx->fname); + return a; +} + + +iobuf_t iobuf_sockopen (int fd, const char *mode) { iobuf_t a; diff --git a/common/iobuf.h b/common/iobuf.h index 1d863fdcd..3ac4fa061 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -23,6 +23,7 @@ #include "../include/types.h" /* fixme: should be moved elsewhere. */ #include "../common/sysutils.h" +#include "../common/estream.h" #define DBG_IOBUF iobuf_debug_mode @@ -102,6 +103,7 @@ iobuf_t iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname, iobuf_t iobuf_open (const char *fname); iobuf_t iobuf_fdopen (int fd, const char *mode); iobuf_t iobuf_fdopen_nc (int fd, const char *mode); +iobuf_t iobuf_esopen (estream_t estream, const char *mode, int keep_open); iobuf_t iobuf_sockopen (int fd, const char *mode); iobuf_t iobuf_create (const char *fname); iobuf_t iobuf_append (const char *fname); diff --git a/common/keyserver.h b/common/keyserver.h index 6455e8c57..d286f7da7 100644 --- a/common/keyserver.h +++ b/common/keyserver.h @@ -1,5 +1,5 @@ /* keyserver.h - Public definitions for gpg keyserver helpers. - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -39,4 +39,26 @@ /* Must be 127 due to shell internal magic. */ #define KEYSERVER_SCHEME_NOT_FOUND 127 +/* Object to hold information pertaining to a keyserver; it further + allows to build a list of keyservers. Note that g10/options.h has + a typedef for this. FIXME: We should make use of the + parse_uri_t. */ +struct keyserver_spec +{ + struct keyserver_spec *next; + char *uri; + char *scheme; + char *auth; + char *host; + char *port; + char *path; + char *opaque; + strlist_t options; + struct + { + unsigned int direct_uri:1; + } flags; +}; + + #endif /*GNUPG_COMMON_KEYSERVER_H*/ diff --git a/common/membuf.c b/common/membuf.c index f9f82d357..8648044a7 100644 --- a/common/membuf.c +++ b/common/membuf.c @@ -1,5 +1,5 @@ /* membuf.c - A simple implementation of a dynamic buffer. - * Copyright (C) 2001, 2003, 2009 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -56,6 +56,26 @@ init_membuf_secure (membuf_t *mb, int initiallen) } +/* Shift the the content of the membuf MB by AMOUNT bytes. The next + operation will then behave as if AMOUNT bytes had not been put into + the buffer. If AMOUNT is greater than the actual accumulated + bytes, the membuf is basically reset to its initial state. */ +void +clear_membuf (membuf_t *mb, size_t amount) +{ + /* No need to clear if we are already out of core. */ + if (mb->out_of_core) + return; + if (amount >= mb->len) + mb->len = 0; + else + { + mb->len -= amount; + memmove (mb->buf, mb->buf+amount, mb->len); + } +} + + void put_membuf (membuf_t *mb, const void *buf, size_t len) { @@ -116,3 +136,26 @@ get_membuf (membuf_t *mb, size_t *len) mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */ return p; } + + +/* Peek at the membuf MB. On success a pointer to the buffer is + returned which is valid until the next operation on MB. If LEN is + not NULL the current LEN of the buffer is stored there. On error + NULL is returned and ERRNO is set. */ +const void * +peek_membuf (membuf_t *mb, size_t *len) +{ + const char *p; + + if (mb->out_of_core) + { + gpg_err_set_errno (mb->out_of_core); + return NULL; + } + + p = mb->buf; + if (len) + *len = mb->len; + return p; +} + diff --git a/common/membuf.h b/common/membuf.h index 75b506d5d..9f1a7a33b 100644 --- a/common/membuf.h +++ b/common/membuf.h @@ -39,9 +39,10 @@ typedef struct private_membuf_s membuf_t; void init_membuf (membuf_t *mb, int initiallen); void init_membuf_secure (membuf_t *mb, int initiallen); +void clear_membuf (membuf_t *mb, size_t amount); void put_membuf (membuf_t *mb, const void *buf, size_t len); void put_membuf_str (membuf_t *mb, const char *string); void *get_membuf (membuf_t *mb, size_t *len); - +const void *peek_membuf (membuf_t *mb, size_t *len); #endif /*GNUPG_COMMON_MEMBUF_H*/ diff --git a/common/util.h b/common/util.h index 44a72d90c..99d58e172 100644 --- a/common/util.h +++ b/common/util.h @@ -36,6 +36,9 @@ #ifndef GPG_ERR_MISSING_ISSUER_CERT #define GPG_ERR_MISSING_ISSUER_CERT 185 #endif +#ifndef GPG_ERR_NO_KEYSERVER +#define GPG_ERR_NO_KEYSERVER 186 +#endif #ifndef GPG_ERR_FULLY_CANCELED #define GPG_ERR_FULLY_CANCELED 198 #endif @@ -147,6 +150,7 @@ struct b64state u32 crc; int stop_seen:1; int invalid_encoding:1; + gpg_error_t lasterr; }; gpg_error_t b64enc_start (struct b64state *state, FILE *fp, const char *title); diff --git a/configure.ac b/configure.ac index ef6d2f9d7..a944e80ac 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,24 @@ show_gnupg_dirmngr_ldap_pgm="(default)" test -n "$GNUPG_DIRMNGR_LDAP_PGM" \ && show_gnupg_dirmngr_ldap_pgm="$GNUPG_DIRMNGR_LDAP_PGM" +# +# On some platforms gpg2 is usually installed as gpg without using a +# symlink. For correct operation of gpgconf it needs to know the +# installed name of gpg. This option sets "gpg2"'s installed name to +# just "gpg". Note that it might be required to rename gpg2 to gpg +# manually after the build process. +# +AC_ARG_ENABLE(gpg2-is-gpg, + AC_HELP_STRING([--enable-gpg2-is-gpg],[Set installed name of gpg2 to gpg]), + gpg2_is_gpg=$enableval) +if test "$gpg2_is_gpg" = "yes"; then + name_of_installed_gpg=gpg +else + name_of_installed_gpg=gpg2 +fi +AC_DEFINE_UNQUOTED(NAME_OF_INSTALLED_GPG, "$name_of_installed_gpg", + [The name of the installed GPG tool]) + # Some folks want to use only the agent from this packet. Make it # easier for them by providing the configure option @@ -1679,9 +1697,6 @@ agent/Makefile scd/Makefile g13/Makefile dirmngr/Makefile -keyserver/Makefile -keyserver/gpg2keys_mailto -keyserver/gpg2keys_test tools/gpg-zip tools/Makefile doc/Makefile @@ -1689,6 +1704,11 @@ tests/Makefile tests/openpgp/Makefile tests/pkits/Makefile ]) +#keyserver/Makefile +#keyserver/gpg2keys_mailto +#keyserver/gpg2keys_test + + AC_OUTPUT diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 2c208755d..39df05d0b 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,3 +1,20 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + * server.c (release_ctrl_keyservers): New. + (cmd_keyserver, cmd_ks_seach, cmd_ks_get, cmd_ks_put): New. + * dirmngr.h (uri_item_t): New. + (struct server_control_s): Add field KEYSERVERS. + * ks-engine-hkp.c: New. + * ks-engine.h: New. + * ks-action.c, ks-action.h: New. + * server.c: Include ks-action.h. + (cmd_ks_search): New. + * Makefile.am (dirmngr_SOURCES): Add new files. + +2011-01-19 Werner Koch <wk@g10code.com> + + * dirmngr.c (main): Use es_printf for --gpgconf-list. + 2010-12-14 Werner Koch <wk@g10code.com> * cdb.h (struct cdb) [W32]: Add field CDB_MAPPING. @@ -1488,7 +1505,8 @@ [Update after merge with GnuPG: see ./ChangeLog.1] - Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 g10 Code GmbH + Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011 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 diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index 128d7c383..79acae9f7 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -49,7 +49,8 @@ noinst_HEADERS = dirmngr.h crlcache.h crlfetch.h misc.h dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \ ldapserver.h ldapserver.c certcache.c certcache.h \ cdb.h cdblib.c ldap.c misc.c dirmngr-err.h w32-ldap-help.h \ - ocsp.c ocsp.h validate.c validate.h ldap-wrapper.h $(ldap_url) + ocsp.c ocsp.h validate.c validate.h ldap-wrapper.h $(ldap_url) \ + ks-action.c ks-action.h ks-engine.h ks-engine-hkp.c if USE_LDAPWRAPPER dirmngr_SOURCES += ldap-wrapper.c diff --git a/dirmngr/crlfetch.c b/dirmngr/crlfetch.c index 83897a698..057742389 100644 --- a/dirmngr/crlfetch.c +++ b/dirmngr/crlfetch.c @@ -160,7 +160,7 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader) *reader = NULL; once_more: - err = http_parse_uri (&uri, url); + err = http_parse_uri (&uri, url, 0); http_release_parsed_uri (uri); if (err && url && !strncmp (url, "https:", 6)) { @@ -172,7 +172,7 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader) if (free_this) { strcpy (stpcpy (free_this,"http:"), url+6); - err = http_parse_uri (&uri, free_this); + err = http_parse_uri (&uri, free_this, 0); http_release_parsed_uri (uri); if (!err) { diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 9b06851bd..ae922fa31 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -1019,7 +1019,7 @@ main (int argc, char **argv) start of the dirmngr. */ #ifdef HAVE_W32_SYSTEM pid = getpid (); - printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid); + es_printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid); #else pid = pth_fork (); if (pid == (pid_t)-1) @@ -1051,11 +1051,11 @@ main (int argc, char **argv) if (csh_style) { *strchr (infostr, '=') = ' '; - printf ( "setenv %s\n", infostr); + es_printf ( "setenv %s\n", infostr); } else { - printf ( "%s; export DIRMNGR_INFO;\n", infostr); + es_printf ( "%s; export DIRMNGR_INFO;\n", infostr); } free (infostr); exit (0); @@ -1220,15 +1220,15 @@ main (int argc, char **argv) "dirmngr.conf", NULL ); filename = percent_escape (opt.config_filename, NULL); - printf ("gpgconf-dirmngr.conf:%lu:\"%s\n", + es_printf ("gpgconf-dirmngr.conf:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, filename); xfree (filename); - printf ("verbose:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("quiet:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("debug-level:%lu:\"none\n", flags | GC_OPT_FLAG_DEFAULT); - printf ("log-file:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("force:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("verbose:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("quiet:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("debug-level:%lu:\"none\n", flags | GC_OPT_FLAG_DEFAULT); + es_printf ("log-file:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("force:%lu:\n", flags | GC_OPT_FLAG_NONE); /* --csh and --sh are mutually exclusive, something we can not express in GPG Conf. --options is only usable from the @@ -1241,34 +1241,34 @@ main (int argc, char **argv) "ldapservers.conf":"dirmngr_ldapservers.conf", NULL); filename_esc = percent_escape (filename, NULL); - printf ("ldapserverlist-file:%lu:\"%s\n", flags | GC_OPT_FLAG_DEFAULT, + es_printf ("ldapserverlist-file:%lu:\"%s\n", flags | GC_OPT_FLAG_DEFAULT, filename_esc); xfree (filename_esc); xfree (filename); - printf ("ldaptimeout:%lu:%u\n", + es_printf ("ldaptimeout:%lu:%u\n", flags | GC_OPT_FLAG_DEFAULT, DEFAULT_LDAP_TIMEOUT); - printf ("max-replies:%lu:%u\n", + es_printf ("max-replies:%lu:%u\n", flags | GC_OPT_FLAG_DEFAULT, DEFAULT_MAX_REPLIES); - printf ("allow-ocsp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ocsp-responder:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ocsp-signer:%lu:\n", flags | GC_OPT_FLAG_NONE); - - printf ("faked-system-time:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("no-greeting:%lu:\n", flags | GC_OPT_FLAG_NONE); - - printf ("disable-http:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("disable-ldap:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("honor-http-proxy:%lu\n", flags | GC_OPT_FLAG_NONE); - printf ("http-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("only-ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-ldap-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-http-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-ocsp-service-url:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("allow-ocsp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ocsp-responder:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ocsp-signer:%lu:\n", flags | GC_OPT_FLAG_NONE); + + es_printf ("faked-system-time:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("no-greeting:%lu:\n", flags | GC_OPT_FLAG_NONE); + + es_printf ("disable-http:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("disable-ldap:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("honor-http-proxy:%lu\n", flags | GC_OPT_FLAG_NONE); + es_printf ("http-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("only-ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ldap-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-http-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ocsp-service-url:%lu:\n", flags | GC_OPT_FLAG_NONE); /* Note: The next one is to fix a typo in gpgconf - should be removed eventually. */ - printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE); } cleanup (); return !!rc; diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h index 01478a64f..1ba90b8ed 100644 --- a/dirmngr/dirmngr.h +++ b/dirmngr/dirmngr.h @@ -32,7 +32,7 @@ #include "../common/membuf.h" #include "../common/sysutils.h" /* (gnupg_fd_t) */ #include "../common/i18n.h" - +#include "../common/http.h" /* (parsed_uri_t) */ /* This objects keeps information about a particular LDAP server and is used as item of a single linked list of servers. */ @@ -49,6 +49,17 @@ struct ldap_server_s typedef struct ldap_server_s *ldap_server_t; +/* This objects is used to build a list of URI consisting of the + original and the parsed URI. */ +struct uri_item_s +{ + struct uri_item_s *next; + parsed_uri_t parsed_uri; /* The broken down URI. */ + char uri[1]; /* The original URI. */ +}; +typedef struct uri_item_s *uri_item_t; + + /* A list of fingerprints. */ struct fingerprint_list_s; typedef struct fingerprint_list_s *fingerprint_list_t; @@ -163,6 +174,7 @@ struct server_control_s response. */ int audit_events; /* Send audit events to client. */ + uri_item_t keyservers; /* List of keyservers. */ }; diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c new file mode 100644 index 000000000..fd2a2b568 --- /dev/null +++ b/dirmngr/ks-action.c @@ -0,0 +1,183 @@ +/* ks-action.c - OpenPGP keyserver actions + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "dirmngr.h" +#include "misc.h" +#include "ks-engine.h" +#include "ks-action.h" + + +/* Copy all data from IN to OUT. */ +static gpg_error_t +copy_stream (estream_t in, estream_t out) +{ + char buffer[512]; + size_t nread; + + while (!es_read (in, buffer, sizeof buffer, &nread)) + { + if (!nread) + return 0; /* EOF */ + if (es_write (out, buffer, nread, NULL)) + break; + + } + return gpg_error_from_syserror (); +} + + + +/* Search all configured keyservers for keys matching PATTERNS and + write the result to the provided output stream. */ +gpg_error_t +ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp) +{ + gpg_error_t err = 0; + int any = 0; + uri_item_t uri; + estream_t infp; + + if (!patterns) + return gpg_error (GPG_ERR_NO_USER_ID); + + /* FIXME: We only take care of the first pattern. To fully support + multiple patterns we might either want to run several queries in + parallel and merge them. We also need to decide what to do with + errors - it might not be the best idea to ignore an error from + one server and silently continue with another server. For now we + stop at the first error. */ + for (uri = ctrl->keyservers; !err && uri; uri = uri->next) + { + if (uri->parsed_uri->is_http) + { + any = 1; + err = ks_hkp_search (ctrl, uri->parsed_uri, patterns->d, &infp); + if (!err) + { + err = copy_stream (infp, outfp); + es_fclose (infp); + break; + } + } + } + + if (!any) + err = gpg_error (GPG_ERR_NO_KEYSERVER); + return err; +} + + +/* Get the requested keys (matching PATTERNS) using all configured + keyservers and write the result to the provided output stream. */ +gpg_error_t +ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp) +{ + gpg_error_t err = 0; + gpg_error_t first_err = 0; + int any = 0; + strlist_t sl; + uri_item_t uri; + estream_t infp; + + if (!patterns) + return gpg_error (GPG_ERR_NO_USER_ID); + + /* FIXME: We only take care of the first keyserver. To fully + support multiple keyservers we need to track the result for each + pattern and use the next keyserver if one key was not found. The + keyservers might not all be fully synced thus it is not clear + whether the first keyserver has the freshest copy of the key. + Need to think about a better strategy. */ + for (uri = ctrl->keyservers; !err && uri; uri = uri->next) + { + if (uri->parsed_uri->is_http) + { + any = 1; + for (sl = patterns; !err && sl; sl = sl->next) + { + err = ks_hkp_get (ctrl, uri->parsed_uri, sl->d, &infp); + if (err) + { + /* It is possible that a server does not carry a + key, thus we only save the error and continue + with the next pattern. FIXME: It is an open + question how to return such an error condition to + the caller. */ + first_err = err; + err = 0; + } + else + { + err = copy_stream (infp, outfp); + /* Reading from the keyserver should nver fail, thus + return this error. */ + es_fclose (infp); + infp = NULL; + } + } + } + } + + if (!any) + err = gpg_error (GPG_ERR_NO_KEYSERVER); + else if (!err && first_err) + err = first_err; /* fixme: Do we really want to do that? */ + return err; +} + + + +/* Send an OpenPGP key to all keyservers. The key in {DATA,DATALEN} + is expected in OpenPGP binary transport format. */ +gpg_error_t +ks_action_put (ctrl_t ctrl, const void *data, size_t datalen) +{ + gpg_error_t err = 0; + gpg_error_t first_err = 0; + int any = 0; + uri_item_t uri; + + for (uri = ctrl->keyservers; !err && uri; uri = uri->next) + { + if (uri->parsed_uri->is_http) + { + any = 1; + err = ks_hkp_put (ctrl, uri->parsed_uri, data, datalen); + if (err) + { + first_err = err; + err = 0; + } + } + } + + if (!any) + err = gpg_error (GPG_ERR_NO_KEYSERVER); + else if (!err && first_err) + err = first_err; /* fixme: Do we really want to do that? */ + return err; +} + diff --git a/dirmngr/ks-action.h b/dirmngr/ks-action.h new file mode 100644 index 000000000..b3bd3fc46 --- /dev/null +++ b/dirmngr/ks-action.h @@ -0,0 +1,28 @@ +/* ks-action.h - OpenPGP keyserver actions definitions + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef DIRMNGR_KS_ACTION_H +#define DIRMNGR_KS_ACTION_H 1 + +gpg_error_t ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp); +gpg_error_t ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp); +gpg_error_t ks_action_put (ctrl_t ctrl, const void *data, size_t datalen); + + +#endif /*DIRMNGR_KS_ACTION_H*/ diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c new file mode 100644 index 000000000..e25900ae1 --- /dev/null +++ b/dirmngr/ks-engine-hkp.c @@ -0,0 +1,558 @@ +/* ks-engine-hkp.c - HKP keyserver engine + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "dirmngr.h" +#include "misc.h" +#include "userids.h" +#include "ks-engine.h" + +/* To match the behaviour of our old gpgkeys helper code we escape + more characters than actually needed. */ +#define EXTRA_ESCAPE_CHARS "@!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~" + +/* How many redirections do we allow. */ +#define MAX_REDIRECTS 2 + + +/* Send an HTTP request. On success returns an estream object at + R_FP. HOSTPORTSTR is only used for diagnostics. If POST_CB is not + NULL a post request is used and that callback is called to allow + writing the post data. */ +static gpg_error_t +send_request (ctrl_t ctrl, const char *request, const char *hostportstr, + gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value, + estream_t *r_fp) +{ + gpg_error_t err; + http_t http = NULL; + int redirects_left = MAX_REDIRECTS; + estream_t fp = NULL; + char *request_buffer = NULL; + + *r_fp = NULL; + once_more: + err = http_open (&http, + post_cb? HTTP_REQ_POST : HTTP_REQ_GET, + request, + /* fixme: AUTH */ NULL, + 0, + /* fixme: proxy*/ NULL, + NULL, NULL, + /*FIXME curl->srvtag*/NULL); + if (!err) + { + fp = http_get_write_ptr (http); + /* Avoid caches to get the most recent copy of the key. We set + both the Pragma and Cache-Control versions of the header, so + we're good with both HTTP 1.0 and 1.1. */ + es_fputs ("Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n", fp); + if (post_cb) + err = post_cb (post_cb_value, http); + if (!err) + { + http_start_data (http); + if (es_ferror (fp)) + err = gpg_error_from_syserror (); + } + } + if (err) + { + /* Fixme: After a redirection we show the old host name. */ + log_error (_("error connecting to `%s': %s\n"), + hostportstr, gpg_strerror (err)); + goto leave; + } + + /* Wait for the response. */ + dirmngr_tick (ctrl); + err = http_wait_response (http); + if (err) + { + log_error (_("error reading HTTP response for `%s': %s\n"), + hostportstr, gpg_strerror (err)); + goto leave; + } + + switch (http_get_status_code (http)) + { + case 200: + err = 0; + break; /* Success. */ + + case 301: + case 302: + { + const char *s = http_get_header (http, "Location"); + + log_info (_("URL `%s' redirected to `%s' (%u)\n"), + request, s?s:"[none]", http_get_status_code (http)); + if (s && *s && redirects_left-- ) + { + xfree (request_buffer); + request_buffer = xtrystrdup (s); + if (request_buffer) + { + request = request_buffer; + http_close (http, 0); + http = NULL; + goto once_more; + } + err = gpg_error_from_syserror (); + } + else + err = gpg_error (GPG_ERR_NO_DATA); + log_error (_("too many redirections\n")); + } + goto leave; + + default: + log_error (_("error accessing `%s': http status %u\n"), + request, http_get_status_code (http)); + err = gpg_error (GPG_ERR_NO_DATA); + goto leave; + } + + fp = http_get_read_ptr (http); + if (!fp) + { + err = gpg_error (GPG_ERR_BUG); + goto leave; + } + + /* Return the read stream and close the HTTP context. */ + *r_fp = fp; + http_close (http, 1); + http = NULL; + + leave: + http_close (http, 0); + xfree (request_buffer); + return err; +} + + +static gpg_error_t +armor_data (char **r_string, const void *data, size_t datalen) +{ + gpg_error_t err; + struct b64state b64state; + estream_t fp; + long length; + char *buffer; + size_t nread; + + *r_string = NULL; + + fp = es_fopenmem (0, "rw"); + if (!fp) + return gpg_error_from_syserror (); + + if ((err=b64enc_start_es (&b64state, fp, "PGP PUBLIC KEY BLOCK")) + || (err=b64enc_write (&b64state, data, datalen)) + || (err = b64enc_finish (&b64state))) + { + es_fclose (fp); + return err; + } + + /* FIXME: To avoid the extra buffer allocation estream should + provide a function to snatch the internal allocated memory from + such a memory stream. */ + length = es_ftell (fp); + if (length < 0) + { + err = gpg_error_from_syserror (); + es_fclose (fp); + return err; + } + + buffer = xtrymalloc (length+1); + if (!buffer) + { + err = gpg_error_from_syserror (); + es_fclose (fp); + return err; + } + + es_rewind (fp); + if (es_read (fp, buffer, length, &nread)) + { + err = gpg_error_from_syserror (); + es_fclose (fp); + return err; + } + buffer[nread] = 0; + es_fclose (fp); + + *r_string = buffer; + return 0; +} + + + + +/* Search the keyserver identified by URI for keys matching PATTERN. + On success R_FP has an open stream to read the data. */ +gpg_error_t +ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, + estream_t *r_fp) +{ + gpg_error_t err; + KEYDB_SEARCH_DESC desc; + char fprbuf[2+40+1]; + const char *scheme; + char portstr[10]; + char *hostport = NULL; + char *request = NULL; + estream_t fp = NULL; + + *r_fp = NULL; + + /* Remove search type indicator and adjust PATTERN accordingly. + Note that HKP keyservers like the 0x to be present when searching + by keyid. We need to re-format the fingerprint and keyids so to + remove the gpg specific force-use-of-this-key flag ("!"). */ + err = classify_user_id (pattern, &desc); + if (err) + return err; + switch (desc.mode) + { + case KEYDB_SEARCH_MODE_EXACT: + case KEYDB_SEARCH_MODE_SUBSTR: + case KEYDB_SEARCH_MODE_MAIL: + case KEYDB_SEARCH_MODE_MAILSUB: + pattern = desc.u.name; + break; + case KEYDB_SEARCH_MODE_SHORT_KID: + snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]); + pattern = fprbuf; + break; + case KEYDB_SEARCH_MODE_LONG_KID: + snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX", + (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]); + pattern = fprbuf; + break; + case KEYDB_SEARCH_MODE_FPR16: + bin2hex (desc.u.fpr, 16, fprbuf); + pattern = fprbuf; + break; + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + bin2hex (desc.u.fpr, 20, fprbuf); + pattern = fprbuf; + break; + default: + return gpg_error (GPG_ERR_INV_USER_ID); + } + + /* Map scheme and port. */ + if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https")) + { + scheme = "https"; + strcpy (portstr, "443"); + } + else /* HKP or HTTP. */ + { + scheme = "http"; + strcpy (portstr, "11371"); + } + if (uri->port) + snprintf (portstr, sizeof portstr, "%hu", uri->port); + else + {} /*fixme_do_srv_lookup ()*/ + + /* Build the request string. */ + { + char *searchkey; + + hostport = strconcat (scheme, "://", + *uri->host? uri->host: "localhost", + ":", portstr, NULL); + if (!hostport) + { + err = gpg_error_from_syserror (); + goto leave; + } + + searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS); + if (!searchkey) + { + err = gpg_error_from_syserror (); + goto leave; + } + + request = strconcat (hostport, + "/pks/lookup?op=index&options=mr&search=", + searchkey, + NULL); + xfree (searchkey); + if (!request) + { + err = gpg_error_from_syserror (); + goto leave; + } + } + + /* Send the request. */ + err = send_request (ctrl, request, hostport, NULL, NULL, &fp); + if (err) + goto leave; + + /* Start reading the response. */ + { + int c = es_getc (fp); + if (c == -1) + { + err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF); + log_error ("error reading response: %s\n", gpg_strerror (err)); + goto leave; + } + if (c == '<') + { + /* The document begins with a '<', assume it's a HTML + response, which we don't support. */ + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + goto leave; + } + es_ungetc (c, fp); + } + + /* Return the read stream. */ + *r_fp = fp; + fp = NULL; + + leave: + es_fclose (fp); + xfree (request); + xfree (hostport); + return err; +} + + +/* Get the key described key the KEYSPEC string from the keyserver + identified by URI. On success R_FP has an open stream to read the + data. */ +gpg_error_t +ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) +{ + gpg_error_t err; + KEYDB_SEARCH_DESC desc; + char kidbuf[8+1]; + const char *scheme; + char portstr[10]; + char *hostport = NULL; + char *request = NULL; + estream_t fp = NULL; + + *r_fp = NULL; + + /* Remove search type indicator and adjust PATTERN accordingly. + Note that HKP keyservers like the 0x to be present when searching + by keyid. We need to re-format the fingerprint and keyids so to + remove the gpg specific force-use-of-this-key flag ("!"). */ + err = classify_user_id (keyspec, &desc); + if (err) + return err; + switch (desc.mode) + { + case KEYDB_SEARCH_MODE_SHORT_KID: + case KEYDB_SEARCH_MODE_LONG_KID: + snprintf (kidbuf, sizeof kidbuf, "%08lX", (ulong)desc.u.kid[1]); + break; + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + /* This is a v4 fingerprint. Take the last 8 hex digits from + the fingerprint which is the expected short keyid. */ + bin2hex (desc.u.fpr+16, 4, kidbuf); + break; + + case KEYDB_SEARCH_MODE_FPR16: + log_error ("HKP keyserver do not support v3 fingerprints\n"); + default: + return gpg_error (GPG_ERR_INV_USER_ID); + } + + /* Map scheme and port. */ + if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https")) + { + scheme = "https"; + strcpy (portstr, "443"); + } + else /* HKP or HTTP. */ + { + scheme = "http"; + strcpy (portstr, "11371"); + } + if (uri->port) + snprintf (portstr, sizeof portstr, "%hu", uri->port); + else + {} /*fixme_do_srv_lookup ()*/ + + /* Build the request string. */ + { + hostport = strconcat (scheme, "://", + *uri->host? uri->host: "localhost", + ":", portstr, NULL); + if (!hostport) + { + err = gpg_error_from_syserror (); + goto leave; + } + + request = strconcat (hostport, + "/pks/lookup?op=get&options=mr&search=0x", + kidbuf, + NULL); + if (!request) + { + err = gpg_error_from_syserror (); + goto leave; + } + } + + /* Send the request. */ + err = send_request (ctrl, request, hostport, NULL, NULL, &fp); + if (err) + goto leave; + + /* Return the read stream and close the HTTP context. */ + *r_fp = fp; + fp = NULL; + + leave: + es_fclose (fp); + xfree (request); + xfree (hostport); + return err; +} + + + + +/* Callback parameters for put_post_cb. */ +struct put_post_parm_s +{ + char *datastring; +}; + + +/* Helper for ks_hkp_put. */ +static gpg_error_t +put_post_cb (void *opaque, http_t http) +{ + struct put_post_parm_s *parm = opaque; + gpg_error_t err = 0; + estream_t fp; + size_t len; + + fp = http_get_write_ptr (http); + len = strlen (parm->datastring); + + es_fprintf (fp, + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */); + http_start_data (http); + if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL)) + err = gpg_error_from_syserror (); + return err; +} + + +/* Send the key in {DATA,DATALEN} to the keyserver identified by URI. */ +gpg_error_t +ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) +{ + gpg_error_t err; + const char *scheme; + char portstr[10]; + char *hostport = NULL; + char *request = NULL; + estream_t fp = NULL; + struct put_post_parm_s parm; + char *armored = NULL; + + parm.datastring = NULL; + + /* Map scheme and port. */ + if (!strcmp (uri->scheme,"hkps") || !strcmp (uri->scheme,"https")) + { + scheme = "https"; + strcpy (portstr, "443"); + } + else /* HKP or HTTP. */ + { + scheme = "http"; + strcpy (portstr, "11371"); + } + if (uri->port) + snprintf (portstr, sizeof portstr, "%hu", uri->port); + else + {} /*fixme_do_srv_lookup ()*/ + + err = armor_data (&armored, data, datalen); + if (err) + goto leave; + + parm.datastring = http_escape_string (armored, EXTRA_ESCAPE_CHARS); + if (!parm.datastring) + { + err = gpg_error_from_syserror (); + goto leave; + } + xfree (armored); + armored = NULL; + + /* Build the request string. */ + hostport = strconcat (scheme, "://", + *uri->host? uri->host: "localhost", + ":", portstr, NULL); + if (!hostport) + { + err = gpg_error_from_syserror (); + goto leave; + } + + request = strconcat (hostport, "/pks/add", NULL); + if (!request) + { + err = gpg_error_from_syserror (); + goto leave; + } + + /* Send the request. */ + err = send_request (ctrl, request, hostport, put_post_cb, &parm, &fp); + if (err) + goto leave; + + leave: + es_fclose (fp); + xfree (parm.datastring); + xfree (armored); + xfree (request); + xfree (hostport); + return err; +} diff --git a/dirmngr/ks-engine.h b/dirmngr/ks-engine.h new file mode 100644 index 000000000..304fc4d1a --- /dev/null +++ b/dirmngr/ks-engine.h @@ -0,0 +1,36 @@ +/* ks-engine.h - Keyserver engines definitions + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef DIRMNGR_KS_ENGINE_H +#define DIRMNGR_KS_ENGINE_H 1 + +#include "../common/estream.h" +#include "../common/http.h" + +/*-- ks-engine-hkp.c --*/ +gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, + estream_t *r_fp); +gpg_error_t ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, + const char *keyspec, estream_t *r_fp); +gpg_error_t ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, + const void *data, size_t datalen); + + + +#endif /*DIRMNGR_KS_ENGINE_H*/ diff --git a/dirmngr/server.c b/dirmngr/server.c index 11ba1fb87..fc7b22989 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -1,6 +1,6 @@ /* dirmngr.c - LDAP access * Copyright (C) 2002 Klarälvdalens Datakonsult AB - * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 g10 Code GmbH + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011 g10 Code GmbH * * This file is part of DirMngr. * @@ -41,11 +41,18 @@ #include "validate.h" #include "misc.h" #include "ldap-wrapper.h" +#include "ks-action.h" /* To avoid DoS attacks we limit the size of a certificate to something reasonable. */ #define MAX_CERT_LENGTH (8*1024) +/* The same goes for OpenPGP keyblocks, but here we need to allow for + much longer blocks; a 200k keyblock is not too unusual for keys + with a lot of signatures (e.g. 0x5b0358a2). */ +#define MAX_KEYBLOCK_LENGTH (512*1024) + + #define PARM_ERROR(t) assuan_set_error (ctx, \ gpg_error (GPG_ERR_ASS_PARAMETER), (t)) #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t)) @@ -58,7 +65,7 @@ struct server_local_s /* Data used to associate an Assuan context with local server data */ assuan_context_t assuan_ctx; - /* Per-session LDAP serfver. */ + /* Per-session LDAP servers. */ ldap_server_t ldapservers; /* If this flag is set to true this dirmngr process will be @@ -94,6 +101,21 @@ get_ldapservers_from_ctrl (ctrl_t ctrl) } +/* Release all configured keyserver info from CTRL. */ +void +release_ctrl_keyservers (ctrl_t ctrl) +{ + while (ctrl->keyservers) + { + uri_item_t tmp = ctrl->keyservers->next; + http_release_parsed_uri (ctrl->keyservers->parsed_uri); + xfree (ctrl->keyservers); + ctrl->keyservers = tmp; + } +} + + + /* Helper to print a message while leaving a command. */ static gpg_error_t leave_cmd (assuan_context_t ctx, gpg_error_t err) @@ -147,7 +169,7 @@ data_line_cookie_close (void *cookie) /* Copy the % and + escaped string S into the buffer D and replace the escape sequences. Note, that it is sufficient to allocate the target string D as long as the source string S, i.e.: strlen(s)+1. - NOte further that If S contains an escaped binary nul the resulting + Note further that if S contains an escaped binary Nul the resulting string D will contain the 0 as well as all other characters but it will be impossible to know whether this is the original EOS or a copied Nul. */ @@ -1335,6 +1357,254 @@ cmd_validate (assuan_context_t ctx, char *line) return leave_cmd (ctx, err); } + +static const char hlp_keyserver[] = + "KEYSERVER [--clear] [<uri>]\n" + "\n" + "If called without arguments list all configured keyserver URLs.\n" + "If called with option \"--clear\" remove all configured keyservers\n" + "If called with an URI add this as keyserver. Note that keyservers\n" + "are configured on a per-session base. A default keyserver may already be\n" + "present, thus the \"--clear\" option must be used to get full control.\n" + "If \"--clear\" and an URI are used together the clear command is\n" + "obviously executed first. A RESET command does not change the list\n" + "of configured keyservers."; +static gpg_error_t +cmd_keyserver (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err; + int clear_flag, add_flag; + uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it + is always initialized. */ + + clear_flag = has_option (line, "--clear"); + line = skip_options (line); + add_flag = !!*line; + + if (add_flag) + { + item = xtrymalloc (sizeof *item + strlen (line)); + if (!item) + { + err = gpg_error_from_syserror (); + goto leave; + } + item->next = NULL; + item->parsed_uri = NULL; + strcpy (item->uri, line); + + err = http_parse_uri (&item->parsed_uri, line, 1); + if (err) + { + xfree (item); + goto leave; + } + } + if (clear_flag) + release_ctrl_keyservers (ctrl); + if (add_flag) + { + item->next = ctrl->keyservers; + ctrl->keyservers = item; + } + + if (!add_flag && !clear_flag) /* List configured keyservers. */ + { + uri_item_t u; + + for (u=ctrl->keyservers; u; u = u->next) + dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL); + } + err = 0; + + leave: + return leave_cmd (ctx, err); +} + + + +static const char hlp_ks_search[] = + "KS_SEARCH {<pattern>}\n" + "\n" + "Search the configured OpenPGP keyservers (see command KEYSERVER)\n" + "for keys matching PATTERN"; +static gpg_error_t +cmd_ks_search (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err; + strlist_t list, sl; + char *p; + estream_t outfp; + + /* No options for now. */ + line = skip_options (line); + + /* Break the line down into an strlist. Each pattern is + percent-plus escaped. */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + err = gpg_error_from_syserror (); + free_strlist (list); + goto leave; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + + /* Setup an output stream and perform the search. */ + outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); + if (!outfp) + err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream"); + else + { + err = ks_action_search (ctrl, list, outfp); + es_fclose (outfp); + } + + leave: + return leave_cmd (ctx, err); +} + + + +static const char hlp_ks_get[] = + "KS_GET {<pattern>}\n" + "\n" + "Get the keys matching PATTERN from the configured OpenPGP keyservers\n" + "(see command KEYSERVER). Each pattern should be a keyid or a fingerprint"; +static gpg_error_t +cmd_ks_get (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err; + strlist_t list, sl; + char *p; + estream_t outfp; + + /* No options for now. */ + line = skip_options (line); + + /* Break the line down into an strlist. Each pattern is by + definition percent-plus escaped. However we only support keyids + and fingerprints and thus the client has no need to apply the + escaping. */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + err = gpg_error_from_syserror (); + free_strlist (list); + goto leave; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + + /* Setup an output stream and perform the get. */ + outfp = es_fopencookie (ctx, "w", data_line_cookie_functions); + if (!outfp) + err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream"); + else + { + err = ks_action_get (ctrl, list, outfp); + es_fclose (outfp); + } + + leave: + return leave_cmd (ctx, err); +} + + + +static const char hlp_ks_put[] = + "KS_PUT\n" + "\n" + "Send a key to the configured OpenPGP keyservers. The actual key material\n" + "is then requested by Dirmngr using\n" + "\n" + " INQUIRE KEYBLOCK\n" + "\n" + "The client shall respond with a binary version of the keyblock. For LDAP\n" + "keyservers Dirmngr may ask for meta information of the provided keyblock\n" + "using:\n" + "\n" + " INQUIRE KEYBLOCK_INFO\n" + "\n" + "The client shall respond with a colon delimited info lines"; +static gpg_error_t +cmd_ks_put (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + gpg_error_t err; + unsigned char *value = NULL; + size_t valuelen; + unsigned char *info = NULL; + size_t infolen; + + /* No options for now. */ + line = skip_options (line); + + /* Ask for the key material. */ + err = assuan_inquire (ctx, "KEYBLOCK", + &value, &valuelen, MAX_KEYBLOCK_LENGTH); + if (err) + { + log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err)); + goto leave; + } + + if (!valuelen) /* No data returned; return a comprehensible error. */ + { + err = gpg_error (GPG_ERR_MISSING_CERT); + goto leave; + } + + /* Ask for the key meta data. Not actually needed for HKP servers + but we do it anyway test the client implementaion. */ + err = assuan_inquire (ctx, "KEYBLOCK_INFO", + &info, &infolen, MAX_KEYBLOCK_LENGTH); + if (err) + { + log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err)); + goto leave; + } + + /* Send the key. */ + err = ks_action_put (ctrl, value, valuelen); + + leave: + xfree (info); + xfree (value); + return leave_cmd (ctx, err); +} + + static const char hlp_getinfo[] = @@ -1469,6 +1739,10 @@ register_commands (assuan_context_t ctx) { "LISTCRLS", cmd_listcrls, hlp_listcrls }, { "CACHECERT", cmd_cachecert, hlp_cachecert }, { "VALIDATE", cmd_validate, hlp_validate }, + { "KEYSERVER", cmd_keyserver, hlp_keyserver }, + { "KS_SEARCH", cmd_ks_search, hlp_ks_search }, + { "KS_GET", cmd_ks_get, hlp_ks_get }, + { "KS_PUT", cmd_ks_put, hlp_ks_put }, { "GETINFO", cmd_getinfo, hlp_getinfo }, { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr }, { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr }, @@ -1487,6 +1761,7 @@ register_commands (assuan_context_t ctx) } +/* Note that we do not reset the list of configured keyservers. */ static gpg_error_t reset_notify (assuan_context_t ctx, char *line) { @@ -1681,8 +1956,8 @@ dirmngr_status (ctrl_t ctrl, const char *keyword, ...) } -/* Note, that we ignore CTRL for now but use the first connection to - send the progress info back. */ +/* Send a tick progress indicator back. Fixme: This is only does for + the currently active channel. */ gpg_error_t dirmngr_tick (ctrl_t ctrl) { diff --git a/doc/debugging.texi b/doc/debugging.texi index 7b1d068d3..c83ab1ef9 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -103,7 +103,7 @@ used. Using the keyserver debug option as in is thus often helpful. Note that the actual output depends on the backend and may change from release to release. - +@ifset gpgtwoone @item Logging on WindowsCE For development, the best logging method on WindowsCE is the use of @@ -113,7 +113,7 @@ on the given port. (@pxref{option watchgnupg --tcp}). For in the field tests it is better to make use of the logging facility provided by the @command{gpgcedev} driver (part of libassuan); this is enabled by using a log file name of @file{GPG2:}. (@pxref{option --log-file}). - +@end ifset @end itemize diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 86e192e0c..7bb54af51 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -34,7 +34,7 @@ Published by the Free Software Foundation@* Boston, MA 02110-1301 USA @end iftex -Copyright @copyright{} 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +Copyright @copyright{} 2002, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -51,8 +51,10 @@ section entitled ``Copying''. * gpg2: (gnupg). OpenPGP encryption and signing tool. * gpgsm: (gnupg). S/MIME encryption and signing tool. * gpg-agent: (gnupg). The secret key daemon. +@ifset gpgtwoone * dirmngr: (gnupg). X.509 CRL and OCSP server. * dirmngr-client: (gnupg). X.509 CRL and OCSP client. +@end ifset @end direntry @@ -124,7 +126,9 @@ the administration and the architecture. * Installation:: A short installation guide. * Invoking GPG-AGENT:: How to launch the secret key daemon. +@ifset gpgtwoone * Invoking DIRMNGR:: How to launch the CRL and OCSP daemon. +@end ifset * Invoking GPG:: Using the OpenPGP protocol. * Invoking GPGSM:: Using the S/MIME protocol. * Invoking SCDAEMON:: How to handle Smartcards. @@ -156,7 +160,9 @@ the administration and the architecture. @include instguide.texi @include gpg-agent.texi +@ifset gpgtwoone @include dirmngr.texi +@end ifset @include gpg.texi @include gpgsm.texi @include scdaemon.texi diff --git a/doc/tools.texi b/doc/tools.texi index a21f41353..c85f9e243 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -16,7 +16,9 @@ GnuPG comes with a couple of smaller tools: * gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpg-preset-passphrase:: Put a passphrase into the cache. * gpg-connect-agent:: Communicate with a running agent. +@ifset gpgtwoone * dirmngr-client:: How to use the Dirmngr client tool. +@end ifset * gpgparsemail:: Parse a mail message into an annotated format * symcryptrun:: Call a simple symmetric encryption tool. * gpg-zip:: Encrypt or sign files into an archive. @@ -1434,6 +1436,7 @@ Print a list of available control commands. @include see-also-note.texi @end ifset +@ifset gpgtwoone @c @c DIRMNGR-CLIENT @c @@ -1594,7 +1597,7 @@ Squid's @option{external_acl_type} option. @command{gpgsm}(1) @include see-also-note.texi @end ifset - +@end ifset @c @c GPGPARSEMAIL diff --git a/g10/ChangeLog b/g10/ChangeLog index 8e79587d8..4c28363a2 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,25 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + * keyserver.c: Rewrite most stuff for use with dirmngr. Get rid + of all spawn code. Work work pending. + + * export.c (export_pubkeys_buffer): New. + + * import.c (import_keys_es_stream): New. + + * call-dirmngr.c, call-dirmngr.h: New. + * gpg.h (server_control_s): Add DIRMNGR_LOCAL. + * gpg.c: Include call-dirmngr.h. + (gpg_deinit_default_ctrl): Call gpg_dirmngr_deinit_session_data. + +2011-01-06 Werner Koch <wk@g10code.com> + + * gpg.c (main): Use keyserver_spec_t. + + * options.h (struct opt): Factor definition of struct keyserver + out to ../common/keyserver.h. + (keyserver_spec_t): New. + 2011-01-21 Werner Koch <wk@g10code.com> * seskey.c (encode_md_value): Truncate the DSA hash again. @@ -11654,7 +11676,7 @@ Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) Copyright 1998,1999,2000,2001,2002,2003,2004,2005, - 2006,2007,2008,2009,2010 Free Software Foundation, Inc. + 2006,2007,2008,2009,2010,2011 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 diff --git a/g10/Makefile.am b/g10/Makefile.am index b82fe07f3..5d2470207 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -103,6 +103,7 @@ gpg2_SOURCES = gpg.c \ helptext.c \ keyserver.c \ keyserver-internal.h \ + call-dirmngr.c call-dirmngr.h \ photoid.c photoid.h \ call-agent.c call-agent.h \ card-util.c \ diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c new file mode 100644 index 000000000..f34b94b60 --- /dev/null +++ b/g10/call-dirmngr.c @@ -0,0 +1,611 @@ +/* call-dirmngr.c - GPG operations to the Dirmngr. + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif + +#include "gpg.h" +#include <assuan.h> +#include "util.h" +#include "membuf.h" +#include "options.h" +#include "i18n.h" +#include "asshelp.h" +#include "keyserver.h" +#include "call-dirmngr.h" + + +/* Parameter structure used with the KS_SEARCH command. */ +struct ks_search_parm_s +{ + gpg_error_t lasterr; /* Last error code. */ + membuf_t saveddata; /* Buffer to build complete lines. */ + char *helpbuf; /* NULL or malloced buffer. */ + size_t helpbufsize; /* Allocated size of HELPBUF. */ + gpg_error_t (*data_cb)(void*, char*); /* Callback. */ + void *data_cb_value; /* First argument for DATA_CB. */ +}; + + +/* Parameter structure used with the KS_GET command. */ +struct ks_get_parm_s +{ + estream_t memfp; +}; + + +/* Parameter structure used with the KS_PUT command. */ +struct ks_put_parm_s +{ + assuan_context_t ctx; + kbnode_t keyblock; /* The optional keyblock. */ + const void *data; /* The key in OpenPGP binary format. */ + size_t datalen; /* The length of DATA. */ +}; + + +/* Data used to associate an session with dirmngr contexts. We can't + use a simple one to one mapping because we sometimes need two + connection s to the dirmngr; for example while doing a listing and + being in a data callback we may want to retrieve a key. The local + dirmngr data takes care of this. At the end of the session the + function dirmngr_deinit_session_data is called bu gpg.c to cleanup + these resources. Note that gpg.h defines a typedef dirmngr_local_t + for this structure. */ +struct dirmngr_local_s +{ + /* Link to other contexts which are used simultaneously. */ + struct dirmngr_local_s *next; + + /* The active Assuan context. */ + assuan_context_t ctx; + + /* Flag set to true while an operation is running on CTX. */ + int is_active; +}; + + + +/* Deinitialize all session data of dirmngr pertaining to CTRL. */ +void +gpg_dirmngr_deinit_session_data (ctrl_t ctrl) +{ + dirmngr_local_t dml; + + while ((dml = ctrl->dirmngr_local)) + { + ctrl->dirmngr_local = dml->next; + if (dml->is_active) + log_error ("oops: trying to cleanup an active dirmngr context\n"); + else + assuan_release (dml->ctx); + xfree (dml); + } +} + + +/* Try to connect to the Dirmngr via a socket or fork it off if + possible. Handle the server's initial greeting and set global + options. */ +static gpg_error_t +create_context (ctrl_t ctrl, assuan_context_t *r_ctx) +{ + gpg_error_t err; + assuan_context_t ctx; + + *r_ctx = NULL; + err = start_new_dirmngr (&ctx, + GPG_ERR_SOURCE_DEFAULT, + opt.homedir, + NULL, + opt.verbose, DBG_ASSUAN, + NULL /*gpg_status2*/, ctrl); + if (!err) + { + keyserver_spec_t ksi; + + /* Tell the dirmngr that we want to collect audit event. */ + /* err = assuan_transact (agent_ctx, "OPTION audit-events=1", */ + /* NULL, NULL, NULL, NULL, NULL, NULL); */ + + /* Set all configured keyservers. We clear existing keyservers + so that any keyserver configured in GPG overrides keyservers + possibly configured in Dirmngr. */ + for (ksi = opt.keyserver; !err && ksi; ksi = ksi->next) + { + char *line; + + line = xtryasprintf ("KEYSERVER%s %s", + ksi == opt.keyserver? " --clear":"", ksi->uri); + if (!line) + err = gpg_error_from_syserror (); + else + { + err = assuan_transact (ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + xfree (line); + } + } + } + + if (err) + assuan_release (ctx); + else + { + /* audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err); */ + *r_ctx = ctx; + } + + return err; +} + + +/* Get a context for accessing dirmngr. If no context is available a + new one is created and - if requred - dirmngr started. On success + an assuan context is stored at R_CTX. This Context may only be + released by means of close_context. Note that NULL is stored at + R_CTX on error. */ +static gpg_error_t +open_context (ctrl_t ctrl, assuan_context_t *r_ctx) +{ + gpg_error_t err; + dirmngr_local_t dml; + + *r_ctx = NULL; + for (;;) + { + for (dml = ctrl->dirmngr_local; dml && dml->is_active; dml = dml->next) + ; + if (dml) + { + /* Found an inactive local session - return that. */ + assert (!dml->is_active); + dml->is_active = 1; + *r_ctx = dml->ctx; + return 0; + } + + dml = xtrycalloc (1, sizeof *dml); + if (!dml) + return gpg_error_from_syserror (); + err = create_context (ctrl, &dml->ctx); + if (err) + { + xfree (dml); + return err; + } + /* To be on the Pth thread safe site we need to add it to a + list; this is far easier than to have a lock for this + function. It should not happen anyway but the code is free + because we need it for the is_active check above. */ + dml->next = ctrl->dirmngr_local; + ctrl->dirmngr_local = dml; + } +} + + +/* Close the assuan context CTX or return it to a pool of unused + contexts. If CTX is NULL, the function does nothing. */ +static void +close_context (ctrl_t ctrl, assuan_context_t ctx) +{ + dirmngr_local_t dml; + + if (!ctx) + return; + + for (dml = ctrl->dirmngr_local; dml; dml = dml->next) + { + if (dml->ctx == ctx) + { + if (!dml->is_active) + log_fatal ("closing inactive dirmngr context %p\n", ctx); + dml->is_active = 0; + return; + } + } + log_fatal ("closing unknown dirmngr ctx %p\n", ctx); +} + + + +/* Data callback for the KS_SEARCH command. */ +static gpg_error_t +ks_search_data_cb (void *opaque, const void *data, size_t datalen) +{ + gpg_error_t err = 0; + struct ks_search_parm_s *parm = opaque; + const char *line, *s; + size_t rawlen, linelen; + char fixedbuf[256]; + + if (parm->lasterr) + return 0; + + if (!data) + return 0; /* Ignore END commands. */ + + put_membuf (&parm->saveddata, data, datalen); + + again: + line = peek_membuf (&parm->saveddata, &rawlen); + if (!line) + { + parm->lasterr = gpg_error_from_syserror (); + return parm->lasterr; /* Tell the server about our problem. */ + } + if ((s = memchr (line, '\n', rawlen))) + { + linelen = s - line; /* That is the length excluding the LF. */ + if (linelen + 1 < sizeof fixedbuf) + { + /* We can use the static buffer. */ + memcpy (fixedbuf, line, linelen); + fixedbuf[linelen] = 0; + if (linelen && fixedbuf[linelen-1] == '\r') + fixedbuf[linelen-1] = 0; + err = parm->data_cb (parm->data_cb_value, fixedbuf); + } + else + { + if (linelen + 1 >= parm->helpbufsize) + { + xfree (parm->helpbuf); + parm->helpbufsize = linelen + 1 + 1024; + parm->helpbuf = xtrymalloc (parm->helpbufsize); + if (!parm->helpbuf) + { + parm->lasterr = gpg_error_from_syserror (); + return parm->lasterr; + } + } + memcpy (parm->helpbuf, line, linelen); + parm->helpbuf[linelen] = 0; + if (linelen && parm->helpbuf[linelen-1] == '\r') + parm->helpbuf[linelen-1] = 0; + err = parm->data_cb (parm->data_cb_value, parm->helpbuf); + } + if (err) + parm->lasterr = err; + else + { + clear_membuf (&parm->saveddata, linelen+1); + goto again; /* There might be another complete line. */ + } + } + + return err; +} + + +/* Run the KS_SEARCH command using the search string SEARCHSTR. All + data lines are passed to the CB function. That function is called + with CB_VALUE as its first argument and the decoded data line as + second argument. The callback function may modify the data line + and it is guaranteed that this data line is a complete line with a + terminating 0 character but without the linefeed. NULL is passed + to the callback to indicate EOF. */ +gpg_error_t +gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr, + gpg_error_t (*cb)(void*, char *), void *cb_value) +{ + gpg_error_t err; + assuan_context_t ctx; + struct ks_search_parm_s parm; + char line[ASSUAN_LINELENGTH]; + + err = open_context (ctrl, &ctx); + if (err) + return err; + + { + char *escsearchstr = percent_plus_escape (searchstr); + if (!escsearchstr) + { + err = gpg_error_from_syserror (); + close_context (ctrl, ctx); + return err; + } + snprintf (line, sizeof line, "KS_SEARCH -- %s", escsearchstr); + xfree (escsearchstr); + } + + memset (&parm, 0, sizeof parm); + init_membuf (&parm.saveddata, 1024); + parm.data_cb = cb; + parm.data_cb_value = cb_value; + + err = assuan_transact (ctx, line, ks_search_data_cb, &parm, + NULL, NULL, NULL, NULL); + if (!err) + err = cb (cb_value, NULL); /* Send EOF. */ + + xfree (get_membuf (&parm.saveddata, NULL)); + xfree (parm.helpbuf); + + close_context (ctrl, ctx); + return err; +} + + + +/* Data callback for the KS_GET command. */ +static gpg_error_t +ks_get_data_cb (void *opaque, const void *data, size_t datalen) +{ + gpg_error_t err = 0; + struct ks_get_parm_s *parm = opaque; + size_t nwritten; + + if (!data) + return 0; /* Ignore END commands. */ + + if (es_write (parm->memfp, data, datalen, &nwritten)) + err = gpg_error_from_syserror (); + + return err; +} + + +/* Run the KS_GET command using the patterns in the array PATTERN. On + success an estream object is returned to retrieve the keys. On + error an error code is returned and NULL stored at R_FP. + + The pattern may only use search specification which a keyserver can + use to retriev keys. Because we know the format of the pattern we + don't need to escape the patterns before sending them to the + server. + + If there are too many patterns the function returns an error. That + could be fixed by issuing several search commands or by + implementing a different interface. However with long keyids we + are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once. */ +gpg_error_t +gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern, estream_t *r_fp) +{ + gpg_error_t err; + assuan_context_t ctx; + struct ks_get_parm_s parm; + char *line = NULL; + size_t linelen; + membuf_t mb; + int idx; + + memset (&parm, 0, sizeof parm); + + *r_fp = NULL; + + err = open_context (ctrl, &ctx); + if (err) + return err; + + /* Lump all patterns into one string. */ + init_membuf (&mb, 1024); + put_membuf_str (&mb, "KS_GET --"); + for (idx=0; pattern[idx]; idx++) + { + put_membuf (&mb, " ", 1); /* Append Delimiter. */ + put_membuf_str (&mb, pattern[idx]); + } + put_membuf (&mb, "", 1); /* Append Nul. */ + line = get_membuf (&mb, &linelen); + if (!line) + { + err = gpg_error_from_syserror (); + goto leave; + } + if (linelen + 2 >= ASSUAN_LINELENGTH) + { + err = gpg_error (GPG_ERR_TOO_MANY); + goto leave; + } + + parm.memfp = es_fopenmem (0, "rwb"); + if (!parm.memfp) + { + err = gpg_error_from_syserror (); + goto leave; + } + err = assuan_transact (ctx, line, ks_get_data_cb, &parm, + NULL, NULL, NULL, NULL); + if (err) + goto leave; + + es_rewind (parm.memfp); + *r_fp = parm.memfp; + parm.memfp = NULL; + + leave: + es_fclose (parm.memfp); + xfree (line); + close_context (ctrl, ctx); + return err; +} + + + +/* Handle the KS_PUT inquiries. */ +static gpg_error_t +ks_put_inq_cb (void *opaque, const char *line) +{ + struct ks_put_parm_s *parm = opaque; + gpg_error_t err = 0; + + if (!strncmp (line, "KEYBLOCK", 8) && (line[8] == ' ' || !line[8])) + { + if (parm->data) + err = assuan_send_data (parm->ctx, parm->data, parm->datalen); + } + else if (!strncmp (line, "KEYBLOCK_INFO", 13) && (line[13]==' ' || !line[13])) + { + kbnode_t node; + estream_t fp; + + /* Parse the keyblock and send info lines back to the server. */ + fp = es_fopenmem (0, "rw"); + if (!fp) + err = gpg_error_from_syserror (); + + for (node = parm->keyblock; !err && node; node=node->next) + { + switch(node->pkt->pkttype) + { + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + { + PKT_public_key *pk = node->pkt->pkt.public_key; + + keyid_from_pk (pk, NULL); + + es_fprintf (fp, "%s:%08lX%08lX:%u:%u:%u:%u:%s%s:\n", + node->pkt->pkttype==PKT_PUBLIC_KEY? "pub" : "sub", + (ulong)pk->keyid[0], (ulong)pk->keyid[1], + pk->pubkey_algo, + nbits_from_pk (pk), + pk->timestamp, + pk->expiredate, + pk->flags.revoked? "r":"", + pk->has_expired? "e":""); + } + break; + + case PKT_USER_ID: + { + PKT_user_id *uid = node->pkt->pkt.user_id; + int r; + + if (!uid->attrib_data) + { + es_fprintf (fp, "uid:"); + + /* Quote ':', '%', and any 8-bit characters. */ + for (r=0; r < uid->len; r++) + { + if (uid->name[r] == ':' + || uid->name[r]== '%' + || (uid->name[r]&0x80)) + es_fprintf (fp, "%%%02X", (byte)uid->name[r]); + else + es_putc (uid->name[r], fp); + } + + es_fprintf (fp, ":%u:%u:%s%s:\n", + uid->created,uid->expiredate, + uid->is_revoked? "r":"", + uid->is_expired? "e":""); + } + } + break; + + /* This bit is really for the benefit of people who + store their keys in LDAP servers. It makes it easy + to do queries for things like "all keys signed by + Isabella". */ + case PKT_SIGNATURE: + { + PKT_signature *sig = node->pkt->pkt.signature; + + if (IS_UID_SIG (sig)) + { + es_fprintf (fp, "sig:%08lX%08lX:%X:%u:%u:\n", + (ulong)sig->keyid[0],(ulong)sig->keyid[1], + sig->sig_class, sig->timestamp, + sig->expiredate); + } + } + break; + + default: + continue; + } + /* Given that the last operation was an es_fprintf we should + get the correct ERRNO if ferror indicates an error. */ + if (es_ferror (fp)) + err = gpg_error_from_syserror (); + } + + /* Without an error and if we have an keyblock at all, send the + data back. */ + if (!err && parm->keyblock) + { + int rc; + char buffer[512]; + size_t nread; + + es_rewind (fp); + while (!(rc=es_read (fp, buffer, sizeof buffer, &nread)) && nread) + { + err = assuan_send_data (parm->ctx, buffer, nread); + if (err) + break; + } + if (!err && rc) + err = gpg_error_from_syserror (); + } + es_fclose (fp); + } + else + return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE); + + return err; +} + + +/* Send a key to the configured server. {DATA,DATLEN} contains the + key in OpenPGP binary transport format. If KEYBLOCK is not NULL it + has the internal representaion of that key; this is for example + used to convey meta data to LDAP keyservers. */ +gpg_error_t +gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock) +{ + gpg_error_t err; + assuan_context_t ctx; + struct ks_put_parm_s parm; + + memset (&parm, 0, sizeof parm); + + /* We are going to parse the keyblock, thus we better make sure the + all information is readily available. */ + if (keyblock) + merge_keys_and_selfsig (keyblock); + + err = open_context (ctrl, &ctx); + if (err) + return err; + + parm.ctx = ctx; + parm.keyblock = keyblock; + parm.data = data; + parm.datalen = datalen; + + err = assuan_transact (ctx, "KS_PUT", NULL, NULL, + ks_put_inq_cb, &parm, NULL, NULL); + + close_context (ctrl, ctx); + return err; +} diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h new file mode 100644 index 000000000..9523bf568 --- /dev/null +++ b/g10/call-dirmngr.h @@ -0,0 +1,32 @@ +/* call-dirmngr.h - GPG operations to the Dirmngr + * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. + */ +#ifndef GNUPG_G10_CALL_DIRMNGR_H +#define GNUPG_G10_CALL_DIRMNGR_H + +void gpg_dirmngr_deinit_session_data (ctrl_t ctrl); + +gpg_error_t gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr, + gpg_error_t (*cb)(void*, char *), + void *cb_value); +gpg_error_t gpg_dirmngr_ks_get (ctrl_t ctrl, char *pattern[], estream_t *r_fp); +gpg_error_t gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, + kbnode_t keyblock); + + +#endif /*GNUPG_G10_CALL_DIRMNGR_H*/ diff --git a/g10/export.c b/g10/export.c index 74a7b0c51..1eb0baa8b 100644 --- a/g10/export.c +++ b/g10/export.c @@ -114,6 +114,60 @@ export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, return rc; } + +/* + * Export a single key into a memory buffer. + */ +gpg_error_t +export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options, + kbnode_t *r_keyblock, void **r_data, size_t *r_datalen) +{ + gpg_error_t err; + iobuf_t iobuf; + int any; + strlist_t helplist; + + *r_keyblock = NULL; + *r_data = NULL; + *r_datalen = 0; + + helplist = NULL; + if (!add_to_strlist_try (&helplist, keyspec)) + return gpg_error_from_syserror (); + + iobuf = iobuf_temp (); + err = do_export_stream (ctrl, iobuf, helplist, 0, r_keyblock, options, &any); + if (!err && !any) + err = gpg_error (GPG_ERR_NOT_FOUND); + if (!err) + { + const void *src; + size_t datalen; + + iobuf_flush_temp (iobuf); + src = iobuf_get_temp_buffer (iobuf); + datalen = iobuf_get_temp_length (iobuf); + if (!datalen) + err = gpg_error (GPG_ERR_NO_PUBKEY); + else if (!(*r_data = xtrymalloc (datalen))) + err = gpg_error_from_syserror (); + else + { + memcpy (*r_data, src, datalen); + *r_datalen = datalen; + } + } + iobuf_close (iobuf); + free_strlist (helplist); + if (err && *r_keyblock) + { + release_kbnode (*r_keyblock); + *r_keyblock = NULL; + } + return err; +} + + int export_seckeys (ctrl_t ctrl, strlist_t users ) { @@ -1,6 +1,6 @@ /* gpg.c - The GnuPG utility (main for gpg) - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + * 2008, 2009, 2010, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -54,6 +54,7 @@ #include "exec.h" #include "gc-opt-flags.h" #include "asshelp.h" +#include "call-dirmngr.h" #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) #define MY_O_BINARY O_BINARY @@ -1822,7 +1823,7 @@ gpg_init_default_ctrl (ctrl_t ctrl) static void gpg_deinit_default_ctrl (ctrl_t ctrl) { - (void)ctrl; + gpg_dirmngr_deinit_session_data (ctrl); } @@ -2658,15 +2659,15 @@ main (int argc, char **argv) break; case oKeyServer: { - struct keyserver_spec *keyserver; - keyserver=parse_keyserver_uri(pargs.r.ret_str,0, - configname,configlineno); - if(!keyserver) - log_error(_("could not parse keyserver URL\n")); + keyserver_spec_t keyserver; + keyserver = parse_keyserver_uri (pargs.r.ret_str,0, + configname,configlineno); + if (!keyserver) + log_error (_("could not parse keyserver URL\n")); else { - keyserver->next=opt.keyserver; - opt.keyserver=keyserver; + keyserver->next = opt.keyserver; + opt.keyserver = keyserver; } } break; @@ -2853,14 +2854,14 @@ main (int argc, char **argv) break; case oDefaultKeyserverURL: { - struct keyserver_spec *keyserver; - keyserver=parse_keyserver_uri(pargs.r.ret_str,1, - configname,configlineno); - if(!keyserver) - log_error(_("could not parse keyserver URL\n")); + keyserver_spec_t keyserver; + keyserver = parse_keyserver_uri (pargs.r.ret_str,1, + configname,configlineno); + if (!keyserver) + log_error (_("could not parse keyserver URL\n")); else - free_keyserver_spec(keyserver); - + free_keyserver_spec (keyserver); + opt.def_keyserver_url = pargs.r.ret_str; } break; @@ -3751,12 +3752,12 @@ main (int argc, char **argv) case aSearchKeys: sl = NULL; - for( ; argc; argc--, argv++ ) - append_to_strlist2( &sl, *argv, utf8_strings ); + for (; argc; argc--, argv++) + append_to_strlist2 (&sl, *argv, utf8_strings); rc = keyserver_search (ctrl, sl); - if(rc) - log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); - free_strlist(sl); + if (rc) + log_error (_("keyserver search failed: %s\n"), gpg_strerror (rc)); + free_strlist (sl); break; case aRefreshKeys: @@ -48,6 +48,10 @@ /* Object used to keep state locally to server.c . */ struct server_local_s; +/* Object used to keep state locally to call-dirmngr.c . */ +struct dirmngr_local_s; +typedef struct dirmngr_local_s *dirmngr_local_t; + /* Object used to describe a keyblok node. */ typedef struct kbnode_struct *KBNODE; typedef struct kbnode_struct *kbnode_t; @@ -58,7 +62,11 @@ typedef struct kbnode_struct *kbnode_t; gpg_init_default_ctrl(). */ struct server_control_s { + /* Local data for server.c */ struct server_local_s *server_local; + + /* Local data for call-dirmngr.c */ + dirmngr_local_t dirmngr_local; }; diff --git a/g10/import.c b/g10/import.c index 31160c33e..88abafd6a 100644 --- a/g10/import.c +++ b/g10/import.c @@ -243,6 +243,32 @@ import_keys_stream (ctrl_t ctrl, IOBUF inp, void *stats_handle, fpr, fpr_len, options); } + +/* Variant of import_keys_stream reading from an estream_t. */ +int +import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle, + unsigned char **fpr, size_t *fpr_len, + unsigned int options) +{ + int rc; + iobuf_t inp; + + inp = iobuf_esopen (fp, "r", 1); + if (!inp) + { + rc = gpg_error_from_syserror (); + log_error ("iobuf_esopen failed: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = import_keys_internal (ctrl, inp, NULL, 0, stats_handle, + fpr, fpr_len, options); + + iobuf_close (inp); + return rc; +} + + static int import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats, unsigned char **fpr,size_t *fpr_len,unsigned int options ) diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index cbf3c04a8..2b1b64e35 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -40,7 +40,7 @@ int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len, int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid, struct keyserver_spec *keyserver); int keyserver_refresh (ctrl_t ctrl, strlist_t users); -int keyserver_search (ctrl_t ctrl, strlist_t tokens); +gpg_error_t keyserver_search (ctrl_t ctrl, strlist_t tokens); int keyserver_fetch (ctrl_t ctrl, strlist_t urilist); int keyserver_import_cert (ctrl_t ctrl, const char *name, unsigned char **fpr,size_t *fpr_len); diff --git a/g10/keyserver.c b/g10/keyserver.c index 422e62e78..2f055ada5 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1,6 +1,6 @@ /* keyserver.c - generic keyserver code * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - * 2009 Free Software Foundation, Inc. + * 2009, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -18,6 +18,9 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ +/* !!! FIXME: Replace all printf by es_printf. FIXME !!! */ + + #include <config.h> #include <ctype.h> #include <stdio.h> @@ -45,7 +48,8 @@ #ifdef USE_DNS_SRV #include "srv.h" #endif - +#include "membuf.h" +#include "call-dirmngr.h" #ifdef HAVE_W32_SYSTEM /* It seems Vista doesn't grok X_OK and so fails access() tests. @@ -65,6 +69,24 @@ struct keyrec unsigned int lines; }; +/* Parameters for the search line handler. */ +struct search_line_handler_parm_s +{ + ctrl_t ctrl; /* The session control structure. */ + char *searchstr_disp; /* Native encoded search string or NULL. */ + KEYDB_SEARCH_DESC *desc; /* Array with search descriptions. */ + int count; /* Number of keys we are currently prepared to + handle. This is the size of the DESC array. If + it is too small, it will grow safely. */ + int validcount; /* Enable the "Key x-y of z" messages. */ + int nkeys; /* Number of processed records. */ + int any_lines; /* At least one line has been processed. */ + unsigned int numlines; /* Counter for displayed lines. */ + int eof_seen; /* EOF encountered. */ + int not_found; /* Set if no keys have been found. */ +}; + + enum ks_action {KS_UNKNOWN=0,KS_GET,KS_GETNAME,KS_SEND,KS_SEARCH}; static struct parse_options keyserver_opts[]= @@ -89,10 +111,12 @@ static struct parse_options keyserver_opts[]= {NULL,0,NULL,NULL} }; -static int keyserver_work (ctrl_t ctrl, enum ks_action action,strlist_t list, - KEYDB_SEARCH_DESC *desc,int count, - unsigned char **fpr,size_t *fpr_len, - struct keyserver_spec *keyserver); +static gpg_error_t keyserver_get (ctrl_t ctrl, + KEYDB_SEARCH_DESC *desc, int ndesc, + struct keyserver_spec *keyserver); +static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs, + struct keyserver_spec *keyserver); + /* Reasonable guess */ #define DEFAULT_MAX_CERT_SIZE 16384 @@ -236,9 +260,9 @@ keyserver_match(struct keyserver_spec *spec) parser any longer so it can be removed, or at least moved to keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */ -struct keyserver_spec * -parse_keyserver_uri(const char *string,int require_scheme, - const char *configname,unsigned int configlineno) +keyserver_spec_t +parse_keyserver_uri (const char *string,int require_scheme, + const char *configname,unsigned int configlineno) { int assume_hkp=0; struct keyserver_spec *keyserver; @@ -555,6 +579,8 @@ print_keyrec(int number,struct keyrec *keyrec) static struct keyrec * parse_keyrec(char *keystring) { + /* FIXME: Remove the static and put the data into the parms we use + for the caller anyway. */ static struct keyrec *work=NULL; struct keyrec *ret=NULL; char *record; @@ -583,12 +609,7 @@ parse_keyrec(char *keystring) work->uidbuf=iobuf_temp(); } - /* Remove trailing whitespace */ - for(i=strlen(keystring);i>0;i--) - if(ascii_isspace(keystring[i-1])) - keystring[i-1]='\0'; - else - break; + trim_trailing_ws (keystring, strlen (keystring)); if((record=strsep(&keystring,":"))==NULL) return ret; @@ -664,7 +685,7 @@ parse_keyrec(char *keystring) case 'R': work->flags|=1; break; - + case 'd': case 'D': work->flags|=2; @@ -727,882 +748,247 @@ parse_keyrec(char *keystring) return ret; } -/* TODO: do this as a list sent to keyserver_work rather than calling - it once for each key to get the correct counts after the import - (cosmetics, really) and to better take advantage of the keyservers - that can do multiple fetches in one go (LDAP). */ -static int -show_prompt (ctrl_t ctrl, - KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) +/* Show a prompt and allow the user to select keys for retrieval. */ +static gpg_error_t +show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc, + int count, const char *search) { - char *answer; + gpg_error_t err; + char *answer = NULL; fflush (stdout); - if(count && opt.command_fd==-1) + if (count && opt.command_fd == -1) { - static int from=1; - tty_printf("Keys %d-%d of %d for \"%s\". ",from,numdesc,count,search); - from=numdesc+1; + static int from = 1; + tty_printf ("Keys %d-%d of %d for \"%s\". ", + from, numdesc, count, search); + from = numdesc + 1; } - answer=cpr_get_no_help("keysearch.prompt", - _("Enter number(s), N)ext, or Q)uit > ")); + again: + err = 0; + xfree (answer); + answer = cpr_get_no_help ("keysearch.prompt", + _("Enter number(s), N)ext, or Q)uit > ")); /* control-d */ - if(answer[0]=='\x04') + if (answer[0]=='\x04') { - printf("Q\n"); - answer[0]='q'; + tty_printf ("Q\n"); + answer[0] = 'q'; } - if(answer[0]=='q' || answer[0]=='Q') - { - xfree(answer); - return 1; - } - else if(atoi(answer)>=1 && atoi(answer)<=numdesc) + if (answer[0]=='q' || answer[0]=='Q') + err = gpg_error (GPG_ERR_CANCELED); + else if (atoi (answer) >= 1 && atoi (answer) <= numdesc) { - char *split=answer,*num; - - while((num=strsep(&split," ,"))!=NULL) - if(atoi(num)>=1 && atoi(num)<=numdesc) - keyserver_work (ctrl, KS_GET,NULL,&desc[atoi(num)-1],1, - NULL,NULL,opt.keyserver); - - xfree(answer); - return 1; - } - - return 0; -} - -/* Count and searchstr are just for cosmetics. If the count is too - small, it will grow safely. If negative it disables the "Key x-y - of z" messages. searchstr should be UTF-8 (rather than native). */ -static void -keyserver_search_prompt (ctrl_t ctrl, IOBUF buffer,const char *searchstr) -{ - int i=0,validcount=0,started=0,header=0,count=1; - unsigned int maxlen,buflen,numlines=0; - KEYDB_SEARCH_DESC *desc; - byte *line=NULL; - char *localstr=NULL; - - if(searchstr) - localstr=utf8_to_native(searchstr,strlen(searchstr),0); - - desc=xmalloc(count*sizeof(KEYDB_SEARCH_DESC)); - - for(;;) - { - struct keyrec *keyrec; - int rl; - - maxlen=1024; - rl=iobuf_read_line(buffer,&line,&buflen,&maxlen); - - if(opt.with_colons) - { - if(!header && ascii_strncasecmp("SEARCH ",line,7)==0 - && ascii_strncasecmp(" BEGIN",&line[strlen(line)-7],6)==0) - { - header=1; - continue; - } - else if(ascii_strncasecmp("SEARCH ",line,7)==0 - && ascii_strncasecmp(" END",&line[strlen(line)-5],4)==0) - continue; - - printf("%s",line); - } - - /* Look for an info: line. The only current info: values - defined are the version and key count. */ - if(!started && rl>0 && ascii_strncasecmp("info:",line,5)==0) - { - char *tok,*str=&line[5]; - - if((tok=strsep(&str,":"))!=NULL) - { - int version; - - if(sscanf(tok,"%d",&version)!=1) - version=1; - - if(version!=1) - { - log_error(_("invalid keyserver protocol " - "(us %d!=handler %d)\n"),1,version); - break; - } - } - - if((tok=strsep(&str,":"))!=NULL && sscanf(tok,"%d",&count)==1) - { - if(count==0) - goto notfound; - else if(count<0) - count=10; - else - validcount=1; - - desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); - } - - started=1; - continue; - } - - if(rl==0) - { - keyrec=parse_keyrec(NULL); - - if(keyrec==NULL) - { - if(i==0) - { - count=0; - break; - } - - if(i!=count) - validcount=0; + char *split = answer; + char *num; + int numarray[50]; + int numidx = 0; + int idx; + + while ((num = strsep (&split, " ,"))) + if (atoi (num) >= 1 && atoi (num) <= numdesc) + { + if (numidx >= DIM (numarray)) + { + tty_printf ("Too many keys selected\n"); + goto again; + } + numarray[numidx++] = atoi (num); + } + + if (!numidx) + goto again; - if (opt.with_colons && opt.batch) - break; - - for(;;) - { - if (show_prompt (ctrl, desc, i, validcount?count:0, localstr)) - break; - validcount=0; - } - - break; - } - } - else - keyrec=parse_keyrec(line); - - if(i==count) - { - /* keyserver helper sent more keys than they claimed in the - info: line. */ - count+=10; - desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); - validcount=0; - } - - if(keyrec) - { - desc[i]=keyrec->desc; - - if(!opt.with_colons) - { - /* screen_lines - 1 for the prompt. */ - if(numlines+keyrec->lines>opt.screen_lines-1) - { - if (show_prompt (ctrl, desc, i, validcount?count:0, localstr)) - break; - else - numlines=0; - } - - print_keyrec(i+1,keyrec); - } - - numlines+=keyrec->lines; - iobuf_close(keyrec->uidbuf); - xfree(keyrec); - - started=1; - i++; - } - } - - notfound: - /* Leave this commented out or now, and perhaps for a very long - time. All HKPish servers return HTML error messages for - no-key-found. */ - /* - if(!started) - log_info(_("keyserver does not support searching\n")); - else - */ - if(count==0) - { - if(localstr) - log_info(_("key \"%s\" not found on keyserver\n"),localstr); - else - log_info(_("key not found on keyserver\n")); + { + KEYDB_SEARCH_DESC *selarray; + + selarray = xtrymalloc (numidx * sizeof *selarray); + if (!selarray) + { + err = gpg_error_from_syserror (); + goto leave; + } + for (idx = 0; idx < numidx; idx++) + selarray[idx] = desc[numarray[idx]-1]; + err = keyserver_get (ctrl, selarray, numidx, NULL); + xfree (selarray); + } } - xfree(localstr); - xfree(desc); - xfree(line); -} - -/* We sometimes want to use a different gpgkeys_xxx for a given - protocol (for example, ldaps is handled by gpgkeys_ldap). Map - these here. */ -static const char * -keyserver_typemap(const char *type) -{ - if(strcmp(type,"ldaps")==0) - return "ldap"; - else if(strcmp(type,"hkps")==0) - return "hkp"; - else - return type; + leave: + xfree (answer); + return err; } -/* The PGP LDAP and the curl fetch-a-LDAP-object methodologies are - sufficiently different that we can't use curl to do LDAP. */ -static int -direct_uri_map(const char *scheme,unsigned int is_direct) -{ - if(is_direct && strcmp(scheme,"ldap")==0) - return 1; - - return 0; -} -#if GNUPG_MAJOR_VERSION == 2 -#define GPGKEYS_PREFIX "gpg2keys_" -#else -#define GPGKEYS_PREFIX "gpgkeys_" -#endif -#define GPGKEYS_CURL GPGKEYS_PREFIX "curl" EXEEXT -#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_CURL)) -#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" -#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" - -static int -keyserver_spawn (ctrl_t ctrl, - enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc, - int count,int *prog,unsigned char **fpr,size_t *fpr_len, - struct keyserver_spec *keyserver) +/* This is a callback used by call-dirmngr.c to process the result of + KS_SEARCH command. LINE is the actual data line received with all + escaping removed and guaranteed to be exactly one line with + stripped LF; an EOF is indicated by LINE passed as NULL. LINE may + be modified after return. */ +static gpg_error_t +search_line_handler (void *opaque, char *line) { - int ret=0,i,gotversion=0,outofband=0; - strlist_t temp; - unsigned int maxlen,buflen; - char *command,*end,*searchstr=NULL; - byte *line=NULL; - struct exec_info *spawn; - const char *scheme; - const char *libexecdir = gnupg_libexecdir (); + struct search_line_handler_parm_s *parm = opaque; + gpg_error_t err = 0; + struct keyrec *keyrec; - assert(keyserver); - -#ifdef EXEC_TEMPFILE_ONLY - opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES; -#endif - - /* Build the filename for the helper to execute */ - scheme=keyserver_typemap(keyserver->scheme); - -#ifdef DISABLE_KEYSERVER_PATH - /* Destroy any path we might have. This is a little tricky, - portability-wise. It's not correct to delete the PATH - environment variable, as that may fall back to a system built-in - PATH. Similarly, it is not correct to set PATH to the null - string (PATH="") since this actually deletes the PATH environment - variable under MinGW. The safest thing to do here is to force - PATH to be GNUPG_LIBEXECDIR. All this is not that meaningful on - Unix-like systems (since we're going to give a full path to - gpgkeys_foo), but on W32 it prevents loading any DLLs from - directories in %PATH%. - - After some more thinking about this we came to the conclusion - that it is better to load the helpers from the directory where - the program of this process lives. Fortunately Windows provides - a way to retrieve this and our gnupg_libexecdir function has been - modified to return just this. Setting the exec-path is not - anymore required. - set_exec_path(libexecdir); - */ -#else - if(opt.exec_path_set) + if (parm->eof_seen && line) { - /* If exec-path was set, and DISABLE_KEYSERVER_PATH is - undefined, then don't specify a full path to gpgkeys_foo, so - that the PATH can work. */ - command=xmalloc(GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1); - command[0]='\0'; + log_debug ("ooops: unexpected data after EOF\n"); + line = NULL; } - else -#endif - { - /* Specify a full path to gpgkeys_foo. */ - command=xmalloc(strlen(libexecdir)+strlen(DIRSEP_S)+ - GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1); - strcpy(command,libexecdir); - strcat(command,DIRSEP_S); - } - - end=command+strlen(command); - - /* Build a path for the keyserver helper. If it is direct_uri - (i.e. an object fetch and not a keyserver), then add "_uri" to - the end to distinguish the keyserver helper from an object - fetcher that can speak that protocol (this is a problem for - LDAP). */ - - strcat(command,GPGKEYS_PREFIX); - strcat(command,scheme); - - /* This "_uri" thing is in case we need to call a direct handler - instead of the keyserver handler. This lets us use gpgkeys_curl - or gpgkeys_ldap_uri (we don't provide it, but a user might) - instead of gpgkeys_ldap to fetch things like - ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 */ - if(direct_uri_map(scheme,keyserver->flags.direct_uri)) - strcat(command,"_uri"); - - strcat(command,EXEEXT); - - /* Can we execute it? If not, try curl as our catchall. */ - if(path_access(command,X_OK)!=0) - strcpy(end,GPGKEYS_CURL); - - if(opt.keyserver_options.options&KEYSERVER_USE_TEMP_FILES) + /* Print the received line. */ + if (opt.with_colons && line) { - if(opt.keyserver_options.options&KEYSERVER_KEEP_TEMP_FILES) - { - command=xrealloc(command,strlen(command)+ - strlen(KEYSERVER_ARGS_KEEP)+1); - strcat(command,KEYSERVER_ARGS_KEEP); - } - else - { - command=xrealloc(command,strlen(command)+ - strlen(KEYSERVER_ARGS_NOKEEP)+1); - strcat(command,KEYSERVER_ARGS_NOKEEP); - } - - ret=exec_write(&spawn,NULL,command,NULL,0,0); + log_debug ("%s\n",line); } - else - ret=exec_write(&spawn,command,NULL,NULL,0,0); - xfree(command); - - if(ret) - return ret; - - fprintf(spawn->tochild, - "# This is a GnuPG %s keyserver communications file\n",VERSION); - fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); - fprintf(spawn->tochild,"PROGRAM %s\n",VERSION); - fprintf(spawn->tochild,"SCHEME %s\n",keyserver->scheme); - - if(keyserver->opaque) - fprintf(spawn->tochild,"OPAQUE %s\n",keyserver->opaque); - else + /* Look for an info: line. The only current info: values defined + are the version and key count. */ + if (line && !parm->any_lines && !ascii_strncasecmp ("info:", line, 5)) { - if(keyserver->auth) - fprintf(spawn->tochild,"AUTH %s\n",keyserver->auth); - - if(keyserver->host) - fprintf(spawn->tochild,"HOST %s\n",keyserver->host); - - if(keyserver->port) - fprintf(spawn->tochild,"PORT %s\n",keyserver->port); - - if(keyserver->path) - fprintf(spawn->tochild,"PATH %s\n",keyserver->path); - } - - /* Write global options */ - - for(temp=opt.keyserver_options.other;temp;temp=temp->next) - fprintf(spawn->tochild,"OPTION %s\n",temp->d); - - /* Write per-keyserver options */ - - for(temp=keyserver->options;temp;temp=temp->next) - fprintf(spawn->tochild,"OPTION %s\n",temp->d); - - switch(action) - { - case KS_GET: - { - fprintf(spawn->tochild,"COMMAND GET\n\n"); - - /* Which keys do we want? */ - - for(i=0;i<count;i++) - { - int quiet=0; - - if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20) - { - int f; - - fprintf(spawn->tochild,"0x"); - - for(f=0;f<MAX_FINGERPRINT_LEN;f++) - fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]); - - fprintf(spawn->tochild,"\n"); - } - else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16) - { - int f; - - fprintf(spawn->tochild,"0x"); - - for(f=0;f<16;f++) - fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]); - - fprintf(spawn->tochild,"\n"); - } - else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID) - fprintf(spawn->tochild,"0x%08lX%08lX\n", - (ulong)desc[i].u.kid[0], - (ulong)desc[i].u.kid[1]); - else if(desc[i].mode==KEYDB_SEARCH_MODE_SHORT_KID) - fprintf(spawn->tochild,"0x%08lX\n", - (ulong)desc[i].u.kid[1]); - else if(desc[i].mode==KEYDB_SEARCH_MODE_EXACT) - { - fprintf(spawn->tochild,"0x0000000000000000\n"); - quiet=1; - } - else if(desc[i].mode==KEYDB_SEARCH_MODE_NONE) - continue; - else - BUG(); - - if(!quiet) - { - if(keyserver->host) - log_info(_("requesting key %s from %s server %s\n"), - keystr_from_desc(&desc[i]), - keyserver->scheme,keyserver->host); - else - log_info(_("requesting key %s from %s\n"), - keystr_from_desc(&desc[i]),keyserver->uri); - } - } - - fprintf(spawn->tochild,"\n"); - - break; - } - - case KS_GETNAME: - { - strlist_t key; - - fprintf(spawn->tochild,"COMMAND GETNAME\n\n"); - - /* Which names do we want? */ - - for(key=list;key!=NULL;key=key->next) - fprintf(spawn->tochild,"%s\n",key->d); - - fprintf(spawn->tochild,"\n"); - - if(keyserver->host) - log_info(_("searching for names from %s server %s\n"), - keyserver->scheme,keyserver->host); - else - log_info(_("searching for names from %s\n"),keyserver->uri); - - break; - } - - case KS_SEND: - { - strlist_t key; - - /* Note the extra \n here to send an empty keylist block */ - fprintf(spawn->tochild,"COMMAND SEND\n\n\n"); - - for(key=list;key!=NULL;key=key->next) - { - armor_filter_context_t *afx; - IOBUF buffer = iobuf_temp (); - KBNODE block; - - temp=NULL; - add_to_strlist(&temp,key->d); - - afx = new_armor_context (); - afx->what = 1; - /* Tell the armor filter to use Unix-style \n line - endings, since we're going to fprintf this to a file - that (on Win32) is open in text mode. The win32 stdio - will transform the \n to \r\n and we'll end up with the - proper line endings on win32. This is a no-op on - Unix. */ - afx->eol[0] = '\n'; - push_armor_filter (afx, buffer); - release_armor_context (afx); - - /* TODO: Remove Comment: lines from keys exported this - way? */ - - if(export_pubkeys_stream (ctrl, buffer,temp,&block, - opt.keyserver_options.export_options)==-1) - iobuf_close(buffer); - else - { - KBNODE node; - - iobuf_flush_temp(buffer); - - merge_keys_and_selfsig(block); - - fprintf(spawn->tochild,"INFO %08lX%08lX BEGIN\n", - (ulong)block->pkt->pkt.public_key->keyid[0], - (ulong)block->pkt->pkt.public_key->keyid[1]); - - for(node=block;node;node=node->next) - { - switch(node->pkt->pkttype) - { - default: - continue; - - case PKT_PUBLIC_KEY: - case PKT_PUBLIC_SUBKEY: - { - PKT_public_key *pk=node->pkt->pkt.public_key; - - keyid_from_pk(pk,NULL); - - fprintf(spawn->tochild,"%sb:%08lX%08lX:%u:%u:%u:%u:", - node->pkt->pkttype==PKT_PUBLIC_KEY?"pu":"su", - (ulong)pk->keyid[0],(ulong)pk->keyid[1], - pk->pubkey_algo, - nbits_from_pk(pk), - pk->timestamp, - pk->expiredate); - - if(pk->flags.revoked) - fprintf(spawn->tochild,"r"); - if(pk->has_expired) - fprintf(spawn->tochild,"e"); - - fprintf(spawn->tochild,"\n"); - } - break; - - case PKT_USER_ID: - { - PKT_user_id *uid=node->pkt->pkt.user_id; - int r; - - if(uid->attrib_data) - continue; - - fprintf(spawn->tochild,"uid:"); - - /* Quote ':', '%', and any 8-bit - characters */ - for(r=0;r<uid->len;r++) - { - if(uid->name[r]==':' || uid->name[r]=='%' - || uid->name[r]&0x80) - fprintf(spawn->tochild,"%%%02X", - (byte)uid->name[r]); - else - fprintf(spawn->tochild,"%c",uid->name[r]); - } - - fprintf(spawn->tochild,":%u:%u:", - uid->created,uid->expiredate); - - if(uid->is_revoked) - fprintf(spawn->tochild,"r"); - if(uid->is_expired) - fprintf(spawn->tochild,"e"); - - fprintf(spawn->tochild,"\n"); - } - break; - - /* This bit is really for the benefit of - people who store their keys in LDAP - servers. It makes it easy to do queries - for things like "all keys signed by - Isabella". */ - case PKT_SIGNATURE: - { - PKT_signature *sig=node->pkt->pkt.signature; - - if(!IS_UID_SIG(sig)) - continue; - - fprintf(spawn->tochild,"sig:%08lX%08lX:%X:%u:%u\n", - (ulong)sig->keyid[0],(ulong)sig->keyid[1], - sig->sig_class,sig->timestamp, - sig->expiredate); - } - break; - } - } - - fprintf(spawn->tochild,"INFO %08lX%08lX END\n", - (ulong)block->pkt->pkt.public_key->keyid[0], - (ulong)block->pkt->pkt.public_key->keyid[1]); - - fprintf(spawn->tochild,"KEY %08lX%08lX BEGIN\n", - (ulong)block->pkt->pkt.public_key->keyid[0], - (ulong)block->pkt->pkt.public_key->keyid[1]); - fwrite(iobuf_get_temp_buffer(buffer), - iobuf_get_temp_length(buffer),1,spawn->tochild); - fprintf(spawn->tochild,"KEY %08lX%08lX END\n", - (ulong)block->pkt->pkt.public_key->keyid[0], - (ulong)block->pkt->pkt.public_key->keyid[1]); - - iobuf_close(buffer); - - if(keyserver->host) - log_info(_("sending key %s to %s server %s\n"), - keystr(block->pkt->pkt.public_key->keyid), - keyserver->scheme,keyserver->host); - else - log_info(_("sending key %s to %s\n"), - keystr(block->pkt->pkt.public_key->keyid), - keyserver->uri); - - release_kbnode(block); - } - - free_strlist(temp); - } - - break; - } - - case KS_SEARCH: - { - strlist_t key; - - fprintf(spawn->tochild,"COMMAND SEARCH\n\n"); - - /* Which keys do we want? Remember that the gpgkeys_ program - is going to lump these together into a search string. */ - - for(key=list;key!=NULL;key=key->next) - { - fprintf(spawn->tochild,"%s\n",key->d); - if(key!=list) - { - searchstr=xrealloc(searchstr, - strlen(searchstr)+strlen(key->d)+2); - strcat(searchstr," "); - } - else - { - searchstr=xmalloc(strlen(key->d)+1); - searchstr[0]='\0'; - } - - strcat(searchstr,key->d); - } - - fprintf(spawn->tochild,"\n"); - - if(keyserver->host) - log_info(_("searching for \"%s\" from %s server %s\n"), - searchstr,keyserver->scheme,keyserver->host); - else - log_info(_("searching for \"%s\" from %s\n"), - searchstr,keyserver->uri); - - break; - } + char *str = line + 5; + char *tok; - default: - log_fatal(_("no keyserver action!\n")); - break; + if ((tok = strsep (&str, ":"))) + { + int version; + + if (sscanf (tok, "%d", &version) !=1 ) + version = 1; + + if (version !=1 ) + { + log_error (_("invalid keyserver protocol " + "(us %d!=handler %d)\n"), 1, version); + return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + } + } + + if ((tok = strsep (&str, ":")) + && sscanf (tok, "%d", &parm->count) == 1) + { + if (!parm->count) + parm->not_found = 1;/* Server indicated that no items follow. */ + else if (parm->count < 0) + parm->count = 10; /* Bad value - assume something reasonable. */ + else + parm->validcount = 1; /* COUNT seems to be okay. */ + } + + parm->any_lines = 1; + return 0; /* Line processing finished. */ } - /* Done sending, so start reading. */ - ret=exec_read(spawn); - if(ret) - goto fail; - - /* Now handle the response */ - - for(;;) + again: + if (line) + keyrec = parse_keyrec (line); + else { - int plen; - char *ptr; - - maxlen=1024; - if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) - { - ret = gpg_error_from_syserror (); - goto fail; /* i.e. EOF */ - } - - ptr=line; - - /* remove trailing whitespace */ - plen=strlen(ptr); - while(plen>0 && ascii_isspace(ptr[plen-1])) - plen--; - plen[ptr]='\0'; - - if(*ptr=='\0') - break; - - if(ascii_strncasecmp(ptr,"VERSION ",8)==0) - { - gotversion=1; - - if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION) - { - log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"), - KEYSERVER_PROTO_VERSION,atoi(&ptr[8])); - goto fail; - } - } - else if(ascii_strncasecmp(ptr,"PROGRAM ",8)==0) - { - if(ascii_strncasecmp(&ptr[8],VERSION,strlen(VERSION))!=0) - log_info(_("WARNING: keyserver handler from a different" - " version of GnuPG (%s)\n"),&ptr[8]); - } - else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0) - outofband=1; /* Currently the only OPTION */ + /* Received EOF - flush data */ + parm->eof_seen = 1; + keyrec = parse_keyrec (NULL); + if (!keyrec) + { + if (!parm->nkeys) + parm->not_found = 1; /* No keys at all. */ + else + { + if (parm->nkeys != parm->count) + parm->validcount = 0; + + if (!(opt.with_colons && opt.batch)) + { + err = show_prompt (parm->ctrl, parm->desc, parm->nkeys, + parm->validcount? parm->count : 0, + parm->searchstr_disp); + return err; + } + } + } } - if(!gotversion) + /* Save the key in the key array. */ + if (keyrec) { - log_error(_("keyserver did not send VERSION\n")); - goto fail; + /* Allocate or enlarge the key array if needed. */ + if (!parm->desc) + { + if (parm->count < 1) + { + parm->count = 10; + parm->validcount = 0; + } + parm->desc = xtrymalloc (parm->count * sizeof *parm->desc); + if (!parm->desc) + { + err = gpg_error_from_syserror (); + iobuf_close (keyrec->uidbuf); + xfree (keyrec); + return err; + } + } + else if (parm->nkeys == parm->count) + { + /* Keyserver sent more keys than claimed in the info: line. */ + KEYDB_SEARCH_DESC *tmp; + int newcount = parm->count + 10; + + tmp = xtryrealloc (parm->desc, newcount * sizeof *parm->desc); + if (!tmp) + { + err = gpg_error_from_syserror (); + iobuf_close (keyrec->uidbuf); + xfree (keyrec); + return err; + } + parm->count = newcount; + parm->desc = tmp; + parm->validcount = 0; + } + + parm->desc[parm->nkeys] = keyrec->desc; + + if (!opt.with_colons) + { + /* SCREEN_LINES - 1 for the prompt. */ + if (parm->numlines + keyrec->lines > opt.screen_lines - 1) + { + err = show_prompt (parm->ctrl, parm->desc, parm->nkeys, + parm->validcount ? parm->count:0, + parm->searchstr_disp); + if (err) + return err; + parm->numlines = 0; + } + + print_keyrec (parm->nkeys+1, keyrec); + } + + parm->numlines += keyrec->lines; + iobuf_close (keyrec->uidbuf); + xfree (keyrec); + + parm->any_lines = 1; + parm->nkeys++; + + /* If we are here due to a flush after the EOF, run again for + the last prompt. Fixme: Make this code better readable. */ + if (parm->eof_seen) + goto again; } - if(!outofband) - switch(action) - { - case KS_GET: - case KS_GETNAME: - { - void *stats_handle; - - stats_handle=import_new_stats_handle(); - - /* Slurp up all the key data. In the future, it might be - nice to look for KEY foo OUTOFBAND and FAILED indicators. - It's harmless to ignore them, but ignoring them does make - gpg complain about "no valid OpenPGP data found". One - way to do this could be to continue parsing this - line-by-line and make a temp iobuf for each key. */ - - /* FIXME: Pass CTRL. */ - import_keys_stream (NULL, spawn->fromchild,stats_handle,fpr,fpr_len, - opt.keyserver_options.import_options); - - import_print_stats(stats_handle); - import_release_stats_handle(stats_handle); - - break; - } - - /* Nothing to do here */ - case KS_SEND: - break; - - case KS_SEARCH: - keyserver_search_prompt (ctrl, spawn->fromchild,searchstr); - break; - - default: - log_fatal(_("no keyserver action!\n")); - break; - } - - fail: - xfree(line); - xfree(searchstr); - - - *prog=exec_finish(spawn); - - return ret; + return 0; } -static int -keyserver_work (ctrl_t ctrl, - enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc, - int count,unsigned char **fpr,size_t *fpr_len, - struct keyserver_spec *keyserver) -{ - int rc=0,ret=0; - - if(!keyserver) - { - log_error(_("no keyserver known (use option --keyserver)\n")); - return G10ERR_BAD_URI; - } - -#ifdef DISABLE_KEYSERVER_HELPERS - - log_error(_("external keyserver calls are not supported in this build\n")); - return G10ERR_KEYSERVER; - -#else - /* Spawn a handler */ - - rc = keyserver_spawn (ctrl, action, list, desc, count, - &ret, fpr, fpr_len, keyserver); - if(ret) - { - switch(ret) - { - case KEYSERVER_SCHEME_NOT_FOUND: - log_error(_("no handler for keyserver scheme `%s'\n"), - keyserver->scheme); - break; - - case KEYSERVER_NOT_SUPPORTED: - log_error(_("action `%s' not supported with keyserver " - "scheme `%s'\n"), - action==KS_GET?"get":action==KS_SEND?"send": - action==KS_SEARCH?"search":"unknown", - keyserver->scheme); - break; - - case KEYSERVER_VERSION_ERROR: - log_error(_(GPGKEYS_PREFIX "%s does not support" - " handler version %d\n"), - keyserver_typemap(keyserver->scheme), - KEYSERVER_PROTO_VERSION); - break; - - case KEYSERVER_TIMEOUT: - log_error(_("keyserver timed out\n")); - break; - - case KEYSERVER_INTERNAL_ERROR: - default: - log_error(_("keyserver internal error\n")); - break; - } - - return G10ERR_KEYSERVER; - } - - if(rc) - { - log_error(_("keyserver communications error: %s\n"),g10_errstr(rc)); - - return rc; - } - return 0; -#endif /* ! DISABLE_KEYSERVER_HELPERS*/ -} -int +int keyserver_export (ctrl_t ctrl, strlist_t users) { gpg_error_t err; @@ -1628,14 +1014,14 @@ keyserver_export (ctrl_t ctrl, strlist_t users) if(sl) { - rc = keyserver_work (ctrl, KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver); + rc = keyserver_put (ctrl, sl, opt.keyserver); free_strlist(sl); } return rc; } -int +int keyserver_import (ctrl_t ctrl, strlist_t users) { gpg_error_t err; @@ -1667,8 +1053,7 @@ keyserver_import (ctrl_t ctrl, strlist_t users) } if(count>0) - rc=keyserver_work (ctrl, KS_GET, NULL, desc, count, - NULL, NULL, opt.keyserver); + rc=keyserver_get (ctrl, desc, count, NULL); xfree(desc); @@ -1694,10 +1079,10 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len, /* TODO: Warn here if the fingerprint we got doesn't match the one we asked for? */ - return keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, keyserver); + return keyserver_get (ctrl, &desc, 1, keyserver); } -int +int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,struct keyserver_spec *keyserver) { @@ -1709,11 +1094,11 @@ keyserver_import_keyid (ctrl_t ctrl, desc.u.kid[0]=keyid[0]; desc.u.kid[1]=keyid[1]; - return keyserver_work (ctrl, KS_GET,NULL,&desc,1,NULL,NULL,keyserver); + return keyserver_get (ctrl, &desc,1, keyserver); } /* code mostly stolen from do_export_stream */ -static int +static int keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) { int rc=0,ndesc,num=100; @@ -1736,13 +1121,13 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) } else { - for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) + for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) ; desc = xmalloc ( ndesc * sizeof *desc); - + for (ndesc=0, sl=users; sl; sl = sl->next) { - gpg_error_t err; + gpg_error_t err; if (!(err = classify_user_id (sl->d, desc+ndesc))) ndesc++; else @@ -1753,7 +1138,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) while (!(rc = keydb_search (kdbhd, desc, ndesc))) { - if (!users) + if (!users) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; /* read the keyblock */ @@ -1856,7 +1241,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) if(rc==-1) rc=0; - + leave: if(rc) xfree(*klist); @@ -1913,9 +1298,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) /* We use the keyserver structure we parsed out before. Note that a preferred keyserver without a scheme:// will be interpreted as hkp:// */ - - rc = keyserver_work (ctrl, KS_GET, NULL, &desc[i], 1, - NULL, NULL, keyserver); + rc = keyserver_get (ctrl, &desc[i], 1, keyserver); if(rc) log_info(_("WARNING: unable to refresh key %s" " via %s: %s\n"),keystr_from_desc(&desc[i]), @@ -1945,8 +1328,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) count,opt.keyserver->uri); } - rc=keyserver_work (ctrl, KS_GET, NULL, desc, numdesc, - NULL, NULL, opt.keyserver); + rc=keyserver_get (ctrl, desc, numdesc, NULL); } xfree(desc); @@ -1961,15 +1343,305 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users) return rc; } -int + +/* Search for keys on the keyservers. The patterns are given in the + string list TOKENS. */ +gpg_error_t keyserver_search (ctrl_t ctrl, strlist_t tokens) { - if (tokens) - return keyserver_work (ctrl, KS_SEARCH, tokens, NULL, 0, - NULL, NULL, opt.keyserver); - return 0; + gpg_error_t err; + char *searchstr; + struct search_line_handler_parm_s parm; + + memset (&parm, 0, sizeof parm); + + if (!tokens) + return 0; /* Return success if no patterns are given. */ + + if (!opt.keyserver) + { + log_error (_("no keyserver known (use option --keyserver)\n")); + return gpg_error (GPG_ERR_NO_KEYSERVER); + } + + /* Write global options */ + + /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */ + /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ + + /* Write per-keyserver options */ + + /* for(temp=keyserver->options;temp;temp=temp->next) */ + /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ + + { + membuf_t mb; + strlist_t item; + + init_membuf (&mb, 1024); + for (item = tokens; item; item = item->next) + { + if (item != tokens) + put_membuf (&mb, " ", 1); + put_membuf_str (&mb, item->d); + } + put_membuf (&mb, "", 1); /* Append Nul. */ + searchstr = get_membuf (&mb, NULL); + if (!searchstr) + { + err = gpg_error_from_syserror (); + goto leave; + } + } + /* FIXME: Enable the next line */ + /* log_info (_("searching for \"%s\" from %s\n"), searchstr, keyserver->uri); */ + + parm.ctrl = ctrl; + if (searchstr) + parm.searchstr_disp = utf8_to_native (searchstr, strlen (searchstr), 0); + + err = gpg_dirmngr_ks_search (ctrl, searchstr, search_line_handler, &parm); + + if (parm.not_found) + { + if (parm.searchstr_disp) + log_info (_("key \"%s\" not found on keyserver\n"), + parm.searchstr_disp); + else + log_info (_("key not found on keyserver\n")); + } + + if (gpg_err_code (err) == GPG_ERR_NO_KEYSERVER) + log_error (_("no keyserver known (use option --keyserver)\n")); + else if (err) + log_error ("error searching keyserver: %s\n", gpg_strerror (err)); + + /* switch(ret) */ + /* { */ + /* case KEYSERVER_SCHEME_NOT_FOUND: */ + /* log_error(_("no handler for keyserver scheme `%s'\n"), */ + /* opt.keyserver->scheme); */ + /* break; */ + + /* case KEYSERVER_NOT_SUPPORTED: */ + /* log_error(_("action `%s' not supported with keyserver " */ + /* "scheme `%s'\n"), "search", opt.keyserver->scheme); */ + /* break; */ + + /* case KEYSERVER_TIMEOUT: */ + /* log_error(_("keyserver timed out\n")); */ + /* break; */ + + /* case KEYSERVER_INTERNAL_ERROR: */ + /* default: */ + /* log_error(_("keyserver internal error\n")); */ + /* break; */ + /* } */ + + /* return gpg_error (GPG_ERR_KEYSERVER); */ + + + leave: + xfree (parm.desc); + xfree (parm.searchstr_disp); + xfree(searchstr); + + return err; } + + +/* Called using: + +import_name: + rc = keyserver_work (ctrl, KS_GETNAME, list, NULL, + 0, fpr, fpr_len, keyserver); + +import_ldap: + rc = keyserver_work (ctrl, KS_GETNAME, list, NULL, + 0, fpr, fpr_len, keyserver); + + */ + +static gpg_error_t +keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, + struct keyserver_spec *keyserver) + +{ + gpg_error_t err = 0; + char **pattern; + int idx, npat; + estream_t datastream; + + /* Create an array filled with a search pattern for each key. The + array is delimited by a NULL entry. */ + pattern = xtrycalloc (ndesc+1, sizeof *pattern); + if (!pattern) + return gpg_error_from_syserror (); + for (npat=idx=0; idx < ndesc; idx++) + { + int quiet = 0; + + if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20 + || desc[idx].mode == KEYDB_SEARCH_MODE_FPR16) + { + pattern[npat] = xtrymalloc (2+2*20+1); + if (!pattern[npat]) + err = gpg_error_from_syserror (); + else + { + strcpy (pattern[npat], "0x"); + bin2hex (desc[idx].u.fpr, + desc[idx].mode == KEYDB_SEARCH_MODE_FPR20? 20 : 16, + pattern[npat]+2); + npat++; + } + } + else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID) + { + pattern[npat] = xtryasprintf ("0x%08lX%08lX", + (ulong)desc[idx].u.kid[0], + (ulong)desc[idx].u.kid[1]); + if (!pattern[npat]) + err = gpg_error_from_syserror (); + else + npat++; + } + else if(desc[idx].mode == KEYDB_SEARCH_MODE_SHORT_KID) + { + pattern[npat] = xtryasprintf ("0x%08lX", (ulong)desc[idx].u.kid[1]); + if (!pattern[npat]) + err = gpg_error_from_syserror (); + else + npat++; + } + else if(desc[idx].mode == KEYDB_SEARCH_MODE_EXACT) + { + /* FIXME: We don't need this. It is used as a dummy by + keyserver_fetch which passes an entire URL. Better use a + separate function here. */ + pattern[npat] = xtrystrdup ("0x0000000000000000"); + if (!pattern[npat]) + err = gpg_error_from_syserror (); + else + { + npat++; + quiet = 1; + } + } + else if (desc[idx].mode == KEYDB_SEARCH_MODE_NONE) + continue; + else + BUG(); + + if (err) + { + for (idx=0; idx < npat; idx++) + xfree (pattern[idx]); + xfree (pattern); + return err; + } + + if (!quiet && keyserver) + { + if (keyserver->host) + log_info (_("requesting key %s from %s server %s\n"), + keystr_from_desc (&desc[idx]), + keyserver->scheme, keyserver->host); + else + log_info (_("requesting key %s from %s\n"), + keystr_from_desc (&desc[idx]), keyserver->uri); + } + } + + + err = gpg_dirmngr_ks_get (ctrl, pattern, &datastream); + for (idx=0; idx < npat; idx++) + xfree (pattern[idx]); + xfree (pattern); + if (!err) + { + void *stats_handle; + + stats_handle = import_new_stats_handle(); + + /* FIXME: Check whether this comment should be moved to dirmngr. + + Slurp up all the key data. In the future, it might be nice + to look for KEY foo OUTOFBAND and FAILED indicators. It's + harmless to ignore them, but ignoring them does make gpg + complain about "no valid OpenPGP data found". One way to do + this could be to continue parsing this line-by-line and make + a temp iobuf for each key. */ + + import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL, + opt.keyserver_options.import_options); + + import_print_stats (stats_handle); + import_release_stats_handle (stats_handle); + } + es_fclose (datastream); + + + return err; +} + + +/* Send all keys specified by KEYSPECS to the KEYSERVERS. */ +static gpg_error_t +keyserver_put (ctrl_t ctrl, strlist_t keyspecs, + struct keyserver_spec *keyserver) + +{ + gpg_error_t err; + strlist_t kspec; + + if (!keyspecs) + return 0; /* Return success if the list is empty. */ + + if (!opt.keyserver) + { + log_error (_("no keyserver known (use option --keyserver)\n")); + return gpg_error (GPG_ERR_NO_KEYSERVER); + } + + for (kspec = keyspecs; kspec; kspec = kspec->next) + { + void *data; + size_t datalen; + kbnode_t keyblock; + + err = export_pubkey_buffer (ctrl, kspec->d, + opt.keyserver_options.export_options, + &keyblock, &data, &datalen); + if (err) + log_error (_("skipped \"%s\": %s\n"), kspec->d, gpg_strerror (err)); + else + { + if (keyserver->host) + log_info (_("sending key %s to %s server %s\n"), + keystr (keyblock->pkt->pkt.public_key->keyid), + keyserver->scheme, keyserver->host); + else + log_info (_("sending key %s to %s\n"), + keystr (keyblock->pkt->pkt.public_key->keyid), + keyserver->uri); + + err = gpg_dirmngr_ks_put (ctrl, data, datalen, keyblock); + release_kbnode (keyblock); + xfree (data); + if (err) + log_error (_("keyserver send failed: %s\n"), gpg_strerror (err)); + } + } + + + return err; + +} + + + int keyserver_fetch (ctrl_t ctrl, strlist_t urilist) { @@ -1996,7 +1668,7 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist) { int rc; - rc = keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, spec); + rc = keyserver_get (ctrl, &desc, 1, spec); if(rc) log_info (_("WARNING: unable to fetch URI %s: %s\n"), sl->d,g10_errstr(rc)); @@ -2139,8 +1811,9 @@ keyserver_import_name (ctrl_t ctrl, const char *name, append_to_strlist(&list,name); - rc = keyserver_work (ctrl, KS_GETNAME, list, NULL, - 0, fpr, fpr_len, keyserver); + rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /* FIXME */ + /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */ + /* 0, fpr, fpr_len, keyserver); */ free_strlist(list); @@ -2196,7 +1869,7 @@ keyserver_import_ldap (ctrl_t ctrl, snprintf(port,7,":%u",srvlist[i].port); strcat(keyserver->host,port); } - + strcat(keyserver->host," "); } @@ -2212,9 +1885,10 @@ keyserver_import_ldap (ctrl_t ctrl, strcat(keyserver->host,domain); append_to_strlist(&list,name); - - rc = keyserver_work (ctrl, KS_GETNAME, list, NULL, - 0, fpr, fpr_len, keyserver); + + rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /*FIXME*/ + /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */ + /* 0, fpr, fpr_len, keyserver); */ free_strlist(list); diff --git a/g10/main.h b/g10/main.h index c7980ac9a..1b6f30516 100644 --- a/g10/main.h +++ b/g10/main.h @@ -287,6 +287,9 @@ void import_keys (ctrl_t ctrl, char **fnames, int nnames, int import_keys_stream (ctrl_t ctrl, iobuf_t inp, void *stats_hd, unsigned char **fpr, size_t *fpr_len, unsigned int options); +int import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle, + unsigned char **fpr, size_t *fpr_len, + unsigned int options); void *import_new_stats_handle (void); void import_release_stats_handle (void *p); void import_print_stats (void *hd); @@ -299,6 +302,10 @@ int parse_export_options(char *str,unsigned int *options,int noisy); int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options ); int export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, kbnode_t *keyblock_out, unsigned int options ); +gpg_error_t export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, + unsigned int options, + kbnode_t *r_keyblock, + void **r_data, size_t *r_datalen); int export_seckeys (ctrl_t ctrl, strlist_t users); int export_secsubkeys (ctrl_t ctrl, strlist_t users); diff --git a/g10/options.h b/g10/options.h index 28a2805a9..cd0140651 100644 --- a/g10/options.h +++ b/g10/options.h @@ -1,6 +1,6 @@ /* options.h * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2010 Free Software Foundation, Inc. + * 2007, 2010, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,6 +35,13 @@ #endif #endif +/* Declaration of a keyserver spec type. The definition is found in + ../common/keyserver.h. */ +struct keyserver_spec; +typedef struct keyserver_spec *keyserver_spec_t; + + +/* Global options for GPG. */ EXTERN_UNLESS_MAIN_MODULE struct { @@ -130,22 +137,7 @@ struct int not_dash_escaped; int escape_from; int lock_once; - struct keyserver_spec - { - char *uri; - char *scheme; - char *auth; - char *host; - char *port; - char *path; - char *opaque; - strlist_t options; - struct - { - unsigned int direct_uri:1; - } flags; - struct keyserver_spec *next; - } *keyserver; + keyserver_spec_t keyserver; /* The list of configured keyservers. */ struct { unsigned int options; @@ -245,7 +237,7 @@ struct AKL_KEYSERVER, AKL_SPEC } type; - struct keyserver_spec *spec; + keyserver_spec_t spec; struct akl *next; } *auto_key_locate; diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog index 14d5f6244..cc42a6426 100644 --- a/keyserver/ChangeLog +++ b/keyserver/ChangeLog @@ -1,3 +1,9 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + * gpgkeys_hkp.c (get_name): Remove test for KS_GETNAME. It is + always true. + (search_key): Remove test for KS_GETNAME. It is always false. + 2009-08-26 Werner Koch <wk@g10code.com> * gpgkeys_hkp.c: Include util.h. diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c index a44f09131..d43a61ab5 100644 --- a/keyserver/gpgkeys_hkp.c +++ b/keyserver/gpgkeys_hkp.c @@ -340,7 +340,7 @@ get_name(const char *getkey) opt->path, appendable_path (opt->path,"/pks/lookup?op=get&options=mr&search="), searchkey_encoded, - opt->action == KS_GETNAME? "&exact=on":"", + "&exact=on", NULL); if(!request) { @@ -429,7 +429,6 @@ search_key(const char *searchkey) appendable_path (opt->path, "/pks/lookup?op=index&options=mr&search="), hexprefix, searchkey_encoded, - opt->action == KS_GETNAME? "&exact=on":"", NULL); if(!request) { @@ -687,7 +686,7 @@ main(int argc,char *argv[]) goto fail; } - if(ks_strcasecmp(opt->scheme,"hkps")==0) + if(ascii_strcasecmp(opt->scheme,"hkps")==0) { proto="https"; port="443"; diff --git a/po/ChangeLog b/po/ChangeLog index c0f6240f5..d8e9c4263 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2011-01-20 Werner Koch <wk@g10code.com> + + * de.po: Fix two fuzzies. + 2010-10-21 Werner Koch <wk@g10code.com> * POTFILES.in: Add files in dirmngr/. @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg-2.1.0\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2010-11-23 19:37+0100\n" -"PO-Revision-Date: 2010-11-23 19:38+0100\n" +"POT-Creation-Date: 2011-01-20 15:15+0100\n" +"PO-Revision-Date: 2011-01-20 15:10+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: German <de@li.org>\n" "MIME-Version: 1.0\n" @@ -114,23 +114,23 @@ msgid "ssh keys greater than %d bits are not supported\n" msgstr "SSH Schlüssel von mehr als %d Bits werden nicht unterstützt\n" #: agent/command-ssh.c:685 common/dotlock.c:326 g10/card-util.c:841 -#: g10/exec.c:481 g10/gpg.c:1128 g10/keygen.c:3202 g10/keyring.c:1213 +#: g10/exec.c:481 g10/gpg.c:1129 g10/keygen.c:3202 g10/keyring.c:1213 #: g10/keyring.c:1521 g10/openfile.c:290 g10/openfile.c:383 g10/sign.c:870 -#: g10/sign.c:1181 g10/tdbio.c:548 +#: g10/sign.c:1181 g10/tdbio.c:562 #, c-format msgid "can't create `%s': %s\n" msgstr "'%s' kann nicht erzeugt werden: %s\n" #: agent/command-ssh.c:697 common/helpfile.c:47 g10/card-util.c:795 #: g10/dearmor.c:60 g10/dearmor.c:107 g10/decrypt.c:67 g10/decrypt.c:129 -#: g10/decrypt.c:146 g10/encrypt.c:198 g10/encrypt.c:547 g10/gpg.c:1129 +#: g10/decrypt.c:146 g10/encrypt.c:198 g10/encrypt.c:547 g10/gpg.c:1130 #: g10/import.c:197 g10/keygen.c:2713 g10/keyring.c:1547 g10/openfile.c:197 #: g10/openfile.c:211 g10/openfile.c:368 g10/plaintext.c:584 g10/sign.c:852 #: g10/sign.c:1047 g10/sign.c:1165 g10/sign.c:1323 g10/tdbdump.c:142 -#: g10/tdbdump.c:150 g10/tdbio.c:552 g10/tdbio.c:616 g10/verify.c:98 +#: g10/tdbdump.c:150 g10/tdbio.c:566 g10/tdbio.c:647 g10/verify.c:98 #: g10/verify.c:161 sm/gpgsm.c:2054 sm/gpgsm.c:2084 sm/gpgsm.c:2122 -#: sm/qualified.c:66 dirmngr/certcache.c:359 dirmngr/crlcache.c:2380 -#: dirmngr/dirmngr.c:1458 +#: sm/qualified.c:66 dirmngr/certcache.c:359 dirmngr/crlcache.c:2405 +#: dirmngr/dirmngr.c:1466 #, c-format msgid "can't open `%s': %s\n" msgstr "'%s' kann nicht geöffnet werden: %s\n" @@ -357,7 +357,7 @@ msgstr "Im Server Modus ausführen" msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausführen" -#: agent/gpg-agent.c:126 g10/gpg.c:493 g10/gpgv.c:71 kbx/kbxutil.c:88 +#: agent/gpg-agent.c:126 g10/gpg.c:494 g10/gpgv.c:71 kbx/kbxutil.c:88 #: scd/scdaemon.c:110 sm/gpgsm.c:281 dirmngr/dirmngr-client.c:68 #: dirmngr/dirmngr.c:149 dirmngr/dirmngr_ldap.c:127 #: tools/gpg-connect-agent.c:71 tools/gpgconf.c:79 tools/symcryptrun.c:163 @@ -446,9 +446,9 @@ msgstr "|DATEI|Schreibe die Umgebungsvariablen auf DATEI" #. 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. -#: agent/gpg-agent.c:334 agent/preset-passphrase.c:93 agent/protect-tool.c:148 -#: g10/gpg.c:820 g10/gpgv.c:114 kbx/kbxutil.c:113 scd/scdaemon.c:247 -#: sm/gpgsm.c:529 dirmngr/dirmngr-client.c:147 dirmngr/dirmngr.c:298 +#: agent/gpg-agent.c:341 agent/preset-passphrase.c:93 agent/protect-tool.c:148 +#: g10/gpg.c:821 g10/gpgv.c:114 kbx/kbxutil.c:113 scd/scdaemon.c:247 +#: sm/gpgsm.c:529 dirmngr/dirmngr-client.c:147 dirmngr/dirmngr.c:302 #: dirmngr/dirmngr_ldap.c:197 tools/gpg-connect-agent.c:188 #: tools/gpgconf.c:101 tools/symcryptrun.c:203 tools/gpg-check-pattern.c:141 msgid "Please report bugs to <@EMAIL@>.\n" @@ -456,11 +456,11 @@ msgstr "" "Berichte über Programmfehler bitte in englisch an <@EMAIL@>.\n" "Sinn- oder Schreibfehler in den deutschen Texten bitte an <de@li.org>.\n" -#: agent/gpg-agent.c:343 +#: agent/gpg-agent.c:350 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Aufruf: gpg-agent [Optionen] (-h für Hilfe)" -#: agent/gpg-agent.c:345 +#: agent/gpg-agent.c:352 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -468,147 +468,147 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Befehl [Argumente]]\n" "Verwaltung von geheimen Schlüsseln für GnuPG\n" -#: agent/gpg-agent.c:391 g10/gpg.c:1013 scd/scdaemon.c:320 sm/gpgsm.c:679 -#: dirmngr/dirmngr.c:367 +#: agent/gpg-agent.c:398 g10/gpg.c:1014 scd/scdaemon.c:320 sm/gpgsm.c:679 +#: dirmngr/dirmngr.c:371 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungültige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:616 agent/protect-tool.c:561 kbx/kbxutil.c:428 -#: scd/scdaemon.c:427 sm/gpgsm.c:919 sm/gpgsm.c:922 dirmngr/dirmngr.c:625 -#: dirmngr/dirmngr.c:628 tools/symcryptrun.c:1001 +#: agent/gpg-agent.c:623 agent/protect-tool.c:561 kbx/kbxutil.c:428 +#: scd/scdaemon.c:427 sm/gpgsm.c:919 sm/gpgsm.c:922 dirmngr/dirmngr.c:629 +#: dirmngr/dirmngr.c:632 tools/symcryptrun.c:1001 #: tools/gpg-check-pattern.c:177 #, c-format msgid "%s is too old (need %s, have %s)\n" msgstr "Die Bibliothek %s ist nicht aktuell (benötige %s, habe %s)\n" -#: agent/gpg-agent.c:730 g10/gpg.c:2121 scd/scdaemon.c:513 sm/gpgsm.c:1019 -#: dirmngr/dirmngr.c:743 +#: agent/gpg-agent.c:737 g10/gpg.c:2122 scd/scdaemon.c:513 sm/gpgsm.c:1019 +#: dirmngr/dirmngr.c:751 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Hinweis: Keine voreingestellte Optionendatei '%s' vorhanden\n" -#: agent/gpg-agent.c:741 agent/gpg-agent.c:1343 g10/gpg.c:2125 -#: scd/scdaemon.c:518 sm/gpgsm.c:1023 dirmngr/dirmngr.c:748 -#: dirmngr/dirmngr.c:1564 tools/symcryptrun.c:934 +#: agent/gpg-agent.c:748 agent/gpg-agent.c:1350 g10/gpg.c:2126 +#: scd/scdaemon.c:518 sm/gpgsm.c:1023 dirmngr/dirmngr.c:756 +#: dirmngr/dirmngr.c:1572 tools/symcryptrun.c:934 #, c-format msgid "option file `%s': %s\n" msgstr "Optionendatei '%s': %s\n" -#: agent/gpg-agent.c:749 g10/gpg.c:2132 scd/scdaemon.c:526 sm/gpgsm.c:1030 -#: dirmngr/dirmngr.c:756 +#: agent/gpg-agent.c:756 g10/gpg.c:2133 scd/scdaemon.c:526 sm/gpgsm.c:1030 +#: dirmngr/dirmngr.c:764 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus '%s' gelesen\n" -#: agent/gpg-agent.c:1118 g10/plaintext.c:160 g10/plaintext.c:169 +#: agent/gpg-agent.c:1125 g10/plaintext.c:160 g10/plaintext.c:169 #: g10/plaintext.c:175 g10/plaintext.c:198 #, c-format msgid "error creating `%s': %s\n" msgstr "Fehler beim Erstellen von `%s': %s\n" -#: agent/gpg-agent.c:1464 agent/gpg-agent.c:1591 agent/gpg-agent.c:1630 +#: agent/gpg-agent.c:1470 agent/gpg-agent.c:1597 agent/gpg-agent.c:1636 #: g10/exec.c:196 g10/openfile.c:444 scd/scdaemon.c:1037 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Verzeichnis `%s' kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1478 scd/scdaemon.c:1051 dirmngr/dirmngr.c:956 +#: agent/gpg-agent.c:1484 scd/scdaemon.c:1051 dirmngr/dirmngr.c:964 msgid "name of socket too long\n" msgstr "Der Name des Sockets ist zu lang\n" -#: agent/gpg-agent.c:1501 scd/scdaemon.c:1074 dirmngr/dirmngr.c:963 +#: agent/gpg-agent.c:1507 scd/scdaemon.c:1074 dirmngr/dirmngr.c:971 #, c-format msgid "can't create socket: %s\n" msgstr "Socket kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1510 +#: agent/gpg-agent.c:1516 #, c-format msgid "socket name `%s' is too long\n" msgstr "Der Name des Sockets `%s' ist zu lang\n" -#: agent/gpg-agent.c:1538 +#: agent/gpg-agent.c:1544 msgid "a gpg-agent is already running - not starting a new one\n" msgstr "Ein gpg-agent läuft bereits - ein weiterer wird nicht gestartet\n" -#: agent/gpg-agent.c:1549 scd/scdaemon.c:1093 dirmngr/dirmngr.c:987 +#: agent/gpg-agent.c:1555 scd/scdaemon.c:1093 dirmngr/dirmngr.c:995 msgid "error getting nonce for the socket\n" msgstr "Fehler beim Ermitteln der \"Nonce\" dieses Sockets\n" -#: agent/gpg-agent.c:1554 scd/scdaemon.c:1096 dirmngr/dirmngr.c:990 +#: agent/gpg-agent.c:1560 scd/scdaemon.c:1096 dirmngr/dirmngr.c:998 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" -#: agent/gpg-agent.c:1566 scd/scdaemon.c:1105 dirmngr/dirmngr.c:999 +#: agent/gpg-agent.c:1572 scd/scdaemon.c:1105 dirmngr/dirmngr.c:1007 #, c-format msgid "listen() failed: %s\n" msgstr "Der listen()-Aufruf ist fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1572 scd/scdaemon.c:1112 dirmngr/dirmngr.c:1005 +#: agent/gpg-agent.c:1578 scd/scdaemon.c:1112 dirmngr/dirmngr.c:1013 #, c-format msgid "listening on socket `%s'\n" msgstr "Es wird auf Socket `%s' gehört\n" -#: agent/gpg-agent.c:1594 agent/gpg-agent.c:1635 g10/openfile.c:447 +#: agent/gpg-agent.c:1600 agent/gpg-agent.c:1641 g10/openfile.c:447 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichnis `%s' erzeugt\n" -#: agent/gpg-agent.c:1641 +#: agent/gpg-agent.c:1647 #, c-format msgid "stat() failed for `%s': %s\n" msgstr "stat()-Aufruf für `%s' fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1645 +#: agent/gpg-agent.c:1651 #, c-format msgid "can't use `%s' as home directory\n" msgstr "Die Datei `%s' kann nicht als Home-Verzeichnis benutzt werden\n" -#: agent/gpg-agent.c:1777 scd/scdaemon.c:1128 dirmngr/dirmngr.c:1681 +#: agent/gpg-agent.c:1785 scd/scdaemon.c:1128 dirmngr/dirmngr.c:1689 #, c-format msgid "error reading nonce on fd %d: %s\n" msgstr "Fehler beim Lesen der \"Nonce\" von FD %d: %s\n" -#: agent/gpg-agent.c:1799 +#: agent/gpg-agent.c:1810 #, c-format msgid "handler 0x%lx for fd %d started\n" msgstr "Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1804 +#: agent/gpg-agent.c:1815 #, c-format msgid "handler 0x%lx for fd %d terminated\n" msgstr "Handhabungsroutine 0x%lx für den fd %d beendet\n" -#: agent/gpg-agent.c:1824 +#: agent/gpg-agent.c:1835 #, c-format msgid "ssh handler 0x%lx for fd %d started\n" msgstr "SSH-Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1829 +#: agent/gpg-agent.c:1840 #, c-format msgid "ssh handler 0x%lx for fd %d terminated\n" msgstr "SSH-Handhabungsroutine 0x%lx für fd %d beendet\n" -#: agent/gpg-agent.c:1973 scd/scdaemon.c:1265 +#: agent/gpg-agent.c:1985 scd/scdaemon.c:1265 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select()-Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:2096 scd/scdaemon.c:1332 +#: agent/gpg-agent.c:2108 scd/scdaemon.c:1332 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" -#: agent/gpg-agent.c:2232 +#: agent/gpg-agent.c:2244 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:2243 common/simple-pwquery.c:352 common/asshelp.c:497 +#: agent/gpg-agent.c:2255 common/simple-pwquery.c:352 common/asshelp.c:497 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "fehlerhaft aufgebaute GPG_AGENT_INFO - Umgebungsvariable\n" -#: agent/gpg-agent.c:2256 common/simple-pwquery.c:364 common/asshelp.c:509 +#: agent/gpg-agent.c:2268 common/simple-pwquery.c:364 common/asshelp.c:509 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "GPG-Agent-Protokoll-Version %d wird nicht unterstützt\n" @@ -625,7 +625,7 @@ msgstr "" "Syntax: gpg-preset-passphrase [Optionen] KEYGRIP\n" "Kennwortpuffer-Pflege\n" -#: agent/protect-tool.c:105 g10/gpg.c:376 kbx/kbxutil.c:71 sm/gpgsm.c:187 +#: agent/protect-tool.c:105 g10/gpg.c:377 kbx/kbxutil.c:71 sm/gpgsm.c:187 #: dirmngr/dirmngr.c:132 tools/gpgconf.c:59 msgid "" "@Commands:\n" @@ -634,7 +634,7 @@ msgstr "" "@Befehle:\n" " " -#: agent/protect-tool.c:114 g10/gpg.c:444 g10/gpgv.c:69 kbx/kbxutil.c:81 +#: agent/protect-tool.c:114 g10/gpg.c:445 g10/gpgv.c:69 kbx/kbxutil.c:81 #: sm/gpgsm.c:227 dirmngr/dirmngr.c:147 tools/gpg-connect-agent.c:69 #: tools/gpgconf.c:76 tools/symcryptrun.c:156 msgid "" @@ -696,45 +696,45 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "error while asking for the passphrase: %s\n" msgstr "Fehler bei der Abfrage der Passphrase: %s\n" -#: agent/trustlist.c:135 agent/trustlist.c:332 dirmngr/dirmngr.c:1366 +#: agent/trustlist.c:135 agent/trustlist.c:335 dirmngr/dirmngr.c:1374 #, c-format msgid "error opening `%s': %s\n" msgstr "Fehler beim Öffnen von `%s': %s\n" -#: agent/trustlist.c:150 common/helpfile.c:63 common/helpfile.c:79 +#: agent/trustlist.c:151 common/helpfile.c:63 common/helpfile.c:79 #, c-format msgid "file `%s', line %d: %s\n" msgstr "Datei `%s', Zeile %d: %s\n" -#: agent/trustlist.c:170 agent/trustlist.c:178 +#: agent/trustlist.c:173 agent/trustlist.c:181 #, c-format msgid "statement \"%s\" ignored in `%s', line %d\n" msgstr "" "Anweisung \"%s\" in `%s', Zeile %d\n" " ignoriert\n" -#: agent/trustlist.c:184 +#: agent/trustlist.c:187 #, c-format msgid "system trustlist `%s' not available\n" msgstr "" "Systemliste der vertrauenswürdigen Zertifikate '%s' ist nicht vorhanden\n" -#: agent/trustlist.c:228 +#: agent/trustlist.c:231 #, c-format msgid "bad fingerprint in `%s', line %d\n" msgstr "fehlerhafter Fingerabdruck in `%s', Zeile %d\n" -#: agent/trustlist.c:253 agent/trustlist.c:260 +#: agent/trustlist.c:256 agent/trustlist.c:263 #, c-format msgid "invalid keyflag in `%s', line %d\n" msgstr "Ungültiges Schlüsselflag in `%s', Zeile %d\n" -#: agent/trustlist.c:294 common/helpfile.c:126 +#: agent/trustlist.c:297 common/helpfile.c:126 #, c-format msgid "error reading `%s', line %d: %s\n" msgstr "Fehler beim Lesen von `%s', Zeile %d: %s\n" -#: agent/trustlist.c:398 agent/trustlist.c:448 +#: agent/trustlist.c:401 agent/trustlist.c:451 msgid "error reading list of trusted root certificates\n" msgstr "Fehler beim Lesen der Liste vertrauenswürdiger root-Zertifikate\n" @@ -746,7 +746,7 @@ msgstr "Fehler beim Lesen der Liste vertrauenswürdiger root-Zertifikate\n" #. plain % sign, you need to encode it as "%%25". The #. "%s" gets replaced by the name as stored in the #. certificate. -#: agent/trustlist.c:609 +#: agent/trustlist.c:612 #, c-format msgid "" "Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " @@ -755,11 +755,11 @@ msgstr "" "Wenn Sie vollständiges Vertrauen haben, daß%%0A \"%s\"%%" "0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit \"Ja\"." -#: agent/trustlist.c:618 common/audit.c:467 +#: agent/trustlist.c:621 common/audit.c:467 msgid "Yes" msgstr "Ja" -#: agent/trustlist.c:618 common/audit.c:469 +#: agent/trustlist.c:621 common/audit.c:469 msgid "No" msgstr "Nein" @@ -771,7 +771,7 @@ msgstr "Nein" #. "%%25". The second "%s" gets replaced by a hexdecimal #. fingerprint string whereas the first one receives the name #. as stored in the certificate. -#: agent/trustlist.c:652 +#: agent/trustlist.c:655 #, c-format msgid "" "Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " @@ -783,11 +783,11 @@ msgstr "" #. TRANSLATORS: "Correct" is the label of a button and intended #. to be hit if the fingerprint matches the one of the CA. The #. other button is "the default "Cancel" of the Pinentry. -#: agent/trustlist.c:666 +#: agent/trustlist.c:669 msgid "Correct" msgstr "Korrekt" -#: agent/trustlist.c:666 +#: agent/trustlist.c:669 msgid "Wrong" msgstr "Falsch" @@ -862,7 +862,7 @@ msgid "error creating a stream for a pipe: %s\n" msgstr "Fehler beim Erzeugen eines \"streams\" zu einer \"pipe\": %s\n" #: common/exechelp-posix.c:399 common/exechelp-posix.c:465 -#: common/exechelp-posix.c:579 dirmngr/dirmngr.c:1019 +#: common/exechelp-posix.c:579 dirmngr/dirmngr.c:1027 #, c-format msgid "error forking process: %s\n" msgstr "Fehler beim \"Forken\" des Prozess: %s\n" @@ -894,12 +894,12 @@ msgstr "Fehler bei Ausführung von `%s': beendet\n" msgid "error getting exit code of process %d: %s\n" msgstr "Fehler beim Holen des Exitwerte des Prozesses %d: %s\n" -#: common/http.c:1550 +#: common/http.c:1607 #, c-format msgid "error creating socket: %s\n" msgstr "Fehler beim Erstellen des Sockets: %s\n" -#: common/http.c:1594 +#: common/http.c:1651 msgid "host not found" msgstr "Host nicht gefunden" @@ -999,45 +999,35 @@ msgstr "" msgid "out of core while allocating %lu bytes" msgstr "Kein Speicher mehr vorhanden, als %lu Byte zugewiesen werden sollten" -#: common/asshelp.c:379 +#: common/asshelp.c:378 #, c-format msgid "no running gpg-agent - starting `%s'\n" msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n" -#: common/asshelp.c:435 +#: common/asshelp.c:436 #, c-format -msgid "waiting %d seconds for the agent to come up\n" -msgstr "Warte %d Sekunden bis der gpg-agent bereit ist\n" +msgid "waiting for the agent to come up ... (%ds)\n" +msgstr "Warte bis der gpg-agent bereit ist ... (%ds)\n" -#: common/asshelp.c:445 -#, c-format -msgid "connection to agent established (%ds)\n" -msgstr "Verbindung zum gpg-agent aufgebaut (%ds)\n" +#: common/asshelp.c:445 common/asshelp.c:534 +msgid "connection to agent established\n" +msgstr "Verbindung zum gpg-agent aufgebaut\n" #: common/asshelp.c:520 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht möglich - Ersatzmethode wird versucht\n" -#: common/asshelp.c:534 -msgid "connection to agent established\n" -msgstr "Verbindung zum gpg-agent aufgebaut\n" - #: common/asshelp.c:596 #, c-format msgid "no running Dirmngr - starting `%s'\n" msgstr "Kein aktiver Dirmngr - `%s' wird gestartet\n" -#: common/asshelp.c:628 -#, c-format -msgid "waiting %d seconds for the dirmngr to come up\n" -msgstr "Warte %d Sekunden bis der Dirmngr bereit ist\n" - -#: common/asshelp.c:638 +#: common/asshelp.c:630 #, c-format -msgid "connection to the dirmngr established (%ds)\n" -msgstr "Verbindung zum Dirmngr aufgebaut (%ds)\n" +msgid "waiting for the dirmngr to come up ... (%ds)\n" +msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n" -#: common/asshelp.c:667 +#: common/asshelp.c:639 common/asshelp.c:668 msgid "connection to the dirmngr established\n" msgstr "Verbindung zum Dirmngr aufgebaut\n" @@ -1285,7 +1275,7 @@ msgstr "Option \"%.50s\" ist mehrdeutig\n" msgid "command \"%.50s\" is ambiguous\n" msgstr "Befehl \"%.50s\" ist mehrdeutig\n" -#: common/argparse.c:266 dirmngr/dirmngr.c:1037 +#: common/argparse.c:266 dirmngr/dirmngr.c:1045 msgid "out of core\n" msgstr "Nicht genügend Speicher\n" @@ -1294,7 +1284,7 @@ msgstr "Nicht genügend Speicher\n" msgid "invalid option \"%.50s\"\n" msgstr "Ungültige Option \"%.50s\"\n" -#: common/logging.c:822 +#: common/logging.c:860 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Programmfehler) gefunden ... (%s:%d)\n" @@ -1562,9 +1552,9 @@ msgstr "Fehler: URL ist zu lang (Grenze beträgt %d Zeichen).\n" msgid "error allocating enough memory: %s\n" msgstr "Fehler beim Zuteilen genügenden Speichers: %s\n" -#: g10/card-util.c:814 g10/import.c:291 dirmngr/crlcache.c:649 +#: g10/card-util.c:814 g10/import.c:317 dirmngr/crlcache.c:649 #: dirmngr/crlcache.c:654 dirmngr/crlcache.c:908 dirmngr/crlcache.c:914 -#: dirmngr/dirmngr.c:1404 +#: dirmngr/dirmngr.c:1412 #, c-format msgid "error reading `%s': %s\n" msgstr "Fehler beim Lesen von `%s': %s\n" @@ -1822,18 +1812,18 @@ msgstr "Ungültiger Befehl (versuchen Sie's mal mit \"help\")\n" msgid "--output doesn't work for this command\n" msgstr "--output funktioniert nicht bei diesem Befehl\n" -#: g10/decrypt.c:240 g10/gpg.c:4049 g10/keyring.c:379 g10/keyring.c:690 +#: g10/decrypt.c:240 g10/gpg.c:4050 g10/keyring.c:379 g10/keyring.c:690 #, c-format msgid "can't open `%s'\n" msgstr "'%s' kann nicht geöffnet werden\n" -#: g10/delkey.c:73 g10/export.c:637 g10/keyedit.c:3355 g10/keyserver.c:1749 +#: g10/delkey.c:73 g10/export.c:691 g10/keyedit.c:3355 g10/keyserver.c:1134 #: g10/revoke.c:227 #, c-format msgid "key \"%s\" not found: %s\n" msgstr "Schlüssel \"%s\" nicht gefunden: %s\n" -#: g10/delkey.c:81 g10/export.c:701 g10/getkey.c:2881 g10/keyserver.c:1763 +#: g10/delkey.c:81 g10/export.c:755 g10/getkey.c:2881 g10/keyserver.c:1148 #: g10/revoke.c:233 g10/revoke.c:479 #, c-format msgid "error reading keyblock: %s\n" @@ -2054,25 +2044,25 @@ msgstr "Während des Exports soviel wie möglich vom Schlüssel entfernen" msgid "export keys in an S-expression based format" msgstr "Exportiere Schlüssel in einem auf S-Ausdrücken basierenden Format" -#: g10/export.c:652 +#: g10/export.c:706 msgid "exporting secret keys not allowed\n" msgstr "Exportieren geheimer Schlüssel ist nicht erlaubt\n" -#: g10/export.c:725 +#: g10/export.c:779 #, c-format msgid "key %s: PGP 2.x style key - skipped\n" msgstr "Schlüssel %s: PGP 2.x-artiger Schlüssel - übersprungen\n" -#: g10/export.c:909 +#: g10/export.c:963 #, c-format msgid "key %s: key material on-card - skipped\n" msgstr "Schlüssel %s: Schlüsselmaterial ist auf einer Karte - übersprungen\n" -#: g10/export.c:1008 +#: g10/export.c:1062 msgid " - skipped" msgstr " - übersprungen" -#: g10/export.c:1079 +#: g10/export.c:1133 msgid "WARNING: nothing exported\n" msgstr "WARNUNG: Nichts exportiert\n" @@ -2115,171 +2105,171 @@ msgid "no secret subkey for public subkey %s - ignoring\n" msgstr "" "Kein privater Unterschlüssel zum öffentlichen Unterschlüssel %s - ignoriert\n" -#: g10/gpg.c:378 sm/gpgsm.c:189 +#: g10/gpg.c:379 sm/gpgsm.c:189 msgid "make a signature" msgstr "Eine Signatur erzeugen" -#: g10/gpg.c:379 sm/gpgsm.c:190 +#: g10/gpg.c:380 sm/gpgsm.c:190 msgid "make a clear text signature" msgstr "Eine Klartextsignatur erzeugen" -#: g10/gpg.c:380 sm/gpgsm.c:191 +#: g10/gpg.c:381 sm/gpgsm.c:191 msgid "make a detached signature" msgstr "Eine abgetrennte Signatur erzeugen" -#: g10/gpg.c:381 sm/gpgsm.c:192 +#: g10/gpg.c:382 sm/gpgsm.c:192 msgid "encrypt data" msgstr "Daten verschlüsseln" -#: g10/gpg.c:383 sm/gpgsm.c:193 +#: g10/gpg.c:384 sm/gpgsm.c:193 msgid "encryption only with symmetric cipher" msgstr "Daten symmetrisch verschlüsseln" -#: g10/gpg.c:385 sm/gpgsm.c:194 +#: g10/gpg.c:386 sm/gpgsm.c:194 msgid "decrypt data (default)" msgstr "Daten entschlüsseln (Voreinstellung)" -#: g10/gpg.c:387 sm/gpgsm.c:195 +#: g10/gpg.c:388 sm/gpgsm.c:195 msgid "verify a signature" msgstr "Signatur prüfen" -#: g10/gpg.c:389 sm/gpgsm.c:196 +#: g10/gpg.c:390 sm/gpgsm.c:196 msgid "list keys" msgstr "Liste der Schlüssel" -#: g10/gpg.c:391 +#: g10/gpg.c:392 msgid "list keys and signatures" msgstr "Liste der Schlüssel und ihrer Signaturen" -#: g10/gpg.c:392 +#: g10/gpg.c:393 msgid "list and check key signatures" msgstr "Signaturen der Schlüssel auflisten und prüfen" -#: g10/gpg.c:393 sm/gpgsm.c:201 +#: g10/gpg.c:394 sm/gpgsm.c:201 msgid "list keys and fingerprints" msgstr "Liste der Schlüssel und ihrer \"Fingerabdrücke\"" -#: g10/gpg.c:394 sm/gpgsm.c:199 +#: g10/gpg.c:395 sm/gpgsm.c:199 msgid "list secret keys" msgstr "Liste der geheimen Schlüssel" -#: g10/gpg.c:395 sm/gpgsm.c:202 +#: g10/gpg.c:396 sm/gpgsm.c:202 msgid "generate a new key pair" msgstr "Ein neues Schlüsselpaar erzeugen" -#: g10/gpg.c:396 +#: g10/gpg.c:397 msgid "generate a revocation certificate" msgstr "Ein Schlüsselwiderruf-Zertifikat erzeugen" -#: g10/gpg.c:398 sm/gpgsm.c:204 +#: g10/gpg.c:399 sm/gpgsm.c:204 msgid "remove keys from the public keyring" msgstr "Schlüssel aus dem öff. Schlüsselbund entfernen" -#: g10/gpg.c:400 +#: g10/gpg.c:401 msgid "remove keys from the secret keyring" msgstr "Schlüssel aus dem geh. Schlüsselbund entfernen" -#: g10/gpg.c:401 +#: g10/gpg.c:402 msgid "sign a key" msgstr "Schlüssel signieren" -#: g10/gpg.c:402 +#: g10/gpg.c:403 msgid "sign a key locally" msgstr "Schlüssel nur für diesen Rechner signieren" -#: g10/gpg.c:403 +#: g10/gpg.c:404 msgid "sign or edit a key" msgstr "Signieren oder bearbeiten eines Schlüssels" -#: g10/gpg.c:405 sm/gpgsm.c:216 +#: g10/gpg.c:406 sm/gpgsm.c:216 msgid "change a passphrase" msgstr "Die Passphrase ändern" -#: g10/gpg.c:407 +#: g10/gpg.c:408 msgid "export keys" msgstr "Schlüssel exportieren" -#: g10/gpg.c:408 sm/gpgsm.c:205 +#: g10/gpg.c:409 sm/gpgsm.c:205 msgid "export keys to a key server" msgstr "Schlüssel zu einem Schlü.server exportieren" -#: g10/gpg.c:409 sm/gpgsm.c:206 +#: g10/gpg.c:410 sm/gpgsm.c:206 msgid "import keys from a key server" msgstr "Schlüssel von einem Schlü.server importieren" -#: g10/gpg.c:411 +#: g10/gpg.c:412 msgid "search for keys on a key server" msgstr "Schlüssel auf einem Schlü.server suchen" -#: g10/gpg.c:413 +#: g10/gpg.c:414 msgid "update all keys from a keyserver" msgstr "alle Schlüssel per Schlü.server aktualisieren" -#: g10/gpg.c:418 +#: g10/gpg.c:419 msgid "import/merge keys" msgstr "Schlüssel importieren/kombinieren" -#: g10/gpg.c:421 +#: g10/gpg.c:422 msgid "print the card status" msgstr "den Karten-Status ausgeben" -#: g10/gpg.c:422 +#: g10/gpg.c:423 msgid "change data on a card" msgstr "Daten auf einer Karte ändern" -#: g10/gpg.c:423 +#: g10/gpg.c:424 msgid "change a card's PIN" msgstr "PIN einer Karte ändern" -#: g10/gpg.c:432 +#: g10/gpg.c:433 msgid "update the trust database" msgstr "Ändern der \"Trust\"-Datenbank" -#: g10/gpg.c:439 +#: g10/gpg.c:440 msgid "print message digests" msgstr "Hashwerte für die Dateien ausgeben" -#: g10/gpg.c:442 sm/gpgsm.c:211 +#: g10/gpg.c:443 sm/gpgsm.c:211 msgid "run in server mode" msgstr "Im Server Modus ausführen" -#: g10/gpg.c:446 sm/gpgsm.c:229 +#: g10/gpg.c:447 sm/gpgsm.c:229 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII-Hülle versehen" -#: g10/gpg.c:449 sm/gpgsm.c:242 +#: g10/gpg.c:450 sm/gpgsm.c:242 msgid "|USER-ID|encrypt for USER-ID" msgstr "|USER-ID|Verschlüsseln für USER-ID" -#: g10/gpg.c:462 sm/gpgsm.c:278 +#: g10/gpg.c:463 sm/gpgsm.c:278 msgid "|USER-ID|use USER-ID to sign or decrypt" msgstr "|USER-ID|Mit USER-ID signieren bzw. entschlüsseln" -#: g10/gpg.c:467 +#: g10/gpg.c:468 msgid "|N|set compress level to N (0 disables)" msgstr "|N|Kompressionsstufe auf N setzen (0=keine)" -#: g10/gpg.c:473 +#: g10/gpg.c:474 msgid "use canonical text mode" msgstr "Textmodus benutzen" -#: g10/gpg.c:490 sm/gpgsm.c:280 +#: g10/gpg.c:491 sm/gpgsm.c:280 msgid "|FILE|write output to FILE" msgstr "|DATEI|Ausgabe auf DATEI schreiben" -#: g10/gpg.c:506 kbx/kbxutil.c:90 sm/gpgsm.c:292 tools/gpgconf.c:81 +#: g10/gpg.c:507 kbx/kbxutil.c:90 sm/gpgsm.c:292 tools/gpgconf.c:81 msgid "do not make any changes" msgstr "Keine wirklichen Änderungen durchführen" -#: g10/gpg.c:507 +#: g10/gpg.c:508 msgid "prompt before overwriting" msgstr "vor Überschreiben nachfragen" -#: g10/gpg.c:559 +#: g10/gpg.c:560 msgid "use strict OpenPGP behavior" msgstr "OpenPGP-Verhalten strikt beachten" -#: g10/gpg.c:589 sm/gpgsm.c:336 +#: g10/gpg.c:590 sm/gpgsm.c:336 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -2288,7 +2278,7 @@ msgstr "" "(Auf der \"man\"-Seite ist eine vollständige Liste aller Befehle und " "Optionen)\n" -#: g10/gpg.c:592 sm/gpgsm.c:339 +#: g10/gpg.c:593 sm/gpgsm.c:339 msgid "" "@\n" "Examples:\n" @@ -2308,11 +2298,11 @@ msgstr "" " --list-keys [Namen] Schlüssel anzeigen\n" " --fingerprint [Namen] \"Fingerabdrücke\" anzeigen\n" -#: g10/gpg.c:842 +#: g10/gpg.c:843 msgid "Usage: gpg [options] [files] (-h for help)" msgstr "Aufruf: gpg [Optionen] [Dateien] (-h für Hilfe)" -#: g10/gpg.c:845 +#: g10/gpg.c:846 msgid "" "Syntax: gpg [options] [files]\n" "sign, check, encrypt or decrypt\n" @@ -2322,7 +2312,7 @@ msgstr "" "Signieren, prüfen, verschlüsseln, entschlüsseln.\n" "Die voreingestellte Operation ist abhängig von den Eingabedaten\n" -#: g10/gpg.c:856 sm/gpgsm.c:553 +#: g10/gpg.c:857 sm/gpgsm.c:553 msgid "" "\n" "Supported algorithms:\n" @@ -2330,73 +2320,73 @@ msgstr "" "\n" "Unterstützte Verfahren:\n" -#: g10/gpg.c:859 +#: g10/gpg.c:860 msgid "Pubkey: " msgstr "Öff. Schlüssel: " -#: g10/gpg.c:866 g10/keyedit.c:2325 +#: g10/gpg.c:867 g10/keyedit.c:2325 msgid "Cipher: " msgstr "Verschlü.: " -#: g10/gpg.c:873 +#: g10/gpg.c:874 msgid "Hash: " msgstr "Hash: " -#: g10/gpg.c:880 g10/keyedit.c:2374 +#: g10/gpg.c:881 g10/keyedit.c:2374 msgid "Compression: " msgstr "Komprimierung: " -#: g10/gpg.c:950 +#: g10/gpg.c:951 msgid "usage: gpg [options] " msgstr "Aufruf: gpg [Optionen] " -#: g10/gpg.c:1164 sm/gpgsm.c:726 +#: g10/gpg.c:1165 sm/gpgsm.c:726 msgid "conflicting commands\n" msgstr "Widersprüchliche Befehle\n" -#: g10/gpg.c:1182 +#: g10/gpg.c:1183 #, c-format msgid "no = sign found in group definition `%s'\n" msgstr "Kein '='-Zeichen in der Gruppendefinition gefunden `%s'\n" -#: g10/gpg.c:1379 +#: g10/gpg.c:1380 #, c-format msgid "WARNING: unsafe ownership on homedir `%s'\n" msgstr "WARNUNG: Unsicheres Besitzverhältnis des Home-Verzeichnis `%s'\n" -#: g10/gpg.c:1382 +#: g10/gpg.c:1383 #, c-format msgid "WARNING: unsafe ownership on configuration file `%s'\n" msgstr "WARNUNG: Unsicheres Besitzverhältnis der Konfigurationsdatei `%s'\n" -#: g10/gpg.c:1385 +#: g10/gpg.c:1386 #, c-format msgid "WARNING: unsafe ownership on extension `%s'\n" msgstr "WARNUNG: Unsicheres Besitzverhältnis auf die Erweiterung `%s'\n" -#: g10/gpg.c:1391 +#: g10/gpg.c:1392 #, c-format msgid "WARNING: unsafe permissions on homedir `%s'\n" msgstr "WARNUNG: Unsichere Zugriffsrechte des Home-Verzeichnis `%s'\n" -#: g10/gpg.c:1394 +#: g10/gpg.c:1395 #, c-format msgid "WARNING: unsafe permissions on configuration file `%s'\n" msgstr "WARNUNG: Unsichere Zugriffsrechte der Konfigurationsdatei `%s'\n" -#: g10/gpg.c:1397 +#: g10/gpg.c:1398 #, c-format msgid "WARNING: unsafe permissions on extension `%s'\n" msgstr "WARNUNG: Unsichere Zugriffsrechte auf die Erweiterung `%s'\n" -#: g10/gpg.c:1403 +#: g10/gpg.c:1404 #, c-format msgid "WARNING: unsafe enclosing directory ownership on homedir `%s'\n" msgstr "" "WARNUNG: Unsicheres Besitzverhältnis des umgebenden Verzeichnisses für Home-" "Verzeichnis `%s'\n" -#: g10/gpg.c:1406 +#: g10/gpg.c:1407 #, c-format msgid "" "WARNING: unsafe enclosing directory ownership on configuration file `%s'\n" @@ -2404,20 +2394,20 @@ msgstr "" "WARNUNG: Unsicheres Besitzverhältnis des umgebenden Verzeichnisses der " "Konfigurationsdatei `%s'\n" -#: g10/gpg.c:1409 +#: g10/gpg.c:1410 #, c-format msgid "WARNING: unsafe enclosing directory ownership on extension `%s'\n" msgstr "" "WARNUNG: Unsicheres Besitzverhältnis des umgebenden Verzeichnisses `%s'\n" -#: g10/gpg.c:1415 +#: g10/gpg.c:1416 #, c-format msgid "WARNING: unsafe enclosing directory permissions on homedir `%s'\n" msgstr "" "WARNUNG: Unsichere Zugriffsrechte des umgebenden Verzeichnisses des Home-" "Verzeichnisses `%s'\n" -#: g10/gpg.c:1418 +#: g10/gpg.c:1419 #, c-format msgid "" "WARNING: unsafe enclosing directory permissions on configuration file `%s'\n" @@ -2425,481 +2415,481 @@ msgstr "" "WARNUNG: Unsichere Zugriffsrechte des umgebenden Verzeichnisses der " "Konfigurationsdatei `%s'\n" -#: g10/gpg.c:1421 +#: g10/gpg.c:1422 #, c-format msgid "WARNING: unsafe enclosing directory permissions on extension `%s'\n" msgstr "" "WARNUNG: Unsichere Zugriffsrechte des umgebenden Verzeichnisses auf " "Erweiterung `%s'\n" -#: g10/gpg.c:1604 +#: g10/gpg.c:1605 #, c-format msgid "unknown configuration item `%s'\n" msgstr "Unbekanntes Konfigurationselement `%s'\n" -#: g10/gpg.c:1710 +#: g10/gpg.c:1711 msgid "display photo IDs during key listings" msgstr "Anzeigen der Foto-ID in den Schlüssellisten" -#: g10/gpg.c:1712 +#: g10/gpg.c:1713 msgid "show policy URLs during signature listings" msgstr "Zeige Richtlinien-URL während des listens der Signaturen" -#: g10/gpg.c:1714 +#: g10/gpg.c:1715 msgid "show all notations during signature listings" msgstr "Alle Notationen mit den Signaturen anlisten" -#: g10/gpg.c:1716 +#: g10/gpg.c:1717 msgid "show IETF standard notations during signature listings" msgstr "Zeige IETF-Standard" -#: g10/gpg.c:1720 +#: g10/gpg.c:1721 msgid "show user-supplied notations during signature listings" msgstr "Zeige Benutzer-Notationen während des listens der Signaturen" -#: g10/gpg.c:1722 +#: g10/gpg.c:1723 msgid "show preferred keyserver URLs during signature listings" msgstr "Der bevorzugten Schlüsselserver mit den Signaturen anlisten" -#: g10/gpg.c:1724 +#: g10/gpg.c:1725 msgid "show user ID validity during key listings" msgstr "Zeige Gültigkeit der User-ID in den Schlüssellisten" -#: g10/gpg.c:1726 +#: g10/gpg.c:1727 msgid "show revoked and expired user IDs in key listings" msgstr "Zeige widerrufene und verfallene User-ID in den Schlüssellisten" -#: g10/gpg.c:1728 +#: g10/gpg.c:1729 msgid "show revoked and expired subkeys in key listings" msgstr "Zeige widerrufene und verfallene Unterschlüssel in den Schlüssellisten" -#: g10/gpg.c:1730 +#: g10/gpg.c:1731 msgid "show the keyring name in key listings" msgstr "Anzeigen des Schlüsselbundes, in dem ein Schlüssel drin ist" -#: g10/gpg.c:1732 +#: g10/gpg.c:1733 msgid "show expiration dates during signature listings" msgstr "Das Ablaufdatum mit den Signaturen anlisten" -#: g10/gpg.c:1866 +#: g10/gpg.c:1867 #, c-format msgid "NOTE: old default options file `%s' ignored\n" msgstr "Hinweis: Alte voreingestellte Optionendatei '%s' wurde ignoriert\n" -#: g10/gpg.c:1957 +#: g10/gpg.c:1958 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" ist zu alt (benötigt wird %s, vorhanden ist %" "s)\n" -#: g10/gpg.c:2359 g10/gpg.c:3065 g10/gpg.c:3077 +#: g10/gpg.c:2360 g10/gpg.c:3066 g10/gpg.c:3078 #, c-format msgid "NOTE: %s is not for normal use!\n" msgstr "Hinweis: %s ist nicht für den üblichen Gebrauch gedacht!\n" -#: g10/gpg.c:2548 g10/gpg.c:2560 +#: g10/gpg.c:2549 g10/gpg.c:2561 #, c-format msgid "`%s' is not a valid signature expiration\n" msgstr "`%s' ist kein gültiges Signaturablaufdatum\n" -#: g10/gpg.c:2642 +#: g10/gpg.c:2643 #, c-format msgid "`%s' is not a valid character set\n" msgstr "`%s' ist kein gültiger Zeichensatz\n" -#: g10/gpg.c:2665 g10/gpg.c:2860 g10/keyedit.c:3951 +#: g10/gpg.c:2666 g10/gpg.c:2861 g10/keyedit.c:3951 msgid "could not parse keyserver URL\n" msgstr "Schlüsselserver-URL konnte nicht analysiert werden\n" -#: g10/gpg.c:2677 +#: g10/gpg.c:2678 #, c-format msgid "%s:%d: invalid keyserver options\n" msgstr "%s:%d: ungültige Schlüsselserver-Option\n" -#: g10/gpg.c:2680 +#: g10/gpg.c:2681 msgid "invalid keyserver options\n" msgstr "Ungültige Schlüsselserver-Option\n" -#: g10/gpg.c:2687 +#: g10/gpg.c:2688 #, c-format msgid "%s:%d: invalid import options\n" msgstr "%s:%d: ungültige Import-Option\n" -#: g10/gpg.c:2690 +#: g10/gpg.c:2691 msgid "invalid import options\n" msgstr "Ungültige Import-Option\n" -#: g10/gpg.c:2697 +#: g10/gpg.c:2698 #, c-format msgid "%s:%d: invalid export options\n" msgstr "%s:%d: ungültige Export-Option.\n" -#: g10/gpg.c:2700 +#: g10/gpg.c:2701 msgid "invalid export options\n" msgstr "Ungültige Export-Option\n" -#: g10/gpg.c:2707 +#: g10/gpg.c:2708 #, c-format msgid "%s:%d: invalid list options\n" msgstr "%s:%d: ungültige Listen-Option.\n" -#: g10/gpg.c:2710 +#: g10/gpg.c:2711 msgid "invalid list options\n" msgstr "Ungültige Listen-Option\n" -#: g10/gpg.c:2718 +#: g10/gpg.c:2719 msgid "display photo IDs during signature verification" msgstr "Foto-ID während der Signaturprüfung anzeigen" -#: g10/gpg.c:2720 +#: g10/gpg.c:2721 msgid "show policy URLs during signature verification" msgstr "Richtlinien-URLs während der Signaturprüfung anzeigen" -#: g10/gpg.c:2722 +#: g10/gpg.c:2723 msgid "show all notations during signature verification" msgstr "Alle Notationen während der Signaturprüfung anzeigen" -#: g10/gpg.c:2724 +#: g10/gpg.c:2725 msgid "show IETF standard notations during signature verification" msgstr "Standard-Notationen während der Signaturprüfung anzeigen" -#: g10/gpg.c:2728 +#: g10/gpg.c:2729 msgid "show user-supplied notations during signature verification" msgstr "Benutzer-Notationen während der Signaturprüfung anzeigen" -#: g10/gpg.c:2730 +#: g10/gpg.c:2731 msgid "show preferred keyserver URLs during signature verification" msgstr "" "Die URL für den bevorzugten Schlüsselserver während der Signaturprüfung " "anzeigen" -#: g10/gpg.c:2732 +#: g10/gpg.c:2733 msgid "show user ID validity during signature verification" msgstr "Die Gültigkeit der User-ID während der Signaturprüfung anzeigen" -#: g10/gpg.c:2734 +#: g10/gpg.c:2735 msgid "show revoked and expired user IDs in signature verification" msgstr "Zeige widerrufene und verfallene User-IDs während der Signaturprüfung" -#: g10/gpg.c:2736 +#: g10/gpg.c:2737 msgid "show only the primary user ID in signature verification" msgstr "Zeige nur die Haupt-User-ID während der Signaturprüfung" -#: g10/gpg.c:2738 +#: g10/gpg.c:2739 msgid "validate signatures with PKA data" msgstr "Prüfe Signaturgültigkeit mittels PKA-Daten" -#: g10/gpg.c:2740 +#: g10/gpg.c:2741 msgid "elevate the trust of signatures with valid PKA data" msgstr "Werte das Vertrauen zu Signaturen durch gültige PKA-Daten auf" -#: g10/gpg.c:2747 +#: g10/gpg.c:2748 #, c-format msgid "%s:%d: invalid verify options\n" msgstr "%s:%d: ungültige Überprüfungs-Option.\n" -#: g10/gpg.c:2750 +#: g10/gpg.c:2751 msgid "invalid verify options\n" msgstr "Ungültige Überprüfungs-Option\n" -#: g10/gpg.c:2757 +#: g10/gpg.c:2758 #, c-format msgid "unable to set exec-path to %s\n" msgstr "Der Ausführungspfad konnte nicht auf %s gesetzt werden.\n" -#: g10/gpg.c:2943 +#: g10/gpg.c:2944 #, c-format msgid "%s:%d: invalid auto-key-locate list\n" msgstr "%s:%d: ungültige \"auto-key-locate\"-Liste\n" -#: g10/gpg.c:2946 +#: g10/gpg.c:2947 msgid "invalid auto-key-locate list\n" msgstr "ungültige \"auto-key-locate\"-Liste\n" -#: g10/gpg.c:3054 sm/gpgsm.c:1452 +#: g10/gpg.c:3055 sm/gpgsm.c:1452 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm könnte eine core-dump-Datei schreiben!\n" -#: g10/gpg.c:3058 +#: g10/gpg.c:3059 #, c-format msgid "WARNING: %s overrides %s\n" msgstr "WARNUNG: %s ersetzt %s\n" -#: g10/gpg.c:3067 +#: g10/gpg.c:3068 #, c-format msgid "%s not allowed with %s!\n" msgstr "%s kann nicht zusammen mit %s verwendet werden!\n" -#: g10/gpg.c:3070 +#: g10/gpg.c:3071 #, c-format msgid "%s makes no sense with %s!\n" msgstr "%s zusammen mit %s ist nicht sinnvoll!\n" -#: g10/gpg.c:3085 sm/gpgsm.c:1469 dirmngr/dirmngr.c:865 +#: g10/gpg.c:3086 sm/gpgsm.c:1469 dirmngr/dirmngr.c:873 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausführung mit gefälschter Systemzeit: " -#: g10/gpg.c:3096 +#: g10/gpg.c:3097 #, c-format msgid "will not run with insecure memory due to %s\n" msgstr "Startet nicht mit unsicherem Speicher, wegen Option %s\n" -#: g10/gpg.c:3110 +#: g10/gpg.c:3111 msgid "you can only make detached or clear signatures while in --pgp2 mode\n" msgstr "" "Im --pgp2-Modus können Sie nur abgetrennte oder Klartextsignaturen machen\n" -#: g10/gpg.c:3116 +#: g10/gpg.c:3117 msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" msgstr "" "Im --pgp2-Modus können Sie nicht gleichzeitig signieren und verschlüsseln\n" -#: g10/gpg.c:3122 +#: g10/gpg.c:3123 msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" msgstr "" "Im --pgp2-Modus müssen Sie Dateien benutzen und können keine Pipes " "verwenden.\n" -#: g10/gpg.c:3135 +#: g10/gpg.c:3136 msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" msgstr "" "Verschlüsseln einer Botschaft benötigt im --pgp2-Modus die IDEA-" "Verschlüsselung\n" -#: g10/gpg.c:3202 g10/gpg.c:3226 sm/gpgsm.c:1524 +#: g10/gpg.c:3203 g10/gpg.c:3227 sm/gpgsm.c:1524 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewählte Verschlüsselungsverfahren ist ungültig\n" -#: g10/gpg.c:3208 g10/gpg.c:3232 sm/gpgsm.c:1530 sm/gpgsm.c:1536 +#: g10/gpg.c:3209 g10/gpg.c:3233 sm/gpgsm.c:1530 sm/gpgsm.c:1536 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewählte Hashverfahren ist ungültig\n" -#: g10/gpg.c:3214 +#: g10/gpg.c:3215 msgid "selected compression algorithm is invalid\n" msgstr "Das ausgewählte Komprimierungsverfahren ist ungültig\n" -#: g10/gpg.c:3220 +#: g10/gpg.c:3221 msgid "selected certification digest algorithm is invalid\n" msgstr "Das ausgewählte Hashverfahren ist ungültig\n" -#: g10/gpg.c:3235 +#: g10/gpg.c:3236 msgid "completes-needed must be greater than 0\n" msgstr "completes-needed müssen größer als 0 sein\n" -#: g10/gpg.c:3237 +#: g10/gpg.c:3238 msgid "marginals-needed must be greater than 1\n" msgstr "marginals-needed müssen größer als 1 sein\n" -#: g10/gpg.c:3239 +#: g10/gpg.c:3240 msgid "max-cert-depth must be in the range from 1 to 255\n" msgstr "max-cert-depth muß im Bereich 1 bis 255 liegen\n" -#: g10/gpg.c:3241 +#: g10/gpg.c:3242 msgid "invalid default-cert-level; must be 0, 1, 2, or 3\n" msgstr "ungültiger \"default-cert-level\"; Wert muß 0, 1, 2 oder 3 sein\n" -#: g10/gpg.c:3243 +#: g10/gpg.c:3244 msgid "invalid min-cert-level; must be 1, 2, or 3\n" msgstr "ungültiger \"min-cert-level\"; Wert muß 0, 1, 2 oder 3 sein\n" -#: g10/gpg.c:3246 +#: g10/gpg.c:3247 msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" msgstr "Hinweis: Vom \"simple S2K\"-Modus (0) ist strikt abzuraten\n" -#: g10/gpg.c:3250 +#: g10/gpg.c:3251 msgid "invalid S2K mode; must be 0, 1 or 3\n" msgstr "ungültiger \"simple S2K\"-Modus; Wert muß 0, 1 oder 3 sein\n" -#: g10/gpg.c:3257 +#: g10/gpg.c:3258 msgid "invalid default preferences\n" msgstr "ungültige Standard-Voreinstellungen\n" -#: g10/gpg.c:3261 +#: g10/gpg.c:3262 msgid "invalid personal cipher preferences\n" msgstr "ungültige private Verschlüsselungsvoreinstellungen\n" -#: g10/gpg.c:3265 +#: g10/gpg.c:3266 msgid "invalid personal digest preferences\n" msgstr "ungültige private Hashvoreinstellungen\n" -#: g10/gpg.c:3269 +#: g10/gpg.c:3270 msgid "invalid personal compress preferences\n" msgstr "ungültige private Komprimierungsvoreinstellungen\n" -#: g10/gpg.c:3302 +#: g10/gpg.c:3303 #, c-format msgid "%s does not yet work with %s\n" msgstr "%s arbeitet noch nicht mit %s zusammen\n" -#: g10/gpg.c:3349 +#: g10/gpg.c:3350 #, c-format msgid "you may not use cipher algorithm `%s' while in %s mode\n" msgstr "" "Die Benutzung des Verschlüsselungsverfahren %s ist im %s-Modus nicht " "erlaubt.\n" -#: g10/gpg.c:3354 +#: g10/gpg.c:3355 #, c-format msgid "you may not use digest algorithm `%s' while in %s mode\n" msgstr "Die Benutzung der Hashmethode %s ist im %s-Modus nicht erlaubt.\n" -#: g10/gpg.c:3359 +#: g10/gpg.c:3360 #, c-format msgid "you may not use compression algorithm `%s' while in %s mode\n" msgstr "" "Die Benutzung des Komprimierverfahren %s ist im %s-Modus nicht erlaubt.\n" -#: g10/gpg.c:3438 +#: g10/gpg.c:3439 #, c-format msgid "failed to initialize the TrustDB: %s\n" msgstr "Die Trust-DB kann nicht initialisiert werden: %s\n" -#: g10/gpg.c:3449 +#: g10/gpg.c:3450 msgid "WARNING: recipients (-r) given without using public key encryption\n" msgstr "" "WARNUNG: Empfänger (-r) angegeben ohne Verwendung von Public-Key-Verfahren\n" -#: g10/gpg.c:3464 +#: g10/gpg.c:3465 msgid "--store [filename]" msgstr "--store [Dateiname]" -#: g10/gpg.c:3471 +#: g10/gpg.c:3472 msgid "--symmetric [filename]" msgstr "--symmetric [Dateiname]" -#: g10/gpg.c:3473 +#: g10/gpg.c:3474 #, c-format msgid "symmetric encryption of `%s' failed: %s\n" msgstr "Symmetrische Entschlüsselung von `%s' fehlgeschlagen: %s\n" -#: g10/gpg.c:3483 +#: g10/gpg.c:3484 msgid "--encrypt [filename]" msgstr "--encrypt [Dateiname]" -#: g10/gpg.c:3496 +#: g10/gpg.c:3497 msgid "--symmetric --encrypt [filename]" msgstr "--symmetric --encrypt [Dateiname]" -#: g10/gpg.c:3498 +#: g10/gpg.c:3499 msgid "you cannot use --symmetric --encrypt with --s2k-mode 0\n" msgstr "" "--symmetric --encrypt kann nicht zusammen mit --s2k-mode 0 verwendet werden\n" -#: g10/gpg.c:3501 +#: g10/gpg.c:3502 #, c-format msgid "you cannot use --symmetric --encrypt while in %s mode\n" msgstr "Im %s-Modus kann --symmetric --encrypt nicht verwendet werden.\n" -#: g10/gpg.c:3519 +#: g10/gpg.c:3520 msgid "--sign [filename]" msgstr "--sign [Dateiname]" -#: g10/gpg.c:3532 +#: g10/gpg.c:3533 msgid "--sign --encrypt [filename]" msgstr "--sign --encrypt [Dateiname]" -#: g10/gpg.c:3547 +#: g10/gpg.c:3548 msgid "--symmetric --sign --encrypt [filename]" msgstr "--symmetric --sign --encrypt [Dateiname]" -#: g10/gpg.c:3549 +#: g10/gpg.c:3550 msgid "you cannot use --symmetric --sign --encrypt with --s2k-mode 0\n" msgstr "" "--symmetric --sign --encrypt kann nicht zusammen mit --s2k-mode 0 verwendet " "werden\n" -#: g10/gpg.c:3552 +#: g10/gpg.c:3553 #, c-format msgid "you cannot use --symmetric --sign --encrypt while in %s mode\n" msgstr "" "Im %s-Modus kann --symmetric --sign --encrypt nicht verwendet werden.\n" -#: g10/gpg.c:3573 +#: g10/gpg.c:3574 msgid "--sign --symmetric [filename]" msgstr "--sign --symmetric [Dateiname]" -#: g10/gpg.c:3582 +#: g10/gpg.c:3583 msgid "--clearsign [filename]" msgstr "--clearsign [Dateiname]" -#: g10/gpg.c:3607 +#: g10/gpg.c:3608 msgid "--decrypt [filename]" msgstr "--decrypt [Dateiname]" -#: g10/gpg.c:3615 +#: g10/gpg.c:3616 msgid "--sign-key user-id" msgstr "--sign-key User-ID" -#: g10/gpg.c:3619 +#: g10/gpg.c:3620 msgid "--lsign-key user-id" msgstr "--lsign-key User-ID" -#: g10/gpg.c:3640 +#: g10/gpg.c:3641 msgid "--edit-key user-id [commands]" msgstr "--edit-key User-ID [Befehle]" -#: g10/gpg.c:3656 +#: g10/gpg.c:3657 msgid "--passwd <user-id>" msgstr "--passwd User-ID" -#: g10/gpg.c:3743 +#: g10/gpg.c:3744 g10/keyserver.c:1634 #, c-format msgid "keyserver send failed: %s\n" msgstr "Senden an Schlüsselserver fehlgeschlagen: %s\n" -#: g10/gpg.c:3745 +#: g10/gpg.c:3746 #, c-format msgid "keyserver receive failed: %s\n" msgstr "Empfangen vom Schlüsselserver fehlgeschlagen: %s\n" -#: g10/gpg.c:3747 +#: g10/gpg.c:3748 #, c-format msgid "key export failed: %s\n" msgstr "Schlüsselexport fehlgeschlagen: %s\n" -#: g10/gpg.c:3758 +#: g10/gpg.c:3759 #, c-format msgid "keyserver search failed: %s\n" msgstr "Suche auf dem Schlüsselserver fehlgeschlagen: %s\n" -#: g10/gpg.c:3768 +#: g10/gpg.c:3769 #, c-format msgid "keyserver refresh failed: %s\n" msgstr "Refresh vom Schlüsselserver fehlgeschlagen: %s\n" -#: g10/gpg.c:3819 +#: g10/gpg.c:3820 #, c-format msgid "dearmoring failed: %s\n" msgstr "Entfernen der ASCII-Hülle ist fehlgeschlagen: %s\n" -#: g10/gpg.c:3827 +#: g10/gpg.c:3828 #, c-format msgid "enarmoring failed: %s\n" msgstr "Anbringen der ASCII-Hülle ist fehlgeschlagen: %s\n" -#: g10/gpg.c:3918 +#: g10/gpg.c:3919 #, c-format msgid "invalid hash algorithm `%s'\n" msgstr "Ungültiges Hashverfahren '%s'\n" -#: g10/gpg.c:4033 +#: g10/gpg.c:4034 msgid "[filename]" msgstr "[Dateiname]" -#: g10/gpg.c:4039 +#: g10/gpg.c:4040 msgid "Go ahead and type your message ...\n" msgstr "Auf geht's - Botschaft eintippen ...\n" -#: g10/gpg.c:4356 +#: g10/gpg.c:4357 msgid "the given certification policy URL is invalid\n" msgstr "Die angegebene Zertifikat-Richtlinien-URL ist ungültig\n" -#: g10/gpg.c:4358 +#: g10/gpg.c:4359 msgid "the given signature policy URL is invalid\n" msgstr "Die angegebene Signatur-Richtlinien-URL ist ungültig\n" -#: g10/gpg.c:4391 +#: g10/gpg.c:4392 msgid "the given preferred keyserver URL is invalid\n" msgstr "Die angegebene URL des bevorzugten Schlüsselserver ist ungültig\n" @@ -2960,92 +2950,92 @@ msgstr "entferne nach dem Import unbrauchbare Teile des Schlüssels" msgid "remove as much as possible from key after import" msgstr "nach dem Import soviel wie möglich aus dem Schlüssel entfernen" -#: g10/import.c:277 +#: g10/import.c:303 #, c-format msgid "skipping block of type %d\n" msgstr "überspringe den Block vom Typ %d\n" -#: g10/import.c:286 +#: g10/import.c:312 #, c-format msgid "%lu keys processed so far\n" msgstr "%lu Schlüssel bislang bearbeitet\n" -#: g10/import.c:303 +#: g10/import.c:329 #, c-format msgid "Total number processed: %lu\n" msgstr "Anzahl insgesamt bearbeiteter Schlüssel: %lu\n" -#: g10/import.c:305 +#: g10/import.c:331 #, c-format msgid " skipped new keys: %lu\n" msgstr " ignorierte neue Schlüssel: %lu\n" -#: g10/import.c:308 +#: g10/import.c:334 #, c-format msgid " w/o user IDs: %lu\n" msgstr " ohne User-ID: %lu\n" -#: g10/import.c:310 sm/import.c:130 +#: g10/import.c:336 sm/import.c:130 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: g10/import.c:316 sm/import.c:134 +#: g10/import.c:342 sm/import.c:134 #, c-format msgid " unchanged: %lu\n" msgstr " unverändert: %lu\n" -#: g10/import.c:318 +#: g10/import.c:344 #, c-format msgid " new user IDs: %lu\n" msgstr " neue User-IDs: %lu\n" -#: g10/import.c:320 +#: g10/import.c:346 #, c-format msgid " new subkeys: %lu\n" msgstr " neue Unterschlüssel: %lu\n" -#: g10/import.c:322 +#: g10/import.c:348 #, c-format msgid " new signatures: %lu\n" msgstr " neue Signaturen: %lu\n" -#: g10/import.c:324 +#: g10/import.c:350 #, c-format msgid " new key revocations: %lu\n" msgstr " neue Schlüsselwiderrufe: %lu\n" -#: g10/import.c:326 sm/import.c:136 +#: g10/import.c:352 sm/import.c:136 #, c-format msgid " secret keys read: %lu\n" msgstr " gelesene geheime Schlüssel: %lu\n" -#: g10/import.c:328 sm/import.c:138 +#: g10/import.c:354 sm/import.c:138 #, c-format msgid " secret keys imported: %lu\n" msgstr " geheime Schlüssel importiert: %lu\n" -#: g10/import.c:330 sm/import.c:140 +#: g10/import.c:356 sm/import.c:140 #, c-format msgid " secret keys unchanged: %lu\n" msgstr " unveränderte geh. Schl.: %lu\n" -#: g10/import.c:332 sm/import.c:142 +#: g10/import.c:358 sm/import.c:142 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: g10/import.c:334 +#: g10/import.c:360 #, c-format msgid " signatures cleaned: %lu\n" msgstr " Signaturen bereinigt: %lu\n" -#: g10/import.c:336 +#: g10/import.c:362 #, c-format msgid " user IDs cleaned: %lu\n" msgstr " User-IDs bereinigt: %lu\n" -#: g10/import.c:614 +#: g10/import.c:640 #, c-format msgid "" "WARNING: key %s contains preferences for unavailable\n" @@ -3054,328 +3044,328 @@ msgstr "" "WARNUNG: Schlüssel %s hat Einstellungen zu nicht verfügbaren\n" "Verfahren für folgende User-ID:\n" -#: g10/import.c:655 +#: g10/import.c:681 #, c-format msgid " \"%s\": preference for cipher algorithm %s\n" msgstr " \"%s\": Einstellungen des Verschlüsselungsverfahren %s\n" -#: g10/import.c:670 +#: g10/import.c:696 #, c-format msgid " \"%s\": preference for digest algorithm %s\n" msgstr " \"%s\": Einstellungen der Hashmethode %s\n" -#: g10/import.c:682 +#: g10/import.c:708 #, c-format msgid " \"%s\": preference for compression algorithm %s\n" msgstr " \"%s\": Einstellungen der Komprimierungsverfahren %s\n" -#: g10/import.c:695 +#: g10/import.c:721 msgid "it is strongly suggested that you update your preferences and\n" msgstr "es ist extrem empfehlenswert Ihre Einstellungen zu ändern und\n" -#: g10/import.c:697 +#: g10/import.c:723 msgid "re-distribute this key to avoid potential algorithm mismatch problems\n" msgstr "" "diesen Schlüssel wieder zu verteilen, um mögliche Probleme durch unpassende " "Verfahrenskombinationen zu vermeiden\n" -#: g10/import.c:721 +#: g10/import.c:747 #, c-format msgid "you can update your preferences with: gpg --edit-key %s updpref save\n" msgstr "" "Sie können Ihren Einstellungen mittels \"gpg --edit-key %s updpref save\" " "ändern\n" -#: g10/import.c:775 g10/import.c:1403 +#: g10/import.c:801 g10/import.c:1429 #, c-format msgid "key %s: no user ID\n" msgstr "Schlüssel %s: Keine User-ID\n" -#: g10/import.c:804 +#: g10/import.c:830 #, c-format msgid "key %s: PKS subkey corruption repaired\n" msgstr "Schlüssel %s: PKS Unterschlüsseldefekt repariert\n" -#: g10/import.c:819 +#: g10/import.c:845 #, c-format msgid "key %s: accepted non self-signed user ID \"%s\"\n" msgstr "Schlüssel %s: Nicht eigenbeglaubigte User-ID `%s' übernommen\n" -#: g10/import.c:825 +#: g10/import.c:851 #, c-format msgid "key %s: no valid user IDs\n" msgstr "Schlüssel %s: Keine gültigen User-IDs\n" -#: g10/import.c:827 +#: g10/import.c:853 msgid "this may be caused by a missing self-signature\n" msgstr "dies könnte durch fehlende Eigenbeglaubigung verursacht worden sein\n" -#: g10/import.c:837 g10/import.c:1523 +#: g10/import.c:863 g10/import.c:1549 #, c-format msgid "key %s: public key not found: %s\n" msgstr "Schlüssel %s: Öffentlicher Schlüssel nicht gefunden: %s\n" -#: g10/import.c:843 +#: g10/import.c:869 #, c-format msgid "key %s: new key - skipped\n" msgstr "Schlüssel %s: neuer Schlüssel - übersprungen\n" -#: g10/import.c:852 +#: g10/import.c:878 #, c-format msgid "no writable keyring found: %s\n" msgstr "kein schreibbarer Schlüsselbund gefunden: %s\n" -#: g10/import.c:857 g10/openfile.c:202 g10/openfile.c:293 g10/sign.c:874 +#: g10/import.c:883 g10/openfile.c:202 g10/openfile.c:293 g10/sign.c:874 #: g10/sign.c:1185 #, c-format msgid "writing to `%s'\n" msgstr "Schreiben nach '%s'\n" -#: g10/import.c:861 g10/import.c:961 g10/import.c:1584 +#: g10/import.c:887 g10/import.c:987 g10/import.c:1610 #, c-format msgid "error writing keyring `%s': %s\n" msgstr "Fehler beim Schreiben des Schlüsselbundes `%s': %s\n" -#: g10/import.c:880 +#: g10/import.c:906 #, c-format msgid "key %s: public key \"%s\" imported\n" msgstr "Schlüssel %s: Öffentlicher Schlüssel \"%s\" importiert\n" -#: g10/import.c:904 +#: g10/import.c:930 #, c-format msgid "key %s: doesn't match our copy\n" msgstr "Schlüssel %s: Stimmt nicht mit unserer Kopie überein\n" -#: g10/import.c:921 g10/import.c:1541 +#: g10/import.c:947 g10/import.c:1567 #, c-format msgid "key %s: can't locate original keyblock: %s\n" msgstr "Schlüssel %s: der originale Schlüsselblock wurde nicht gefunden: %s\n" -#: g10/import.c:929 g10/import.c:1548 +#: g10/import.c:955 g10/import.c:1574 #, c-format msgid "key %s: can't read original keyblock: %s\n" msgstr "Schlüssel %s: Lesefehler im originalen Schlüsselblock: %s\n" -#: g10/import.c:971 +#: g10/import.c:997 #, c-format msgid "key %s: \"%s\" 1 new user ID\n" msgstr "Schlüssel %s: \"%s\" 1 neue User-ID\n" -#: g10/import.c:974 +#: g10/import.c:1000 #, c-format msgid "key %s: \"%s\" %d new user IDs\n" msgstr "Schlüssel %s: \"%s\" %d neue User-IDs\n" -#: g10/import.c:977 +#: g10/import.c:1003 #, c-format msgid "key %s: \"%s\" 1 new signature\n" msgstr "Schlüssel %s: \"%s\" 1 neue Signatur\n" -#: g10/import.c:980 +#: g10/import.c:1006 #, c-format msgid "key %s: \"%s\" %d new signatures\n" msgstr "Schlüssel %s: \"%s\" %d neue Signaturen\n" -#: g10/import.c:983 +#: g10/import.c:1009 #, c-format msgid "key %s: \"%s\" 1 new subkey\n" msgstr "Schlüssel %s: \"%s\" 1 neuer Unterschlüssel\n" -#: g10/import.c:986 +#: g10/import.c:1012 #, c-format msgid "key %s: \"%s\" %d new subkeys\n" msgstr "Schlüssel %s: \"%s\" %d neue Unterschlüssel\n" -#: g10/import.c:989 +#: g10/import.c:1015 #, c-format msgid "key %s: \"%s\" %d signature cleaned\n" msgstr "Schlüssel %s: \"%s\" %d Signaturen bereinigt\n" -#: g10/import.c:992 +#: g10/import.c:1018 #, c-format msgid "key %s: \"%s\" %d signatures cleaned\n" msgstr "Schlüssel %s: \"%s\" %d Signaturen bereinigt\n" -#: g10/import.c:995 +#: g10/import.c:1021 #, c-format msgid "key %s: \"%s\" %d user ID cleaned\n" msgstr "Schlüssel %s: \"%s\" %d User-ID bereinigt\n" -#: g10/import.c:998 +#: g10/import.c:1024 #, c-format msgid "key %s: \"%s\" %d user IDs cleaned\n" msgstr "Schlüssel %s: \"%s\" %d User-IDs bereinigt\n" -#: g10/import.c:1021 +#: g10/import.c:1047 #, c-format msgid "key %s: \"%s\" not changed\n" msgstr "Schlüssel %s: \"%s\" nicht geändert\n" -#: g10/import.c:1275 g10/import.c:1468 +#: g10/import.c:1301 g10/import.c:1494 #, c-format msgid "key %s: secret key imported\n" msgstr "Schlüssel %s: geheimer Schlüssel importiert\n" -#: g10/import.c:1282 +#: g10/import.c:1308 #, c-format msgid "key %s: secret key already exists\n" msgstr "Schlüssel %s: geheimer Schlüssel bereits vorhanden\n" -#: g10/import.c:1289 +#: g10/import.c:1315 #, c-format msgid "key %s: error sending to agent: %s\n" msgstr "Schlüssel %s: Fehler beim Senden zum gpg-agent: %s\n" -#: g10/import.c:1419 +#: g10/import.c:1445 #, c-format msgid "key %s: secret key with invalid cipher %d - skipped\n" msgstr "" "Schlüssel %s: geheimer Schlüssel mit ungültiger Verschlüsselung %d - " "übersprungen\n" -#: g10/import.c:1430 +#: g10/import.c:1456 msgid "importing secret keys not allowed\n" msgstr "Importieren geheimer Schlüssel ist nicht erlaubt\n" -#: g10/import.c:1481 +#: g10/import.c:1507 #, c-format msgid "key %s: secret key part already available\n" msgstr "Schlüssel %s: Die geheimen Teile sind bereits vorhanden\n" -#: g10/import.c:1516 +#: g10/import.c:1542 #, c-format msgid "key %s: no public key - can't apply revocation certificate\n" msgstr "" "Schlüssel %s: Kein öffentlicher Schlüssel - der Schlüsselwiderruf kann nicht " "angebracht werden\n" -#: g10/import.c:1559 +#: g10/import.c:1585 #, c-format msgid "key %s: invalid revocation certificate: %s - rejected\n" msgstr "Schlüssel %s: Ungültiges Widerrufzertifikat: %s - zurückgewiesen\n" -#: g10/import.c:1591 +#: g10/import.c:1617 #, c-format msgid "key %s: \"%s\" revocation certificate imported\n" msgstr "Schlüssel %s: \"%s\" Widerrufzertifikat importiert\n" -#: g10/import.c:1667 +#: g10/import.c:1693 #, c-format msgid "key %s: no user ID for signature\n" msgstr "Schlüssel %s: Keine User-ID für Signatur\n" -#: g10/import.c:1684 +#: g10/import.c:1710 #, c-format msgid "key %s: unsupported public key algorithm on user ID \"%s\"\n" msgstr "" "Schlüssel %s: Nicht unterstütztes Public-Key-Verfahren für User-ID \"%s\"\n" -#: g10/import.c:1686 +#: g10/import.c:1712 #, c-format msgid "key %s: invalid self-signature on user ID \"%s\"\n" msgstr "Schlüssel %s: Ungültige Eigenbeglaubigung für User-ID \"%s\"\n" -#: g10/import.c:1703 g10/import.c:1729 g10/import.c:1780 +#: g10/import.c:1729 g10/import.c:1755 g10/import.c:1806 #, c-format msgid "key %s: unsupported public key algorithm\n" msgstr "Schlüssel %s: Nicht unterstütztes Public-Key-Verfahren\n" -#: g10/import.c:1704 +#: g10/import.c:1730 #, c-format msgid "key %s: invalid direct key signature\n" msgstr "Schlüssel %s: Ungültige \"direct-key\"-Signatur\n" -#: g10/import.c:1718 +#: g10/import.c:1744 #, c-format msgid "key %s: no subkey for key binding\n" msgstr "Schlüssel %s: Kein Unterschlüssel für die Unterschlüsselanbindung\n" -#: g10/import.c:1731 +#: g10/import.c:1757 #, c-format msgid "key %s: invalid subkey binding\n" msgstr "Schlüssel %s: Ungültige Unterschlüssel-Anbindung\n" -#: g10/import.c:1747 +#: g10/import.c:1773 #, c-format msgid "key %s: removed multiple subkey binding\n" msgstr "Schlüssel %s: Mehrfache Unterschlüssel-Anbindung entfernt\n" -#: g10/import.c:1769 +#: g10/import.c:1795 #, c-format msgid "key %s: no subkey for key revocation\n" msgstr "Schlüssel %s: Kein Unterschlüssel für Schlüsselwiderruf\n" -#: g10/import.c:1782 +#: g10/import.c:1808 #, c-format msgid "key %s: invalid subkey revocation\n" msgstr "Schlüssel %s: Ungültiger Unterschlüsselwiderruf\n" -#: g10/import.c:1797 +#: g10/import.c:1823 #, c-format msgid "key %s: removed multiple subkey revocation\n" msgstr "Schlüssel %s: Mehrfacher Unterschlüsselwiderruf entfernt\n" -#: g10/import.c:1839 +#: g10/import.c:1865 #, c-format msgid "key %s: skipped user ID \"%s\"\n" msgstr "Schlüssel %s: User-ID übersprungen \"%s\"\n" -#: g10/import.c:1860 +#: g10/import.c:1886 #, c-format msgid "key %s: skipped subkey\n" msgstr "Schlüssel %s: Unterschlüssel übersprungen\n" -#: g10/import.c:1887 +#: g10/import.c:1913 #, c-format msgid "key %s: non exportable signature (class 0x%02X) - skipped\n" msgstr "" "Schlüssel %s: Nicht exportfähige Signatur (Klasse %02x) - übersprungen\n" -#: g10/import.c:1897 +#: g10/import.c:1923 #, c-format msgid "key %s: revocation certificate at wrong place - skipped\n" msgstr "Schlüssel %s: Widerrufzertifikat an falschem Platz - übersprungen\n" -#: g10/import.c:1914 +#: g10/import.c:1940 #, c-format msgid "key %s: invalid revocation certificate: %s - skipped\n" msgstr "Schlüssel %s: Ungültiges Widerrufzertifikat: %s - übersprungen\n" -#: g10/import.c:1928 +#: g10/import.c:1954 #, c-format msgid "key %s: subkey signature in wrong place - skipped\n" msgstr "" "Schlüssel %s: Unterschlüssel-Widerrufzertifikat an falschem Platz - " "übersprungen\n" -#: g10/import.c:1936 +#: g10/import.c:1962 #, c-format msgid "key %s: unexpected signature class (0x%02X) - skipped\n" msgstr "Schlüssel %s: unerwartete Signaturklasse (0x%02x) - übersprungen\n" -#: g10/import.c:2065 +#: g10/import.c:2091 #, c-format msgid "key %s: duplicated user ID detected - merged\n" msgstr "Schlüssel %s: Doppelte User-ID entdeckt - zusammengeführt\n" -#: g10/import.c:2127 +#: g10/import.c:2153 #, c-format msgid "WARNING: key %s may be revoked: fetching revocation key %s\n" msgstr "WARNUNG: Schlüssel %s ist u.U. widerrufen: hole Widerrufschlüssel %s\n" -#: g10/import.c:2142 +#: g10/import.c:2168 #, c-format msgid "WARNING: key %s may be revoked: revocation key %s not present.\n" msgstr "" "WARNUNG: Schlüssel %s ist u.U. widerrufen: Widerrufschlüssel %s ist nicht " "vorhanden\n" -#: g10/import.c:2201 +#: g10/import.c:2227 #, c-format msgid "key %s: \"%s\" revocation certificate added\n" msgstr "Schlüssel %s: \"%s\" Widerrufzertifikat hinzugefügt\n" -#: g10/import.c:2235 +#: g10/import.c:2261 #, c-format msgid "key %s: direct key signature added\n" msgstr "Schlüssel %s: \"direct-key\"-Signaturen hinzugefügt\n" @@ -4058,7 +4048,7 @@ msgstr "" msgid "(sensitive)" msgstr "(empfindlich)" -#: g10/keyedit.c:2775 g10/keyedit.c:2888 g10/keyserver.c:533 +#: g10/keyedit.c:2775 g10/keyedit.c:2888 g10/keyserver.c:557 #, c-format msgid "created: %s" msgstr "erzeugt: %s" @@ -4074,7 +4064,7 @@ msgid "expired: %s" msgstr "verfallen: %s" #: g10/keyedit.c:2782 g10/keyedit.c:2890 g10/keylist.c:822 g10/keylist.c:945 -#: g10/keyserver.c:539 g10/mainproc.c:1014 +#: g10/keyserver.c:563 g10/mainproc.c:1014 #, c-format msgid "expires: %s" msgstr "verfällt: %s" @@ -4110,13 +4100,13 @@ msgstr "" "Bitte beachten Sie, daß ohne einen Programmneustart die angezeigte\n" "Schlüsselgültigkeit nicht notwendigerweise korrekt ist.\n" -#: g10/keyedit.c:2907 g10/keyedit.c:3219 g10/keyserver.c:543 +#: g10/keyedit.c:2907 g10/keyedit.c:3219 g10/keyserver.c:567 #: g10/mainproc.c:1874 g10/trustdb.c:1202 g10/trustdb.c:1731 #: dirmngr/ocsp.c:699 msgid "revoked" msgstr "widerrufen" -#: g10/keyedit.c:2909 g10/keyedit.c:3221 g10/keyserver.c:547 +#: g10/keyedit.c:2909 g10/keyedit.c:3221 g10/keyserver.c:571 #: g10/mainproc.c:1876 g10/trustdb.c:549 g10/trustdb.c:1733 msgid "expired" msgstr "verfallen" @@ -4985,184 +4975,122 @@ msgstr "%lu Schlüssel gepuffert (%lu Beglaubigungen)\n" msgid "%s: keyring created\n" msgstr "%s: Schlüsselbund erstellt\n" -#: g10/keyserver.c:75 +#: g10/keyserver.c:97 msgid "include revoked keys in search results" msgstr "Widerrufene Schlüssel in den Suchergebnissen aufführen" -#: g10/keyserver.c:76 +#: g10/keyserver.c:98 msgid "include subkeys when searching by key ID" msgstr "Unterschlüssel in der Suche über Schlüssel-IDs aufführen" -#: g10/keyserver.c:78 +#: g10/keyserver.c:100 msgid "use temporary files to pass data to keyserver helpers" msgstr "" "verwende temporäre Dateien, um Daten an die Schlüsselserverhilfsprogramme zu " "geben" -#: g10/keyserver.c:80 +#: g10/keyserver.c:102 msgid "do not delete temporary files after using them" msgstr "Temporäre Dateien nach Nutzung nicht löschen" -#: g10/keyserver.c:84 +#: g10/keyserver.c:106 msgid "automatically retrieve keys when verifying signatures" msgstr "Schlüssel für die Signaturprüfung automatisch holen" -#: g10/keyserver.c:86 +#: g10/keyserver.c:108 msgid "honor the preferred keyserver URL set on the key" msgstr "" "Die im Schlüssel enthaltene bevorzugte URL für Schlüsselserver beachten" -#: g10/keyserver.c:88 +#: g10/keyserver.c:110 msgid "honor the PKA record set on a key when retrieving keys" msgstr "Die im Schlüssel enthaltenen PKA-Daten beim Schlüsselholen beachten" -#: g10/keyserver.c:154 +#: g10/keyserver.c:178 #, c-format msgid "WARNING: keyserver option `%s' is not used on this platform\n" msgstr "" "WARNUNG: Schlüsselserver-Option `%s' wird auf dieser Plattform nicht " "verwendet\n" -#: g10/keyserver.c:545 +#: g10/keyserver.c:569 msgid "disabled" msgstr "abgeschaltet" -#: g10/keyserver.c:750 +#: g10/keyserver.c:773 msgid "Enter number(s), N)ext, or Q)uit > " msgstr "Eingabe von Nummern, Nächste (N) oder Abbrechen (Q) > " -#: g10/keyserver.c:834 g10/keyserver.c:1462 +#: g10/keyserver.c:867 #, c-format msgid "invalid keyserver protocol (us %d!=handler %d)\n" msgstr "Ungültiges Schlüsselserverprotokoll (wir %d!=Handhabungsroutine %d)\n" -#: g10/keyserver.c:935 +#: g10/keyserver.c:1008 g10/keyserver.c:1043 +#, c-format +msgid "\"%s\" not a key ID: skipping\n" +msgstr "\"%s\" ist keine Schlüssel-ID: überspringe\n" + +#: g10/keyserver.c:1303 +#, c-format +msgid "WARNING: unable to refresh key %s via %s: %s\n" +msgstr "WARNUNG: Schlüssel %s kann per %s nicht aktualisiert werden: %s\n" + +#: g10/keyserver.c:1325 +#, c-format +msgid "refreshing 1 key from %s\n" +msgstr "ein Schlüssel wird per %s aktualisiert\n" + +#: g10/keyserver.c:1327 +#, c-format +msgid "refreshing %d keys from %s\n" +msgstr "%d Schlüssel werden per %s aktualisiert\n" + +#: g10/keyserver.c:1363 g10/keyserver.c:1415 g10/keyserver.c:1604 +#: g10/keyserver.c:1754 +msgid "no keyserver known (use option --keyserver)\n" +msgstr "Kein Schlüsselserver bekannt (Option --keyserver verwenden)\n" + +#: g10/keyserver.c:1408 #, c-format msgid "key \"%s\" not found on keyserver\n" msgstr "Schlüssel \"%s\" wurde auf dem Schlüsselserver nicht gefunden\n" -#: g10/keyserver.c:937 +#: g10/keyserver.c:1411 msgid "key not found on keyserver\n" msgstr "Schlüssel wurde auf dem Schlüsselserver nicht gefunden\n" -#: g10/keyserver.c:1181 +#: g10/keyserver.c:1548 #, c-format msgid "requesting key %s from %s server %s\n" msgstr "fordere Schlüssel %s von %s-Server %s an\n" -#: g10/keyserver.c:1185 +#: g10/keyserver.c:1552 #, c-format msgid "requesting key %s from %s\n" msgstr "fordere Schlüssel %s von %s an\n" -#: g10/keyserver.c:1209 -#, c-format -msgid "searching for names from %s server %s\n" -msgstr "suche Namen auf %s-Server %s\n" - -#: g10/keyserver.c:1212 +#: g10/keyserver.c:1618 g10/skclist.c:191 g10/skclist.c:219 #, c-format -msgid "searching for names from %s\n" -msgstr "suche Namen auf %s\n" +msgid "skipped \"%s\": %s\n" +msgstr "übersprungen \"%s\": %s\n" -#: g10/keyserver.c:1365 +#: g10/keyserver.c:1622 #, c-format msgid "sending key %s to %s server %s\n" msgstr "sende Schlüssel %s auf den %s-Server %s\n" -#: g10/keyserver.c:1369 +#: g10/keyserver.c:1626 #, c-format msgid "sending key %s to %s\n" msgstr "sende Schlüssel %s auf %s\n" -#: g10/keyserver.c:1412 -#, c-format -msgid "searching for \"%s\" from %s server %s\n" -msgstr "suche nach \"%s\" auf %s-Server %s\n" - -#: g10/keyserver.c:1415 -#, c-format -msgid "searching for \"%s\" from %s\n" -msgstr "suche nach \"%s\" auf %s\n" - -#: g10/keyserver.c:1422 g10/keyserver.c:1519 -msgid "no keyserver action!\n" -msgstr "Kein Schlüsselserver-Vorgang\n" - -#: g10/keyserver.c:1470 -#, c-format -msgid "WARNING: keyserver handler from a different version of GnuPG (%s)\n" -msgstr "" -"WARNUNG: Die Schlüsselserver-Handhabungsroutine stammt von einer anderen " -"GnuPG-Version (%s)\n" - -#: g10/keyserver.c:1479 -msgid "keyserver did not send VERSION\n" -msgstr "Schlüsselserver sendete VERSION nicht\n" - -#: g10/keyserver.c:1543 g10/keyserver.c:2082 -msgid "no keyserver known (use option --keyserver)\n" -msgstr "Kein Schlüsselserver bekannt (Option --keyserver verwenden)\n" - -#: g10/keyserver.c:1549 -msgid "external keyserver calls are not supported in this build\n" -msgstr "" -"Externe Schlüsselserveraufrufe werden in diesem \"Build\" nicht unterstützt\n" - -#: g10/keyserver.c:1562 -#, c-format -msgid "no handler for keyserver scheme `%s'\n" -msgstr "Keine Handhabungsroutine für Schlüsselserverschema `%s'\n" - -#: g10/keyserver.c:1567 -#, c-format -msgid "action `%s' not supported with keyserver scheme `%s'\n" -msgstr "Vorgang `%s' wird vom Schlüsselserverschema `%s' nicht unterstützt\n" - -#: g10/keyserver.c:1575 -#, c-format -msgid "%s does not support handler version %d\n" -msgstr "%s unterstützt Hilfsroutinenversion %d nicht\n" - -#: g10/keyserver.c:1582 -msgid "keyserver timed out\n" -msgstr "Schlüsselserver-Zeitüberschreitung\n" - -#: g10/keyserver.c:1587 -msgid "keyserver internal error\n" -msgstr "interner Fehler Schlüsselserver\n" - -#: g10/keyserver.c:1596 -#, c-format -msgid "keyserver communications error: %s\n" -msgstr "Schlüsselserver-Datenübertragunsfehler: %s\n" - -#: g10/keyserver.c:1622 g10/keyserver.c:1657 -#, c-format -msgid "\"%s\" not a key ID: skipping\n" -msgstr "\"%s\" ist keine Schlüssel-ID: überspringe\n" - -#: g10/keyserver.c:1920 -#, c-format -msgid "WARNING: unable to refresh key %s via %s: %s\n" -msgstr "WARNUNG: Schlüssel %s kann per %s nicht aktualisiert werden: %s\n" - -#: g10/keyserver.c:1942 -#, c-format -msgid "refreshing 1 key from %s\n" -msgstr "ein Schlüssel wird per %s aktualisiert\n" - -#: g10/keyserver.c:1944 -#, c-format -msgid "refreshing %d keys from %s\n" -msgstr "%d Schlüssel werden per %s aktualisiert\n" - -#: g10/keyserver.c:2001 +#: g10/keyserver.c:1673 #, c-format msgid "WARNING: unable to fetch URI %s: %s\n" msgstr "WARNUNG: die URI %s kann nicht geholt werden: %s\n" -#: g10/keyserver.c:2007 +#: g10/keyserver.c:1679 #, c-format msgid "WARNING: unable to parse URI %s\n" msgstr "WARNUNG: die URI %s kann nicht analysiert werden\n" @@ -6281,11 +6209,6 @@ msgstr "" msgid "skipped \"%s\": duplicated\n" msgstr "übersprungen \"%s\": doppelt\n" -#: g10/skclist.c:191 g10/skclist.c:219 -#, c-format -msgid "skipped \"%s\": %s\n" -msgstr "übersprungen \"%s\": %s\n" - #: g10/skclist.c:201 msgid "skipped: secret key already present\n" msgstr "übersprungen: geheimer Schlüssel bereits vorhanden\n" @@ -6346,131 +6269,131 @@ msgstr "Lesefehler in `%s': %s\n" msgid "trustdb: sync failed: %s\n" msgstr "\"Trust-DB\": sync fehlgeschlagen: %s\n" -#: g10/tdbio.c:128 g10/tdbio.c:1450 +#: g10/tdbio.c:135 g10/tdbio.c:1482 #, c-format msgid "trustdb rec %lu: lseek failed: %s\n" msgstr "trustdb Satz %lu: lseek fehlgeschlagen: %s\n" -#: g10/tdbio.c:135 g10/tdbio.c:1457 +#: g10/tdbio.c:142 g10/tdbio.c:1489 #, c-format msgid "trustdb rec %lu: write failed (n=%d): %s\n" msgstr "trustdb Satz %lu: write fehlgeschlagen (n=%d): %s\n" -#: g10/tdbio.c:245 +#: g10/tdbio.c:252 msgid "trustdb transaction too large\n" msgstr "trustdb Transaktion zu groß\n" -#: g10/tdbio.c:498 +#: g10/tdbio.c:512 #, c-format msgid "can't access `%s': %s\n" msgstr "kann aus `%s' nicht zugreifen: %s\n" -#: g10/tdbio.c:525 +#: g10/tdbio.c:539 #, c-format msgid "%s: directory does not exist!\n" msgstr "%s: Verzeichnis existiert nicht!\n" -#: g10/tdbio.c:535 g10/tdbio.c:558 g10/tdbio.c:599 sm/keydb.c:221 +#: g10/tdbio.c:549 g10/tdbio.c:572 g10/tdbio.c:613 sm/keydb.c:221 #, c-format msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: g10/tdbio.c:537 g10/tdbio.c:602 +#: g10/tdbio.c:551 g10/tdbio.c:616 #, c-format msgid "can't lock `%s'\n" msgstr "'%s' kann nicht gesperrt werden\n" -#: g10/tdbio.c:563 +#: g10/tdbio.c:577 #, c-format msgid "%s: failed to create version record: %s" msgstr "%s: Fehler beim Erzeugen des Versionsatzes: %s" -#: g10/tdbio.c:567 +#: g10/tdbio.c:581 #, c-format msgid "%s: invalid trustdb created\n" msgstr "%s: ungültige trust-db erzeugt\n" -#: g10/tdbio.c:570 +#: g10/tdbio.c:584 #, c-format msgid "%s: trustdb created\n" msgstr "%s: trust-db erzeugt\n" -#: g10/tdbio.c:613 +#: g10/tdbio.c:644 msgid "NOTE: trustdb not writable\n" msgstr "Notiz: Die \"trustdb\" ist nicht schreibbar\n" -#: g10/tdbio.c:621 +#: g10/tdbio.c:653 #, c-format msgid "%s: invalid trustdb\n" msgstr "%s: ungültige 'Trust'-Datenbank\n" -#: g10/tdbio.c:653 +#: g10/tdbio.c:685 #, c-format msgid "%s: failed to create hashtable: %s\n" msgstr "%s: hashtable kann nicht erzeugt werden: %s\n" -#: g10/tdbio.c:661 +#: g10/tdbio.c:693 #, c-format msgid "%s: error updating version record: %s\n" msgstr "%s: Fehler beim Ändern des Versionsatzes: %s\n" -#: g10/tdbio.c:678 g10/tdbio.c:698 g10/tdbio.c:714 g10/tdbio.c:728 -#: g10/tdbio.c:758 g10/tdbio.c:1382 g10/tdbio.c:1409 +#: g10/tdbio.c:710 g10/tdbio.c:730 g10/tdbio.c:746 g10/tdbio.c:760 +#: g10/tdbio.c:790 g10/tdbio.c:1414 g10/tdbio.c:1441 #, c-format msgid "%s: error reading version record: %s\n" msgstr "%s: Fehler beim Lesen des Versionsatzes: %s\n" -#: g10/tdbio.c:737 +#: g10/tdbio.c:769 #, c-format msgid "%s: error writing version record: %s\n" msgstr "%s: Fehler beim Schreiben des Versionsatzes: %s\n" -#: g10/tdbio.c:1177 +#: g10/tdbio.c:1209 #, c-format msgid "trustdb: lseek failed: %s\n" msgstr "trustdb: lseek fehlgeschlagen: %s\n" -#: g10/tdbio.c:1186 +#: g10/tdbio.c:1218 #, c-format msgid "trustdb: read failed (n=%d): %s\n" msgstr "trustdb: read failed (n=%d): %s\n" -#: g10/tdbio.c:1207 +#: g10/tdbio.c:1239 #, c-format msgid "%s: not a trustdb file\n" msgstr "%s: keine trustdb Datei\n" -#: g10/tdbio.c:1225 +#: g10/tdbio.c:1257 #, c-format msgid "%s: version record with recnum %lu\n" msgstr "%s: version record with recnum %lu\n" -#: g10/tdbio.c:1230 +#: g10/tdbio.c:1262 #, c-format msgid "%s: invalid file version %d\n" msgstr "%s: invalid file version %d\n" -#: g10/tdbio.c:1415 +#: g10/tdbio.c:1447 #, c-format msgid "%s: error reading free record: %s\n" msgstr "%s: Fehler beim Lesen eines freien Satzes: %s\n" -#: g10/tdbio.c:1423 +#: g10/tdbio.c:1455 #, c-format msgid "%s: error writing dir record: %s\n" msgstr "%s: Fehler beim Schreiben eines Verzeichnis-Satzes: %s\n" -#: g10/tdbio.c:1433 +#: g10/tdbio.c:1465 #, c-format msgid "%s: failed to zero a record: %s\n" msgstr "%s: konnte einen Satz nicht Nullen: %s\n" -#: g10/tdbio.c:1463 +#: g10/tdbio.c:1495 #, c-format msgid "%s: failed to append a record: %s\n" msgstr "%s: konnte Satz nicht anhängen: %s\n" -#: g10/tdbio.c:1506 +#: g10/tdbio.c:1538 msgid "Error: The trustdb is corrupted.\n" msgstr "Fehler: Die Vertrauensdatenbank ist fehlerhaft\n" @@ -6984,7 +6907,7 @@ msgstr "Im Multiserver Modus ausführen" msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: scd/scdaemon.c:125 tools/gpgconf-comp.c:626 +#: scd/scdaemon.c:125 tools/gpgconf-comp.c:632 msgid "|FILE|write a log to FILE" msgstr "|DATEI|Schreibe Logs auf DATEI" @@ -7034,12 +6957,12 @@ msgstr "" "Bitte die Option `--daemon' nutzen, um das Programm im Hintergund " "auszuführen\n" -#: scd/scdaemon.c:1137 dirmngr/dirmngr.c:1710 +#: scd/scdaemon.c:1137 dirmngr/dirmngr.c:1718 #, c-format msgid "handler for fd %d started\n" msgstr "Handhabungsroutine für fd %d gestartet\n" -#: scd/scdaemon.c:1149 dirmngr/dirmngr.c:1715 +#: scd/scdaemon.c:1149 dirmngr/dirmngr.c:1723 #, c-format msgid "handler for fd %d terminated\n" msgstr "Handhabungsroutine für den fd %d beendet\n" @@ -7692,7 +7615,7 @@ msgstr "|DATEI|DATEI als öffentlichen Schlüsselbund mitbenutzen" msgid "|USER-ID|use USER-ID as default secret key" msgstr "|USER-ID|USER-ID als voreingestellten Schlüssel benutzen" -#: sm/gpgsm.c:311 tools/gpgconf-comp.c:758 +#: sm/gpgsm.c:311 tools/gpgconf-comp.c:770 msgid "|SPEC|use this keyserver to lookup keys" msgstr "|SPEC|Schlüssel bei diesem Server nachschlagen" @@ -8097,7 +8020,7 @@ msgstr "Die Zwischenspeicherdatei `%s' wird entfernt\n" msgid "not removing file `%s'\n" msgstr "Die Datei `%s' wird nicht gelöscht\n" -#: dirmngr/crlcache.c:374 dirmngr/crlcache.c:1112 +#: dirmngr/crlcache.c:374 dirmngr/crlcache.c:1112 dirmngr/crlcache.c:2197 #, c-format msgid "error closing cache file: %s\n" msgstr "Fehler beim Schließen der Zwischenspeicherdatei: %s\n" @@ -8479,12 +8402,12 @@ msgstr "Fehler beim Lesen einer CRL Erweiterung: %s\n" msgid "creating cache file `%s'\n" msgstr "Zwischenspeicherdatei `%s' wird erzeugt\n" -#: dirmngr/crlcache.c:2186 +#: dirmngr/crlcache.c:2211 #, c-format msgid "problem renaming `%s' to `%s': %s\n" msgstr "Problem beim Umbenennen von `%s' nach `%s': %s\n" -#: dirmngr/crlcache.c:2200 +#: dirmngr/crlcache.c:2225 msgid "" "updating the DIR file failed - cache entry will get lost with the next " "program start\n" @@ -8492,69 +8415,69 @@ msgstr "" "Update der Zwischenspeicherverzeichnisdatei fehlgeschlagen - " "Zwischenspeichereintrag wird mit dem nächste Programmstart verloren gehen\n" -#: dirmngr/crlcache.c:2237 +#: dirmngr/crlcache.c:2262 #, c-format msgid "Begin CRL dump (retrieved via %s)\n" msgstr "Anfang CRL Ausgabe (geholt via %s)\n" -#: dirmngr/crlcache.c:2260 +#: dirmngr/crlcache.c:2285 msgid "" " ERROR: The CRL will not be used because it was still too old after an " "update!\n" msgstr "" " FEHLER: Die CRL wird nicht benutzt, da sie trotz eines Updates zu alt war!\n" -#: dirmngr/crlcache.c:2263 +#: dirmngr/crlcache.c:2288 msgid "" " ERROR: The CRL will not be used due to an unknown critical extension!\n" msgstr "" " FEHLER: Die CRL wird nicht benutzt, da sie eine unbekannte kritische CRL " "Erweiterung trägt!\n" -#: dirmngr/crlcache.c:2266 +#: dirmngr/crlcache.c:2291 msgid " ERROR: The CRL will not be used\n" msgstr " FEHLER: Die CRL wird nicht benutzt\n" -#: dirmngr/crlcache.c:2273 +#: dirmngr/crlcache.c:2298 msgid " ERROR: This cached CRL may has been tampered with!\n" msgstr "" " FEHLER: Diese zwischengespeicherte CRL ist möglicherweise abgeändert " "worden!\n" -#: dirmngr/crlcache.c:2291 +#: dirmngr/crlcache.c:2316 msgid " WARNING: invalid cache record length\n" msgstr " WARNUNG: Ungültige Länge eines Zwischenspeicherdatensatzes\n" -#: dirmngr/crlcache.c:2298 +#: dirmngr/crlcache.c:2323 #, c-format msgid "problem reading cache record: %s\n" msgstr "Problem beim Lesen eines Zwischenspeicherdatensatzes: %s\n" -#: dirmngr/crlcache.c:2309 +#: dirmngr/crlcache.c:2334 #, c-format msgid "problem reading cache key: %s\n" msgstr "Problem beim Lesen eines Zwischenspeicherschlüssels: %s\n" -#: dirmngr/crlcache.c:2340 +#: dirmngr/crlcache.c:2365 #, c-format msgid "error reading cache entry from db: %s\n" msgstr "Fehler beim Lesen eine Zwischenspeichereintrags aus der DB: %s\n" -#: dirmngr/crlcache.c:2343 +#: dirmngr/crlcache.c:2368 msgid "End CRL dump\n" msgstr "Ende CRL Ausgabe\n" -#: dirmngr/crlcache.c:2464 +#: dirmngr/crlcache.c:2489 #, c-format msgid "crl_fetch via DP failed: %s\n" msgstr "crl_fetch über den DP fehlgeschlagen: %s\n" -#: dirmngr/crlcache.c:2475 +#: dirmngr/crlcache.c:2500 #, c-format msgid "crl_cache_insert via DP failed: %s\n" msgstr "crl_cache_insert über den DP fehlgeschlagen: %s\n" -#: dirmngr/crlcache.c:2535 +#: dirmngr/crlcache.c:2560 #, c-format msgid "crl_cache_insert via issuer failed: %s\n" msgstr "crl_cache_insert über den Issuer fehlgeschlagen: %s\n" @@ -8721,7 +8644,7 @@ msgstr "Erhielt Status: `%s'\n" msgid "error writing base64 encoding: %s\n" msgstr "Fehler beim Schreiben der Base-64 Darstellung: %s\n" -#: dirmngr/dirmngr-client.c:453 dirmngr/server.c:1529 +#: dirmngr/dirmngr-client.c:453 dirmngr/server.c:1804 #, c-format msgid "failed to allocate assuan context: %s\n" msgstr "Fehler beim Bereitstellen eines Assuan Kontext: %s\n" @@ -8790,8 +8713,8 @@ msgstr "Den Dirmngr herunterfahren" msgid "flush the cache" msgstr "Den Zwischenspeicher löschen" -#: dirmngr/dirmngr.c:158 tools/gpgconf-comp.c:507 tools/gpgconf-comp.c:689 -#: tools/gpgconf-comp.c:772 tools/gpgconf-comp.c:854 +#: dirmngr/dirmngr.c:158 tools/gpgconf-comp.c:509 tools/gpgconf-comp.c:698 +#: tools/gpgconf-comp.c:784 tools/gpgconf-comp.c:870 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" @@ -8873,11 +8796,11 @@ msgstr "" "(Im \"info\"-Handbuch findet sich eine vollständige Liste aller Kommandos " "und Optionen)\n" -#: dirmngr/dirmngr.c:301 +#: dirmngr/dirmngr.c:305 msgid "Usage: dirmngr [options] (-h for help)" msgstr "Gebrauch: dirmnr [Optionen] [Kommando [Argumente]]" -#: dirmngr/dirmngr.c:303 +#: dirmngr/dirmngr.c:307 msgid "" "Syntax: dirmngr [options] [command [args]]\n" "LDAP and OCSP access for GnuPG\n" @@ -8885,87 +8808,87 @@ msgstr "" "Syntax: dirmngr [Optionen] [Kommando [Argumente]]\n" "LDAP und OCSP Zugriff für GnuPG\n" -#: dirmngr/dirmngr.c:368 +#: dirmngr/dirmngr.c:372 #, c-format msgid "valid debug levels are: %s\n" msgstr "Gültige Debugebenen sind: %s\n" -#: dirmngr/dirmngr.c:391 +#: dirmngr/dirmngr.c:395 msgid "usage: dirmngr [options] " msgstr "Gebrauch: dirmngr [Optionen] " -#: dirmngr/dirmngr.c:950 +#: dirmngr/dirmngr.c:958 msgid "colons are not allowed in the socket name\n" msgstr "Doppelpunkte sind im Namen des Sockets nicht erlaubt\n" -#: dirmngr/dirmngr.c:1156 dirmngr/server.c:1163 +#: dirmngr/dirmngr.c:1164 dirmngr/server.c:1185 #, c-format msgid "fetching CRL from `%s' failed: %s\n" msgstr "Holen der CRL von `%s' fehlgeschlagen: %s\n" -#: dirmngr/dirmngr.c:1162 dirmngr/server.c:1169 +#: dirmngr/dirmngr.c:1170 dirmngr/server.c:1191 #, c-format msgid "processing CRL from `%s' failed: %s\n" msgstr "Verarbeitung der CRL von `%s' fehlgeschlagen: %s\n" -#: dirmngr/dirmngr.c:1381 +#: dirmngr/dirmngr.c:1389 #, c-format msgid "%s:%u: line too long - skipped\n" msgstr "%s:%u: Zeile ist zu lang - übergangen\n" -#: dirmngr/dirmngr.c:1436 dirmngr/dirmngr.c:1520 +#: dirmngr/dirmngr.c:1444 dirmngr/dirmngr.c:1528 #, c-format msgid "%s:%u: invalid fingerprint detected\n" msgstr "%s:%u: ungültiger Fingerabdruck erkannt\n" -#: dirmngr/dirmngr.c:1472 dirmngr/dirmngr.c:1498 +#: dirmngr/dirmngr.c:1480 dirmngr/dirmngr.c:1506 #, c-format msgid "%s:%u: read error: %s\n" msgstr "%s:%u: Lesefehler: %s\n" -#: dirmngr/dirmngr.c:1527 +#: dirmngr/dirmngr.c:1535 #, c-format msgid "%s:%u: garbage at end of line ignored\n" msgstr "%s:%u: Müll am Ende der Zeile wird ignoriert\n" -#: dirmngr/dirmngr.c:1593 +#: dirmngr/dirmngr.c:1601 msgid "SIGHUP received - re-reading configuration and flushing caches\n" msgstr "" "SIGHUP empfangen - lese die Konfiguration erneut und lösche die " "Zwischenspeicher\n" -#: dirmngr/dirmngr.c:1620 +#: dirmngr/dirmngr.c:1628 msgid "SIGUSR2 received - no action defined\n" msgstr "SIGUSR2 empfangen - keine Aktion definiert\n" -#: dirmngr/dirmngr.c:1625 dirmngr/dirmngr.c:1662 +#: dirmngr/dirmngr.c:1633 dirmngr/dirmngr.c:1670 msgid "SIGTERM received - shutting down ...\n" msgstr "SIGTERM empfangen - wird heruntergefahren ...\n" -#: dirmngr/dirmngr.c:1627 +#: dirmngr/dirmngr.c:1635 #, c-format msgid "SIGTERM received - still %d active connections\n" msgstr "SIGTERM empfangen - immer noch %d Verbindungen aktiv\n" -#: dirmngr/dirmngr.c:1632 dirmngr/dirmngr.c:1665 +#: dirmngr/dirmngr.c:1640 dirmngr/dirmngr.c:1673 msgid "shutdown forced\n" msgstr "Herunterfahren wurde erzwungen\n" -#: dirmngr/dirmngr.c:1640 +#: dirmngr/dirmngr.c:1648 msgid "SIGINT received - immediate shutdown\n" msgstr "SIGINT empfangen - wird sofort heruntergefahren\n" -#: dirmngr/dirmngr.c:1647 +#: dirmngr/dirmngr.c:1655 #, c-format msgid "signal %d received - no action defined\n" msgstr "Signal %d empfangen - keine Aktion definiert\n" -#: dirmngr/dirmngr.c:1799 +#: dirmngr/dirmngr.c:1807 #, c-format msgid "accept failed: %s - waiting 1s\n" msgstr "accept() fehlgeschlagen: %s - warte 1s\n" -#: dirmngr/dirmngr.c:1829 +#: dirmngr/dirmngr.c:1837 #, c-format msgid "error spawning connection handler: %s\n" msgstr "Fehler beim Starten des Verbindungshandler: %s\n" @@ -9392,71 +9315,71 @@ msgstr "OCSP Responder gab einen nicht aktuellen Status zurück\n" msgid "OCSP responder returned an too old status\n" msgstr "OCSP Responder gab einen zu alten Status zurück\n" -#: dirmngr/server.c:269 dirmngr/server.c:381 dirmngr/server.c:427 +#: dirmngr/server.c:291 dirmngr/server.c:403 dirmngr/server.c:449 #, c-format msgid "assuan_inquire(%s) failed: %s\n" msgstr "assuan_inquire(%s) fehlgeschlagen: %s\n" -#: dirmngr/server.c:524 +#: dirmngr/server.c:546 msgid "ldapserver missing" msgstr "LDAP Server fehlt" -#: dirmngr/server.c:594 +#: dirmngr/server.c:616 msgid "serialno missing in cert ID" msgstr "Seriennummer fehlt in der Cert-ID" -#: dirmngr/server.c:730 dirmngr/server.c:816 dirmngr/server.c:1248 -#: dirmngr/server.c:1299 +#: dirmngr/server.c:752 dirmngr/server.c:838 dirmngr/server.c:1270 +#: dirmngr/server.c:1321 dirmngr/server.c:1578 dirmngr/server.c:1594 #, c-format msgid "assuan_inquire failed: %s\n" msgstr "assuan_inquire fehlgeschlagen: %s\n" -#: dirmngr/server.c:859 +#: dirmngr/server.c:881 #, c-format msgid "fetch_cert_by_url failed: %s\n" msgstr "fetch_cert_by_url() fehlgeschlagen: %s\n" -#: dirmngr/server.c:871 dirmngr/server.c:902 dirmngr/server.c:1058 +#: dirmngr/server.c:893 dirmngr/server.c:924 dirmngr/server.c:1080 #, c-format msgid "error sending data: %s\n" msgstr "Fehler beim Senden der Daten: %s\n" -#: dirmngr/server.c:1006 +#: dirmngr/server.c:1028 #, c-format msgid "start_cert_fetch failed: %s\n" msgstr "start_cert_fetch fehlgeschlagen: %s\n" -#: dirmngr/server.c:1039 +#: dirmngr/server.c:1061 #, c-format msgid "fetch_next_cert failed: %s\n" msgstr "fetch_next_cert fehlgeschlagen: %s\n" -#: dirmngr/server.c:1066 +#: dirmngr/server.c:1088 #, c-format msgid "max_replies %d exceeded\n" msgstr "max_replies %d überschritten\n" -#: dirmngr/server.c:1518 +#: dirmngr/server.c:1793 #, c-format msgid "can't allocate control structure: %s\n" msgstr "Fehler beim Erzeugen der Kontrollstruktur: %s\n" -#: dirmngr/server.c:1550 +#: dirmngr/server.c:1825 #, c-format msgid "failed to initialize the server: %s\n" msgstr "Fehler beim Initialisieren des Servers: %s\n" -#: dirmngr/server.c:1558 +#: dirmngr/server.c:1833 #, c-format msgid "failed to the register commands with Assuan: %s\n" msgstr "Fehler beim Registrieren der Kommandos gegen Assuan: %s\n" -#: dirmngr/server.c:1598 +#: dirmngr/server.c:1873 #, c-format msgid "Assuan accept problem: %s\n" msgstr "Assuan accept Problem: %s\n" -#: dirmngr/server.c:1617 +#: dirmngr/server.c:1892 #, c-format msgid "Assuan processing failed: %s\n" msgstr "Assuan Verarbeitung fehlgeschlagen: %s\n" @@ -9592,141 +9515,141 @@ msgstr "Senden der Zeile schlug fehl: %s\n" msgid "error sending standard options: %s\n" msgstr "Fehler beim Senden der Standardoptionen: %s\n" -#: tools/gpgconf-comp.c:479 tools/gpgconf-comp.c:583 tools/gpgconf-comp.c:650 -#: tools/gpgconf-comp.c:725 tools/gpgconf-comp.c:816 +#: tools/gpgconf-comp.c:481 tools/gpgconf-comp.c:589 tools/gpgconf-comp.c:659 +#: tools/gpgconf-comp.c:737 tools/gpgconf-comp.c:832 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung der Diagnoseausgaben" -#: tools/gpgconf-comp.c:492 tools/gpgconf-comp.c:596 tools/gpgconf-comp.c:663 -#: tools/gpgconf-comp.c:738 tools/gpgconf-comp.c:839 +#: tools/gpgconf-comp.c:494 tools/gpgconf-comp.c:602 tools/gpgconf-comp.c:672 +#: tools/gpgconf-comp.c:750 tools/gpgconf-comp.c:855 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" -#: tools/gpgconf-comp.c:502 tools/gpgconf-comp.c:621 tools/gpgconf-comp.c:684 -#: tools/gpgconf-comp.c:767 tools/gpgconf-comp.c:846 +#: tools/gpgconf-comp.c:504 tools/gpgconf-comp.c:627 tools/gpgconf-comp.c:693 +#: tools/gpgconf-comp.c:779 tools/gpgconf-comp.c:862 msgid "Options useful for debugging" msgstr "Nützliche Optionen zur Fehlersuche" -#: tools/gpgconf-comp.c:515 tools/gpgconf-comp.c:631 tools/gpgconf-comp.c:780 +#: tools/gpgconf-comp.c:517 tools/gpgconf-comp.c:637 tools/gpgconf-comp.c:792 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" -#: tools/gpgconf-comp.c:522 +#: tools/gpgconf-comp.c:524 msgid "|N|expire SSH keys after N seconds" msgstr "|N|lasse SSH Schlüssel im Cache nach N Sekunden verfallen" -#: tools/gpgconf-comp.c:526 +#: tools/gpgconf-comp.c:528 msgid "|N|set maximum PIN cache lifetime to N seconds" msgstr "|N|setze die maximale Lebensdauer von PINs im Cache auf N Sekunden" -#: tools/gpgconf-comp.c:530 +#: tools/gpgconf-comp.c:532 msgid "|N|set maximum SSH key lifetime to N seconds" msgstr "|N|setze die maximale Lebenszeit von SSH Schlüsseln auf N Sekunden" -#: tools/gpgconf-comp.c:544 +#: tools/gpgconf-comp.c:546 msgid "Options enforcing a passphrase policy" msgstr "Optionen für eine Passphrase-Policy" -#: tools/gpgconf-comp.c:547 +#: tools/gpgconf-comp.c:549 msgid "do not allow to bypass the passphrase policy" msgstr "Einhaltung der Passphrase-Policy erzwingen" -#: tools/gpgconf-comp.c:551 +#: tools/gpgconf-comp.c:553 msgid "|N|set minimal required length for new passphrases to N" msgstr "|N|setze die kleinste erlaubte Länge von Passphrasen auf N" -#: tools/gpgconf-comp.c:555 +#: tools/gpgconf-comp.c:557 msgid "|N|require at least N non-alpha characters for a new passphrase" msgstr "|N|Verlange mindestens N Nicht-Buchstaben für eine neue Passphrase" -#: tools/gpgconf-comp.c:559 +#: tools/gpgconf-comp.c:561 msgid "|FILE|check new passphrases against pattern in FILE" msgstr "|DATEI|Prüfe neue Passphrases gegen die Regelen in DATEI" -#: tools/gpgconf-comp.c:563 +#: tools/gpgconf-comp.c:565 msgid "|N|expire the passphrase after N days" msgstr "|N|Lasse die Passphrase nach N Tagen verfallen" -#: tools/gpgconf-comp.c:567 +#: tools/gpgconf-comp.c:569 msgid "do not allow the reuse of old passphrases" msgstr "Verbiete die Wiedernutzung alter Passphrases." -#: tools/gpgconf-comp.c:665 tools/gpgconf-comp.c:740 +#: tools/gpgconf-comp.c:674 tools/gpgconf-comp.c:752 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|NAME als voreingestellten Schlüssel benutzen" -#: tools/gpgconf-comp.c:668 tools/gpgconf-comp.c:743 +#: tools/gpgconf-comp.c:677 tools/gpgconf-comp.c:755 msgid "|NAME|encrypt to user ID NAME as well" msgstr "|NAME|Auch an NAME verschlüsseln" -#: tools/gpgconf-comp.c:671 +#: tools/gpgconf-comp.c:680 msgid "|SPEC|set up email aliases" msgstr "|SPEC|Email Alias festlegen" -#: tools/gpgconf-comp.c:697 +#: tools/gpgconf-comp.c:706 msgid "Configuration for Keyservers" msgstr "Konfiguration der Schlüsselserver" -#: tools/gpgconf-comp.c:699 +#: tools/gpgconf-comp.c:708 msgid "|URL|use keyserver at URL" msgstr "Benutze Schlüsselserver unter der URL" -#: tools/gpgconf-comp.c:702 +#: tools/gpgconf-comp.c:711 msgid "allow PKA lookups (DNS requests)" msgstr "Erlaube PKA Zugriffe (DNS Anfragen)" -#: tools/gpgconf-comp.c:705 +#: tools/gpgconf-comp.c:714 msgid "|MECHANISMS|use MECHANISMS to locate keys by mail address" msgstr "" "|MECHANISMEN|Benutze MECHANISMEN um Schlüssel über die Mailadresse " "aufzufinden." -#: tools/gpgconf-comp.c:752 +#: tools/gpgconf-comp.c:764 msgid "disable all access to the dirmngr" msgstr "Jeglichen Zugriff auf den Dirmngr verhindern" -#: tools/gpgconf-comp.c:755 +#: tools/gpgconf-comp.c:767 msgid "|NAME|use encoding NAME for PKCS#12 passphrases" msgstr "|NAME|Benutze die Kodierung NAME für PKCS#12 Passphrasen" -#: tools/gpgconf-comp.c:785 +#: tools/gpgconf-comp.c:797 msgid "do not check CRLs for root certificates" msgstr "CRL bei Wurzelzertifikaten nicht überprüfen" -#: tools/gpgconf-comp.c:829 +#: tools/gpgconf-comp.c:845 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:865 +#: tools/gpgconf-comp.c:881 msgid "Options controlling the interactivity and enforcement" msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" -#: tools/gpgconf-comp.c:875 +#: tools/gpgconf-comp.c:891 msgid "Configuration for HTTP servers" msgstr "Konfiguration für HTTP Server" -#: tools/gpgconf-comp.c:886 +#: tools/gpgconf-comp.c:902 msgid "use system's HTTP proxy setting" msgstr "Benutze die HTTP Proxy Einstellung des Systems" -#: tools/gpgconf-comp.c:891 +#: tools/gpgconf-comp.c:907 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:920 +#: tools/gpgconf-comp.c:936 msgid "LDAP server list" msgstr "Liste der LDAP Server" -#: tools/gpgconf-comp.c:928 +#: tools/gpgconf-comp.c:944 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" -#: tools/gpgconf-comp.c:3074 +#: tools/gpgconf-comp.c:3091 #, c-format msgid "External verification of component %s failed" msgstr "Die externe Überprüfung der Komponente %s war nicht erfolgreich" -#: tools/gpgconf-comp.c:3224 +#: tools/gpgconf-comp.c:3241 msgid "Note that group specifications are ignored\n" msgstr "Beachten Sie, daß Gruppenspezifiaktionen ignoriert werden\n" @@ -9986,6 +9909,59 @@ msgstr "" "Syntax: gpg-check-pattern [optionen] Musterdatei\n" "Die von stdin gelesene Passphrase gegen die Musterdatei prüfen\n" +#~ msgid "searching for names from %s server %s\n" +#~ msgstr "suche Namen auf %s-Server %s\n" + +#~ msgid "searching for names from %s\n" +#~ msgstr "suche Namen auf %s\n" + +#~ msgid "searching for \"%s\" from %s server %s\n" +#~ msgstr "suche nach \"%s\" auf %s-Server %s\n" + +#~ msgid "searching for \"%s\" from %s\n" +#~ msgstr "suche nach \"%s\" auf %s\n" + +#~ msgid "no keyserver action!\n" +#~ msgstr "Kein Schlüsselserver-Vorgang\n" + +#~ msgid "WARNING: keyserver handler from a different version of GnuPG (%s)\n" +#~ msgstr "" +#~ "WARNUNG: Die Schlüsselserver-Handhabungsroutine stammt von einer anderen " +#~ "GnuPG-Version (%s)\n" + +#~ msgid "keyserver did not send VERSION\n" +#~ msgstr "Schlüsselserver sendete VERSION nicht\n" + +#~ msgid "no handler for keyserver scheme `%s'\n" +#~ msgstr "Keine Handhabungsroutine für Schlüsselserverschema `%s'\n" + +#~ msgid "action `%s' not supported with keyserver scheme `%s'\n" +#~ msgstr "" +#~ "Vorgang `%s' wird vom Schlüsselserverschema `%s' nicht unterstützt\n" + +#~ msgid "%s does not support handler version %d\n" +#~ msgstr "%s unterstützt Hilfsroutinenversion %d nicht\n" + +#~ msgid "keyserver timed out\n" +#~ msgstr "Schlüsselserver-Zeitüberschreitung\n" + +#~ msgid "keyserver internal error\n" +#~ msgstr "interner Fehler Schlüsselserver\n" + +#~ msgid "keyserver communications error: %s\n" +#~ msgstr "Schlüsselserver-Datenübertragunsfehler: %s\n" + +#~ msgid "connection to agent established (%ds)\n" +#~ msgstr "Verbindung zum gpg-agent aufgebaut (%ds)\n" + +#~ msgid "connection to the dirmngr established (%ds)\n" +#~ msgstr "Verbindung zum Dirmngr aufgebaut (%ds)\n" + +#~ msgid "external keyserver calls are not supported in this build\n" +#~ msgstr "" +#~ "Externe Schlüsselserveraufrufe werden in diesem \"Build\" nicht " +#~ "unterstützt\n" + #~ msgid "This key is not protected.\n" #~ msgstr "Dieser Schlüssel ist nicht geschützt.\n" |