diff options
author | Werner Koch <[email protected]> | 2007-10-01 14:44:46 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2007-10-01 14:44:46 +0000 |
commit | 88fa870976dfef9403532ee07ff901535645c578 (patch) | |
tree | a8877d852adfeb8ad7d328144ed8866714973d5d | |
parent | Fixed a name clash in internal symbols used only under W32. (diff) | |
download | libassuan-88fa870976dfef9403532ee07ff901535645c578.tar.gz libassuan-88fa870976dfef9403532ee07ff901535645c578.zip |
Add socket wrapper API.
Changed the ABI ofthe W32 socket emulation.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/assuan.texi | 67 | ||||
-rw-r--r-- | src/ChangeLog | 11 | ||||
-rw-r--r-- | src/assuan-defs.h | 19 | ||||
-rw-r--r-- | src/assuan-io-pth.c | 17 | ||||
-rw-r--r-- | src/assuan-io.c | 31 | ||||
-rw-r--r-- | src/assuan-logging.c | 4 | ||||
-rw-r--r-- | src/assuan-socket-connect.c | 1 | ||||
-rw-r--r-- | src/assuan-socket-server.c | 2 | ||||
-rw-r--r-- | src/assuan-socket.c | 355 | ||||
-rw-r--r-- | src/assuan.h | 88 |
11 files changed, 503 insertions, 95 deletions
@@ -1,6 +1,9 @@ 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) ------------------------------------------------ diff --git a/doc/assuan.texi b/doc/assuan.texi index b580848..943fa10 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -118,6 +118,7 @@ interprocess communcation library. * 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 @@ string. @end deftypefun +@c +@c S O C K E T W R A P P E R S +@c +@node Socket wrappers +@chapter Socket wrapper functions + +@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. + + +@deftypefun int assuan_sock_close (@w{assuan_fd_t @var{fd}}) + +Wrapper for close which does a closesocket on Windows if needed. +@end deftypefun + +@deftypefun assuan_fd_t assuan_sock_new (@w{int @var{domain}}, @w{int @var{type}}, @w{int @var{proto}}); + +Wrapper around socket. +@end deftypefun + +@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. +@end deftypefun + + +@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. +@end deftypefun + +@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. +@end deftypefun + +@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. +@end deftypefun + + + @c --------------------------------------------------------------------- @c Legal BS @c --------------------------------------------------------------------- diff --git a/src/ChangeLog b/src/ChangeLog index 7b43bef..3156c7f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2007-10-01 Werner Koch <[email protected]> + + * 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 <[email protected]> * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add diff --git a/src/assuan-defs.h b/src/assuan-defs.h index e423ab2..6c992ef 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -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 @@ pid_t _assuan_waitpid (pid_t pid, int *status, int options); 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,9 +298,13 @@ ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg); /*-- 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. */ diff --git a/src/assuan-io-pth.c b/src/assuan-io-pth.c index e0cf8b9..6b287c0 100644 --- a/src/assuan-io-pth.c +++ b/src/assuan-io-pth.c @@ -56,15 +56,28 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) { /* 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) diff --git a/src/assuan-io.c b/src/assuan-io.c index 9c2ef91..df5fe57 100644 --- a/src/assuan-io.c +++ b/src/assuan-io.c @@ -47,7 +47,7 @@ _assuan_waitpid (pid_t pid, int *status, int options) 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 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) 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,12 +75,20 @@ _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) } 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 @@ -88,12 +96,12 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) 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 @@ _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) } 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) diff --git a/src/assuan-logging.c b/src/assuan-logging.c index 39752a3..fd40dcc 100644 --- a/src/assuan-logging.c +++ b/src/assuan-logging.c @@ -118,8 +118,8 @@ _assuan_log_printf (const char *format, ...) /* 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) { diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c index 9c574dc..828f6ea 100644 --- a/src/assuan-socket-connect.c +++ b/src/assuan-socket-connect.c @@ -137,7 +137,6 @@ assuan_socket_connect_ext (assuan_context_t *r_ctx, 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", diff --git a/src/assuan-socket-server.c b/src/assuan-socket-server.c index 664c99f..d346f66 100644 --- a/src/assuan-socket-server.c +++ b/src/assuan-socket-server.c @@ -131,7 +131,7 @@ assuan_init_socket_server (assuan_context_t *r_ctx, assuan_fd_t listen_fd) } /* 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) { diff --git a/src/assuan-socket.c b/src/assuan-socket.c index 13f4e77..26ccd05 100644 --- a/src/assuan-socket.c +++ b/src/assuan-socket.c @@ -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 @@ _assuan_close (assuan_fd_t fd) /* 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 @@ _assuan_sock_new (int domain, int type, int proto) 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; - - 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; +#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); - 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; + /* 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; - 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); - if (rc) - return rc; - rc = getsockname (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; + { + 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); +} diff --git a/src/assuan.h b/src/assuan.h index 788a742..eec9842 100644 --- a/src/assuan.h +++ b/src/assuan.h @@ -23,18 +23,28 @@ #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 @@ typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED; 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_send_data (assuan_context_t ctx, 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 @@ void assuan_set_assuan_log_prefix (const char *text); 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 |