More work on the dirmngr. It now builds for W32 and W32CE and quick

tests show that it works on W32.
This commit is contained in:
Werner Koch 2010-08-06 13:52:01 +00:00
parent be622bd268
commit dc5a80930b
14 changed files with 353 additions and 153 deletions

View File

@ -1,3 +1,7 @@
2010-08-05 Werner Koch <wk@g10code.com>
* configure.ac (AH_BOTTOM): Remove HTTP_USE_ESTREAM.
2010-08-02 Werner Koch <wk@g10code.com> 2010-08-02 Werner Koch <wk@g10code.com>
* configure.ac: Require libksba 1.1.0 due to the use of * configure.ac: Require libksba 1.1.0 due to the use of

View File

@ -1,3 +1,17 @@
2010-08-06 Werner Koch <wk@g10code.com>
* homedir.c (dirmngr_socket_name) [W32CE]: Base on default homedir.
(gnupg_cachedir) [W32CE]: Drop drive letter.
* http.c (http_open_document): Rename to _http_open_document and
add arg ERRSOURCE. Pass ERRSOURCE to all called funcs.
(http_wait_response, http_open, http_parse_uri): Likewise.
(do_parse_uri, parse_response, store_header): Change to return an
gpg_err_code_t. Change callers.
(send_request): Add arg ERRSOURCE. Change callers.
* http.h (http_open_document, http_wait_response, http_open)
(http_parse_uri): Define as macro.
2010-08-05 Werner Koch <wk@g10code.com> 2010-08-05 Werner Koch <wk@g10code.com>
* estream.h (es_asprintf, es_vasprintf): Add lost prototyps. * estream.h (es_asprintf, es_vasprintf): Add lost prototyps.

View File

@ -412,7 +412,12 @@ gnupg_cachedir (void)
dir = tmp; dir = tmp;
} }
else else
dir = "c:\\temp\\cache\\dirmngr"; {
dir = "c:\\temp\\cache\\gnupg";
#ifdef HAVE_W32CE_SYSTEM
dir += 2;
#endif
}
} }
return dir; return dir;
#else /*!HAVE_W32_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/
@ -430,6 +435,12 @@ dirmngr_socket_name (void)
if (!name) if (!name)
{ {
char *p;
# ifdef HAVE_W32CE_SYSTEM
const char *s1, *s2;
s1 = default_homedir ();
# else
char s1[MAX_PATH]; char s1[MAX_PATH];
const char *s2; const char *s2;
@ -440,9 +451,13 @@ dirmngr_socket_name (void)
that. */ that. */
if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0) if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0)
strcpy (s1, "C:\\WINDOWS"); strcpy (s1, "C:\\WINDOWS");
# endif
s2 = DIRSEP_S "S.dirmngr"; s2 = DIRSEP_S "S.dirmngr";
name = xmalloc (strlen (s1) + strlen (s2) + 1); name = xmalloc (strlen (s1) + strlen (s2) + 1);
strcpy (stpcpy (name, s1), s2); strcpy (stpcpy (name, s1), s2);
for (p=name; *p; p++)
if (*p == '/')
*p = '\\';
} }
return name; return name;
#else /*!HAVE_W32_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/

View File

