Added tlspool_configvar() to libtlspool
[tlspool] / lib / libtlspool.c
index 26b8983..a57949d 100644 (file)
@@ -1,5 +1,7 @@
 /* tlspool/libtlspool.c -- Library function for starttls go-get-it */
 
+#include "whoami.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <syslog.h>
 
+#include <tlspool/starttls.h>
+#include <tlspool/commands.h>
+
+#ifdef WINDOWS_PORT
+#include <winsock2.h>
+#else
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/select.h>
 #include <sys/resource.h>
+#endif
 
-#include <tlspool/starttls.h>
-#include <tlspool/commands.h>
-
-
-#ifdef __CYGWIN__
-#define WEOF ((wint_t)(0xFFFF))
+#if !defined(WINDOWS_PORT)
+#define closesocket(s) close(s)
+#endif
 
+#ifdef WINDOWS_PORT
 #define PIPE_TIMEOUT 5000
 #define BUFSIZE 4096
+#define random rand
+#define srandom srand
 
 #define _tprintf printf
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
 
 /* The master thread will run the receiving side of the socket that connects
  * to the TLS Pool.  The have_master_lock is used with _trylock() and will
@@ -60,8 +69,12 @@ int tlspool_pid (char *opt_pidfile) {
        unsigned long pid;
 
        if (opt_pidfile == NULL) {
+               opt_pidfile = tlspool_configvar (NULL, "daemon_pidfile");
+       }
+       if (opt_pidfile == NULL) {
                opt_pidfile = TLSPOOL_DEFAULT_PIDFILE_PATH;
        }
+       assert (opt_pidfile != NULL);
        fd = open (opt_pidfile, O_RDONLY);
        if (fd != -1) {
                len = read (fd, str_pid, sizeof (str_pid) -1);
@@ -99,16 +112,23 @@ pool_handle_t tlspool_open_poolhandle (char *path) {
                        unsigned int seed;
                        pid_t me;
                        if (!path) {
+                               path = tlspool_configvar (NULL, "socket_name");
+                       }
+                       if (!path) {
                                path = TLSPOOL_DEFAULT_SOCKET_PATH;
                        }
-                       if (strlen (path) + 1 > sizeof (((struct sockaddr_un *) NULL)->sun_path)) {
-                               syslog (LOG_ERR, "TLS Pool path name too long for UNIX domain socket");
-                               exit (1);
+                       assert (path != NULL);
+                       fprintf (stderr, "DEBUG: Opening TLS Pool on socket path %s\n", path);
+#ifndef WINDOWS_PORT
+                       if (strlen(path) + 1 > sizeof(((struct sockaddr_un *) NULL)->sun_path)) {
+                               syslog(LOG_ERR, "TLS Pool path name too long for UNIX domain socket");
+                               exit(1);
                        }
-                       if (pthread_create (&thr, NULL, master_thread, (void *) path) != 0) {
-                               syslog (LOG_NOTICE, "Failed to create TLS Pool client master thread");
-                               pthread_mutex_unlock (&have_master_lock);
-                               tlspool_close_poolhandle (poolfd);
+#endif
+                       if (pthread_create(&thr, NULL, master_thread, (void *)path) != 0) {
+                               syslog(LOG_NOTICE, "Failed to create TLS Pool client master thread");
+                               pthread_mutex_unlock(&have_master_lock);
+                               tlspool_close_poolhandle(poolfd);
                                poolfd = INVALID_POOL_HANDLE;
                                return INVALID_POOL_HANDLE;
                        }
@@ -143,7 +163,10 @@ pool_handle_t tlspool_open_poolhandle (char *path) {
  * number of available file descriptors.  Note: The result is cached, so
  * don't use root to increase beyond max in setrlimit() after calling this.
  */
