[svn] assuan - r267 - in trunk: . doc src

svn author wk cvs at cvs.gnupg.org
Mon Oct 1 16:44:56 CEST 2007


Author: wk
Date: 2007-10-01 16:44:46 +0200 (Mon, 01 Oct 2007)
New Revision: 267

Modified:
   trunk/NEWS
   trunk/doc/assuan.texi
   trunk/src/ChangeLog
   trunk/src/assuan-defs.h
   trunk/src/assuan-io-pth.c
   trunk/src/assuan-io.c
   trunk/src/assuan-logging.c
   trunk/src/assuan-socket-connect.c
   trunk/src/assuan-socket-server.c
   trunk/src/assuan-socket.c
   trunk/src/assuan.h
Log:
Add socket wrapper API.
Changed the ABI ofthe W32 socket emulation.


Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/NEWS	2007-10-01 14:44:46 UTC (rev 267)
@@ -1,7 +1,10 @@
 Noteworthy changes in version 1.0.4
 ------------------------------------------------
 
+ * New socket wrapper fucntions to support Unix domain sockets under
+   Windows.
 
+
 Noteworthy changes in version 1.0.3 (2007-08-24)
 ------------------------------------------------
 

Modified: trunk/doc/assuan.texi
===================================================================
--- trunk/doc/assuan.texi	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/doc/assuan.texi	2007-10-01 14:44:46 UTC (rev 267)
@@ -118,6 +118,7 @@
 * Server code::         How to develop an Assuan server.
 * External I/O Loop::   How to use external I/O event loops.
 * Utilities::           Utility functions.
+* Socket wrappers::     Socket wrapper functions.
 
 Miscellaneous
 
@@ -1580,6 +1581,72 @@
 @end deftypefun
 
 
+ at c
+ at c     S O C K E T   W R A P P E R S
+ at c
+ at node Socket wrappers
+ at chapter Socket wrapper functions
+
+ at noindent
+It is sometimes useful to support Unix domain sockets on Windows.  To do
+this in a portable way, Assuan provides a set of wrapper functions which
+may be used on any system but will enhance Windows to support these
+socket types.  The actual implementation is based on local TCP sockets
+and fully transparent for the client.  Server code needs to utilize two
+extra functions to check the permissions.
+
+
+ at deftypefun int assuan_sock_close (@w{assuan_fd_t @var{fd}})
+
+Wrapper for close which does a closesocket on Windows if needed.
+ at end deftypefun
+
+ at deftypefun assuan_fd_t assuan_sock_new (@w{int @var{domain}}, @w{int @var{type}}, @w{int @var{proto}});
+
+Wrapper around socket.
+ at end deftypefun
+
+ at deftypefun int assuan_sock_connect (@w{assuan_fd_t @var{sockfd}}, @
+         @w{struct sockaddr *@var{addr}},  @
+         @w{int @var{addrlen}})
+
+Wrapper around connect.  For Unix domain sockets under Windows this
+function also does a write immediatley after the the connect to send the
+nonce as read from the socket's file.
+ at end deftypefun
+
+
+ at deftypefun int assuan_sock_bind ( @
+        @w{assuan_fd_t @var{sockfd}}, @
+        @w{struct sockaddr *@var{addr}}, @
+        @w{int @var{addrlen}})
+
+Wrapper around bind.  Under Windows this creates a file and writes the
+port number and a random nonce to this file.
+ at end deftypefun
+
+ at deftypefun int assuan_sock_get_nonce ( @
+        @w{struct sockaddr *@var{addr}}, @
+        @w{int @var{addrlen}}, @
+        @w{assuan_sock_nonce_t *@var{nonce}})
+
+This is used by the server after a bind to return the random nonce.  To
+keep the code readable this may also be used on POSIX system. 
+ at end deftypefun
+
+ at deftypefun int assuan_sock_check_nonce ( @
+        @w{assuan_fd_t @var{fd}}, @
+        @w{assuan_sock_nonce_t *@var{nonce}})
+
+On Windows this is used by the server after an accept to read the nonce
+from the client and compare it with the saved @var{nonce}.  If this
+function fails the server should immediatly drop the connection.  To
+keep the code readable this may also be used on POSIX system; it is a
+dummy function then.
+ at end deftypefun
+
+
+
 @c ---------------------------------------------------------------------
 @c Legal BS
 @c ---------------------------------------------------------------------

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/ChangeLog	2007-10-01 14:44:46 UTC (rev 267)
@@ -1,3 +1,14 @@
+2007-10-01  Werner Koch  <wk at g10code.com>
+
+	* assuan-socket.c: Rewritten.
+	(assuan_sock_new, assuan_sock_connect, assuan_sock_bind) 
+	(assuan_sock_get_nonce, assuan_sock_check_nonce): New APIs.
+
+	* assuan-io.c (_assuan_simple_read, _assuan_simple_write):
+	Factored code out to ...
+	(_assuan_io_read, _assuan_io_write): .. new.
+	* assuan-io-pth.c (_assuan_io_read, _assuan_io_write): New.
+
 2007-09-25  Werner Koch  <wk at g10code.com>
 
 	* assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add