@ -131,21 +131,18 @@ typedef unsigned long longcounter_t;
# define counter_strtoul(a) strtoul ((a), NULL, 10) # define counter_strtoul(a) strtoul ((a), NULL, 10)
#endif #endif
#if defined(HTTP_USE_ESTREAM) && defined (__GNUC__)
# warning HTTP_USE_ESTREAM is an obsolete macro
#endif
#ifndef HTTP_USE_GNUTLS #ifndef HTTP_USE_GNUTLS
typedef void * gnutls_session_t; typedef void * gnutls_session_t;
#endif #endif
static gpg_error_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);
static int remove_escapes (char *string); static int remove_escapes (char *string);
static int insert_escapes (char *buffer, const char *string, static int insert_escapes (char *buffer, const char *string,
const char *special); const char *special);
static uri_tuple_t parse_tuple (char *string); static uri_tuple_t parse_tuple (char *string);
static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy, static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy,
const char *srvtag,strlist_t headers); const char *srvtag,strlist_t headers,
gpg_err_source_t errsource);
static char *build_rel_path (parsed_uri_t uri); static char *build_rel_path (parsed_uri_t uri);
static gpg_error_t parse_response (http_t hd); static gpg_error_t parse_response (http_t hd);
@ -334,9 +331,10 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) )
pointer for completing the the request and to wait for the pointer for completing the the request and to wait for the
response. */ response. */
gpg_error_t gpg_error_t
http_open (http_t *r_hd, http_req_t reqtype, const char *url, _http_open (http_t *r_hd, http_req_t reqtype, const char *url,
const char *auth, unsigned int flags, const char *proxy, const char *auth, unsigned int flags, const char *proxy,
void *tls_context, const char *srvtag,strlist_t headers) void *tls_context, const char *srvtag, strlist_t headers,
gpg_err_source_t errsource)
{ {
gpg_error_t err; gpg_error_t err;
http_t hd; http_t hd;
@ -344,7 +342,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
*r_hd = NULL; *r_hd = NULL;
if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST)) if (!(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST))
return gpg_error (GPG_ERR_INV_ARG); return gpg_err_make (errsource, GPG_ERR_INV_ARG);
/* Create the handle. */ /* Create the handle. */
hd = xtrycalloc (1, sizeof *hd); hd = xtrycalloc (1, sizeof *hd);
@ -355,9 +353,9 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
hd->flags = flags; hd->flags = flags;
hd->tls_context = tls_context; hd->tls_context = tls_context;
err = http_parse_uri (&hd->uri, url); err = _http_parse_uri (&hd->uri, url, errsource);
if (!err) if (!err)
err = send_request (hd, auth, proxy, srvtag, headers); err = send_request (hd, auth, proxy, srvtag, headers, errsource);
if (err) if (err)
{ {
@ -391,7 +389,7 @@ http_start_data (http_t hd)
gpg_error_t gpg_error_t
http_wait_response (http_t hd) _http_wait_response (http_t hd, gpg_err_source_t errsource)
{ {
gpg_error_t err; gpg_error_t err;
cookie_t cookie; cookie_t cookie;
@ -402,7 +400,7 @@ http_wait_response (http_t hd)
/* Close the write stream but keep the socket open. */ /* Close the write stream but keep the socket open. */
cookie = hd->write_cookie; cookie = hd->write_cookie;
if (!cookie) if (!cookie)
return gpg_error (GPG_ERR_INTERNAL); return gpg_err_make (errsource, GPG_ERR_INTERNAL);
cookie->keep_socket = 1; cookie->keep_socket = 1;
es_fclose (hd->fp_write); es_fclose (hd->fp_write);
@ -420,7 +418,7 @@ http_wait_response (http_t hd)
/* Create a new cookie and a stream for reading. */ /* Create a new cookie and a stream for reading. */
cookie = xtrycalloc (1, sizeof *cookie); cookie = xtrycalloc (1, sizeof *cookie);
if (!cookie) if (!cookie)
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
cookie->fd = hd->sock; cookie->fd = hd->sock;
if (hd->uri->use_tls) if (hd->uri->use_tls)
cookie->tls_session = hd->tls_context; cookie->tls_session = hd->tls_context;
@ -431,7 +429,7 @@ http_wait_response (http_t hd)
{ {
xfree (cookie); xfree (cookie);
hd->read_cookie = NULL; hd->read_cookie = NULL;
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
} }
err = parse_response (hd); err = parse_response (hd);
@ -444,18 +442,19 @@ http_wait_response (http_t hd)
be used as an HTTP proxy and any enabled $http_proxy gets be used as an HTTP proxy and any enabled $http_proxy gets
ignored. */ ignored. */
gpg_error_t gpg_error_t
http_open_document (http_t *r_hd, const char *document, _http_open_document (http_t *r_hd, const char *document,
const char *auth, unsigned int flags, const char *proxy, const char *auth, unsigned int flags, const char *proxy,
void *tls_context, const char *srvtag,strlist_t headers) void *tls_context, const char *srvtag, strlist_t headers,
gpg_err_source_t errsource)
{ {
gpg_error_t err; gpg_error_t err;
err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, err = _http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
proxy, tls_context, srvtag, headers); proxy, tls_context, srvtag, headers, errsource);
if (err) if (err)
return err; return err;
err = http_wait_response (*r_hd); err = _http_wait_response (*r_hd, errsource);
if (err) if (err)
http_close (*r_hd, 0); http_close (*r_hd, 0);
@ -513,13 +512,14 @@ http_get_status_code (http_t hd)
* resources (even on error). * resources (even on error).
*/ */
gpg_error_t gpg_error_t
http_parse_uri (parsed_uri_t * ret_uri, const char *uri) _http_parse_uri (parsed_uri_t * ret_uri, const char *uri,
gpg_err_source_t errsource)
{ {
*ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri)); *ret_uri = xtrycalloc (1, sizeof **ret_uri + strlen (uri));
if (!*ret_uri) if (!*ret_uri)
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
strcpy ((*ret_uri)->buffer, uri); strcpy ((*ret_uri)->buffer, uri);
return do_parse_uri (*ret_uri, 0); return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0));
} }
void void
@ -539,7 +539,7 @@ http_release_parsed_uri (parsed_uri_t uri)
} }
static gpg_error_t 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)
{ {
uri_tuple_t *tail; uri_tuple_t *tail;
@ -557,13 +557,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
/* A quick validity check. */ /* A quick validity check. */
if (strspn (p, VALID_URI_CHARS) != n) if (strspn (p, VALID_URI_CHARS) != n)
return gpg_error (GPG_ERR_BAD_URI); /* Invalid characters found. */ return GPG_ERR_BAD_URI; /* Invalid characters found. */
if (!only_local_part) if (!only_local_part)
{ {
/* Find the scheme. */ /* Find the scheme. */
if (!(p2 = strchr (p, ':')) || p2 == p) if (!(p2 = strchr (p, ':')) || p2 == p)
return gpg_error (GPG_ERR_BAD_URI); /* No scheme. */ return GPG_ERR_BAD_URI; /* No scheme. */
*p2++ = 0; *p2++ = 0;
for (pp=p; *pp; pp++) for (pp=p; *pp; pp++)
*pp = tolower (*(unsigned char*)pp); *pp = tolower (*(unsigned char*)pp);
@ -578,13 +578,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
} }
#endif #endif
else else
return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */ return GPG_ERR_INV_URI; /* Unsupported scheme */
p = p2; p = p2;
/* Find the hostname */ /* Find the hostname */
if (*p != '/') if (*p != '/')
return gpg_error (GPG_ERR_INV_URI); /* Does not start with a slash. */ return GPG_ERR_INV_URI; /* Does not start with a slash. */
p++; p++;
if (*p == '/') /* There seems to be a hostname. */ if (*p == '/') /* There seems to be a hostname. */
@ -622,9 +622,9 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
} }
if ((n = remove_escapes (uri->host)) < 0) if ((n = remove_escapes (uri->host)) < 0)
return gpg_error (GPG_ERR_BAD_URI); return GPG_ERR_BAD_URI;
if (n != strlen (uri->host)) if (n != strlen (uri->host))
return gpg_error (GPG_ERR_BAD_URI); /* Hostname incudes a Nul. */ return GPG_ERR_BAD_URI; /* Hostname incudes a Nul. */
p = p2 ? p2 : NULL; p = p2 ? p2 : NULL;
} }
} /* End global URI part. */ } /* End global URI part. */
@ -641,9 +641,9 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
uri->path = p; uri->path = p;
if ((n = remove_escapes (p)) < 0) if ((n = remove_escapes (p)) < 0)
return gpg_error (GPG_ERR_BAD_URI); return GPG_ERR_BAD_URI;
if (n != strlen (p)) if (n != strlen (p))
return gpg_error (GPG_ERR_BAD_URI); /* Path includes a Nul. */ return GPG_ERR_BAD_URI; /* Path includes a Nul. */
p = p2 ? p2 : NULL; p = p2 ? p2 : NULL;
if (!p || !*p) if (!p || !*p)
@ -658,7 +658,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
if ((p2 = strchr (p, '&'))) if ((p2 = strchr (p, '&')))
*p2++ = 0; *p2++ = 0;
if (!(elem = parse_tuple (p))) if (!(elem = parse_tuple (p)))
return gpg_error (GPG_ERR_BAD_URI); return GPG_ERR_BAD_URI;
*tail = elem; *tail = elem;
tail = &elem->next; tail = &elem->next;
@ -816,7 +816,8 @@ parse_tuple (char *string)
*/ */
static gpg_error_t static gpg_error_t
send_request (http_t hd, const char *auth, send_request (http_t hd, const char *auth,
const char *proxy,const char *srvtag,strlist_t headers) const char *proxy, const char *srvtag, strlist_t headers,
gpg_err_source_t errsource)
{ {
gnutls_session_t tls_session; gnutls_session_t tls_session;
gpg_error_t err; gpg_error_t err;
@ -832,7 +833,7 @@ send_request (http_t hd, const char *auth,
if (hd->uri->use_tls && !tls_session) if (hd->uri->use_tls && !tls_session)
{ {
log_error ("TLS requested but no GNUTLS context provided\n"); log_error ("TLS requested but no GNUTLS context provided\n");
return gpg_error (GPG_ERR_INTERNAL); return gpg_err_make (errsource, GPG_ERR_INTERNAL);
} }
server = *hd->uri->host ? hd->uri->host : "localhost"; server = *hd->uri->host ? hd->uri->host : "localhost";
@ -848,14 +849,13 @@ send_request (http_t hd, const char *auth,
if (proxy) if (proxy)
http_proxy = proxy; http_proxy = proxy;
err = http_parse_uri (&uri, http_proxy); err = _http_parse_uri (&uri, http_proxy, errsource);
if (err) if (err)
{ {
log_error ("invalid HTTP proxy (%s): %s\n", log_error ("invalid HTTP proxy (%s): %s\n",
http_proxy, gpg_strerror (err)); http_proxy, gpg_strerror (err));
http_release_parsed_uri (uri); http_release_parsed_uri (uri);
return gpg_error (GPG_ERR_CONFIGURATION); return gpg_err_make (errsource, GPG_ERR_CONFIGURATION);
} }
if (uri->auth) if (uri->auth)
@ -866,7 +866,7 @@ send_request (http_t hd, const char *auth,
uri->auth, strlen(uri->auth)); uri->auth, strlen(uri->auth));
if (!proxy_authstr) if (!proxy_authstr)
{ {
err = gpg_error_from_syserror (); err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
http_release_parsed_uri (uri); http_release_parsed_uri (uri);
return err; return err;
} }
@ -887,9 +887,9 @@ send_request (http_t hd, const char *auth,
if (hd->sock == -1) if (hd->sock == -1)
{ {
xfree (proxy_authstr); xfree (proxy_authstr);
return (save_errno return gpg_err_make (errsource, (save_errno
? gpg_error_from_errno (save_errno) ? gpg_err_code_from_errno (save_errno)
: gpg_error (GPG_ERR_NOT_FOUND)); : GPG_ERR_NOT_FOUND));
} }
#ifdef HTTP_USE_GNUTLS #ifdef HTTP_USE_GNUTLS
@ -907,7 +907,7 @@ send_request (http_t hd, const char *auth,
{ {
log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc)); log_info ("TLS handshake failed: %s\n", gnutls_strerror (rc));
xfree (proxy_authstr); xfree (proxy_authstr);
return gpg_error (GPG_ERR_NETWORK); return gpg_err_make (errsource, GPG_ERR_NETWORK);
} }
if (tls_callback) if (tls_callback)
@ -934,7 +934,7 @@ send_request (http_t hd, const char *auth,
if (!myauth) if (!myauth)
{ {
xfree (proxy_authstr); xfree (proxy_authstr);
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
} }
remove_escapes (myauth); remove_escapes (myauth);
} }
@ -952,13 +952,13 @@ send_request (http_t hd, const char *auth,
if (!authstr) if (!authstr)
{ {
xfree (proxy_authstr); xfree (proxy_authstr);
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
} }
} }
p = build_rel_path (hd->uri); p = build_rel_path (hd->uri);
if (!p) if (!p)
return gpg_error_from_syserror (); return gpg_err_make (errsource, gpg_err_code_from_syserror ());
if (http_proxy && *http_proxy) if (http_proxy && *http_proxy)
{ {
@ -991,7 +991,7 @@ send_request (http_t hd, const char *auth,
xfree (p); xfree (p);
if (!request) if (!request)
{ {
err = gpg_error_from_syserror (); err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
xfree (authstr); xfree (authstr);
xfree (proxy_authstr); xfree (proxy_authstr);
return err; return err;
@ -1006,7 +1006,7 @@ send_request (http_t hd, const char *auth,
cookie = xtrycalloc (1, sizeof *cookie); cookie = xtrycalloc (1, sizeof *cookie);
if (!cookie) if (!cookie)
{ {
err = gpg_error_from_syserror (); err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
goto leave; goto leave;
} }
cookie->fd = hd->sock; cookie->fd = hd->sock;
@ -1017,12 +1017,12 @@ send_request (http_t hd, const char *auth,
hd->fp_write = es_fopencookie (cookie, "w", cookie_functions); hd->fp_write = es_fopencookie (cookie, "w", cookie_functions);
if (!hd->fp_write) if (!hd->fp_write)
{ {
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
xfree (cookie); xfree (cookie);
hd->write_cookie = NULL; hd->write_cookie = NULL;
err = gpg_error_from_syserror ();
} }
else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write)) else if (es_fputs (request, hd->fp_write) || es_fflush (hd->fp_write))
err = gpg_error_from_syserror (); err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
else else
err = 0; err = 0;
@ -1033,7 +1033,7 @@ send_request (http_t hd, const char *auth,
if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write)) if ((es_fputs (headers->d, hd->fp_write) || es_fflush (hd->fp_write))
|| (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write))) || (es_fputs("\r\n",hd->fp_write) || es_fflush(hd->fp_write)))
{ {
err = gpg_error_from_syserror (); err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
break; break;
} }
} }
@ -1128,7 +1128,7 @@ capitalize_header_name (char *name)
/* Store an HTTP header line in LINE away. Line continuation is /* Store an HTTP header line in LINE away. Line continuation is
supported as well as merging of headers with the same name. This supported as well as merging of headers with the same name. This
function may modify LINE. */ function may modify LINE. */
static gpg_error_t static gpg_err_code_t
store_header (http_t hd, char *line) store_header (http_t hd, char *line)
{ {
size_t n; size_t n;
@ -1143,17 +1143,17 @@ store_header (http_t hd, char *line)
line[--n] = 0; line[--n] = 0;
} }
if (!n) /* we are never called to hit this. */ if (!n) /* we are never called to hit this. */
return gpg_error (GPG_ERR_BUG); return GPG_ERR_BUG;
if (*line == ' ' || *line == '\t') if (*line == ' ' || *line == '\t')
{ {
/* Continuation. This won't happen too often as it is not /* Continuation. This won't happen too often as it is not
recommended. We use a straightforward implementaion. */ recommended. We use a straightforward implementaion. */
if (!hd->headers) if (!hd->headers)
return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); return GPG_ERR_PROTOCOL_VIOLATION;
n += strlen (hd->headers->value); n += strlen (hd->headers->value);
p = xtrymalloc (n+1); p = xtrymalloc (n+1);
if (!p) if (!p)
return gpg_error_from_syserror (); return gpg_err_code_from_syserror ();
strcpy (stpcpy (p, hd->headers->value), line); strcpy (stpcpy (p, hd->headers->value), line);
xfree (hd->headers->value); xfree (hd->headers->value);
hd->headers->value = p; hd->headers->value = p;
@ -1163,7 +1163,7 @@ store_header (http_t hd, char *line)
capitalize_header_name (line); capitalize_header_name (line);
p = strchr (line, ':'); p = strchr (line, ':');
if (!p) if (!p)
return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); return GPG_ERR_PROTOCOL_VIOLATION;
*p++ = 0; *p++ = 0;
while (*p == ' ' || *p == '\t') while (*p == ' ' || *p == '\t')
p++; p++;
@ -1178,7 +1178,7 @@ store_header (http_t hd, char *line)
it is a comma separated list and merge them. */ it is a comma separated list and merge them. */
p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1); p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
if (!p) if (!p)
return gpg_error_from_syserror (); return gpg_err_code_from_syserror ();
strcpy (stpcpy (stpcpy (p, h->value), ","), value); strcpy (stpcpy (stpcpy (p, h->value), ","), value);
xfree (h->value); xfree (h->value);
h->value = p; h->value = p;
@ -1188,13 +1188,13 @@ store_header (http_t hd, char *line)
/* Append a new header. */ /* Append a new header. */
h = xtrymalloc (sizeof *h + strlen (line)); h = xtrymalloc (sizeof *h + strlen (line));
if (!h) if (!h)
return gpg_error_from_syserror (); return gpg_err_code_from_syserror ();
strcpy (h->name, line); strcpy (h->name, line);
h->value = xtrymalloc (strlen (value)+1); h->value = xtrymalloc (strlen (value)+1);
if (!h->value) if (!h->value)
{ {
xfree (h); xfree (h);
return gpg_error_from_syserror (); return gpg_err_code_from_syserror ();
} }
strcpy (h->value, value); strcpy (h->value, value);
h->next = hd->headers; h->next = hd->headers;
@ -1226,7 +1226,7 @@ http_get_header (http_t hd, const char *name)
* Parse the response from a server. * Parse the response from a server.
* Returns: Errorcode and sets some files in the handle * Returns: Errorcode and sets some files in the handle
*/ */
static gpg_error_t static gpg_err_code_t
parse_response (http_t hd) parse_response (http_t hd)
{ {
char *line, *p, *p2; char *line, *p, *p2;
@ -1250,12 +1250,13 @@ parse_response (http_t hd)
len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen); len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
line = hd->buffer; line = hd->buffer;
if (!line) if (!line)
return gpg_error_from_syserror (); /* Out of core. */ return gpg_err_code_from_syserror (); /* Out of core. */
if (!maxlen) if (!maxlen)
return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */ return GPG_ERR_TRUNCATED; /* Line has been truncated. */
if (!len) if (!len)
return gpg_error (GPG_ERR_EOF); return GPG_ERR_EOF;
if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
if ((hd->flags & HTTP_FLAG_LOG_RESP))
log_info ("RESP: `%.*s'\n", log_info ("RESP: `%.*s'\n",
(int)strlen(line)-(*line&&line[1]?2:0),line); (int)strlen(line)-(*line&&line[1]?2:0),line);
} }
@ -1294,21 +1295,21 @@ parse_response (http_t hd)
len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen); len = es_read_line (hd->fp_read, &hd->buffer, &hd->buffer_size, &maxlen);
line = hd->buffer; line = hd->buffer;
if (!line) if (!line)
return gpg_error_from_syserror (); /* Out of core. */ return gpg_err_code_from_syserror (); /* Out of core. */
/* Note, that we can silently ignore truncated lines. */ /* Note, that we can silently ignore truncated lines. */
if (!len) if (!len)
return gpg_error (GPG_ERR_EOF); return GPG_ERR_EOF;
/* Trim line endings of empty lines. */ /* Trim line endings of empty lines. */
if ((*line == '\r' && line[1] == '\n') || *line == '\n') if ((*line == '\r' && line[1] == '\n') || *line == '\n')
*line = 0; *line = 0;
if ( (hd->flags & HTTP_FLAG_LOG_RESP) ) if ((hd->flags & HTTP_FLAG_LOG_RESP))
log_info ("RESP: `%.*s'\n", log_info ("RESP: `%.*s'\n",
(int)strlen(line)-(*line&&line[1]?2:0),line); (int)strlen(line)-(*line&&line[1]?2:0),line);
if (*line) if (*line)
{ {
gpg_error_t err = store_header (hd, line); gpg_err_code_t ec = store_header (hd, line);
if (err) if (ec)
return err; return ec;
} }
} }
while (len && *line); while (len && *line);

