More work on the dirmngr. It now builds for W32 and W32CE and quick
authorWerner Koch <wk@gnupg.org>
Fri, 6 Aug 2010 13:52:01 +0000 (13:52 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 6 Aug 2010 13:52:01 +0000 (13:52 +0000)
tests show that it works on W32.

14 files changed:
ChangeLog
common/ChangeLog
common/homedir.c
common/http.c
common/http.h
dirmngr/ChangeLog
dirmngr/certcache.c
dirmngr/crlcache.c
dirmngr/crlfetch.c
dirmngr/dirmngr.c
dirmngr/ldap-wrapper-ce.c
dirmngr/misc.c
dirmngr/misc.h
dirmngr/server.c

index 4755b9d..433b50d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * configure.ac: Require libksba 1.1.0 due to the use of
index 2096ffd..d690534 100644 (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>
 
        * estream.h (es_asprintf, es_vasprintf): Add lost prototyps.
index 3cd8e9d..b1bde09 100644 (file)
@@ -412,7 +412,12 @@ gnupg_cachedir (void)
           dir = tmp;
         }
       else
-        dir = "c:\\temp\\cache\\dirmngr";
+        {
+          dir = "c:\\temp\\cache\\gnupg";
+#ifdef HAVE_W32CE_SYSTEM
+          dir += 2;
+#endif
+        }
     }
   return dir;
 #else /*!HAVE_W32_SYSTEM*/
@@ -430,6 +435,12 @@ dirmngr_socket_name (void)
 
   if (!name)
     {
+      char *p;
+# ifdef HAVE_W32CE_SYSTEM
+      const char *s1, *s2;
+
+      s1 = default_homedir ();
+# else
       char s1[MAX_PATH];
       const char *s2;
 
@@ -440,9 +451,13 @@ dirmngr_socket_name (void)
         that. */
       if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0)
        strcpy (s1, "C:\\WINDOWS");
+# endif
       s2 = DIRSEP_S "S.dirmngr";
       name = xmalloc (strlen (s1) + strlen (s2) + 1);
       strcpy (stpcpy (name, s1), s2);
+      for (p=name; *p; p++)
+        if (*p == '/')
+          *p = '\\';
     }
   return name;
 #else /*!HAVE_W32_SYSTEM*/
index 4ce7420..1e3e897 100644 (file)
@@ -131,21 +131,18 @@ typedef unsigned long longcounter_t;
 # define counter_strtoul(a) strtoul ((a), NULL, 10)
 #endif
 
-#if defined(HTTP_USE_ESTREAM) && defined (__GNUC__)
-# warning HTTP_USE_ESTREAM is an obsolete macro
-#endif
-
 #ifndef HTTP_USE_GNUTLS
 typedef void * gnutls_session_t;
 #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 insert_escapes (char *buffer, const char *string,
                            const char *special);
 static uri_tuple_t parse_tuple (char *string);
 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 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
    response. */
 gpg_error_t
