aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2011-01-24 11:24:11 +0000
committerWerner Koch <[email protected]>2011-01-24 11:24:11 +0000
commitc5e8a4c0fdde7f4aef2163a3710483c87bdf3161 (patch)
treeae9da511231485f5c8ba8faeb3e7db3b971fe8ff /common
parentFix regression introduced by "editing only change". (diff)
parentRemove keyserver/ from the build system. (diff)
downloadgnupg-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.tar.gz
gnupg-c5e8a4c0fdde7f4aef2163a3710483c87bdf3161.zip
Merge branch 'master' into ECC-INTEGRATION-2-1
Diffstat (limited to 'common')
-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
13 files changed, 392 insertions, 59 deletions
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 <[email protected]>
+
+ 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * homedir.c (gnupg_module_name): Use NAME_OF_INSTALLED_GPG instead
+ of "gpg2".
+
+2011-01-18 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
+
+ * session-env.c (update_var): Fix same value detection. Fixes
+ bug#1311.
+
2011-01-10 Werner Koch <[email protected]>
* 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);