View File

@ -70,33 +70,44 @@ typedef struct http_context_s *http_t;
void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int)); 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_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)
void http_release_parsed_uri (parsed_uri_t uri); void http_release_parsed_uri (parsed_uri_t uri);
gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, gpg_error_t _http_open (http_t *r_hd, http_req_t reqtype,
const char *url, const char *url,
const char *auth, const char *auth,
unsigned int flags, unsigned int flags,
const char *proxy, const char *proxy,
void *tls_context, void *tls_context,
const char *srvtag, const char *srvtag,
strlist_t headers); strlist_t headers,
gpg_err_source_t errsource);
#define http_open(a,b,c,d,e,f,g,h,i) \
_http_open ((a),(b),(c),(d),(e),(f),(g),(h),(i), GPG_ERR_SOURCE_DEFAULT)
void http_start_data (http_t hd); void http_start_data (http_t hd);
gpg_error_t http_wait_response (http_t hd); gpg_error_t _http_wait_response (http_t hd, gpg_err_source_t errsource);
#define http_wait_response(a) \
_http_wait_response ((a), GPG_ERR_SOURCE_DEFAULT)
void http_close (http_t hd, int keep_read_stream); void http_close (http_t hd, int keep_read_stream);
gpg_error_t http_open_document (http_t *r_hd, gpg_error_t _http_open_document (http_t *r_hd,
const char *document, const char *document,
const char *auth, const char *auth,
unsigned int flags, unsigned int flags,
const char *proxy, const char *proxy,
void *tls_context, void *tls_context,
const char *srvtag, const char *srvtag,
strlist_t headers); strlist_t headers,
gpg_err_source_t errsource);
#define http_open_document(a,b,c,d,e,f,g,h) \
_http_open_document ((a),(b),(c),(d),(e),(f),(g),(h), GPG_ERR_SOURCE_DEFAULT)
estream_t http_get_read_ptr (http_t hd); estream_t http_get_read_ptr (http_t hd);
estream_t http_get_write_ptr (http_t hd); estream_t http_get_write_ptr (http_t hd);