-http_open (http_t *r_hd, http_req_t reqtype, const char *url, 
-           const char *auth, unsigned int flags, const char *proxy,
-           void *tls_context, const char *srvtag,strlist_t headers)
+_http_open (http_t *r_hd, http_req_t reqtype, const char *url, 
+            const char *auth, unsigned int flags, const char *proxy,
+            void *tls_context, const char *srvtag, strlist_t headers,
+            gpg_err_source_t errsource)
 {
   gpg_error_t err;
   http_t hd;
@@ -344,7 +342,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
   *r_hd = NULL;
 
   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. */
   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->tls_context = tls_context;
 
-  err = http_parse_uri (&hd->uri, url);
+  err = _http_parse_uri (&hd->uri, url, errsource);
   if (!err)
-    err = send_request (hd, auth, proxy, srvtag, headers);
+    err = send_request (hd, auth, proxy, srvtag, headers, errsource);
   
   if (err)
     {
@@ -391,7 +389,7 @@ http_start_data (http_t hd)
 
 
 gpg_error_t
-http_wait_response (http_t hd)
+_http_wait_response (http_t hd, gpg_err_source_t errsource)
 {
   gpg_error_t err;
   cookie_t cookie;
@@ -402,7 +400,7 @@ http_wait_response (http_t hd)
   /* Close the write stream but keep the socket open.  */
   cookie = hd->write_cookie;
   if (!cookie)
-    return gpg_error (GPG_ERR_INTERNAL);
+    return gpg_err_make (errsource, GPG_ERR_INTERNAL);
 
   cookie->keep_socket = 1;
   es_fclose (hd->fp_write);
@@ -420,7 +418,7 @@ http_wait_response (http_t hd)
   /* Create a new cookie and a stream for reading.  */
   cookie = xtrycalloc (1, sizeof *cookie);
   if (!cookie)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
   cookie->fd = hd->sock;
   if (hd->uri->use_tls)
     cookie->tls_session = hd->tls_context;
@@ -431,7 +429,7 @@ http_wait_response (http_t hd)
     {
       xfree (cookie);
       hd->read_cookie = NULL;
-      return gpg_error_from_syserror ();
+      return gpg_err_make (errsource, gpg_err_code_from_syserror ());
     }
 
   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
    ignored. */
 gpg_error_t
-http_open_document (http_t *r_hd, const char *document, 
-                    const char *auth, unsigned int flags, const char *proxy,
-                    void *tls_context, const char *srvtag,strlist_t headers)
+_http_open_document (http_t *r_hd, const char *document, 
+                     const char *auth, unsigned int flags, const char *proxy,
+                     void *tls_context, const char *srvtag, strlist_t headers,
+                     gpg_err_source_t errsource)
 {
   gpg_error_t err;
 
-  err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
-                   proxy, tls_context, srvtag, headers);
+  err = _http_open (r_hd, HTTP_REQ_GET, document, auth, flags,
+                    proxy, tls_context, srvtag, headers, errsource);
   if (err)
     return err;
 
-  err = http_wait_response (*r_hd);
+  err = _http_wait_response (*r_hd, errsource);
   if (err)
     http_close (*r_hd, 0);
 
@@ -513,13 +512,14 @@ http_get_status_code (http_t hd)
  * resources (even on error).
  */
 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));
   if (!*ret_uri)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
   strcpy ((*ret_uri)->buffer, uri);
-  return do_parse_uri (*ret_uri, 0);
+  return gpg_err_make (errsource, do_parse_uri (*ret_uri, 0));
 }
 
 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)
 {
   uri_tuple_t *tail;
@@ -557,13 +557,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
 
   /* A quick validity check. */
   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)
     {
       /* Find the scheme. */
       if (!(p2 = strchr (p, ':')) || p2 == p)
-       return gpg_error (GPG_ERR_BAD_URI); /* No scheme. */
+       return GPG_ERR_BAD_URI; /* No scheme. */
       *p2++ = 0;
       for (pp=p; *pp; pp++)
        *pp = tolower (*(unsigned char*)pp);
@@ -578,13 +578,13 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
         }
 #endif
       else
-       return gpg_error (GPG_ERR_INV_URI); /* Unsupported scheme */
+       return GPG_ERR_INV_URI; /* Unsupported scheme */
 
       p = p2;
 
       /* Find the hostname */
       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++;
       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)
-           return gpg_error (GPG_ERR_BAD_URI);
+           return GPG_ERR_BAD_URI;
          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;
        }
     } /* End global URI part. */
@@ -641,9 +641,9 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
 
   uri->path = p;
   if ((n = remove_escapes (p)) < 0)
-    return gpg_error (GPG_ERR_BAD_URI);
+    return GPG_ERR_BAD_URI;
   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;
 
   if (!p || !*p)       
@@ -658,7 +658,7 @@ do_parse_uri (parsed_uri_t uri, int only_local_part)
       if ((p2 = strchr (p, '&')))
        *p2++ = 0;
       if (!(elem = parse_tuple (p)))
-       return gpg_error (GPG_ERR_BAD_URI);
+       return GPG_ERR_BAD_URI;
       *tail = elem;
       tail = &elem->next;
 
@@ -816,7 +816,8 @@ parse_tuple (char *string)
  */
 static gpg_error_t
 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;
   gpg_error_t err;