Modified: trunk/src/assuan-defs.h
===================================================================
--- trunk/src/assuan-defs.h	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-defs.h	2007-10-01 14:44:46 UTC (rev 267)
@@ -40,17 +40,6 @@
 #endif
 
 #ifdef HAVE_W32_SYSTEM
-#define AF_LOCAL AF_UNIX
-/* We need to prefix the structure with a sockaddr_in header so we can
-   use it later for sendto and recvfrom. */
-struct sockaddr_un
-{
-  short          sun_family;
-  unsigned short sun_port;
-  struct         in_addr sun_addr;
-  char           sun_path[108-2-4]; /* Path name.  */
-};
-
 /* Not needed anymore because the current mingw32 defines this in
    sys/types.h */
 /* typedef int ssize_t; */
@@ -296,6 +285,8 @@
 ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
 ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
 			      size_t size);
+ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size);
+ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size);
 #ifdef HAVE_W32_SYSTEM
 int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg);
 int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg);
@@ -307,10 +298,14 @@
 /*-- assuan-socket.c --*/
 int _assuan_close (assuan_fd_t fd);
 assuan_fd_t _assuan_sock_new (int domain, int type, int proto);
-int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
 int _assuan_sock_connect (assuan_fd_t sockfd,
                           struct sockaddr *addr, int addrlen);
+int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
+int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
+                            assuan_sock_nonce_t *nonce);
+int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
 