View File

@ -1,3 +1,24 @@
2010-08-06 Werner Koch <wk@g10code.com>
* dirmngr.c (JNLIB_NEED_AFLOCAL): Define macro.
(main): Use SUN_LEN macro.
(main) [W32]: Allow EEXIST in addition to EADDRINUSE.
(JNLIB_NEED_AFLOCAL):
2010-08-05 Werner Koch <wk@g10code.com>
* server.c (set_error, leave_cmd): New.
(cmd_validate, cmd_ldapserver, cmd_isvalid, cmd_checkcrl)
(cmd_checkocsp, cmd_lookup, cmd_listcrls, cmd_cachecert): Use
leave_cmd.
(cmd_getinfo): New.
(data_line_cookie_write, data_line_cookie_close): New.
(cmd_listcrls): Replace assuan_get_data_fp by es_fopencookie.
* misc.c (create_estream_ksba_reader, my_estream_ksba_reader_cb): New.
* certcache.c (load_certs_from_dir): Use create_estream_ksba_reader.
* crlcache.c (crl_cache_load): Ditto.
2010-08-03 Werner Koch <wk@g10code.com> 2010-08-03 Werner Koch <wk@g10code.com>
* dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn * dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn

View File

@ -360,13 +360,10 @@ load_certs_from_dir (const char *dirname, int are_trusted)
fname, strerror (errno)); fname, strerror (errno));
continue; continue;
} }
err = ksba_reader_new (&reader);
if (!err) err = create_estream_ksba_reader (&reader, fp);
err = ksba_reader_set_file (reader, fp);
if (err) if (err)
{ {
log_error (_("can't setup KSBA reader: %s\n"), gpg_strerror (err));
ksba_reader_release (reader);
es_fclose (fp); es_fclose (fp);
continue; continue;
} }

