summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2011-01-24 12:24:11 +0100
committerWerner Koch <wk@gnupg.org>2011-01-24 12:24:11 +0100
commitc5e8a4c0fdde7f4aef2163a3710483c87bdf3161 (patch)
treeae9da511231485f5c8ba8faeb3e7db3b971fe8ff
parentFix regression introduced by "editing only change". (diff)
parentRemove keyserver/ from the build system. (diff)
downloadgnupg2-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.tar.xz
gnupg2-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.zip
Merge branch 'master' into ECC-INTEGRATION-2-1
-rw-r--r--ChangeLog12
-rw-r--r--Makefile.am2
-rw-r--r--NEWS3
-rw-r--r--agent/ChangeLog4
-rw-r--r--agent/trustlist.c9
-rwxr-xr-xautogen.sh3
-rw-r--r--common/ChangeLog52
-rw-r--r--common/b64dec.c32
-rw-r--r--common/b64enc.c22
-rw-r--r--common/estream.c2
-rw-r--r--common/homedir.c2
-rw-r--r--common/http.c121
-rw-r--r--common/http.h15
-rw-r--r--common/iobuf.c127
-rw-r--r--common/iobuf.h2
-rw-r--r--common/keyserver.h24
-rw-r--r--common/membuf.c45
-rw-r--r--common/membuf.h3
-rw-r--r--common/util.h4
-rw-r--r--configure.ac26
-rw-r--r--dirmngr/ChangeLog20
-rw-r--r--dirmngr/Makefile.am3
-rw-r--r--dirmngr/crlfetch.c4
-rw-r--r--dirmngr/dirmngr.c58
-rw-r--r--dirmngr/dirmngr.h14
-rw-r--r--dirmngr/ks-action.c183
-rw-r--r--dirmngr/ks-action.h28
-rw-r--r--dirmngr/ks-engine-hkp.c558
-rw-r--r--dirmngr/ks-engine.h36
-rw-r--r--dirmngr/server.c285
-rw-r--r--doc/debugging.texi4
-rw-r--r--doc/gnupg.texi8
-rw-r--r--doc/tools.texi5
-rw-r--r--g10/ChangeLog24
-rw-r--r--g10/Makefile.am1
-rw-r--r--g10/call-dirmngr.c611
-rw-r--r--g10/call-dirmngr.h32
-rw-r--r--g10/export.c54
-rw-r--r--g10/gpg.c45
-rw-r--r--g10/gpg.h8
-rw-r--r--g10/import.c26
-rw-r--r--g10/keyserver-internal.h2
-rw-r--r--g10/keyserver.c1438
-rw-r--r--g10/main.h7
-rw-r--r--g10/options.h28
-rw-r--r--keyserver/ChangeLog6
-rw-r--r--keyserver/gpgkeys_hkp.c5
-rw-r--r--po/ChangeLog4
-rw-r--r--po/de.po1158
49 files changed, 3536 insertions, 1629 deletions
diff --git a/ChangeLog b/ChangeLog
index 287e4d1c2..d3e7eb1a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 =
diff --git a/NEWS b/NEWS
index 215373345..5f9fd0ab6 100644
--- a/NEWS
+++ b/NEWS
@@ -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 )
{
diff --git a/g10/gpg.c b/g10/gpg.c
index 3794aa2b7..47e8b361f 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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:
diff --git a/g10/gpg.h b/g10/gpg.h
index 1d645ea25..29db15a45 100644
--- a/g10/gpg.h
+++ b/g10/gpg.h
@@ -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/.
diff --git a/po/de.po b/po/de.po
index eec7d0427..3f4a9781f 100644
--- a/po/de.po
+++ b/po/de.po
@@ -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"