@@ -832,7 +833,7 @@ send_request (http_t hd, const char *auth,
   if (hd->uri->use_tls && !tls_session)
     {
       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";
@@ -848,14 +849,13 @@ send_request (http_t hd, const char *auth,
       if (proxy)
        http_proxy = proxy;
 
-      err = http_parse_uri (&uri, http_proxy);
+      err = _http_parse_uri (&uri, http_proxy, errsource);
       if (err)
        {
          log_error ("invalid HTTP proxy (%s): %s\n",
                     http_proxy, gpg_strerror (err));
          http_release_parsed_uri (uri);
-         return gpg_error (GPG_ERR_CONFIGURATION);
-
+         return gpg_err_make (errsource, GPG_ERR_CONFIGURATION);
        }
 
       if (uri->auth)
@@ -866,7 +866,7 @@ send_request (http_t hd, const char *auth,
                                             uri->auth, strlen(uri->auth));
           if (!proxy_authstr)
             {
-              err = gpg_error_from_syserror ();
+              err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
               http_release_parsed_uri (uri);
               return err;
             }
@@ -887,9 +887,9 @@ send_request (http_t hd, const char *auth,
   if (hd->sock == -1)
     {
       xfree (proxy_authstr);
-      return (save_errno 
-              ? gpg_error_from_errno (save_errno)
-              : gpg_error (GPG_ERR_NOT_FOUND));
+      return gpg_err_make (errsource, (save_errno 
+                                       ? gpg_err_code_from_errno (save_errno)
+                                       : GPG_ERR_NOT_FOUND));
     }
 
 #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));
           xfree (proxy_authstr);
-          return gpg_error (GPG_ERR_NETWORK);
+          return gpg_err_make (errsource, GPG_ERR_NETWORK);
         }
 
       if (tls_callback)
@@ -934,7 +934,7 @@ send_request (http_t hd, const char *auth,
           if (!myauth)
             {
               xfree (proxy_authstr);
-              return gpg_error_from_syserror ();
+              return gpg_err_make (errsource, gpg_err_code_from_syserror ());
             }
           remove_escapes (myauth);
         }
@@ -952,13 +952,13 @@ send_request (http_t hd, const char *auth,
       if (!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);
   if (!p)
-    return gpg_error_from_syserror ();
+    return gpg_err_make (errsource, gpg_err_code_from_syserror ());
 
   if (http_proxy && *http_proxy)
     {
@@ -991,7 +991,7 @@ send_request (http_t hd, const char *auth,
   xfree (p);
   if (!request)
     {
-      err = gpg_error_from_syserror ();
+      err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
       xfree (authstr);
       xfree (proxy_authstr);
       return err;
@@ -1006,7 +1006,7 @@ send_request (http_t hd, const char *auth,
     cookie = xtrycalloc (1, sizeof *cookie);
     if (!cookie)
       {
-        err = gpg_error_from_syserror ();
+        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
         goto leave;
       }
     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);
     if (!hd->fp_write)
       {
+        err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
         xfree (cookie);
         hd->write_cookie = NULL;
-        err = gpg_error_from_syserror ();
       }
     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
       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))
               || (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;
             }
         }
@@ -1128,7 +1128,7 @@ capitalize_header_name (char *name)
 /* Store an HTTP header line in LINE away.  Line continuation is
    supported as well as merging of headers with the same name. This
    function may modify LINE. */
-static gpg_error_t
+static gpg_err_code_t
 store_header (http_t hd, char *line)
 {
   size_t n;
@@ -1143,17 +1143,17 @@ store_header (http_t hd, char *line)
         line[--n] = 0;
     }
   if (!n)  /* we are never called to hit this. */
-    return gpg_error (GPG_ERR_BUG);
+    return GPG_ERR_BUG;
   if (*line == ' ' || *line == '\t')
     {
       /* Continuation. This won't happen too often as it is not
          recommended.  We use a straightforward implementaion. */
       if (!hd->headers)
-        return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
+        return GPG_ERR_PROTOCOL_VIOLATION;
       n += strlen (hd->headers->value);
       p = xtrymalloc (n+1);
       if (!p)
-        return gpg_error_from_syserror ();
+        return gpg_err_code_from_syserror ();
       strcpy (stpcpy (p, hd->headers->value), line);
       xfree (hd->headers->value);
       hd->headers->value = p;
@@ -1163,7 +1163,7 @@ store_header (http_t hd, char *line)
   capitalize_header_name (line);
   p = strchr (line, ':');
   if (!p)
-    return gpg_error (GPG_ERR_PROTOCOL_VIOLATION);
+    return GPG_ERR_PROTOCOL_VIOLATION;
   *p++ = 0;
   while (*p == ' ' || *p == '\t')
     p++;
@@ -1178,7 +1178,7 @@ store_header (http_t hd, char *line)
          it is a comma separated list and merge them.  */
       p = xtrymalloc (strlen (h->value) + 1 + strlen (value)+ 1);
       if (!p)
-        return gpg_error_from_syserror ();
+        return gpg_err_code_from_syserror ();
       strcpy (stpcpy (stpcpy (p, h->value), ","), value);
       xfree (h->value);
       h->value = p;
@@ -1188,13 +1188,13 @@ store_header (http_t hd, char *line)
   /* Append a new header. */
   h = xtrymalloc (sizeof *h + strlen (line));
   if (!h)
-    return gpg_error_from_syserror ();
+    return gpg_err_code_from_syserror ();
   strcpy (h->name, line);
   h->value = xtrymalloc (strlen (value)+1);
   if (!h->value)
     {
       xfree (h);
-      return gpg_error_from_syserror ();
+      return gpg_err_code_from_syserror ();
     }
   strcpy (h->value, value);
   h->next = hd->headers;
@@ -1226,7 +1226,7 @@ http_get_header (http_t hd, const char *name)
  * Parse the response from a server.
  * Returns: Errorcode and sets some files in the handle
  */
-static gpg_error_t
+static gpg_err_code_t
 parse_response (http_t hd)
 {
   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);
       line = hd->buffer;
       if (!line)
-       return gpg_error_from_syserror (); /* Out of core. */
+       return gpg_err_code_from_syserror (); /* Out of core. */
       if (!maxlen)
-       return gpg_error (GPG_ERR_TRUNCATED); /* Line has been truncated. */
+       return GPG_ERR_TRUNCATED; /* Line has been truncated. */
       if (!len)
-       return gpg_error (GPG_ERR_EOF);
-      if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
+       return GPG_ERR_EOF;
+
+      if ((hd->flags & HTTP_FLAG_LOG_RESP))
         log_info ("RESP: `%.*s'\n",
                   (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);
       line = hd->buffer;
       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. */
       if (!len)
-       return gpg_error (GPG_ERR_EOF);
+       return GPG_ERR_EOF;
       /* Trim line endings of empty lines. */
       if ((*line == '\r' && line[1] == '\n') || *line == '\n')
        *line = 0;
-      if ( (hd->flags & HTTP_FLAG_LOG_RESP) )
+      if ((hd->flags & HTTP_FLAG_LOG_RESP))
         log_info ("RESP: `%.*s'\n",
                   (int)strlen(line)-(*line&&line[1]?2:0),line);
       if (*line)
         {
-          gpg_error_t err = store_header (hd, line);
-          if (err)
-            return err;
+          gpg_err_code_t ec = store_header (hd, line);
+          if (ec)
+            return ec;
         }
     }
   while (len && *line);
index 2dd612e..ac9cb15 100644 (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));
 
-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);
 
-gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
-                       const char *url,
-                       const char *auth,
-                       unsigned int flags,
-                       const char *proxy,
-                       void *tls_context,
-                      const char *srvtag,
-                      strlist_t headers);
+gpg_error_t _http_open (http_t *r_hd, http_req_t reqtype,
+                        const char *url,
+                        const char *auth,
+                        unsigned int flags,
+                        const char *proxy,
+                        void *tls_context,
+                        const char *srvtag,
+                        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);
 
-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);
 
-gpg_error_t http_open_document (http_t *r_hd,
-                                const char *document,
-                                const char *auth,
-                                unsigned int flags,
-                                const char *proxy,
-                                void *tls_context,
-                               const char *srvtag,
-                               strlist_t headers);
+gpg_error_t _http_open_document (http_t *r_hd,
+                                 const char *document,
+                                 const char *auth,
+                                 unsigned int flags,
+                                 const char *proxy,
+                                 void *tls_context,
+                                 const char *srvtag,
+                                 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_write_ptr (http_t hd);
index 57cc1c7..737ff35 100644 (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>
 
        * dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn
index 46d2ac3..d852811 100644 (file)
@@ -360,13 +360,10 @@ load_certs_from_dir (const char *dirname, int are_trusted)
                      fname, strerror (errno));
           continue;
         }
-      err = ksba_reader_new (&reader);
-      if (!err)
-        err = ksba_reader_set_file (reader, fp);
+
+      err = create_estream_ksba_reader (&reader, fp);
       if (err)
         {
-          log_error (_("can't setup KSBA reader: %s\n"), gpg_strerror (err));
-          ksba_reader_release (reader);
           es_fclose (fp);
           continue;
         }
index 441ae9e..e087419 100644 (file)
@@ -2369,18 +2369,12 @@ crl_cache_load (ctrl_t ctrl, const char *filename)
       return err;
     }
 