View File

@ -2369,18 +2369,12 @@ crl_cache_load (ctrl_t ctrl, const char *filename)
return err; return err;
} }
err = ksba_reader_new (&reader); err = create_estream_ksba_reader (&reader, fp);
if (!err) if (!err)
err = ksba_reader_set_file (reader, fp);
if (err)
{ {
log_error (_("error initializing reader object: %s\n"), err = crl_cache_insert (ctrl, filename, reader);
gpg_strerror (err));
ksba_reader_release (reader); ksba_reader_release (reader);
return err;
} }
err = crl_cache_insert (ctrl, filename, reader);
ksba_reader_release (reader);
es_fclose (fp); es_fclose (fp);
return err; return err;
} }

View File

@ -30,6 +30,7 @@
#include "http.h" #include "http.h"
#include "estream.h" #include "estream.h"
#include "ldap-wrapper.h"
/* For detecting armored CRLs received via HTTP (yes, such CRLS really /* For detecting armored CRLs received via HTTP (yes, such CRLS really
@ -228,7 +229,8 @@ crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
pointer (or well the callback context) with the pointer (or well the callback context) with the
reader. It is only required when closing the reader. It is only required when closing the
reader thus there is no performance issue doing it reader thus there is no performance issue doing it
this way. */ this way. FIXME: We now have a close notification
which might be used here. */
register_file_reader (*reader, cb_ctx); register_file_reader (*reader, cb_ctx);
http_close (hd, 1); http_close (hd, 1);
} }

