Added tlspool_configvar() to libtlspool
[tlspool] / lib / libtlspool.c
1 /* tlspool/libtlspool.c -- Library function for starttls go-get-it */
2
3 #include "whoami.h"
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <stdint.h>
11 #include <limits.h>
12 #include <ctype.h>
13
14 #include <unistd.h>
15 #include <pthread.h>
16 #include <fcntl.h>
17 #include <syslog.h>
18
19 #include <tlspool/starttls.h>
20 #include <tlspool/commands.h>
21
22 #ifdef WINDOWS_PORT
23 #include <winsock2.h>
24 #else
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/select.h>
29 #include <sys/resource.h>
30 #endif
31
32 #if !defined(WINDOWS_PORT)
33 #define closesocket(s) close(s)
34 #endif
35
36 #ifdef WINDOWS_PORT
37 #define PIPE_TIMEOUT 5000
38 #define BUFSIZE 4096
39 #define random rand
40 #define srandom srand
41
42 #define _tprintf printf
43 #endif /* WINDOWS_PORT */
44
45 /* The master thread will run the receiving side of the socket that connects
46  * to the TLS Pool.  The have_master_lock is used with _trylock() and will
47  * succeed to lock once, thereby approving the creation of the master thread.
48  */
49
50 static pthread_mutex_t have_master_lock = PTHREAD_MUTEX_INITIALIZER;
51
52 static void *master_thread (void *path);
53
54 static pool_handle_t poolfd = INVALID_POOL_HANDLE;              /* Blocked retrieval with tlspool_socket() */
55
56 static pthread_cond_t updated_poolfd = PTHREAD_COND_INITIALIZER;
57
58 static pthread_mutex_t prng_lock = PTHREAD_MUTEX_INITIALIZER;
59
60
61 /* Retrieve the process identity of the TLS Pool from the named file, or fall
62  * back on the default file if the name is set to NULL.  Returns -1 on failure.
63  */
64 int tlspool_pid (char *opt_pidfile) {
65         int fd;
66         char str_pid [256];
67         char *endptr;
68         size_t len;
69         unsigned long pid;
70
71         if (opt_pidfile == NULL) {
72                 opt_pidfile = tlspool_configvar (NULL, "daemon_pidfile");
73         }
74         if (opt_pidfile == NULL) {
75                 opt_pidfile = TLSPOOL_DEFAULT_PIDFILE_PATH;
76         }
77         assert (opt_pidfile != NULL);
78         fd = open (opt_pidfile, O_RDONLY);
79         if (fd != -1) {
80                 len = read (fd, str_pid, sizeof (str_pid) -1);
81                 close (fd);
82                 if ((len > 0) && (len < sizeof (str_pid))) {
83                         str_pid [len] = '\0';
84                         pid = strtoul (str_pid, &endptr, 10);
85                         while ((endptr != NULL) && (isspace (*endptr))) {
86                                 endptr++;
87                         }
88                         if ((pid >= 0) && (pid <= INT_MAX) && (!*endptr)) {
89                                 return (int) pid;
90                         }
91                 }
92         }
93         return -1;
94 }
95
96 /* The library function for starttls, which is normally called through one
97  * of the two inline variations below, which start client and server sides.
98  *
99  * As a side effect, this routine ensures that a master thread is running
100  * on the poolfd.  This is the process that actually contacts the TLS Pool
101  * and sets up the poolfd socket.
102  */
103 pool_handle_t tlspool_open_poolhandle (char *path) {
104         pool_handle_t poolfdsample = poolfd;
105         if (poolfdsample == INVALID_POOL_HANDLE) {
106                 pthread_mutex_t local_cond_wait = PTHREAD_MUTEX_INITIALIZER;
107                 //
108                 // Now that we have established a (first) poolfd, start up
109                 // the master thread that will recv() from it, and distribute.
110                 if (pthread_mutex_trylock (&have_master_lock) == 0) {
111                         pthread_t thr;
112                         unsigned int seed;
113                         pid_t me;
114                         if (!path) {
115                                 path = tlspool_configvar (NULL, "socket_name");
116                         }
117                         if (!path) {
118                                 path = TLSPOOL_DEFAULT_SOCKET_PATH;
119                         }
120                         assert (path != NULL);
121                         fprintf (stderr, "DEBUG: Opening TLS Pool on socket path %s\n", path);
122 #ifndef WINDOWS_PORT
123                         if (strlen(path) + 1 > sizeof(((struct sockaddr_un *) NULL)->sun_path)) {
124                                 syslog(LOG_ERR, "TLS Pool path name too long for UNIX domain socket");
125                                 exit(1);
126                         }
127 #endif
128                         if (pthread_create(&thr, NULL, master_thread, (void *)path) != 0) {
129                                 syslog(LOG_NOTICE, "Failed to create TLS Pool client master thread");
130                                 pthread_mutex_unlock(&have_master_lock);
131                                 tlspool_close_poolhandle(poolfd);
132                                 poolfd = INVALID_POOL_HANDLE;
133                                 return INVALID_POOL_HANDLE;
134                         }
135                         pthread_detach (thr);
136                         //
137                         // We need enough randomness to avoid clashing ctlkeys
138                         me = getpid ();
139                         seed = ((unsigned int) time (NULL)) ^ (((unsigned int) me) << 16);
140                         srandom (seed);
141                 }
142                 //
143                 // Wait until the master thread signals that it updated the
144                 // poolfd, as long as it is invalid.
145                 //
146                 // The cond_wait requires a mutex to wait on; the specs leave
147                 // room for different mutexes for each waiter (otherwise it
148                 // would not have been supplied with each pthread_cond_wait()
149                 // call) and that helps to avoid threads to contend on a
150                 // shared mutex -- which is why we use a local mutex per
151                 // thread: we don't need to wait for unique access.
152                 assert (pthread_mutex_lock (&local_cond_wait) == 0);
153                 while (poolfdsample = poolfd, poolfdsample == INVALID_POOL_HANDLE) {
154                         pthread_cond_wait (&updated_poolfd, &local_cond_wait);
155                 }
156                 pthread_mutex_unlock (&local_cond_wait);
157         }
158         return poolfdsample;
159 }
160
161
162 /* Determine an upper limit for simultaneous STARTTLS threads, based on the
163  * number of available file descriptors.  Note: The result is cached, so
164  * don't use root to increase beyond max in setrlimit() after calling this.
165  */
166 int tlspool_simultaneous_starttls(void) {
167 #ifdef WINDOWS_PORT
168         return 512;
169 #else /* WINDOWS_PORT */
170         static int simu = -1;
171         if (simu < 0) {
172                 struct rlimit rlimit_nofile;
173                 if (getrlimit (RLIMIT_NOFILE, &rlimit_nofile) == -1) {
174                         syslog (LOG_NOTICE, "Failed to determine simultaneous STARTTLS: %s", strerror (errno));
175                         rlimit_nofile.rlim_max = 1024;  // Pick something
176                 }
177                 simu = rlimit_nofile.rlim_max / 2;  // 2 FDs per STARTTLS
178         }
179         return simu;
180 #endif /* WINDOWS_PORT */
181 }
182
183
184 /* The request registry is an array of pointers, filled by the starttls_xxx()
185  * functions for as long as they have requests standing out.  The registry
186  * permits instant lookup of a mutex to signal, so the receiving end may
187  * pickup the message in its also-registered tlspool command buffer.
188  */
189
190 struct registry_entry {
191         pthread_mutex_t *sig;           /* Wait for master thread's recvmsg() */
192         struct tlspool_command *buf;    /* Buffer to hold received command */
193         pool_handle_t pfd;                      /* Client thread's assumed poolfd */
194 };
195
196 static struct registry_entry **registry;
197
198 static pthread_mutex_t registry_lock = PTHREAD_MUTEX_INITIALIZER;
199
200
201 /* Register a request handling structure under a request ID.  Registers the
202  * registry entry at the given reqid; if reqid is -1, a new one, mappable to
203  * the uint16_t type for the field is allocated and set in *reqid.  When the
204  * registry entry is NULL, it will be removed from the registry and the reqid
205  * is reset to -1.
206  *
207  * The return value is 0 on success, or -1 on failure; the most probable
208  * cause for failure is
209  */
210 static int registry_update (int *reqid, struct registry_entry *entry) {
211         static int simu = -1;
212         static uint16_t pos = 0;
213         int ctr;
214         if (registry == NULL) {
215                 simu = tlspool_simultaneous_starttls ();
216                 registry = calloc (simu, sizeof (struct registry_entry *));
217                 if (registry == NULL) {
218                         syslog (LOG_NOTICE, "Failed to allocate TLS Pool request registry");
219                         return -1;
220                 }
221         }
222         if (entry != NULL) {
223                 /* Set the entry in the given entry */
224                 if (*reqid < 0) {
225                         /* Allocate an entry in the registry */
226                         assert (pthread_mutex_lock (&registry_lock) == 0);
227                         ctr = simu;
228                         while (ctr-- > 0) {
229                                 if (registry [pos] == NULL) {
230                                         registry [pos] = entry;
231                                         *reqid = pos;
232                                         break;
233                                 }
234                                 pos++;
235                                 if (pos >= simu) {
236                                         pos = 0;
237                                 }
238                         }
239                         pthread_mutex_unlock (&registry_lock);
240                 }
241                 if (*reqid < 0) {
242                         return -1;
243                 }
244         } else {
245                 if ((*reqid < 0) || (*reqid >= simu)) {
246                         return -1;
247                 }
248                 /* Remove the entry from the given entry */
249                 assert (pthread_mutex_lock (&registry_lock) == 0);
250                 registry [*reqid] = NULL;       /* may not be atomic */
251                 *reqid = -1;
252                 pthread_mutex_unlock (&registry_lock);
253         }
254         return 0;
255 }
256
257
258 /* Flush registry entries with an older poolfd value; this is used after
259  * reconnecting to the TLS Pool, presumably having closed the old poolfd.
260  * Any outstanding registry entries will be sent an ERROR value at this
261  * time.
262  */
263 static void registry_flush (pool_handle_t poolfd) {
264         int regid = tlspool_simultaneous_starttls ();
265         assert (pthread_mutex_lock (&registry_lock) == 0);
266         while (regid-- > 0) {
267                 struct registry_entry *entry = registry [regid];
268                 if ((entry != NULL) && (entry->pfd != poolfd)) {
269                         // Fill the cmd buffer with an error message
270                         entry->buf->pio_cmd = PIOC_ERROR_V2;
271                         entry->buf->pio_data.pioc_error.tlserrno = EPIPE;
272                         strncpy (entry->buf->pio_data.pioc_error.message,
273                                 "No reply from TLS Pool",
274                                 sizeof (entry->buf->pio_data.pioc_error.message));
275                         // Signal continuation to the recipient
276                         pthread_mutex_unlock (entry->sig);
277                         // Do not remove the entry; the recipient will do this
278                 }
279         }
280         pthread_mutex_unlock (&registry_lock);
281 }
282
283 #ifdef WINDOWS_PORT
284 static pool_handle_t open_named_pipe (LPCTSTR lpszPipename)
285 {
286         HANDLE hPipe;
287         //struct tlspool_command chBuf;
288         BOOL   fSuccess = FALSE;
289         DWORD  dwMode;
290
291         // Try to open a named pipe; wait for it, if necessary.
292
293         while (1)
294         {
295                 hPipe = CreateFile(
296                         lpszPipename,   // pipe name
297                         GENERIC_READ |  // read and write access
298                         GENERIC_WRITE,
299                         0,              // no sharing
300                         NULL,           // default security attributes
301                         OPEN_EXISTING,  // opens existing pipe
302                         FILE_FLAG_OVERLAPPED, // overlapped
303                         NULL);          // no template file
304
305                 // Break if the pipe handle is valid.
306                 if (hPipe != INVALID_POOL_HANDLE)
307                         break;
308
309                 // Exit if an error other than ERROR_PIPE_BUSY occurs.
310                 if (GetLastError() != ERROR_PIPE_BUSY)
311                 {
312                         _tprintf(TEXT("Could not open pipe. GLE=%d\n"), GetLastError());
313                         return INVALID_POOL_HANDLE;
314                 }
315
316                 // All pipe instances are busy, so wait for 20 seconds.
317                 if (!WaitNamedPipe(lpszPipename, 20000))
318                 {
319                         printf("Could not open pipe: 20 second wait timed out.");
320                         return INVALID_POOL_HANDLE;
321                 }
322         }
323         // The pipe connected; change to message-read mode.
324         dwMode = PIPE_READMODE_MESSAGE;
325         fSuccess = SetNamedPipeHandleState(
326                 hPipe,    // pipe handle
327                 &dwMode,  // new pipe mode
328                 NULL,     // don't set maximum bytes
329                 NULL);    // don't set maximum time
330         if (!fSuccess)
331         {
332                 _tprintf(TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError());
333                 return INVALID_POOL_HANDLE;
334         }
335         ULONG ServerProcessId;
336         if (GetNamedPipeServerProcessId(hPipe, &ServerProcessId)) {
337                 printf("GetNamedPipeServerProcessId: ServerProcessId = %ld\n", ServerProcessId);
338         } else {
339                 _tprintf(TEXT("GetNamedPipeServerProcessId failed. GLE=%d\n"), GetLastError());
340         }
341         return hPipe;
342 }
343
344 static int np_send_command(struct tlspool_command *cmd) {
345         DWORD  cbToWrite, cbWritten;
346         OVERLAPPED overlapped;
347         BOOL fSuccess;
348
349         /* Send the request */
350         // Send a message to the pipe server.
351
352         cbToWrite = sizeof (struct tlspool_command);
353         _tprintf(TEXT("Sending %d byte cmd\n"), cbToWrite);
354
355         memset(&overlapped, 0, sizeof(overlapped));
356         overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
357
358         fSuccess = WriteFile(
359                 poolfd,                  // pipe handle
360                 cmd,                    // cmd message
361                 cbToWrite,              // cmd message length
362                 NULL,                  // bytes written
363                 &overlapped);            // overlapped
364
365         if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
366         {
367 // printf ("DEBUG: Write I/O pending\n");
368                 fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
369         }
370
371         if (fSuccess) {
372                 fSuccess = GetOverlappedResult(poolfd, &overlapped, &cbWritten, TRUE);
373         }
374
375         if (!fSuccess)
376         {
377                 _tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
378                 errno = EPIPE;
379                 return -1;
380         } else {
381 // printf ("DEBUG: Wrote %ld bytes to pipe\n", cbWritten);
382         }
383 // printf("DEBUG: Message sent to server, receiving reply as follows:\n");
384         return 0;
385 }
386 #endif /* WINDOWS_PORT */
387
388 /* The master thread issues the recv() commands on the TLS Pool socket, and
389  * redistributes the result to the registry entries that are waiting for
390  * the data.  The thread is started when the poolfd is first requested.
391  *
392  * Having a dedicated master thread is a great design simplification over
393  * temporary promotion of one of the application threads to a master status.
394  * The locking involved in the distinct state without a master, and the
395  * raceconditions while establishing the first on-demand master are dreadful.
396  *
397  * An additional advantage of a separate master thread is that it will
398  * instantly notice when the TLS Pool goes offline.  At this time, it will
399  * lock the registry and cancel any requests in the registry that are
400  * waiting for the older connection.  Subsequent attempts to receive are
401  * stopped immediately.  The TLS Pool then tries to reconnect to the
402  * TLS Pool anew, using exponential back-off.
403  */
404 static void *master_thread (void *path) {
405 #ifndef WINDOWS_PORT
406         useconds_t usec;
407         struct sockaddr_un sun;
408         //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
409         struct iovec iov;
410         struct cmsghdr *cmsg;
411         struct msghdr mh = { 0 };
412 #else
413         DWORD usec;
414 #endif
415         struct tlspool_command cmd;
416         //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
417         struct registry_entry *entry;
418 #ifdef WINDOWS_PORT
419         BOOL   fSuccess = FALSE;
420         DWORD  cbRead;
421 #endif
422
423 #ifndef WINDOWS_PORT
424         //
425         // Setup path information -- value and size were checked
426         memset (&sun, 0, sizeof (sun));
427         strcpy (sun.sun_path, (char *) path);
428         sun.sun_family = AF_UNIX;
429 #endif
430
431         //
432         // Service forever
433         while (1) {
434                 //
435                 // If any old socket clients persist, tell them that the
436                 // TLS Pool has been disconnected.
437                 if (poolfd != INVALID_POOL_HANDLE) {
438                         pool_handle_t poolfdcopy = poolfd;
439 // printf ("DEBUG: Removing old poolfd %d\n", poolfd);
440                         poolfd = INVALID_POOL_HANDLE;
441                         registry_flush (INVALID_POOL_HANDLE);
442                         tlspool_close_poolhandle (poolfdcopy);
443                 }
444                 //
445                 // First, connect to the TLS Pool; upon failure, retry
446                 // with 1s, 2s, 4s, 8s, 16s, 32s, 32s, 32s, ... intervals.
447                 usec = 1000000;
448                 while (poolfd == INVALID_POOL_HANDLE) {
449 #ifdef WINDOWS_PORT
450 // printf ("DEBUG: path = %s\n", (char *) path);
451                         pool_handle_t newpoolfd = open_named_pipe ((LPCTSTR) path);
452 // printf ("DEBUG: newpoolfd = %d\n", newpoolfd);
453                         if (newpoolfd != INVALID_POOL_HANDLE) {
454                                 poolfd = newpoolfd;
455                         }
456 #else
457                         pool_handle_t newpoolfd = socket (AF_UNIX, SOCK_STREAM, 0);
458                         if (newpoolfd != INVALID_POOL_HANDLE) {
459                                 if (connect (newpoolfd, (struct sockaddr *) &sun, SUN_LEN (&sun)) == 0) {
460 // printf ("DEBUG: Succeeded connect() to TLS Pool\n");
461                                         poolfd = newpoolfd;
462                                 } else {
463                                         tlspool_close_poolhandle (newpoolfd);
464                                         newpoolfd = INVALID_POOL_HANDLE;
465                                 }
466                         }
467 // printf ("DEBUG: Trying new poolfd %d for path %s\n", poolfd, sun.sun_path);
468 #endif
469                         //
470                         // Signal a newly set poolfd value to all waiting.
471                         // Note that we do not need to claim a mutex first;
472                         // there is always one writer to poolfd (namely, this
473                         // master_thread) and the rest simply reads it.  This
474                         // makes a silent assumption of atomic writes to the
475                         // poolfd, which seems fair because the size of an
476                         // fd table has been smaller than the size of the
477                         // data bus since the times of ZX Spectrum and CP/M.
478                         pthread_cond_broadcast (&updated_poolfd);
479 // printf ("DEBUG: Signalled slave threads with poolfd %d\n", poolfd);
480                         //
481                         // Wait before repeating, with exponential back-off
482                         if (poolfd == INVALID_POOL_HANDLE) {
483 #ifdef WINDOWS_PORT
484                                 Sleep(usec / 1000);
485 #else
486                                 usleep(usec);
487 #endif
488                                 usec <<= 1;
489                                 if (usec > 32000000) {
490                                         usec = 32000000;
491                                 }
492                         }
493                 }
494                 //
495                 // We now have an established link to the TLS Pool, until
496                 // further notice -- that is, until the TLS Pool terminates.
497                 // At that time, a break ends the following loop and jumps
498                 // back up to the re-connection logic.
499                 while (1) {
500                         int retval;
501 #ifdef WINDOWS_PORT
502                         OVERLAPPED overlapped;
503
504                         memset(&overlapped, 0, sizeof(overlapped));
505                         overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
506
507                         // Read from the pipe.
508                         fSuccess = ReadFile(
509                                 poolfd,       // pipe handle
510                                 &cmd,         // buffer to receive reply
511                                 sizeof (cmd), // size of buffer
512                                 NULL,         // number of bytes read
513                                 &overlapped); // not overlapped
514
515                         if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
516                         {
517 // printf ("DEBUG: Read I/O pending\n");
518                                 fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
519                         }
520
521                         if (fSuccess) {
522                                 fSuccess = GetOverlappedResult(poolfd, &overlapped, &cbRead, TRUE);
523                         }
524
525                         if (!fSuccess)
526                         {
527                                 _tprintf(TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError());
528                                 retval = -1;
529                         } else {
530 // printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
531                         }
532 #else
533                         iov.iov_base = &cmd;
534                         iov.iov_len = sizeof (cmd);
535                         mh.msg_iov = &iov;
536                         mh.msg_iovlen = 1;
537                         //NOT-USED// mh.msg_control = anc;
538                         //NOT-USED// mh.msg_controllen = sizeof (anc);
539                         retval = recvmsg (poolfd, &mh, MSG_NOSIGNAL);
540                         if ((retval == -1) && (errno = EINTR)) {
541                                 continue;       // Badly masked user signal
542                         }
543                         if (retval == 0) {
544                                 errno = EPIPE;
545                                 retval = -1;
546                         }
547                         if (retval == -1) {
548                                 // This includes EPIPE, or EOF, for detached
549                                 // TLS Pool; the treatment is to reconnect.
550 // printf ("DEBUG: recvmsg() returned -1 due to: %s\n", strerror (errno));
551                                 break;
552                         }
553 #endif /* WINDOWS_PORT */
554                         //
555                         // Determine where to post the received message
556                         entry = registry [cmd.pio_reqid];
557                         if (entry == NULL) {
558                                 // Protocol error!  Client detached!
559 // printf ("DEBUG: Client detached! poolfd=%d, cmd=0x%08x, reqid=%d, cbid=%d\n", poolfd, cmd.pio_cmd, cmd.pio_reqid, cmd.pio_cbid);
560                                 if ((cmd.pio_cbid != 0) && (cmd.pio_cmd != PIOC_ERROR_V2)) {
561 // printf ("DEBUG: Will send PIOC_ERROR_V2 as callback to TLS Pool\n");
562                                         // TLS Pool is waiting for a callback;
563                                         // Send it an ERROR message instead.
564                                         cmd.pio_cmd = PIOC_ERROR_V2;
565                                         cmd.pio_data.pioc_error.tlserrno = EPIPE;
566                                         strncpy (cmd.pio_data.pioc_error.message, "Client prematurely left TLS Pool negotiations", sizeof (cmd.pio_data.pioc_error.message));
567 #ifdef WINDOWS_PORT
568                                         np_send_command (&cmd);
569 #else
570                                         sendmsg (poolfd, &mh, MSG_NOSIGNAL);
571 #endif
572                                         // Ignore errors
573 // printf ("DEBUG: Sent      PIOC_ERROR_V2 as callback to TLS Pool\n");
574                                 }
575                                 // Do not attempt delivery
576                                 continue;
577                         }
578                         if (entry->pfd != poolfd) {
579 // printf ("DEBUG: Registry entry has older poolfd %d not %d, flushing registry\n", entry->pfd, poolfd);
580                                 registry_flush (poolfd);
581                         }
582                         memcpy (entry->buf, &cmd, sizeof (cmd));
583                         //NOT-USED// deliver anc or passfd to recipient
584                         pthread_mutex_unlock (entry->sig);
585 // printf ("DEBUG: Signalled slave with new message in place\n");
586                 }
587         }
588 }
589
590
591 /* Consider handling the message reception interface, if no other thread is
592  * doing that yet.  Then, wait until a message has been received.
593  */
594 static void registry_recvmsg (struct registry_entry *entry) {
595         static pool_handle_t lastpoolfd = INVALID_POOL_HANDLE;
596         //
597         // Detect poolfd socket change for potential dangling recipients
598         if (entry->pfd != lastpoolfd) {
599                 lastpoolfd = tlspool_open_poolhandle (NULL);
600                 if ((entry->pfd != lastpoolfd) && (lastpoolfd != INVALID_POOL_HANDLE)) {
601                         // Signal PIOC_ERROR to outdated recipients.
602                         // (That will include the current recipient.)
603                         registry_flush (lastpoolfd);
604                 }
605         }
606         //
607         // Now wait for the registered command structure to be filled
608         // by the master thread.  Note that the call to tlspool_open_poolhandle()
609         // above is made when this function is first called, and that
610         // routine ensures running of the master thread.
611         assert (pthread_mutex_lock (entry->sig) == 0);
612 }
613
614
615 /* The library function for ping, which is called to establish the API
616  * version and a list of facilities supported by the TLS Pool.  The data
617  * supplied to the TLS Pool should represent the environment of the
618  * application, which is why no defaults are provided by this function
619  * but the application should supply all ping data.
620  *
621  * The pioc_ping structure will be copied into the command structure,
622  * and upon completion it will be copied back.  Normally, the application
623  * would set YYYYMMDD_producer to TLSPOOL_IDENTITY_V2, and facilities
624  * to PIOF_FACILITY_ALL_CURRENT.  The TLS Pool overwrites the former and
625  * resets unsupported bits in the latter.  Note that facilities may be
626  * unsupported due to the compile-time environment of the TLS Pool or
627  * because it was configured without the requested support.
628  *
629  * This function returns zero on success, and -1 on failure.  In case of
630  * failure, errno will be set.
631  */
632 int tlspool_ping (pingpool_t *pingdata) {
633         struct tlspool_command cmd;
634         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
635         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
636         int entry_reqid = -1;
637         pool_handle_t poolfd = INVALID_POOL_HANDLE;
638
639         /* Prepare command structure */
640         poolfd = tlspool_open_poolhandle (NULL);
641 // printf ("DEBUG: poolfd = %d\n", poolfd);
642         if (poolfd == INVALID_POOL_HANDLE) {
643                 errno = ENODEV;
644                 return -1;
645         }
646         /* Finish setting up the registry entry */
647         regent.pfd = poolfd;
648         pthread_mutex_lock (&recvwait);         // Will await unlock by master
649         /* Determine the request ID */
650         if (registry_update (&entry_reqid, &regent) != 0) {
651                 errno = EBUSY;
652                 return -1;
653         }
654         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
655         cmd.pio_reqid = entry_reqid;
656         cmd.pio_cbid = 0;
657         cmd.pio_cmd = PIOC_PING_V2;
658         memcpy (&cmd.pio_data.pioc_ping, pingdata, sizeof (struct pioc_ping));
659 #ifdef WINDOWS_PORT
660         if (np_send_command (&cmd) == -1) {
661                 // errno inherited from np_send_command ()
662                 registry_update (&entry_reqid, NULL);
663                 return -1;
664         }
665 #else
666         /* Send the request */
667         if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
668                 // Let SIGPIPE be reported as EPIPE
669                 registry_update (&entry_reqid, NULL);
670                 // errno inherited from sendmsg()
671                 return -1;
672         }
673 #endif
674         /* Await response and process it */
675         registry_recvmsg (&regent);
676         registry_update (&entry_reqid, NULL);
677         switch (cmd.pio_cmd) {
678         case PIOC_ERROR_V2:
679                 /* Bad luck, we failed */
680                 syslog (LOG_INFO, "TLS Pool error to tlspool_ping(): %s", cmd.pio_data.pioc_error.message);
681                 errno = cmd.pio_data.pioc_error.tlserrno;
682                 return -1;
683         case PIOC_PING_V2:
684                 /* Wheee!!! we're done */
685                 memcpy (pingdata, &cmd.pio_data.pioc_ping, sizeof (pingpool_t));
686                 return 0;
687         default:
688                 /* V2 protocol error */
689                 errno = EPROTO;
690                 return -1;
691         }
692 }
693
694 #if defined(WINDOWS_PORT)
695 static int socket_dup_protocol_info(int fd, int pid, LPWSAPROTOCOL_INFOW lpProtocolInfo)
696 {
697         if (WSADuplicateSocketW((SOCKET)fd, pid, lpProtocolInfo) == SOCKET_ERROR) {
698                 errno = EPIPE;
699                 return -1;
700         } else {
701                 return 0;
702         }       
703 }
704 #endif
705
706 /* The library function for starttls, which is normally called through one
707  * of the two inline variations below, which start client and server sides.
708  *
709  * The cryptfd handle supplies the TLS connection that is assumed to have
710  * been setup.  When the function ends, either in success or failure, this
711  * handle will no longer be available to the caller; the responsibility of
712  * closing it is passed on to the function and/or the TLS Pool.
713  *
714  * The tlsdata structure will be copied into the command structure,
715  * and upon completion it will be copied back.  You can use it to
716  * communicate flags, protocols and other parameters, including the
717  * most important settings -- local and remote identifiers.  See
718  * the socket protocol document for details.
719  *
720  * The privdata handle is used in conjunction with the namedconnect() call;
721  * it is passed on to connect the latter to the context from which it was
722  * called and is not further acted upon by this function.
723  *
724  * The namedconnect() function is called when the identities have been
725  * exchanged, and established, in the TLS handshake.  This is the point
726  * at which a connection to the plaintext side is needed, and a callback
727  * to namedconnect() is made to find a handle for it.  The function is
728  * called with a version of the tlsdata that has been updated by the
729  * TLS Pool to hold the local and remote identities.  The return value
730  * should be -1 on error, with errno set, or it should be a valid file
731  * handle that can be passed back to the TLS Pool to connect to.
732  *
733  * When the namedconnect argument passed is NULL, default behaviour is
734  * triggered.  This interprets the privdata handle as an (int *) holding
735  * a file descriptor.  If its value is valid, that is, >= 0, it will be
736  * returned directly; otherwise, a socketpair is constructed, one of the
737  * sockets is stored in privdata for use by the caller and the other is
738  * returned as the connected file descriptor for use by the TLS Pool.
739  * This means that the privdata must be properly initialised for this
740  * use, with either -1 (to create a socketpair) or the TLS Pool's
741  * plaintext file descriptor endpoint.  The file handle returned in
742  * privdata, if it is >= 0, should be closed by the caller, both in case
743  * of success and failure.
744  *
745  * This function returns zero on success, and -1 on failure.  In case of
746  * failure, errno will be set.
747  */
748 int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
749                         void *privdata,
750                         int (*namedconnect) (starttls_t *tlsdata,void *privdata)) {
751         struct tlspool_command cmd;
752         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
753         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
754         int entry_reqid = -1;
755         pool_handle_t poolfd = INVALID_POOL_HANDLE;
756         int plainfd = -1;
757         int sentfd = -1;
758 #ifndef WINDOWS_PORT
759         struct iovec iov;
760         struct cmsghdr *cmsg;
761         struct msghdr mh = { 0 };
762         char anc[CMSG_SPACE(sizeof(int))];
763 #endif
764         int processing;
765         int renegotiate = 0 != (tlsdata->flags & PIOF_STARTTLS_RENEGOTIATE);
766
767         /* Prepare command structure */
768         poolfd = tlspool_open_poolhandle (NULL);
769         if (poolfd == INVALID_POOL_HANDLE) {
770                 closesocket(cryptfd);
771                 errno = ENODEV;
772                 return -1;
773         }
774         /* Finish setting up the registry entry */
775         regent.pfd = poolfd;
776         pthread_mutex_lock (&recvwait);         // Will await unlock by master
777         /* Determine the request ID */
778         if (registry_update (&entry_reqid, &regent) != 0) {
779                 closesocket(cryptfd);
780                 errno = EBUSY;
781                 return -1;
782         }
783         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
784         cmd.pio_reqid = entry_reqid;
785         cmd.pio_cbid = 0;
786         cmd.pio_cmd = PIOC_STARTTLS_V2;
787         memcpy (&cmd.pio_data.pioc_starttls, tlsdata, sizeof (struct pioc_starttls));
788
789 #if TLSPOOL_CTLKEYLEN != 16
790 #  error "Failure on assumption of 16 bytes per ctlkey"
791 #endif
792
793         if (!renegotiate) {
794                 assert (pthread_mutex_lock (&prng_lock) == 0);
795 #if RAND_MAX >= 0xffffffff
796                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
797                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
798                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
799                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
800 #elif RAND_MAX >= 0xffff
801                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
802                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
803                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
804                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
805                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
806                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
807                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
808                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
809 #elif RAND_MAX >= 0xff
810                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
811                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 1] = random ();
812                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
813                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 3] = random ();
814                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
815                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 5] = random ();
816                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
817                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 7] = random ();
818                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
819                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 9] = random ();
820                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
821                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [11] = random ();
822                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
823                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [13] = random ();
824                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
825                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [15] = random ();
826 #else
827 #  error "Unsuitable random() function due to RAND_MAX value < 0xff"
828 #endif
829                 pthread_mutex_unlock (&prng_lock);
830         }
831 // printf ("DEBUG: ctlkey =");
832 // {int i; for (i=0;i<16;i++) printf (" %02x", cmd.pio_data.pioc_starttls.ctlkey [i]);}
833 // printf ("\n");
834
835         /* Send the request */
836 #ifndef WINDOWS_PORT
837         iov.iov_base = &cmd;
838         iov.iov_len = sizeof(cmd);
839         mh.msg_iov = &iov;
840         mh.msg_iovlen = 1;
841 #endif
842         if (!renegotiate) {
843 #ifndef WINDOWS_PORT
844                 mh.msg_control = anc;
845                 mh.msg_controllen = sizeof (anc);
846                 cmsg = CMSG_FIRSTHDR (&mh);
847                 cmsg->cmsg_level = SOL_SOCKET;
848                 cmsg->cmsg_type = SCM_RIGHTS;
849                 *(int *)CMSG_DATA(cmsg) = cryptfd;      /* cannot close it yet */
850                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
851 #else /* WINDOWS_PORT */
852                 // cmd was already set to 0, including ancilary data simulation
853                 if (1 /*is_sock(wsock)*/) {
854                         // Send a socket
855                         LONG pid;
856
857                         GetNamedPipeServerProcessId(poolfd, &pid);
858                         cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
859                         printf("DEBUG: pid = %d, cryptfd = %d\n", pid, cryptfd);
860                         if (socket_dup_protocol_info(cryptfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
861                                 // printf("DEBUG: cygwin_socket_dup_protocol_info error\n");
862                                 // Let SIGPIPE be reported as EPIPE
863                                 closesocket(cryptfd);
864                                 registry_update (&entry_reqid, NULL);
865                                 // errno inherited from socket_dup_protocol_info()
866                                 return -1;
867                         }
868                         //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
869                 } else {
870                         // Send a file handle
871                         cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
872                         //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
873                 }
874 #endif /* WINDOWS_PORT */
875         }
876 #ifdef WINDOWS_PORT
877         if (np_send_command (&cmd) == -1) {
878                 close (cryptfd);
879                 registry_update (&entry_reqid, NULL);
880                 // errno inherited from np_send_command ()
881                 return -1;
882         }
883 #else
884         if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
885                 // Let SIGPIPE be reported as EPIPE
886                 close (cryptfd);
887                 registry_update (&entry_reqid, NULL);
888                 // errno inherited from sendmsg()
889                 return -1;
890         }
891 #endif /* WINDOWS_PORT */
892         sentfd = cryptfd;  /* Close anytime after response and before fn end */
893
894         /* Handle responses until success or error */
895         processing = 1;
896         while (processing) {
897                 //NOTUSED// mh.msg_control = anc;
898                 //NOTUSED// mh.msg_controllen = sizeof (anc);
899                 registry_recvmsg (&regent);
900                 if (sentfd >= 0) {
901                         closesocket(sentfd);
902                 }
903                 sentfd = -1;
904                 switch (cmd.pio_cmd) {
905                 case PIOC_ERROR_V2:
906                         /* Bad luck, we failed */
907                         syslog (LOG_INFO, "TLS Pool error to tlspool_starttls(): %s", cmd.pio_data.pioc_error.message);
908                         registry_update (&entry_reqid, NULL);
909                         errno = cmd.pio_data.pioc_error.tlserrno;
910                         return -1;
911                 case PIOC_STARTTLS_LOCALID_V2:
912                 case PIOC_PLAINTEXT_CONNECT_V2:
913                         if (namedconnect) {
914                                 plainfd = (*namedconnect) (tlsdata, privdata);
915                         } else {
916                                 /* default namedconnect() implementation */
917                                 plainfd = * (int *) privdata;
918                                 if ((plainfd < 0) && (cmd.pio_cmd == PIOC_PLAINTEXT_CONNECT_V2)) {
919 #if !defined(WINDOWS_PORT)
920                                         int soxx[2];
921 #else
922                                         // https://github.com/ncm/selectable-socketpair
923                                         extern int dumb_socketpair(SOCKET socks[2], int make_overlapped);
924                                         SOCKET soxx[2];
925 #endif
926                                         //TODO// Setup for TCP, UDP, SCTP
927 #ifndef WINDOWS_PORT
928                                         if (socketpair (AF_UNIX, SOCK_SEQPACKET, 0, soxx) == 0) {
929 #else /* WINDOWS_PORT */
930                                         if (dumb_socketpair(soxx, 1) == 0) {
931 #endif /* WINDOWS_PORT */
932                                                 // printf("DEBUG: socketpair succeeded\n");
933                                                 /* Socketpair created */
934                                                 plainfd = soxx [0];
935                                                 * (int *) privdata = soxx [1];
936                                         } else {
937                                                 /* Socketpair failed */
938                                                 // printf("DEBUG: socketpair failed\n");
939                                                 cmd.pio_cmd = PIOC_ERROR_V2;
940                                                 cmd.pio_data.pioc_error.tlserrno = errno;
941                                                 plainfd = -1;
942                                         }
943                                 }
944                         }
945                         /* We may now have a value to send in plainfd */
946                         if (plainfd >= 0) {
947 #ifndef WINDOWS_PORT
948                                 mh.msg_control = anc;
949                                 mh.msg_controllen = sizeof (anc);
950                                 cmsg = CMSG_FIRSTHDR (&mh);
951                                 cmsg->cmsg_level = SOL_SOCKET;
952                                 cmsg->cmsg_type = SCM_RIGHTS;
953                                 * (int *) CMSG_DATA (cmsg) = plainfd;
954                                 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
955 #else /* ifdef WINDOWS_PORT */
956                                 // cmd was already set to 0, including ancilary data simulation
957                                 if (1 /*is_sock(wsock)*/) {
958                                         // Send a socket
959                                         ULONG pid;
960                                         GetNamedPipeServerProcessId(poolfd, &pid);
961                                         cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
962                                         // printf("DEBUG: pid = %d, plainfd = %d\n", pid, plainfd);
963                                         if (socket_dup_protocol_info(plainfd, pid, &cmd.pio_ancil_data.pioa_socket) == -1) {
964                                                 // printf("DEBUG: cygwin_socket_dup_protocol_info error\n");
965                                                 // Let SIGPIPE be reported as EPIPE
966                                                 closesocket(plainfd);
967                                                 registry_update (&entry_reqid, NULL);
968                                                 // errno inherited from socket_dup_protocol_info()
969                                                 return -1;
970                                         }
971                                         //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
972                                 } else {
973                                         // Send a file handle
974                                         cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
975                                         //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
976                                 }
977 #endif /* WINDOWS_PORT */
978                         }
979
980                         /* Now supply plainfd in the callback response */
981                         sentfd = plainfd;
982 #ifdef WINDOWS_PORT
983                         if (np_send_command (&cmd) == -1) {
984                                 if (sentfd >= 0) {
985                                         closesocket(sentfd);
986                                         sentfd = -1;
987                                 }
988                                 registry_update (&entry_reqid, NULL);
989                                 // errno inherited from np_send_command()
990                                 return -1;
991                         }
992 #else
993                         if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
994                                 // Let SIGPIPE be reported as EPIPE
995                                 if (sentfd >= 0) {
996                                         close (sentfd);
997                                         sentfd = -1;
998                                 }
999                                 registry_update (&entry_reqid, NULL);
1000                                 // errno inherited from sendmsg()
1001                                 return -1;
1002                         }
1003 #endif /* WINDOWS_PORT */
1004                         break;  // Loop around and try again
1005                 case PIOC_STARTTLS_V2:
1006                         /* Wheee!!! we're done */
1007                         processing = 0;
1008                         break;
1009                 default:
1010                         /* V2 protocol error */
1011                         registry_update (&entry_reqid, NULL);
1012                         errno = EPROTO;
1013                         return -1;
1014                 }
1015         }
1016
1017         /* Close the now-duplicated or now-erradicated plaintext fd */
1018
1019         memcpy (tlsdata, &cmd.pio_data.pioc_starttls, sizeof (struct pioc_starttls));
1020 // 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]);
1021         registry_update (&entry_reqid, NULL);
1022         return 0;
1023 }
1024
1025
1026 /* The library function to send a control connection command, notably
1027  * TLSPOOL_CONTROL_DETACH and TLSPOOL_CONTROL_REATTACH.
1028  *
1029  * This function returns zero on success, and -1 on failure.  In case of
1030  * failure, errno will be set.
1031  */
1032 int _tlspool_control_command (int cmdcode, uint8_t *ctlkey) {
1033         struct tlspool_command cmd;
1034         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
1035         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
1036         int entry_reqid = -1;
1037         int retval;
1038
1039         /* Prepare command structure */
1040         poolfd = tlspool_open_poolhandle (NULL);
1041         if (poolfd == INVALID_POOL_HANDLE) {
1042                 errno = ENODEV;
1043                 return -1;
1044         }
1045         /* Finish setting up the registry entry */
1046         regent.pfd = poolfd;
1047         pthread_mutex_lock (&recvwait);         // Will await unlock by master
1048         /* Determine the request ID */
1049         if (registry_update (&entry_reqid, &regent) != 0) {
1050                 errno = EBUSY;
1051                 return -1;
1052         }
1053         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
1054         cmd.pio_reqid = entry_reqid;
1055         cmd.pio_cbid = 0;
1056         cmd.pio_cmd = cmdcode;
1057         memcpy (&cmd.pio_data.pioc_control.ctlkey, ctlkey, TLSPOOL_CTLKEYLEN);
1058 // 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]);
1059
1060 #ifdef WINDOWS_PORT
1061         if (np_send_command (&cmd) == -1) {
1062                 registry_update (&entry_reqid, NULL);
1063                 // errno inherited from np_send_command ()
1064                 return -1;
1065         }
1066 #else
1067         /* Send the request */
1068         if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
1069                 // Let SIGPIPE be reported as EPIPE
1070                 registry_update (&entry_reqid, NULL);
1071                 // errno inherited from send()
1072                 return -1;
1073         }
1074 #endif
1075         /* Receive the response */
1076         registry_recvmsg (&regent);
1077         switch (cmd.pio_cmd) {
1078         case PIOC_SUCCESS_V2:
1079                 retval = 0;
1080                 break;
1081         case PIOC_ERROR_V2:
1082                 retval = -1;
1083                 errno = cmd.pio_data.pioc_error.tlserrno;
1084                 break;
1085         default:
1086                 errno = EPROTO;
1087                 retval = -1;
1088                 break;
1089         }
1090         return retval;
1091 }
1092
1093 /* Generate a pseudo-random sequence based on session cryptographic keys.
1094  *
1095  * In the case of TLS, this adheres to RFC 5705; other protocols may or
1096  * may not support a similar mechanism, in which case an error is returned.
1097  *
1098  * This leans on access privileges to an existing connection at a meta-level,
1099  * for which we use the customary ctlkey verification mechanism introduced with
1100  * tlspool_starttls ().  Note that random material may be used for security
1101  * purposes, such as finding the same session key for both sides deriving from
1102  * prior key negotiation; the protection of a ctlkey for such applications is
1103  * important.
1104  *
1105  * The inputs to this function must adhere to the following restrictions:
1106  *  - label must not be a NULL pointer, but opt_ctxvalue may be set to NULL
1107  *    to bypass the use of a context value.  Note that passing an empty string
1108  *    in opt_ctxvalue is different from not providing the string at all by
1109  *    setting it to NULL.
1110  *  - label  and  opt_ctxvalue  (if non-NULL) refer to ASCII strings with
1111  *    printable characters, terminated with a NUL character.  The maximum
1112  *    string length of each is 254 bytes.
1113  *  - prng_len holds the requested number of pseudo-random bytes
1114  *  - prng_buf points is a non-NULL pointer to a buffer that can hold
1115  *    prng_len bytes.
1116  *
1117  * If the operation succeeds, then prng_buf holds prng_len bytes of random
1118  * material, and zero is returned.  If the operation fails, then prng_buf
1119  * is filled with zero bytes (to make it stand out as a rather rare case of
1120  * a random byte string) and -1 is returned.
1121  *
1122  * Note a few restrictions to the generality of this function, as a result of
1123  * the underlying packet format for the communication with the TLS Pool; but
1124  * the dimensions have been choosen such that these restrictions would not
1125  * typically be a problem in practice:
1126  *  - it constrains the string lengths of label and opt_ctxvalue
1127  *  - it constrains prng_len to a maximum value of TLSPOOL_PRNGBUFLEN
1128  *
1129  * The TLS Pool may limit certain TLS PRNG labels, in adherence to the
1130  * IANA-maintained TLS Exporter Label Registry.  It additionally supports
1131  * the EXPERIMENTAL label prefix specified in RFC 5705.
1132  *
1133  * Be advised that the maximum size of buffer may increase in future releases.
1134  * So, be sure to use TLSPOOL_PRNGBUFLEN which holds the header-file defined
1135  * size.
1136  */
1137 int tlspool_prng (char *label, char *opt_ctxvalue,
1138                 uint16_t prng_len, uint8_t *prng_buf,
1139                 uint8_t *ctlkey) {
1140         struct tlspool_command cmd;
1141         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
1142         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
1143         int entry_reqid = -1;
1144         pool_handle_t poolfd = INVALID_POOL_HANDLE;
1145         memset (prng_buf, 0, prng_len);
1146
1147         /* Sanity checks */
1148         if ((prng_len > TLSPOOL_PRNGBUFLEN) ||
1149                         (label == NULL) || (strlen (label) > 254) ||
1150                         ((opt_ctxvalue != NULL) &&
1151                                 ((strlen (opt_ctxvalue) > 254) ||
1152                                         (strlen (label) + strlen (opt_ctxvalue) > TLSPOOL_PRNGBUFLEN - TLSPOOL_CTLKEYLEN)))) {
1153                 errno = EINVAL;
1154                 return -1;
1155         }
1156
1157
1158         /* Prepare command structure */
1159         poolfd = tlspool_open_poolhandle (NULL);
1160         if (poolfd == INVALID_POOL_HANDLE) {
1161                 errno = ENODEV;
1162                 return -1;
1163         }
1164         /* Finish setting up the registry entry */
1165         regent.pfd = poolfd;
1166         pthread_mutex_lock (&recvwait);         // Will await unlock by master
1167         /* Determine the request ID */
1168         if (registry_update (&entry_reqid, &regent) != 0) {
1169                 errno = EBUSY;
1170                 return -1;
1171         }
1172         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
1173         cmd.pio_reqid = entry_reqid;
1174         cmd.pio_cbid = 0;
1175         cmd.pio_cmd = PIOC_PRNG_V2;
1176         cmd.pio_data.pioc_prng.prng_len = prng_len;
1177         memcpy (cmd.pio_data.pioc_prng.buffer, ctlkey, TLSPOOL_CTLKEYLEN);
1178         cmd.pio_data.pioc_prng.in1_len = strlen (label);
1179         memcpy (cmd.pio_data.pioc_prng.buffer + TLSPOOL_CTLKEYLEN, label, cmd.pio_data.pioc_prng.in1_len);
1180         if (opt_ctxvalue != NULL) {
1181                 cmd.pio_data.pioc_prng.in2_len = strlen (opt_ctxvalue);
1182                 memcpy (cmd.pio_data.pioc_prng.buffer + TLSPOOL_CTLKEYLEN + cmd.pio_data.pioc_prng.in1_len, opt_ctxvalue, cmd.pio_data.pioc_prng.in2_len);
1183         } else {
1184                 cmd.pio_data.pioc_prng.in2_len = -1;
1185         }
1186
1187 #ifdef WINDOWS_PORT
1188 if (np_send_command (&cmd) == -1) {
1189         // errno inherited from np_send_command ()
1190         registry_update (&entry_reqid, NULL);
1191         return -1;
1192 }
1193 #else
1194         /* Send the request */
1195         if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
1196                 // Let SIGPIPE be reported as EPIPE
1197                 registry_update (&entry_reqid, NULL);
1198                 // errno inherited from sendmsg()
1199                 return -1;
1200         }
1201 #endif
1202         /* Await response and process it */
1203         registry_recvmsg (&regent);
1204         registry_update (&entry_reqid, NULL);
1205         switch (cmd.pio_cmd) {
1206         case PIOC_ERROR_V2:
1207                 /* Bad luck, we failed */
1208                 syslog (LOG_INFO, "TLS Pool error to tlspool_ping(): %s", cmd.pio_data.pioc_error.message);
1209                 errno = cmd.pio_data.pioc_error.tlserrno;
1210                 return -1;
1211         case PIOC_PRNG_V2:
1212                 /* Wheee!!! we're done */
1213                 memcpy (prng_buf, cmd.pio_data.pioc_prng.buffer, prng_len);
1214                 return 0;
1215         default:
1216                 /* V2 protocol error */
1217                 errno = EPROTO;
1218                 return -1;
1219         }
1220 }
1221
1222
1223 /* Fetch a configuration variable value from the configuration file.  This is not
1224  * an efficient procedure, at best suited for startup of tools or daemons; it
1225  * will iterate over the config file until it reads the desired value.  The value
1226  * returned is allocated and should be freed by the caller using free().
1227  *
1228  * When cfgfile is NULL, the environment variable TLSPOOL_CONFIGFILE is
1229  * tried first, followed by the default setting from the macro 
1230  * TLSPOOL_DEFAULT_CONFIG_PATH as defined in <tlspool/starttls.h>.
1231  *
1232  * The value returned is NULL when the variable is not found, including when this
1233  * is due to errors such as not being able to open the file.
1234  */
1235 char *tlspool_configvar (char *cfgfile, char *varname) {
1236         FILE *cf;
1237         char line [514];
1238         int linelen;
1239         int eof = 0;
1240         char *here;
1241         struct cfgopt *curopt;
1242         int found;
1243         char *retval = NULL;
1244
1245         if (cfgfile == NULL) {
1246                 cfgfile = getenv ("TLSPOOL_CFGFILE");
1247         }
1248         if (cfgfile == NULL) {
1249                 cfgfile = TLSPOOL_DEFAULT_CONFIG_PATH;
1250         }
1251
1252         assert (cfgfile != NULL);
1253         assert (varname != NULL);
1254
1255         cf = fopen (cfgfile, "r");
1256         if (cf == NULL) {
1257                 perror ("Failed to open configuration file");
1258                 goto cleanup;
1259         }
1260
1261         while (!eof) {
1262                 if (!fgets (line, sizeof (line)-1, cf)) {
1263                         if (feof (cf)) {
1264                                 eof = 1;
1265                                 continue;
1266                         } else {
1267                                 perror ("Error while reading configuration file");
1268                                 exit (1);
1269                         }
1270                 }
1271                 linelen = strlen (line);
1272                 if (linelen == 0) {
1273                         eof = 1;
1274                         continue;
1275                 }
1276                 if (line [linelen-1] == (char) EOF) {
1277                         linelen--;
1278                         eof = 1;
1279                 }
1280                 if (line [linelen-1] != '\n') {
1281                         fprintf (stderr, "Configuration line too long\n");
1282                         goto cleanup;
1283                 }
1284                 line [--linelen] = 0;
1285                 if (linelen == 0) {
1286                         continue;
1287                 }
1288                 if (line [0] == '#') {
1289                         continue;
1290                 }
1291                 here = line;
1292                 while ((*here) && isspace (*here)) {
1293                         here++;
1294                 }
1295                 if (!*here) {
1296                         continue;
1297                 }
1298                 if (here != line) {
1299                         fprintf (stderr, "Configuration line starts with whitespace:\n%s\n", line);
1300                         goto cleanup;
1301                 }
1302                 while ((*here) && (*here != ' ')) {
1303                         here++;
1304                 }
1305                 if (!*here) {
1306                         fprintf (stderr, "Configuration line misses space after keyword:\n%s\n", line);
1307                         goto cleanup;
1308                 }
1309                 *here++ = '\0';
1310                 if (strcmp (varname, line) == 0) {
1311                         // Success!  We set the return value and end the loop
1312                         retval = here;
1313                         goto cleanup;
1314                 }
1315         }
1316
1317 cleanup:
1318         if (cf != NULL) {
1319                 fclose (cf);
1320                 cf = NULL;
1321         }
1322         return retval;
1323 }
1324