-  err = ksba_reader_new (&reader);
+  err = create_estream_ksba_reader (&reader, fp);
   if (!err)
-    err = ksba_reader_set_file (reader, fp);
-  if (err)
     {
-      log_error (_("error initializing reader object: %s\n"),
-                 gpg_strerror (err));
+      err = crl_cache_insert (ctrl, filename, reader);
       ksba_reader_release (reader);
-      return err;
     }
-  err = crl_cache_insert (ctrl, filename, reader);
-  ksba_reader_release (reader);
   es_fclose (fp);
   return err;
 }
index 6c2762c..83897a6 100644 (file)
@@ -30,6 +30,7 @@
 #include "http.h"
 
 #include "estream.h"
+#include "ldap-wrapper.h"
 
 
 /* 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
                    reader.  It is only required when closing the
                    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);
                 http_close (hd, 1);
               }
index 52efb9b..7aafc48 100644 (file)
@@ -44,6 +44,7 @@
 
 
 #define JNLIB_NEED_LOG_LOGV
+#define JNLIB_NEED_AFLOCAL
 #include "dirmngr.h"
 
 #include <assuan.h> 
@@ -963,12 +964,17 @@ main (int argc, char **argv)
       memset (&serv_addr, 0, sizeof serv_addr);
       serv_addr.sun_family = AF_UNIX;
       strcpy (serv_addr.sun_path, socket_name);
-      len = (offsetof (struct sockaddr_un, sun_path)
-             + strlen (serv_addr.sun_path) + 1);
+      len = SUN_LEN (&serv_addr);
 
       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);
          rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len);
        }
index b551534..9e6f785 100644 (file)
@@ -199,7 +199,7 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
   const char *src;
   size_t nread = 0;
 
-  if (!buffer && !count && !nread)
+  if (!buffer && !count && !r_nread)
     return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported.  */
 
   *r_nread = 0;