View File

@ -44,6 +44,7 @@
#define JNLIB_NEED_LOG_LOGV #define JNLIB_NEED_LOG_LOGV
#define JNLIB_NEED_AFLOCAL
#include "dirmngr.h" #include "dirmngr.h"
#include <assuan.h> #include <assuan.h>
@ -963,12 +964,17 @@ main (int argc, char **argv)
memset (&serv_addr, 0, sizeof serv_addr); memset (&serv_addr, 0, sizeof serv_addr);
serv_addr.sun_family = AF_UNIX; serv_addr.sun_family = AF_UNIX;
strcpy (serv_addr.sun_path, socket_name); strcpy (serv_addr.sun_path, socket_name);
len = (offsetof (struct sockaddr_un, sun_path) len = SUN_LEN (&serv_addr);
+ strlen (serv_addr.sun_path) + 1);
rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
if (rc == -1 && errno == EADDRINUSE) if (rc == -1
&& (errno == EADDRINUSE
#ifdef HAVE_W32_SYSTEM
|| errno == EEXIST
#endif
))
{ {
/* Fixme: We should test whether a dirmngr is already running. */
gnupg_remove (socket_name); gnupg_remove (socket_name);
rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
} }

View File

@ -199,7 +199,7 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
const char *src; const char *src;
size_t nread = 0; size_t nread = 0;
if (!buffer && !count && !nread) if (!buffer && !count && !r_nread)
return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported. */ return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported. */
*r_nread = 0; *r_nread = 0;

View File