-int tlspool_simultaneous_starttls (void) {
+int tlspool_simultaneous_starttls(void) {
+#ifdef WINDOWS_PORT
+       return 512;
+#else /* WINDOWS_PORT */
        static int simu = -1;
        if (simu < 0) {
                struct rlimit rlimit_nofile;
@@ -154,6 +177,7 @@ int tlspool_simultaneous_starttls (void) {
                simu = rlimit_nofile.rlim_max / 2;  // 2 FDs per STARTTLS
        }
        return simu;
+#endif /* WINDOWS_PORT */
 }
 
 
@@ -256,7 +280,7 @@ static void registry_flush (pool_handle_t poolfd) {
        pthread_mutex_unlock (&registry_lock);
 }
 
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
 static pool_handle_t open_named_pipe (LPCTSTR lpszPipename)
 {
        HANDLE hPipe;
@@ -340,7 +364,7 @@ static int np_send_command(struct tlspool_command *cmd) {
 
        if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
        {
-printf ("DEBUG: Write I/O pending\n");
+// printf ("DEBUG: Write I/O pending\n");
                fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
        }
 
@@ -351,16 +375,15 @@ printf ("DEBUG: Write I/O pending\n");
        if (!fSuccess)
        {
                _tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
-#warning better errno
-               errno = ENOSYS;
+               errno = EPIPE;
                return -1;
        } else {
-printf ("DEBUG: Wrote %ld bytes to pipe\n", cbWritten);
+// printf ("DEBUG: Wrote %ld bytes to pipe\n", cbWritten);
        }
-printf("DEBUG: Message sent to server, receiving reply as follows:\n");
+// printf("DEBUG: Message sent to server, receiving reply as follows:\n");
        return 0;
 }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
 
 /* The master thread issues the recv() commands on the TLS Pool socket, and
  * redistributes the result to the registry entries that are waiting for
@@ -379,23 +402,28 @@ printf("DEBUG: Message sent to server, receiving reply as follows:\n");
  * TLS Pool anew, using exponential back-off.
  */
 static void *master_thread (void *path) {
+#ifndef WINDOWS_PORT
        useconds_t usec;
        struct sockaddr_un sun;
-       struct tlspool_command cmd;
        //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
        struct iovec iov;
        struct cmsghdr *cmsg;
        struct msghdr mh = { 0 };
+#else
+       DWORD usec;
+#endif
+       struct tlspool_command cmd;
+       //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
        struct registry_entry *entry;
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
        BOOL   fSuccess = FALSE;
        DWORD  cbRead;
 #endif
 
-#ifndef __CYGWIN__
+#ifndef WINDOWS_PORT
        //
        // Setup path information -- value and size were checked
-       bzero (&sun, sizeof (sun));
+       memset (&sun, 0, sizeof (sun));
        strcpy (sun.sun_path, (char *) path);
        sun.sun_family = AF_UNIX;
 #endif
@@ -418,8 +446,8 @@ static void *master_thread (void *path) {
                // with 1s, 2s, 4s, 8s, 16s, 32s, 32s, 32s, ... intervals.
                usec = 1000000;
                while (poolfd == INVALID_POOL_HANDLE) {
-#ifdef __CYGWIN__
-printf ("DEBUG: path = %s\n", (char *) path);
+#ifdef WINDOWS_PORT
+// printf ("DEBUG: path = %s\n", (char *) path);
                        pool_handle_t newpoolfd = open_named_pipe ((LPCTSTR) path);
 // printf ("DEBUG: newpoolfd = %d\n", newpoolfd);
                        if (newpoolfd != INVALID_POOL_HANDLE) {
@@ -452,7 +480,11 @@ printf ("DEBUG: path = %s\n", (char *) path);
                        //
                        // Wait before repeating, with exponential back-off
                        if (poolfd == INVALID_POOL_HANDLE) {
-                               usleep (usec);
+#ifdef WINDOWS_PORT
+                               Sleep(usec / 1000);
+#else
+                               usleep(usec);
+#endif
                                usec <<= 1;
                                if (usec > 32000000) {
                                        usec = 32000000;
@@ -466,7 +498,7 @@ printf ("DEBUG: path = %s\n", (char *) path);
                // back up to the re-connection logic.
                while (1) {
                        int retval;
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
                        OVERLAPPED overlapped;
 
                        memset(&overlapped, 0, sizeof(overlapped));
@@ -482,7 +514,7 @@ printf ("DEBUG: path = %s\n", (char *) path);
 
                        if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
                        {
-printf ("DEBUG: Read I/O pending\n");
+// printf ("DEBUG: Read I/O pending\n");
                                fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
                        }
 
@@ -495,7 +527,7 @@ printf ("DEBUG: Read I/O pending\n");
                                _tprintf(TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError());
                                retval = -1;
                        } else {
-printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
+// printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
                        }
 #else
                        iov.iov_base = &cmd;
@@ -518,7 +550,7 @@ printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
 // printf ("DEBUG: recvmsg() returned -1 due to: %s\n", strerror (errno));
                                break;
                        }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
                        //
                        // Determine where to post the received message
                        entry = registry [cmd.pio_reqid];
@@ -532,13 +564,13 @@ printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
                                        cmd.pio_cmd = PIOC_ERROR_V2;
                                        cmd.pio_data.pioc_error.tlserrno = EPIPE;
                                        strncpy (cmd.pio_data.pioc_error.message, "Client prematurely left TLS Pool negotiations", sizeof (cmd.pio_data.pioc_error.message));
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
                                        np_send_command (&cmd);
 #else
                                        sendmsg (poolfd, &mh, MSG_NOSIGNAL);
 #endif
                                        // Ignore errors
-printf ("DEBUG: Sent      PIOC_ERROR_V2 as callback to TLS Pool\n");
+// printf ("DEBUG: Sent      PIOC_ERROR_V2 as callback to TLS Pool\n");
                                }
                                // Do not attempt delivery
                                continue;
@@ -603,16 +635,10 @@ int tlspool_ping (pingpool_t *pingdata) {
        struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
        int entry_reqid = -1;
        pool_handle_t poolfd = INVALID_POOL_HANDLE;
-       struct iovec iov;
-       struct msghdr mh = { 0 };
-#ifdef __CYGWIN__
-       BOOL   fSuccess = FALSE;
-       OVERLAPPED overlapped;
-#endif
 
        /* Prepare command structure */
        poolfd = tlspool_open_poolhandle (NULL);
-printf ("DEBUG: poolfd = %d\n", poolfd);
+// printf ("DEBUG: poolfd = %d\n", poolfd);
        if (poolfd == INVALID_POOL_HANDLE) {
                errno = ENODEV;
                return -1;
@@ -625,12 +651,12 @@ printf ("DEBUG: poolfd = %d\n", poolfd);
                errno = EBUSY;
                return -1;
        }
-       bzero (&cmd, sizeof (cmd));     /* Do not leak old stack info */
+       memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
        cmd.pio_reqid = entry_reqid;
        cmd.pio_cbid = 0;
        cmd.pio_cmd = PIOC_PING_V2;
        memcpy (&cmd.pio_data.pioc_ping, pingdata, sizeof (struct pioc_ping));
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
        if (np_send_command (&cmd) == -1) {
                // errno inherited from np_send_command ()
                registry_update (&entry_reqid, NULL);
@@ -638,11 +664,7 @@ printf ("DEBUG: poolfd = %d\n", poolfd);
        }
 #else
        /* Send the request */
-       iov.iov_base = &cmd;
-       iov.iov_len = sizeof (cmd);
-       mh.msg_iov = &iov;
-       mh.msg_iovlen = 1;
-       if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
+       if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
                // Let SIGPIPE be reported as EPIPE
                registry_update (&entry_reqid, NULL);
                // errno inherited from sendmsg()
@@ -669,6 +691,18 @@ printf ("DEBUG: poolfd = %d\n", poolfd);
        }
 }
 
+#if defined(WINDOWS_PORT)
+static int socket_dup_protocol_info(int fd, int pid, LPWSAPROTOCOL_INFOW lpProtocolInfo)
+{
+       if (WSADuplicateSocketW((SOCKET)fd, pid, lpProtocolInfo) == SOCKET_ERROR) {
+               errno = EPIPE;
+               return -1;
+       } else {
+               return 0;
+       }       
+}
+#endif
+
 /* The library function for starttls, which is normally called through one
  * of the two inline variations below, which start client and server sides.
  *
@@ -721,17 +755,19 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
        pool_handle_t poolfd = INVALID_POOL_HANDLE;
        int plainfd = -1;
        int sentfd = -1;
-       char anc [CMSG_SPACE(sizeof (int))];
+#ifndef WINDOWS_PORT
        struct iovec iov;
        struct cmsghdr *cmsg;
        struct msghdr mh = { 0 };
+       char anc[CMSG_SPACE(sizeof(int))];
+#endif
        int processing;
        int renegotiate = 0 != (tlsdata->flags & PIOF_STARTTLS_RENEGOTIATE);
 
        /* Prepare command structure */
        poolfd = tlspool_open_poolhandle (NULL);
        if (poolfd == INVALID_POOL_HANDLE) {
-               close (cryptfd);
+               closesocket(cryptfd);
                errno = ENODEV;
                return -1;
        }
@@ -740,26 +776,28 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
        pthread_mutex_lock (&recvwait);         // Will await unlock by master
        /* Determine the request ID */
        if (registry_update (&entry_reqid, &regent) != 0) {
-               close (cryptfd);
+               closesocket(cryptfd);
                errno = EBUSY;
                return -1;
        }
-       bzero (&cmd, sizeof (cmd));     /* Do not leak old stack info */
+       memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
        cmd.pio_reqid = entry_reqid;
        cmd.pio_cbid = 0;
        cmd.pio_cmd = PIOC_STARTTLS_V2;
        memcpy (&cmd.pio_data.pioc_starttls, tlsdata, sizeof (struct pioc_starttls));
 
-#if RAND_MAX < 0xfffff
-#  error "Failure on assumption of 16 bits of random material per random() call"
-#endif
-
 #if TLSPOOL_CTLKEYLEN != 16
 #  error "Failure on assumption of 16 bytes per ctlkey"
 #endif
 
        if (!renegotiate) {
                assert (pthread_mutex_lock (&prng_lock) == 0);
+#if RAND_MAX >= 0xffffffff
+               * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
+               * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
+               * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
+               * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
+#elif RAND_MAX >= 0xffff
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
@@ -768,6 +806,26 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
                * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
+#elif RAND_MAX >= 0xff
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 1] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 3] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 5] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 7] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 9] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [11] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [13] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
+               * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [15] = random ();
+#else
+#  error "Unsuitable random() function due to RAND_MAX value < 0xff"
+#endif
                pthread_mutex_unlock (&prng_lock);
        }
 // printf ("DEBUG: ctlkey =");
@@ -775,39 +833,36 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
 // printf ("\n");
 
        /* Send the request */
+#ifndef WINDOWS_PORT
        iov.iov_base = &cmd;
-       iov.iov_len = sizeof (cmd);
+       iov.iov_len = sizeof(cmd);
        mh.msg_iov = &iov;
        mh.msg_iovlen = 1;
+#endif
        if (!renegotiate) {
-#ifndef __CYGWIN__
+#ifndef WINDOWS_PORT
                mh.msg_control = anc;
                mh.msg_controllen = sizeof (anc);
                cmsg = CMSG_FIRSTHDR (&mh);
                cmsg->cmsg_level = SOL_SOCKET;
                cmsg->cmsg_type = SCM_RIGHTS;
-               * (int *) CMSG_DATA (cmsg) = cryptfd;   /* cannot close it yet */
-               cmsg->cmsg_len = CMSG_LEN (sizeof (int));
-#else /* ifdef __CYGWIN__ */
+               *(int *)CMSG_DATA(cmsg) = cryptfd;      /* cannot close it yet */
+               cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+#else /* WINDOWS_PORT */
                // cmd was already set to 0, including ancilary data simulation
                if (1 /*is_sock(wsock)*/) {
                        // Send a socket
-                       int pid = tlspool_pid (NULL);
-                       if (pid == -1) {
-                               close (cryptfd);
-                               registry_update (&entry_reqid, NULL);
-                               // errno inherited from tlspool_pid()
-                               return -1;
-                       }
+                       LONG pid;
+
+                       GetNamedPipeServerProcessId(poolfd, &pid);
                        cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
-                       // printf("DEBUG: pid = %d, cryptfd = %d\n", pid, cryptfd);
-                       if (cygwin_socket_dup_protocol_info (cryptfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
-#warning set errno
+                       printf("DEBUG: pid = %d, cryptfd = %d\n", pid, cryptfd);
+                       if (socket_dup_protocol_info(cryptfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
                                // printf("DEBUG: cygwin_socket_dup_protocol_info error\n");
                                // Let SIGPIPE be reported as EPIPE
-                               close (cryptfd);
+                               closesocket(cryptfd);
                                registry_update (&entry_reqid, NULL);
-                               // errno inherited from sendmsg()
+                               // errno inherited from socket_dup_protocol_info()
                                return -1;
                        }
                        //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
@@ -816,9 +871,9 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                        cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
                        //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
                }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
        }
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
        if (np_send_command (&cmd) == -1) {
                close (cryptfd);
                registry_update (&entry_reqid, NULL);
@@ -833,7 +888,7 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                // errno inherited from sendmsg()
                return -1;
        }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
        sentfd = cryptfd;  /* Close anytime after response and before fn end */
 
        /* Handle responses until success or error */
@@ -843,7 +898,7 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                //NOTUSED// mh.msg_controllen = sizeof (anc);
                registry_recvmsg (&regent);
                if (sentfd >= 0) {
-                       close (sentfd);
+                       closesocket(sentfd);
                }
                sentfd = -1;
                switch (cmd.pio_cmd) {
@@ -861,13 +916,19 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                                /* default namedconnect() implementation */
                                plainfd = * (int *) privdata;
                                if ((plainfd < 0) && (cmd.pio_cmd == PIOC_PLAINTEXT_CONNECT_V2)) {
-                                       int soxx [2];
+#if !defined(WINDOWS_PORT)
+                                       int soxx[2];
+#else
+                                       // https://github.com/ncm/selectable-socketpair
+                                       extern int dumb_socketpair(SOCKET socks[2], int make_overlapped);
+                                       SOCKET soxx[2];
+#endif
                                        //TODO// Setup for TCP, UDP, SCTP
-#ifndef __CYGWIN__
+#ifndef WINDOWS_PORT
                                        if (socketpair (AF_UNIX, SOCK_SEQPACKET, 0, soxx) == 0) {
-#else /* ifdef __CYGWIN__ */
-                                       if (socketpair (AF_UNIX, SOCK_STREAM, 0, soxx) == 0) {
-#endif /* __CYGWIN__ */
+#else /* WINDOWS_PORT */
+                                       if (dumb_socketpair(soxx, 1) == 0) {
+#endif /* WINDOWS_PORT */
                                                // printf("DEBUG: socketpair succeeded\n");
                                                /* Socketpair created */
                                                plainfd = soxx [0];
@@ -883,7 +944,7 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                        }
                        /* We may now have a value to send in plainfd */
                        if (plainfd >= 0) {
-#ifndef __CYGWIN__
+#ifndef WINDOWS_PORT
                                mh.msg_control = anc;
                                mh.msg_controllen = sizeof (anc);
                                cmsg = CMSG_FIRSTHDR (&mh);
@@ -891,26 +952,20 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                                cmsg->cmsg_type = SCM_RIGHTS;
                                * (int *) CMSG_DATA (cmsg) = plainfd;
                                cmsg->cmsg_len = CMSG_LEN (sizeof (int));
-#else /* ifdef __CYGWIN__ */
+#else /* ifdef WINDOWS_PORT */
                                // cmd was already set to 0, including ancilary data simulation
                                if (1 /*is_sock(wsock)*/) {
                                        // Send a socket
-                                       int pid = tlspool_pid (NULL);
-                                       if (pid == -1) {
-                                               close (plainfd);
-                                               registry_update (&entry_reqid, NULL);
-                                               // errno inherited from tlspool_pid()
-                                               return -1;
-                                       }
+                                       ULONG pid;
+                                       GetNamedPipeServerProcessId(poolfd, &pid);
                                        cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
                                        // printf("DEBUG: pid = %d, plainfd = %d\n", pid, plainfd);
-                                       if (cygwin_socket_dup_protocol_info (plainfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
-#warning set errno
+                                       if (socket_dup_protocol_info(plainfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
                                                // printf("DEBUG: cygwin_socket_dup_protocol_info error\n");
                                                // Let SIGPIPE be reported as EPIPE
-                                               close (plainfd);
+                                               closesocket(plainfd);
                                                registry_update (&entry_reqid, NULL);
-                                               // errno inherited from cygwin_socket_dup_protocol_info()
+                                               // errno inherited from socket_dup_protocol_info()
                                                return -1;
                                        }
                                        //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
@@ -919,15 +974,15 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                                        cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
                                        //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
                                }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
                        }
 
                        /* Now supply plainfd in the callback response */
                        sentfd = plainfd;
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
                        if (np_send_command (&cmd) == -1) {
                                if (sentfd >= 0) {
-                                       close (sentfd);
+                                       closesocket(sentfd);
                                        sentfd = -1;
                                }
                                registry_update (&entry_reqid, NULL);
@@ -945,7 +1000,7 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
                                // errno inherited from sendmsg()
                                return -1;
                        }
-#endif /* __CYGWIN__ */
+#endif /* WINDOWS_PORT */
                        break;  // Loop around and try again
                case PIOC_STARTTLS_V2:
                        /* Wheee!!! we're done */
@@ -962,7 +1017,7 @@ int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
        /* Close the now-duplicated or now-erradicated plaintext fd */
 
        memcpy (tlsdata, &cmd.pio_data.pioc_starttls, sizeof (struct pioc_starttls));
-printf ("DEBUG: Returning control key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", tlsdata->ctlkey [0], tlsdata->ctlkey [1], tlsdata->ctlkey [2], tlsdata->ctlkey [3], tlsdata->ctlkey [4], tlsdata->ctlkey [5], tlsdata->ctlkey [6], tlsdata->ctlkey [7], tlsdata->ctlkey [8], tlsdata->ctlkey [9], tlsdata->ctlkey [10], tlsdata->ctlkey [11], tlsdata->ctlkey [12], tlsdata->ctlkey [13], tlsdata->ctlkey [14], tlsdata->ctlkey [15]);
+// printf ("DEBUG: Returning control key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", tlsdata->ctlkey [0], tlsdata->ctlkey [1], tlsdata->ctlkey [2], tlsdata->ctlkey [3], tlsdata->ctlkey [4], tlsdata->ctlkey [5], tlsdata->ctlkey [6], tlsdata->ctlkey [7], tlsdata->ctlkey [8], tlsdata->ctlkey [9], tlsdata->ctlkey [10], tlsdata->ctlkey [11], tlsdata->ctlkey [12], tlsdata->ctlkey [13], tlsdata->ctlkey [14], tlsdata->ctlkey [15]);
        registry_update (&entry_reqid, NULL);
        return 0;
 }
@@ -995,14 +1050,14 @@ int _tlspool_control_command (int cmdcode, uint8_t *ctlkey) {
                errno = EBUSY;
                return -1;
        }
-       bzero (&cmd, sizeof (cmd));     /* Do not leak old stack info */
+       memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
        cmd.pio_reqid = entry_reqid;
        cmd.pio_cbid = 0;
        cmd.pio_cmd = cmdcode;
        memcpy (&cmd.pio_data.pioc_control.ctlkey, ctlkey, TLSPOOL_CTLKEYLEN);
 // printf ("DEBUG: Using control key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", cmd.pio_data.pioc_control.ctlkey [0], cmd.pio_data.pioc_control.ctlkey [1], cmd.pio_data.pioc_control.ctlkey [2], cmd.pio_data.pioc_control.ctlkey [3], cmd.pio_data.pioc_control.ctlkey [4], cmd.pio_data.pioc_control.ctlkey [5], cmd.pio_data.pioc_control.ctlkey [6], cmd.pio_data.pioc_control.ctlkey [7], cmd.pio_data.pioc_control.ctlkey [8], cmd.pio_data.pioc_control.ctlkey [9], cmd.pio_data.pioc_control.ctlkey [10], cmd.pio_data.pioc_control.ctlkey [11], cmd.pio_data.pioc_control.ctlkey [12], cmd.pio_data.pioc_control.ctlkey [13], cmd.pio_data.pioc_control.ctlkey [14], cmd.pio_data.pioc_control.ctlkey [15]);
 
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
        if (np_send_command (&cmd) == -1) {
                registry_update (&entry_reqid, NULL);
                // errno inherited from np_send_command ()
@@ -1087,10 +1142,7 @@ int tlspool_prng (char *label, char *opt_ctxvalue,
        struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
        int entry_reqid = -1;
        pool_handle_t poolfd = INVALID_POOL_HANDLE;
-       struct iovec iov;
-       struct msghdr mh = { 0 };
-
-       bzero (prng_buf, prng_len);
+       memset (prng_buf, 0, prng_len);
 
        /* Sanity checks */
        if ((prng_len > TLSPOOL_PRNGBUFLEN) ||
@@ -1117,7 +1169,7 @@ int tlspool_prng (char *label, char *opt_ctxvalue,
                errno = EBUSY;
                return -1;
        }
-       bzero (&cmd, sizeof (cmd));     /* Do not leak old stack info */
+       memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
        cmd.pio_reqid = entry_reqid;
        cmd.pio_cbid = 0;
        cmd.pio_cmd = PIOC_PRNG_V2;
@@ -1132,7 +1184,7 @@ int tlspool_prng (char *label, char *opt_ctxvalue,
                cmd.pio_data.pioc_prng.in2_len = -1;
        }
 
-#ifdef __CYGWIN__
+#ifdef WINDOWS_PORT
 if (np_send_command (&cmd) == -1) {
        // errno inherited from np_send_command ()
        registry_update (&entry_reqid, NULL);
@@ -1140,11 +1192,7 @@ if (np_send_command (&cmd) == -1) {
 }
 #else
        /* Send the request */
-       iov.iov_base = &cmd;
-       iov.iov_len = sizeof (cmd);
-       mh.msg_iov = &iov;
-       mh.msg_iovlen = 1;
-       if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
+       if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
                // Let SIGPIPE be reported as EPIPE
                registry_update (&entry_reqid, NULL);
                // errno inherited from sendmsg()
@@ -1170,3 +1218,107 @@ if (np_send_command (&cmd) == -1) {
                return -1;
        }
 }
+
+
+/* Fetch a configuration variable value from the configuration file.  This is not
+ * an efficient procedure, at best suited for startup of tools or daemons; it
+ * will iterate over the config file until it reads the desired value.  The value
+ * returned is allocated and should be freed by the caller using free().
+ *
+ * When cfgfile is NULL, the environment variable TLSPOOL_CONFIGFILE is
+ * tried first, followed by the default setting from the macro 
+ * TLSPOOL_DEFAULT_CONFIG_PATH as defined in <tlspool/starttls.h>.
+ *
+ * The value returned is NULL when the variable is not found, including when this
+ * is due to errors such as not being able to open the file.
+ */
+char *tlspool_configvar (char *cfgfile, char *varname) {
+       FILE *cf;
+       char line [514];
+       int linelen;
+       int eof = 0;
+       char *here;
+       struct cfgopt *curopt;
+       int found;
+       char *retval = NULL;
+
+       if (cfgfile == NULL) {
+               cfgfile = getenv ("TLSPOOL_CFGFILE");
+       }
+       if (cfgfile == NULL) {
+               cfgfile = TLSPOOL_DEFAULT_CONFIG_PATH;
+       }
+
+       assert (cfgfile != NULL);
+       assert (varname != NULL);
+
+       cf = fopen (cfgfile, "r");
+       if (cf == NULL) {
+               perror ("Failed to open configuration file");
+               goto cleanup;
+       }
+
+       while (!eof) {
+               if (!fgets (line, sizeof (line)-1, cf)) {
+                       if (feof (cf)) {
+                               eof = 1;
+                               continue;
+                       } else {
+                               perror ("Error while reading configuration file");
+                               exit (1);
+                       }
+               }
+               linelen = strlen (line);
+               if (linelen == 0) {
+                       eof = 1;
+                       continue;
+               }
+               if (line [linelen-1] == (char) EOF) {
+                       linelen--;
+                       eof = 1;
+               }
+               if (line [linelen-1] != '\n') {
+                       fprintf (stderr, "Configuration line too long\n");
+                       goto cleanup;
+               }
+               line [--linelen] = 0;
+               if (linelen == 0) {
+                       continue;
+               }
+               if (line [0] == '#') {
+                       continue;
+               }
+               here = line;
+               while ((*here) && isspace (*here)) {
+                       here++;
+               }
+               if (!*here) {
+                       continue;
+               }
+               if (here != line) {
+                       fprintf (stderr, "Configuration line starts with whitespace:\n%s\n", line);
+                       goto cleanup;
+               }
+               while ((*here) && (*here != ' ')) {
+                       here++;
+               }
+               if (!*here) {
+                       fprintf (stderr, "Configuration line misses space after keyword:\n%s\n", line);
+                       goto cleanup;
+               }
+               *here++ = '\0';
+               if (strcmp (varname, line) == 0) {
+                       // Success!  We set the return value and end the loop
+                       retval = here;
+                       goto cleanup;
+               }
+       }
+
+cleanup:
+       if (cf != NULL) {
+               fclose (cf);
+               cf = NULL;
+       }
+       return retval;
+}
+