index 040d443..3d33bee 100644 (file)
@@ -1,6 +1,6 @@
 /* misc.c - miscellaneous
  *     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.
  *
@@ -484,3 +484,48 @@ host_and_port_from_url (const char *url, int *port)
   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;
+}
index b721549..928bf78 100644 (file)
@@ -73,15 +73,9 @@ void dump_cert (const char *text, ksba_cert_t cert);
    URL.  */
 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 */
index ce0a5b3..584cae7 100644 (file)
@@ -40,6 +40,7 @@
 #include "certcache.h"
 #include "validate.h"
 #include "misc.h"
+#include "ldap-wrapper.h"
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable. */
@@ -47,6 +48,7 @@
 
 #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))
 
 
 
@@ -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
+  };
+
+
+
 
 \f
 /* 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
    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))
     line++;
   if (*line == '\0')
-    return PARM_ERROR (_("ldapserver missing"));
+    return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
 
   server = ldapserver_parse_one (line, "", 0);
   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;
   while (*last_next_p)
     last_next_p = &(*last_next_p)->next;
   *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)
         {
           xfree (issuerhash);
-          return PARM_ERROR (_("serialno missing in cert ID"));
+          return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
         }
       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);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
@@ -688,10 +751,8 @@ cmd_checkcrl (assuan_context_t ctx, char *line)
     }
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CHECKCRL", gpg_strerror (err));
   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);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CHECKOCSP", gpg_strerror (err));
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
@@ -1066,10 +1125,7 @@ cmd_lookup (assuan_context_t ctx, char *line)
   else
     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
 
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LOOKUP", gpg_strerror (err));
-
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
@@ -1126,9 +1182,7 @@ cmd_loadcrl (assuan_context_t ctx, char *line)
         }
     }
 
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LOADCRL", gpg_strerror (err));
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
@@ -1143,17 +1197,19 @@ static gpg_error_t
 cmd_listcrls (assuan_context_t ctx, char *line)
 {
   gpg_error_t err;
-  estream_t fp = assuan_get_data_fp (ctx);
+  estream_t fp;
 
   (void)line;
 
+  fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
   if (!fp)
-    return PARM_ERROR (_("no data stream"));
-
-  err = crl_cache_list (fp);
-  if (err)
-    log_error (_("command %s failed: %s\n"), "LISTCRLS", gpg_strerror (err));
-  return err;
+    err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
+  else
+    {
+      err = crl_cache_list (fp);
+      es_fclose (fp);
+    }
+  return leave_cmd (ctx, err);
 }
 
 
@@ -1204,10 +1260,8 @@ cmd_cachecert (assuan_context_t ctx, char *line)
   err = cache_cert (cert);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "CACHECERT", gpg_strerror (err));
   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);
 
  leave:
-  if (err)
-    log_error (_("command %s failed: %s\n"), "VALIDATE", gpg_strerror (err));
   ksba_cert_release (cert);
-  return err;
+  return leave_cmd (ctx, err);
 }
 
 
+\f
+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);
+}
+
+
+
+\f
 /* Tell the assuan library about our commands. */
 static int
 register_commands (assuan_context_t ctx)
@@ -1299,8 +1396,7 @@ register_commands (assuan_context_t ctx)
     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
     { "VALIDATE",   cmd_validate,   hlp_validate },
-    { "INPUT",      NULL },
-    { "OUTPUT",     NULL },
+    { "GETINFO",    cmd_getinfo,    hlp_getinfo },
     { NULL, NULL }
   };
   int i, j, rc;