@ -1,6 +1,6 @@
/* misc.c - miscellaneous /* misc.c - miscellaneous
* Copyright (C) 2002 Klarälvdalens Datakonsult AB * Copyright (C) 2002 Klarälvdalens Datakonsult AB
* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
* *
* This file is part of DirMngr. * This file is part of DirMngr.
* *
@ -484,3 +484,48 @@ host_and_port_from_url (const char *url, int *port)
return buf; return buf;
} }
/* A KSBA reader callback to read from an estream. */
static int
my_estream_ksba_reader_cb (void *cb_value, char *buffer, size_t count,
size_t *r_nread)
{
estream_t fp = cb_value;
if (!fp)
return gpg_error (GPG_ERR_INV_VALUE);
if (!buffer && !count && !r_nread)
{
es_rewind (fp);
return 0;
}
*r_nread = es_fread (buffer, 1, count, fp);
if (!*r_nread)
return -1; /* EOF or error. */
return 0; /* Success. */
}
/* Create a KSBA reader object and connect it to the estream FP. */
gpg_error_t
create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp)
{
gpg_error_t err;
ksba_reader_t reader;
*r_reader = NULL;
err = ksba_reader_new (&reader);
if (!err)
err = ksba_reader_set_cb (reader, my_estream_ksba_reader_cb, fp);
if (err)
{
log_error (_("error initializing reader object: %s\n"),
gpg_strerror (err));
ksba_reader_release (reader);
return err;
}
*r_reader = reader;
return 0;
}

View File

@ -73,15 +73,9 @@ void dump_cert (const char *text, ksba_cert_t cert);
URL. */ URL. */
char *host_and_port_from_url (const char *url, int *port); char *host_and_port_from_url (const char *url, int *port);
/* Create a KSBA reader object and connect it to the estream FP. */
gpg_error_t create_estream_ksba_reader (ksba_reader_t *r_reader, estream_t fp);
#ifdef HAVE_FOPENCOOKIE
/* We have to implement funopen in terms of glibc's fopencookie. */
FILE *funopen(void *cookie,
int (*readfn)(void *, char *, int),
int (*writefn)(void *, const char *, int),
fpos_t (*seekfn)(void *, fpos_t, int),
int (*closefn)(void *));
#endif /*HAVE_FOPENCOOKIE*/
#endif /* MISC_H */ #endif /* MISC_H */

View File