+
 #ifdef HAVE_FOPENCOOKIE
 /* We have to implement funopen in terms of glibc's fopencookie. */
 FILE *_assuan_funopen(void *cookie,

Modified: trunk/src/assuan-io-pth.c
===================================================================
--- trunk/src/assuan-io-pth.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-io-pth.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -56,15 +56,28 @@
 {
   /* Fixme: For W32 we should better not cast the HANDLE type to int.
      However, this requires changes in w32pth too.  */
-  return pth_read ((int)ctx->inbound.fd, buffer, size);
+  return _assuan_io_read (ctx->inbound.fd, buffer, size);
 }
 
 ssize_t
 _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
 {
-  return pth_write ((int)ctx->outbound.fd, buffer, size);
+  return _assuan_io_write (ctx->outbound.fd, buffer, size);
 }
 
+ssize_t
+_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
+{
+  return pth_read ((int)fd, buffer, size);
+}
+
+ssize_t
+_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
+{
+  return pth_write ((int)fd, buffer, size);
+}
+
+
 #ifdef HAVE_W32_SYSTEM
 int
 _assuan_simple_sendmsg (assuan_context_t ctx, void *msg)

Modified: trunk/src/assuan-io.c
===================================================================
--- trunk/src/assuan-io.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-io.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -47,7 +47,7 @@
 
 
 ssize_t
-_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
+_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
 {
 #ifdef HAVE_W32_SYSTEM
   /* Due to the peculiarities of the W32 API we can't use read for a
@@ -55,12 +55,12 @@
      read if recv detects that it is not a network socket.  */
   int n;
 
-  n = recv (HANDLE2SOCKET(ctx->inbound.fd), buffer, size, 0);
+  n = recv (HANDLE2SOCKET(fd), buffer, size, 0);
   if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
     {
       DWORD nread = 0;
 
-      n = ReadFile (ctx->inbound.fd, buffer, size, &nread, NULL);
+      n = ReadFile (fd, buffer, size, &nread, NULL);
       if (!n)
         {
           switch (GetLastError())
@@ -75,25 +75,33 @@
     }
   return n;
 #else /*!HAVE_W32_SYSTEM*/
-  return read (ctx->inbound.fd, buffer, size);
+  return read (fd, buffer, size);
 #endif /*!HAVE_W32_SYSTEM*/
 }
 
+
 ssize_t
-_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
+_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
 {
+  return _assuan_io_read (ctx->inbound.fd, buffer, size);
+}
+
+
+ssize_t
+_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
+{
 #ifdef HAVE_W32_SYSTEM
   /* Due to the peculiarities of the W32 API we can't use write for a
      network socket and thus we try to use send first and fallback to
      write if send detects that it is not a network socket.  */
   int n;
 
-  n = send (HANDLE2SOCKET(ctx->outbound.fd), buffer, size, 0);
+  n = send (HANDLE2SOCKET(fd), buffer, size, 0);
   if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
     {
       DWORD nwrite;
 
-      n = WriteFile (ctx->outbound.fd, buffer, size, &nwrite, NULL);
+      n = WriteFile (fd, buffer, size, &nwrite, NULL);
       if (!n)
         {
           switch (GetLastError ())
@@ -109,11 +117,18 @@
     }
   return n;
 #else /*!HAVE_W32_SYSTEM*/
-  return write (ctx->outbound.fd, buffer, size);
+  return write (fd, buffer, size);
 #endif /*!HAVE_W32_SYSTEM*/
 }
 
 
+ssize_t
+_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
+{
+  return _assuan_io_write (ctx->outbound.fd, buffer, size);
+}
+
+
 #ifdef HAVE_W32_SYSTEM
 int
 _assuan_simple_sendmsg (assuan_context_t ctx, void *msg)

Modified: trunk/src/assuan-logging.c
===================================================================
--- trunk/src/assuan-logging.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-logging.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -118,8 +118,8 @@
 
 /* Dump a possibly binary string (used for debugging).  Distinguish
    ascii text from binary and print it accordingly.  This function
-   takes FILE pointer arg becuase logging may be enabled on a per
-   context basis. */
+   takes FILE pointer arg because logging may be enabled on a per
+   context basis.  */
 void
 _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
 {

Modified: trunk/src/assuan-socket-connect.c
===================================================================
--- trunk/src/assuan-socket-connect.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-socket-connect.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -137,7 +137,6 @@
   srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
   len = SUN_LEN (&srvr_addr);
 
-
   if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 )
     {
       _assuan_log_printf ("can't connect to `%s': %s\n",

Modified: trunk/src/assuan-socket-server.c
===================================================================
--- trunk/src/assuan-socket-server.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-socket-server.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -131,7 +131,7 @@
 }
 
 /* Initialize a server using the already accepted socket FD.  This
-   fucntion is deprecated. */
+   function is deprecated. */
 int
 assuan_init_connected_socket_server (assuan_context_t *r_ctx, assuan_fd_t fd)
 {

Modified: trunk/src/assuan-socket.c
===================================================================
--- trunk/src/assuan-socket.c	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan-socket.c	2007-10-01 14:44:46 UTC (rev 267)
@@ -19,13 +19,19 @@
 
 #include <config.h>
 #include <stdio.h>
+#include <stdlib.h>
 #ifdef HAVE_W32_SYSTEM
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <wincrypt.h>
 #include <io.h>
 #else
 #include <sys/types.h>
 #include <sys/socket.h>
 #endif
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include "assuan-defs.h"
 
 /* Hacks for Slowaris.  */
@@ -40,20 +46,89 @@
 # define AF_LOCAL AF_UNIX
 #endif
 
+#ifdef HAVE_W32_SYSTEM
+#ifndef S_IRGRP
+# define S_IRGRP 0
+# define S_IWGRP 0
+#endif
+#endif
+
+
+#ifdef HAVE_W32_SYSTEM
+/* W32: Fill BUFFER with LENGTH bytes of random.  Returns -1 on
+   failure, 0 on success.  */
+static int
+get_nonce (char *buffer, size_t nbytes) 
+{
+  HCRYPTPROV prov;
+  int ret = -1;
+
+  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, 
+                            (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
+    errno = ENODEV;
+  else 
+    {
+      if (!CryptGenRandom (prov, nbytes, buffer))
+        errno = ENODEV;
+      else
+        ret = 0;
+      CryptReleaseContext (prov, 0);
+    }
+  return ret;
+}
+
+
+/* W32: The buffer for NONCE needs to be at least 16 bytes.  Returns 0 on
+   success. */
+static int
+read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
+{
+  FILE *fp;
+  char buffer[50], *p;
+  size_t nread;
+  int aval;
+
+  fp = fopen (fname, "rb");
+  if (!fp)
+    return -1;
+  nread = fread (buffer, 1, sizeof buffer - 1, fp);
+  fclose (fp);
+  if (!nread)
+    {
+      errno = ENOFILE;
+      return -1;
+    }
+  buffer[nread] = 0;
+  aval = atoi (buffer);
+  if (aval < 1 || aval > 65535)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  *port = (unsigned int)aval;
+  for (p=buffer; nread && *p != '\n'; p++, nread--)
+    ;
+  if (*p != '\n' || nread != 17)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  p++; nread--;
+  memcpy (nonce, p, 16);
+  return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+
 int
 _assuan_close (assuan_fd_t fd)
 {
 #ifdef HAVE_W32_SYSTEM
   int rc = closesocket (HANDLE2SOCKET(fd));
-/*   if (rc) */
-/*     _assuan_log_printf ("_assuan_close(%p): closesocket failed: %d/%ld\n", */
-/*                         fd, rc, WSAGetLastError ()); */
   if (rc && WSAGetLastError () == WSAENOTSOCK)
     {
       rc = CloseHandle (fd);
-/*       if (rc) */
-/*         _assuan_log_printf ("_assuan_close(%p): CloseHandle failed: %d\n", */
-/*                             fd, rc ); */
     }
   return rc;
 #else
@@ -64,16 +139,16 @@
 
 /* Return a new socket.  Note that under W32 we consider a socket the
    same as an System Handle; all functions using such a handle know
-   about this dual use and act accordingly.  */ 
+   about this dual use and act accordingly. */ 
 assuan_fd_t
 _assuan_sock_new (int domain, int type, int proto)
 {
-#ifndef HAVE_W32_SYSTEM
-  return socket (domain, type, proto);
-#else
+#ifdef HAVE_W32_SYSTEM
   if (domain == AF_UNIX || domain == AF_LOCAL)
     domain = AF_INET;
   return SOCKET2HANDLE(socket (domain, type, proto));
+#else
+  return socket (domain, type, proto);
 #endif
 }
 
@@ -81,78 +156,242 @@
 int
 _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
 {
-#ifndef HAVE_W32_SYSTEM
-  return connect (sockfd, addr, addrlen);
-#else
-  struct sockaddr_in myaddr;
-  struct sockaddr_un * unaddr;
-  FILE * fp;
-  int port = 0;
+#ifdef HAVE_W32_SYSTEM
+  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
+    {
+      struct sockaddr_in myaddr;
+      struct sockaddr_un *unaddr;
+      unsigned short port;
+      char nonce[16];
+      int ret;
+      
+      unaddr = (struct sockaddr_un *)addr;
+      if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
+        return -1;
+      
+      myaddr.sin_family = AF_INET;
+      myaddr.sin_port = htons (port); 
+      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   
-  unaddr = (struct sockaddr_un *)addr;
-  fp = fopen (unaddr->sun_path, "rb");
-  if (!fp)
-      return -1;
-  fscanf (fp, "%d", &port);
-  fclose (fp);
-  /* XXX: set errno in this case */
-  if (port < 0 || port > 65535)
-    return -1;
+      /* Set return values.  */
+      unaddr->sun_family = myaddr.sin_family;
+      unaddr->sun_port = myaddr.sin_port;
+      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
   
-  myaddr.sin_family = AF_INET;
-  myaddr.sin_port = port; 
-  myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-
-  /* we need this later. */
-  unaddr->sun_family = myaddr.sin_family;
-  unaddr->sun_port = myaddr.sin_port;
-  unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
-  
-  return connect (HANDLE2SOCKET(sockfd), (struct sockaddr *)&myaddr, sizeof myaddr);
+      ret = connect (HANDLE2SOCKET(sockfd), 
+                     (struct sockaddr *)&myaddr, sizeof myaddr);
+      if (!ret)
+        {
+          /* Send the nonce. */
+          ret = _assuan_io_write (sockfd, nonce, 16);
+          if (ret >= 0 && ret != 16)
+            {
+              errno = EIO;
+              ret = -1;
+            }
+        }
+      return ret;
+    }
+  else
+    return connect (HANDLE2SOCKET (sockfd), addr, addrlen);
+#else
+  return connect (sockfd, addr, addrlen);
 #endif
 }
 
 
 int
-_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr * addr, int addrlen)
+_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
 {
-#ifndef HAVE_W32_SYSTEM
-  return bind (sockfd, addr, addrlen);
-#else
+#ifdef HAVE_W32_SYSTEM
   if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
     {
       struct sockaddr_in myaddr;
-      struct sockaddr_un * unaddr;
-      FILE * fp;
+      struct sockaddr_un *unaddr;
+      int filefd;
+      FILE *fp;
       int len = sizeof myaddr;
       int rc;
+      char nonce[16];
 
+      if (get_nonce (nonce, 16))
+        return -1;
+
+      unaddr = (struct sockaddr_un *)addr;
+
       myaddr.sin_port = 0;
       myaddr.sin_family = AF_INET;
       myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
 
-      rc = bind (HANDLE2SOCKET(sockfd), (struct sockaddr *)&myaddr, len);
+      filefd = open (unaddr->sun_path, 
+                     (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), 
+                     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
+      if (filefd == -1)
+        {
+          if (errno == EEXIST)
+            errno = WSAEADDRINUSE;
+          return -1;
+        }
+      fp = fdopen (filefd, "wb");
+      if (!fp)
+        { 
+          int save_e = errno;
+          close (filefd);
+          errno = save_e;
+          return -1;
+        }
+
+      rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
+      if (!rc)
+        rc = getsockname (HANDLE2SOCKET (sockfd), 
+                          (struct sockaddr *)&myaddr, &len);
       if (rc)
-        return rc;
-      rc = getsockname (HANDLE2SOCKET(sockfd),
-                        (struct sockaddr *)&myaddr, &len);
-      if (rc)
-        return rc;
+        {
+          int save_e = errno;
+          fclose (fp);
+          remove (unaddr->sun_path);
+          errno = save_e;
+          return rc;
+        }
+      fprintf (fp, "%d\n", ntohs (myaddr.sin_port));
+      fwrite (nonce, 16, 1, fp);
+      fclose (fp);
+
+      return 0;
+    }
+  else
+    return bind (HANDLE2SOCKET(sockfd), addr, addrlen);
+#else
+  return bind (sockfd, addr, addrlen);
+#endif
+}
+
+
+int
+_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
+                        assuan_sock_nonce_t *nonce)
+{
+#ifdef HAVE_W32_SYSTEM
+  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
+    {
+      struct sockaddr_un *unaddr;
+      unsigned short port;
+
+      if (sizeof nonce->nonce != 16)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      nonce->length = 16;
       unaddr = (struct sockaddr_un *)addr;
-      fp = fopen (unaddr->sun_path, "wb");
-      if (!fp)
+      if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
         return -1;
-      fprintf (fp, "%d", myaddr.sin_port);
-      fclose (fp);
+    }
+  else
+    {
+      nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */
+      nonce->nonce[0] = 42;
+    }
+#else
+  (void)addr;
+  (void)addrlen;
+  nonce->length = 0;
+#endif
+  return 0;
+}
+ 
+ 
+int
+_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
+{
+#ifdef HAVE_W32_SYSTEM
+  char buffer[16], *p;
+  size_t nleft, n;
 
-      /* we need this later. */
-      unaddr->sun_family = myaddr.sin_family;
-      unaddr->sun_port = myaddr.sin_port;
-      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
+  if (sizeof nonce->nonce != 16)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (nonce->length == 42 && nonce->nonce[0] == 42)
+    return 0; /* Not a Unix domain socket.  */
+
+  if (nonce->length != 16)
+    {
+      errno = EINVAL;
+      return -1;
+    }
       
-      return 0;
+  p = buffer;
+  nleft = 16;
+  while (nleft)
+    {
+      n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft);
+      if (n < 0 && errno == EINTR)
+        ;
+      else if (n < 0 && errno == EAGAIN)
+        Sleep (100);
+      else if (n < 0)
+        return -1;
+      else if (!n)
+        {
+          errno = EIO;
+          return -1;
+        }
+      else
+        {
+          p += n;
+          nleft -= n;
+        }
     }
-  return bind (HANDLE2SOCKET(sockfd), addr, addrlen);
+  if (memcmp (buffer, nonce->nonce, 16))
+    {
+      errno = EACCES;
+      return -1;
+    }
+#else
+  (void)fd;
+  (void)nonce;
 #endif
+  return 0;
 }
 
+
+/* Public API.  */
+int
+assuan_sock_close (assuan_fd_t fd)
+{
+  return _assuan_close (fd);
+}
+
+assuan_fd_t 
+assuan_sock_new (int domain, int type, int proto)
+{
+  return _assuan_sock_new (domain, type, proto);
+}
+
+int
+assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
+{
+  return _assuan_sock_connect (sockfd, addr, addrlen);
+}
+
+int
+assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
+{
+  return _assuan_sock_bind (sockfd, addr, addrlen);
+}
+
+int
+assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
+                       assuan_sock_nonce_t *nonce)
+{     
+  return _assuan_sock_get_nonce (addr, addrlen, nonce);
+}
+
+int
+assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
+{
+  return _assuan_sock_check_nonce (fd, nonce);
+}

Modified: trunk/src/assuan.h
===================================================================
--- trunk/src/assuan.h	2007-09-25 15:09:54 UTC (rev 266)
+++ trunk/src/assuan.h	2007-10-01 14:44:46 UTC (rev 267)
@@ -23,19 +23,29 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
+#ifndef _ASSUAN_NO_SOCKET_WRAPPER
+#ifdef _WIN32
+#include <ws2tcpip.h> 
+#else
+#include <sys/socket.h>
+#endif
+#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/
 
-
 /* To use this file with libraries the following macros are useful:
 
      #define _ASSUAN_EXT_SYM_PREFIX _foo_
    
-     This prefixes all external symbols with "_foo_".
+       This prefixes all external symbols with "_foo_".
 
      #define _ASSUAN_ONLY_GPG_ERRORS
 
-     If this is defined all old-style Assuan error codes are made
-     inactive as well as other dereacted stuff.
+       If this is defined all old-style Assuan error codes are made
+       inactive as well as other deprecated stuff.
 
+     #define _ASSUAN_NO_SOCKET_WRAPPER
+
+       Do not include the definitions for the socket wrapper feature.
+
    The follwing macros are used internally in the implementation of
    libassuan:
 
@@ -132,6 +142,12 @@
 #define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2)
 #define assuan_set_assuan_log_prefix \
   _ASSUAN_PREFIX(assuan_set_assuan_log_prefix)
+#define assuan_sock_close       _ASSUAN_PREFIX(assuan_sock_close)      
+#define assuan_sock_new         _ASSUAN_PREFIX(assuan_sock_new)        
+#define assuan_sock_connect     _ASSUAN_PREFIX(assuan_sock_connect)    
+#define assuan_sock_bind        _ASSUAN_PREFIX(assuan_sock_bind)       
+#define assuan_sock_get_nonce   _ASSUAN_PREFIX(assuan_sock_get_nonce)
+#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce)
 
 
 /* And now the internal functions, argh...  */
@@ -144,8 +160,8 @@
   _ASSUAN_PREFIX(_assuan_register_std_commands)
 #define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
 #define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
-#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
-#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
+#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read)
+#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write)
 #define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)
 #define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)
 #define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc)
@@ -162,10 +178,6 @@
 #define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r)
 #define _assuan_gpg_strsource  _ASSUAN_PREFIX(_assuan_gpg_strsource)
 #define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
-#define _assuan_close _ASSUAN_PREFIX(_assuan_close)   
-#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)  
-#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind)
-#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)
 #define _assuan_error _ASSUAN_PREFIX(_assuan_error)
 #define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io)
 #define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds)
@@ -173,6 +185,12 @@
 #define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg)
 #define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg)
 #define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid)
+#define _assuan_sock_close       _ASSUAN_PREFIX(_assuan_close)      
+#define _assuan_sock_new         _ASSUAN_PREFIX(_assuan_sock_new)        
+#define _assuan_sock_connect     _ASSUAN_PREFIX(_assuan_sock_connect)    
+#define _assuan_sock_bind        _ASSUAN_PREFIX(_assuan_sock_bind)       
+#define _assuan_sock_get_nonce   _ASSUAN_PREFIX(_assuan_sock_get_nonce)
+#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce)
 
 #endif /*_ASSUAN_EXT_SYM_PREFIX*/
 
@@ -357,13 +375,45 @@
    actually is a plain pointer).  This is required to eventually
    support 64 bit Windows systems.  */
 #ifdef _WIN32
-typedef void * assuan_fd_t;
+typedef void *assuan_fd_t;
 #define ASSUAN_INVALID_FD ((void*)(-1))
 #else
 typedef int assuan_fd_t;
 #define ASSUAN_INVALID_FD (-1)
 #endif
 
+
+/* Assuan features an emulation of Unix domain sockets based on a
+   local TCP connections.  To implement access permissions based on
+   file permissions a nonce is used which is expected by th server as
+   the first bytes received.  This structure is used by the server to
+   save the nonce created initially by bind.  On POSIX systems this is
+   a dummy operation. */  
+struct assuan_sock_nonce_s
+{
+  size_t length;
+#ifdef _WIN32
+  char nonce[16];
+#endif
+};
+typedef struct assuan_sock_nonce_s assuan_sock_nonce_t;
+
+/* Define the Unix domain socket structure for Windows.  */
+#if defined(_WIN32) && !defined(_ASSUAN_NO_SOCKET_WRAPPER)
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+#define EADDRINUSE WSAEADDRINUSE
+struct sockaddr_un
+{
+  short          sun_family;
+  unsigned short sun_port;
+  struct         in_addr sun_addr;
+  char           sun_path[108-2-4]; 
+};
+#endif
+
+
 /*-- assuan-handler.c --*/
 int assuan_register_command (assuan_context_t ctx,
                              const char *cmd_string,
@@ -498,6 +548,7 @@
 assuan_error_t assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd);
 assuan_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd);
 
+
 /*-- assuan-util.c --*/
 void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
                                void *(*new_realloc_func)(void *p, size_t n),
@@ -563,6 +614,21 @@
    string, i.e. ""  */
 const char *assuan_get_assuan_log_prefix (void);
 
+
+/*-- assuan-socket.c --*/
+
+/* These are socket wrapper functions to support an emulation of Unix
+   domain sockets on Windows W32.  */
+int assuan_sock_close (assuan_fd_t fd);
+assuan_fd_t assuan_sock_new (int domain, int type, int proto);
+int assuan_sock_connect (assuan_fd_t sockfd, 
+                         struct sockaddr *addr, int addrlen);
+int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);
+int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
+                           assuan_sock_nonce_t *nonce);
+int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce);
+
+
 #ifdef __cplusplus
 }
 #endif




More information about the Gnupg-commits mailing list