@ -40,6 +40,7 @@
#include "certcache.h" #include "certcache.h"
#include "validate.h" #include "validate.h"
#include "misc.h" #include "misc.h"
#include "ldap-wrapper.h"
/* To avoid DoS attacks we limit the size of a certificate to /* To avoid DoS attacks we limit the size of a certificate to
something reasonable. */ something reasonable. */
@ -47,6 +48,7 @@
#define PARM_ERROR(t) assuan_set_error (ctx, \ #define PARM_ERROR(t) assuan_set_error (ctx, \
gpg_error (GPG_ERR_ASS_PARAMETER), (t)) gpg_error (GPG_ERR_ASS_PARAMETER), (t))
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
@ -61,6 +63,20 @@ struct server_local_s
}; };
/* Cookie definition for assuan data line output. */
static ssize_t data_line_cookie_write (void *cookie,
const void *buffer, size_t size);
static int data_line_cookie_close (void *cookie);
static es_cookie_io_functions_t data_line_cookie_functions =
{
NULL,
data_line_cookie_write,
NULL,
data_line_cookie_close
};
/* Accessor for the local ldapservers variable. */ /* Accessor for the local ldapservers variable. */
@ -74,6 +90,55 @@ get_ldapservers_from_ctrl (ctrl_t ctrl)
} }
/* Helper to print a message while leaving a command. */
static gpg_error_t
leave_cmd (assuan_context_t ctx, gpg_error_t err)
{
if (err)
{
const char *name = assuan_get_command_name (ctx);
if (!name)
name = "?";
if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
log_error ("command '%s' failed: %s\n", name,
gpg_strerror (err));
else
log_error ("command '%s' failed: %s <%s>\n", name,
gpg_strerror (err), gpg_strsource (err));
}
return err;
}
/* A write handler used by es_fopencookie to write assuan data
lines. */
static ssize_t
data_line_cookie_write (void *cookie, const void *buffer, size_t size)
{
assuan_context_t ctx = cookie;
if (assuan_send_data (ctx, buffer, size))
{
gpg_err_set_errno (EIO);
return -1;
}
return size;
}
static int
data_line_cookie_close (void *cookie)
{
assuan_context_t ctx = cookie;
if (assuan_send_data (ctx, NULL, 0))
{
gpg_err_set_errno (EIO);
return -1;
}
return 0;
}
/* Copy the % and + escaped string S into the buffer D and replace the /* Copy the % and + escaped string S into the buffer D and replace the
escape sequences. Note, that it is sufficient to allocate the escape sequences. Note, that it is sufficient to allocate the
@ -452,17 +517,17 @@ cmd_ldapserver (assuan_context_t ctx, char *line)
while (spacep (line)) while (spacep (line))
line++; line++;
if (*line == '\0') if (*line == '\0')
return PARM_ERROR (_("ldapserver missing")); return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
server = ldapserver_parse_one (line, "", 0); server = ldapserver_parse_one (line, "", 0);
if (! server) if (! server)
return gpg_error (GPG_ERR_INV_ARG); return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
last_next_p = &ctrl->server_local->ldapservers; last_next_p = &ctrl->server_local->ldapservers;
while (*last_next_p) while (*last_next_p)
last_next_p = &(*last_next_p)->next; last_next_p = &(*last_next_p)->next;
*last_next_p = server; *last_next_p = server;
return 0; return leave_cmd (ctx, 0);
} }
@ -522,7 +587,7 @@ cmd_isvalid (assuan_context_t ctx, char *line)
if (strlen (issuerhash) != 40) if (strlen (issuerhash) != 40)
{ {
xfree (issuerhash); xfree (issuerhash);
return PARM_ERROR (_("serialno missing in cert ID")); return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
} }
ocsp_mode = 1; ocsp_mode = 1;
} }
@ -574,10 +639,8 @@ cmd_isvalid (assuan_context_t ctx, char *line)
} }
} }
if (err)
log_error (_("command %s failed: %s\n"), "ISVALID", gpg_strerror (err));
xfree (issuerhash); xfree (issuerhash);
return err; return leave_cmd (ctx, err);
} }
@ -688,10 +751,8 @@ cmd_checkcrl (assuan_context_t ctx, char *line)
} }
leave: leave:
if (err)
log_error (_("command %s failed: %s\n"), "CHECKCRL", gpg_strerror (err));
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return leave_cmd (ctx, err);
} }
@ -773,10 +834,8 @@ cmd_checkocsp (assuan_context_t ctx, char *line)
err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder); err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
leave: leave:
if (err)
log_error (_("command %s failed: %s\n"), "CHECKOCSP", gpg_strerror (err));
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return leave_cmd (ctx, err);
} }
@ -1066,10 +1125,7 @@ cmd_lookup (assuan_context_t ctx, char *line)
else else
err = lookup_cert_by_pattern (ctx, line, single, cache_only); err = lookup_cert_by_pattern (ctx, line, single, cache_only);
if (err) return leave_cmd (ctx, err);
log_error (_("command %s failed: %s\n"), "LOOKUP", gpg_strerror (err));
return err;
} }
@ -1126,9 +1182,7 @@ cmd_loadcrl (assuan_context_t ctx, char *line)
} }
} }
if (err) return leave_cmd (ctx, err);
log_error (_("command %s failed: %s\n"), "LOADCRL", gpg_strerror (err));
return err;
} }
@ -1143,17 +1197,19 @@ static gpg_error_t
cmd_listcrls (assuan_context_t ctx, char *line) cmd_listcrls (assuan_context_t ctx, char *line)
{ {
gpg_error_t err; gpg_error_t err;
estream_t fp = assuan_get_data_fp (ctx); estream_t fp;
(void)line; (void)line;
fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
if (!fp) if (!fp)
return PARM_ERROR (_("no data stream")); err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
else
err = crl_cache_list (fp); {
if (err) err = crl_cache_list (fp);
log_error (_("command %s failed: %s\n"), "LISTCRLS", gpg_strerror (err)); es_fclose (fp);
return err; }
return leave_cmd (ctx, err);
} }
@ -1204,10 +1260,8 @@ cmd_cachecert (assuan_context_t ctx, char *line)
err = cache_cert (cert); err = cache_cert (cert);
leave: leave:
if (err)
log_error (_("command %s failed: %s\n"), "CACHECERT", gpg_strerror (err));
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return leave_cmd (ctx, err);
} }
@ -1273,14 +1327,57 @@ cmd_validate (assuan_context_t ctx, char *line)
err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL); err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
leave: leave:
if (err)
log_error (_("command %s failed: %s\n"), "VALIDATE", gpg_strerror (err));
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return leave_cmd (ctx, err);
}
static const char hlp_getinfo[] =
"GETINFO <what>\n"
"\n"
"Multi purpose command to return certain information. \n"
"Supported values of WHAT are:\n"
"\n"
"version - Return the version of the program.\n"
"pid - Return the process id of the server.\n"
"\n"
"socket_name - Return the name of the socket.\n";
static gpg_error_t
cmd_getinfo (assuan_context_t ctx, char *line)
{
gpg_error_t err;
if (!strcmp (line, "version"))
{
const char *s = VERSION;
err = assuan_send_data (ctx, s, strlen (s));
}
else if (!strcmp (line, "pid"))
{
char numbuf[50];
snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
err = assuan_send_data (ctx, numbuf, strlen (numbuf));
}
else if (!strcmp (line, "socket_name"))
{
const char *s = dirmngr_socket_name ();
if (s)
err = assuan_send_data (ctx, s, strlen (s));
else
err = gpg_error (GPG_ERR_NO_DATA);
}
else
err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
return leave_cmd (ctx, err);
} }
/* Tell the assuan library about our commands. */ /* Tell the assuan library about our commands. */
static int static int
register_commands (assuan_context_t ctx) register_commands (assuan_context_t ctx)
@ -1299,8 +1396,7 @@ register_commands (assuan_context_t ctx)
{ "LISTCRLS", cmd_listcrls, hlp_listcrls }, { "LISTCRLS", cmd_listcrls, hlp_listcrls },
{ "CACHECERT", cmd_cachecert, hlp_cachecert }, { "CACHECERT", cmd_cachecert, hlp_cachecert },
{ "VALIDATE", cmd_validate, hlp_validate }, { "VALIDATE", cmd_validate, hlp_validate },
{ "INPUT", NULL }, { "GETINFO", cmd_getinfo, hlp_getinfo },
{ "OUTPUT", NULL },
{ NULL, NULL } { NULL, NULL }
}; };
int i, j, rc; int i, j, rc;