Integration doc for containers and systemd
[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 <string.h>
8 #include <assert.h>
9 #include <stdint.h>
10 #include <limits.h>
11 #include <ctype.h>
12
13 #include <errno.h>
14 #include <com_err.h>
15 #include <errortable.h>
16
17 #include <pthread.h>
18 #include <fcntl.h>
19 #include <syslog.h>
20
21 #include <tlspool/starttls.h>
22 #include <tlspool/commands.h>
23
24 #ifndef WINDOWS_PORT
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <sys/select.h>
30 #include <sys/resource.h>
31 #include <netinet/in.h>
32 #endif
33
34 #if !defined(WINDOWS_PORT)
35 #define closesocket(s) close(s)
36 #endif
37
38 #ifdef WINDOWS_PORT
39 #define random rand
40 #define srandom srand
41 #define _tprintf printf
42 #endif /* WINDOWS_PORT */
43
44 /* Windows supports SCTP but fails to define this IANA-standardised symbol: */
45 #ifndef IPPROTO_SCTP
46 #define IPPROTO_SCTP 132
47 #endif
48
49 #ifdef WINDOWS_PORT
50 #include "libtlspool_windows.c"
51 #else
52 #include "libtlspool_posix.c"
53 #endif
54
55 /* The master thread will run the receiving side of the socket that connects
56  * to the TLS Pool.  The have_master_lock is used with _trylock() and will
57  * succeed to lock once, thereby approving the creation of the master thread.
58  */
59
60 static pthread_mutex_t have_master_lock = PTHREAD_MUTEX_INITIALIZER;
61
62 static void *master_thread (void *path);
63
64 static int poolfd = -1;         /* Blocked retrieval with tlspool_socket() */
65
66 static pthread_cond_t updated_poolfd = PTHREAD_COND_INITIALIZER;
67
68 static pthread_mutex_t prng_lock = PTHREAD_MUTEX_INITIALIZER;
69
70
71 /* Retrieve the process identity of the TLS Pool from the named file, or fall
72  * back on the default file if the name is set to NULL.  Returns -1 on failure.
73  */
74 int tlspool_pid (char *opt_pidfile) {
75         int fd;
76         char str_pid [256];
77         char *endptr;
78
79         if (opt_pidfile == NULL) {
80                 opt_pidfile = tlspool_configvar (NULL, "daemon_pidfile");
81         }
82         if (opt_pidfile == NULL) {
83                 opt_pidfile = TLSPOOL_DEFAULT_PIDFILE_PATH;
84         }
85         assert (opt_pidfile != NULL);
86         fd = open (opt_pidfile, O_RDONLY);
87         if (fd != -1) {
88                 size_t len = read (fd, str_pid, sizeof (str_pid) -1);
89                 close (fd);
90                 if ((len > 0) && (len < sizeof (str_pid))) {
91                         str_pid [len] = '\0';
92                         /* pid_t */ unsigned long pid = strtoul (str_pid, &endptr, 10);
93                         while ((endptr != NULL) && (isspace (*endptr))) {
94                                 endptr++;
95                         }
96                         if ((pid <= INT_MAX) && (!*endptr)) {
97                                 return (int) pid;
98                         }
99                 }
100         }
101         return -1;
102 }
103
104 /* The library function for starttls, which is normally called through one
105  * of the two inline variations below, which start client and server sides.
106  *
107  * As a side effect, this routine ensures that a master thread is running
108  * on the poolfd.  This is the process that actually contacts the TLS Pool
109  * and sets up the poolfd socket.
110  */
111 int tlspool_open_poolhandle (char *path) {
112         int poolfdsample = poolfd;
113         if (poolfdsample < 0) {
114                 pthread_mutex_t local_cond_wait = PTHREAD_MUTEX_INITIALIZER;
115                 //
116                 // Now that we have established a (first) poolfd, start up
117                 // the master thread that will recv() from it, and distribute.
118                 if (pthread_mutex_trylock (&have_master_lock) == 0) {
119                         pthread_t thr;
120                         unsigned int seed;
121                         pid_t me;
122                         if (!path) {
123                                 path = tlspool_configvar (NULL, "socket_name");
124                         }
125                         if (!path) {
126                                 path = TLSPOOL_DEFAULT_SOCKET_PATH;
127                         }
128                         assert (path != NULL);
129                         fprintf (stderr, "DEBUG: Opening TLS Pool on socket path %s\n", path);
130 #ifndef WINDOWS_PORT
131                         if (strlen(path) + 1 > sizeof(((struct sockaddr_un *) NULL)->sun_path)) {
132                                 syslog(LOG_ERR, "TLS Pool path name too long for UNIX domain socket");
133                                 exit(1);
134                         }
135 #endif
136                         if (pthread_create(&thr, NULL, master_thread, (void *)path) != 0) {
137                                 syslog(LOG_NOTICE, "Failed to create TLS Pool client master thread");
138                                 pthread_mutex_unlock(&have_master_lock);
139                                 tlspool_close_poolhandle(poolfd);
140                                 poolfd = -1;
141                                 return -1;
142                         }
143                         pthread_detach (thr);
144                         //
145                         // We need enough randomness to avoid clashing ctlkeys
146                         me = getpid ();
147                         seed = ((unsigned int) time (NULL)) ^ (((unsigned int) me) << 16);
148                         srandom (seed);
149                 }
150                 //
151                 // Wait until the master thread signals that it updated the
152                 // poolfd, as long as it is invalid.
153                 //
154                 // The cond_wait requires a mutex to wait on; the specs leave
155                 // room for different mutexes for each waiter (otherwise it
156                 // would not have been supplied with each pthread_cond_wait()
157                 // call) and that helps to avoid threads to contend on a
158                 // shared mutex -- which is why we use a local mutex per
159                 // thread: we don't need to wait for unique access.
160                 assert (pthread_mutex_lock (&local_cond_wait) == 0);
161                 while (poolfdsample = poolfd, poolfdsample < 0) {
162                         pthread_cond_wait (&updated_poolfd, &local_cond_wait);
163                 }
164                 pthread_mutex_unlock (&local_cond_wait);
165         }
166         return poolfdsample;
167 }
168
169 /* The request registry is an array of pointers, filled by the starttls_xxx()
170  * functions for as long as they have requests standing out.  The registry
171  * permits instant lookup of a mutex to signal, so the receiving end may
172  * pickup the message in its also-registered tlspool command buffer.
173  */
174
175 struct registry_entry {
176         pthread_mutex_t *sig;           /* Wait for master thread's recvmsg() */
177         struct tlspool_command *buf;    /* Buffer to hold received command */
178         int pfd;                        /* Client thread's assumed poolfd */
179 };
180
181 static struct registry_entry **registry;
182
183 static pthread_mutex_t registry_lock = PTHREAD_MUTEX_INITIALIZER;
184
185
186 /* Register a request handling structure under a request ID.  Registers the
187  * registry entry at the given reqid; if reqid is -1, a new one, mappable to
188  * the uint16_t type for the field is allocated and set in *reqid.  When the
189  * registry entry is NULL, it will be removed from the registry and the reqid
190  * is reset to -1.
191  *
192  * The return value is 0 on success, or -1 on failure; the most probable
193  * cause for failure is
194  */
195 static int registry_update (int *reqid, struct registry_entry *entry) {
196         static int simu = -1;
197         static uint16_t pos = 0;
198         int ctr;
199         if (registry == NULL) {
200                 simu = tlspool_simultaneous_starttls ();
201                 registry = calloc (simu, sizeof (struct registry_entry *));
202                 if (registry == NULL) {
203                         syslog (LOG_NOTICE, "Failed to allocate TLS Pool request registry");
204                         return -1;
205                 }
206         }
207         if (entry != NULL) {
208                 /* Set the entry in the given entry */
209                 if (*reqid < 0) {
210                         /* Allocate an entry in the registry */
211                         assert (pthread_mutex_lock (&registry_lock) == 0);
212                         ctr = simu;
213                         while (ctr-- > 0) {
214                                 if (registry [pos] == NULL) {
215                                         registry [pos] = entry;
216                                         *reqid = pos;
217                                         break;
218                                 }
219                                 pos++;
220                                 if (pos >= simu) {
221                                         pos = 0;
222                                 }
223                         }
224                         pthread_mutex_unlock (&registry_lock);
225                 }
226                 if (*reqid < 0) {
227                         return -1;
228                 }
229         } else {
230                 if ((*reqid < 0) || (*reqid >= simu)) {
231                         return -1;
232                 }
233                 /* Remove the entry from the given entry */
234                 assert (pthread_mutex_lock (&registry_lock) == 0);
235                 registry [*reqid] = NULL;       /* may not be atomic */
236                 *reqid = -1;
237                 pthread_mutex_unlock (&registry_lock);
238         }
239         return 0;
240 }
241
242
243 /* Flush registry entries with an older poolfd value; this is used after
244  * reconnecting to the TLS Pool, presumably having closed the old poolfd.
245  * Any outstanding registry entries will be sent an ERROR value at this
246  * time.
247  */
248 static void registry_flush (int poolfd) {
249         int regid = tlspool_simultaneous_starttls ();
250         assert (pthread_mutex_lock (&registry_lock) == 0);
251         while (regid-- > 0) {
252                 struct registry_entry *entry = registry [regid];
253                 if ((entry != NULL) && (entry->pfd != poolfd)) {
254                         // Fill the cmd buffer with an error message
255                         entry->buf->pio_cmd = PIOC_ERROR_V2;
256                         entry->buf->pio_data.pioc_error.tlserrno = E_TLSPOOL_CLIENT_DISCONNECT;
257                         strncpy (entry->buf->pio_data.pioc_error.message,
258                                 "TLS Pool connection closed",
259                                 sizeof (entry->buf->pio_data.pioc_error.message));
260                         // Signal continuation to the recipient
261                         pthread_mutex_unlock (entry->sig);
262                         // Do not remove the entry; the recipient will do this
263                 }
264         }
265         pthread_mutex_unlock (&registry_lock);
266 }
267
268 /* The master thread issues the recv() commands on the TLS Pool socket, and
269  * redistributes the result to the registry entries that are waiting for
270  * the data.  The thread is started when the poolfd is first requested.
271  *
272  * Having a dedicated master thread is a great design simplification over
273  * temporary promotion of one of the application threads to a master status.
274  * The locking involved in the distinct state without a master, and the
275  * raceconditions while establishing the first on-demand master are dreadful.
276  *
277  * An additional advantage of a separate master thread is that it will
278  * instantly notice when the TLS Pool goes offline.  At this time, it will
279  * lock the registry and cancel any requests in the registry that are
280  * waiting for the older connection.  Subsequent attempts to receive are
281  * stopped immediately.  The TLS Pool then tries to reconnect to the
282  * TLS Pool anew, using exponential back-off.
283  */
284 static void *master_thread (void *path) {
285         unsigned int usec;
286         struct tlspool_command cmd;
287         //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
288         struct registry_entry *entry;
289
290
291         //
292         // Service forever
293         while (1) {
294                 //
295                 // If any old socket clients persist, tell them that the
296                 // TLS Pool has been disconnected.
297                 if (poolfd >= 0) {
298                         int poolfdcopy = poolfd;
299 // printf ("DEBUG: Removing old poolfd %d\n", poolfd);
300                         poolfd = -1;
301                         registry_flush (-1);
302                         tlspool_close_poolhandle (poolfdcopy);
303                 }
304                 //
305                 // First, connect to the TLS Pool; upon failure, retry
306                 // with 1s, 2s, 4s, 8s, 16s, 32s, 32s, 32s, ... intervals.
307                 usec = 1000000;
308                 while (poolfd < 0) {
309                         int newpoolfd = open_pool (path);                       
310                         if (newpoolfd >= 0) {
311                                 poolfd = newpoolfd;
312                         }
313                         //
314                         // Signal a newly set poolfd value to all waiting.
315                         // Note that we do not need to claim a mutex first;
316                         // there is always one writer to poolfd (namely, this
317                         // master_thread) and the rest simply reads it.  This
318                         // makes a silent assumption of atomic writes to the
319                         // poolfd, which seems fair because the size of an
320                         // fd table has been smaller than the size of the
321                         // data bus since the times of ZX Spectrum and CP/M.
322                         pthread_cond_broadcast (&updated_poolfd);
323 // printf ("DEBUG: Signalled slave threads with poolfd %d\n", poolfd);
324                         //
325                         // Wait before repeating, with exponential back-off
326                         if (poolfd < 0) {
327                                 os_usleep(usec);
328                                 usec <<= 1;
329                                 if (usec > 32000000) {
330                                         usec = 32000000;
331                                 }
332                         }
333                 }
334                 //
335                 // We now have an established link to the TLS Pool, until
336                 // further notice -- that is, until the TLS Pool terminates.
337                 // At that time, a break ends the following loop and jumps
338                 // back up to the re-connection logic.
339                 while (1) {
340                         int retval = os_recvmsg_command(poolfd, &cmd);
341 #ifndef WINDOWS_PORT
342                         if ((retval == -1) && (errno = EINTR)) {
343                                 continue;       // Badly masked user signal
344                         }
345                         if (retval == 0) {
346                                 errno = EPIPE;
347                                 retval = -1;
348                         }
349 #endif /* !WINDOWS_PORT */
350                         if (retval == -1) {
351                                 // This includes EPIPE, or EOF, for detached
352                                 // TLS Pool; the treatment is to reconnect.
353 // printf ("DEBUG: recvmsg() returned -1 due to: %s\n", strerror (errno));
354                                 break;
355                         }
356                         //
357                         // Determine where to post the received message
358                         entry = registry [cmd.pio_reqid];
359                         if (entry == NULL) {
360                                 // Protocol error!  Client detached!
361 // printf ("DEBUG: Client detached! poolfd=%d, cmd=0x%08x, reqid=%d, cbid=%d\n", poolfd, cmd.pio_cmd, cmd.pio_reqid, cmd.pio_cbid);
362                                 if ((cmd.pio_cbid != 0) && (cmd.pio_cmd != PIOC_ERROR_V2)) {
363 // printf ("DEBUG: Will send PIOC_ERROR_V2 as callback to TLS Pool\n");
364                                         // TLS Pool is waiting for a callback;
365                                         // Send it an ERROR message instead.
366                                         cmd.pio_cmd = PIOC_ERROR_V2;
367                                         cmd.pio_data.pioc_error.tlserrno = E_TLSPOOL_CLIENT_REFUSES_CALLBACK;
368                                         strncpy (cmd.pio_data.pioc_error.message,
369                                                         "TLS Pool client will not partake in callback",
370                                                         sizeof (cmd.pio_data.pioc_error.message));
371                                         os_sendmsg_command (poolfd, &cmd, -1);
372                                         // Ignore errors
373 // printf ("DEBUG: Sent      PIOC_ERROR_V2 as callback to TLS Pool\n");
374                                 }
375                                 // Do not attempt delivery
376                                 continue;
377                         }
378                         if (entry->pfd != poolfd) {
379 // printf ("DEBUG: Registry entry has older poolfd %d not %d, flushing registry\n", entry->pfd, poolfd);
380                                 registry_flush (poolfd);
381                         }
382                         memcpy (entry->buf, &cmd, sizeof (cmd));
383                         //NOT-USED// deliver anc or passfd to recipient
384                         pthread_mutex_unlock (entry->sig);
385 // printf ("DEBUG: Signalled slave with new message in place\n");
386                 }
387         }
388 }
389
390
391 /* Consider handling the message reception interface, if no other thread is
392  * doing that yet.  Then, wait until a message has been received.
393  */
394 static void registry_recvmsg (struct registry_entry *entry) {
395         static int lastpoolfd = -1;
396         //
397         // Detect poolfd socket change for potential dangling recipients
398         if (entry->pfd != lastpoolfd) {
399                 lastpoolfd = tlspool_open_poolhandle (NULL);
400                 if ((entry->pfd != lastpoolfd) && (lastpoolfd >= 0)) {
401                         // Signal PIOC_ERROR to outdated recipients.
402                         // (That will include the current recipient.)
403                         registry_flush (lastpoolfd);
404                 }
405         }
406         //
407         // Now wait for the registered command structure to be filled
408         // by the master thread.  Note that the call to tlspool_open_poolhandle()
409         // above is made when this function is first called, and that
410         // routine ensures running of the master thread.
411         assert (pthread_mutex_lock (entry->sig) == 0);
412 }
413
414
415 /* The library function for ping, which is called to establish the API
416  * version and a list of facilities supported by the TLS Pool.  The data
417  * supplied to the TLS Pool should represent the environment of the
418  * application, which is why no defaults are provided by this function
419  * but the application should supply all ping data.
420  *
421  * The pioc_ping structure will be copied into the command structure,
422  * and upon completion it will be copied back.  Normally, the application
423  * would set YYYYMMDD_producer to TLSPOOL_IDENTITY_V2, and facilities
424  * to PIOF_FACILITY_ALL_CURRENT.  The TLS Pool overwrites the former and
425  * resets unsupported bits in the latter.  Note that facilities may be
426  * unsupported due to the compile-time environment of the TLS Pool or
427  * because it was configured without the requested support.
428  *
429  * This function returns zero on success, and -1 on failure.  In case of
430  * failure, errno will be set.
431  */
432 int tlspool_ping (pingpool_t *pingdata) {
433         struct tlspool_command cmd;
434         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
435         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
436         int entry_reqid = -1;
437         int poolfd = -1;
438
439         /* Prepare command structure */
440         poolfd = tlspool_open_poolhandle (NULL);
441 // printf ("DEBUG: poolfd = %d\n", poolfd);
442         if (poolfd < 0) {
443                 errno = ENODEV;
444                 return -1;
445         }
446         /* Finish setting up the registry entry */
447         regent.pfd = poolfd;
448         pthread_mutex_lock (&recvwait);         // Will await unlock by master
449         /* Determine the request ID */
450         if (registry_update (&entry_reqid, &regent) != 0) {
451                 errno = EBUSY;
452                 return -1;
453         }
454         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
455         cmd.pio_reqid = entry_reqid;
456         cmd.pio_cbid = 0;
457         cmd.pio_cmd = PIOC_PING_V2;
458         memcpy (&cmd.pio_data.pioc_ping, pingdata, sizeof (struct pioc_ping));
459         if (os_sendmsg_command (poolfd, &cmd, -1) == -1) {
460                 // Let SIGPIPE be reported as EPIPE
461                 registry_update (&entry_reqid, NULL);
462                 // errno inherited from sendmsg()
463                 return -1;
464         }
465         /* Await response and process it */
466         registry_recvmsg (&regent);
467         registry_update (&entry_reqid, NULL);
468         switch (cmd.pio_cmd) {
469         case PIOC_ERROR_V2:
470                 /* Bad luck, we failed */
471                 syslog (LOG_INFO, "TLS Pool error to tlspool_ping(): %s", cmd.pio_data.pioc_error.message);
472                 errno = cmd.pio_data.pioc_error.tlserrno;
473                 return -1;
474         case PIOC_PING_V2:
475                 /* Wheee!!! we're done */
476                 memcpy (pingdata, &cmd.pio_data.pioc_ping, sizeof (pingpool_t));
477                 return 0;
478         default:
479                 /* V2 protocol error */
480                 errno = EPROTO;
481                 return -1;
482         }
483 }
484
485
486 /* The library function for starttls, which is normally called through one
487  * of the two inline variations below, which start client and server sides.
488  *
489  * The cryptfd handle supplies the TLS connection that is assumed to have
490  * been setup.  When the function ends, either in success or failure, this
491  * handle will no longer be available to the caller; the responsibility of
492  * closing it is passed on to the function and/or the TLS Pool.
493  *
494  * The tlsdata structure will be copied into the command structure,
495  * and upon completion it will be copied back.  You can use it to
496  * communicate flags, protocols and other parameters, including the
497  * most important settings -- local and remote identifiers.  See
498  * the socket protocol document for details.
499  *
500  * The privdata handle is used in conjunction with the namedconnect() call;
501  * it is passed on to connect the latter to the context from which it was
502  * called and is not further acted upon by this function.
503  *
504  * This function returns zero on success, and -1 on failure.  In case of
505  * failure, errno will be set.
506  */
507 int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
508                         void *privdata,
509                         int (*namedconnect) (starttls_t *tlsdata,void *privdata)) {
510         struct tlspool_command cmd;
511         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
512         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
513         int entry_reqid = -1;
514         int poolfd = -1;
515         int plainfd = -1;
516         int sentfd = -1;
517         int processing;
518         int renegotiate = 0 != (tlsdata->flags & PIOF_STARTTLS_RENEGOTIATE);
519         int type = ipproto_to_sockettype (tlsdata->ipproto);
520         if (type == -1) {
521                 errno = EINVAL;
522                 return -1;
523         }
524         /* Prepare command structure */
525         poolfd = tlspool_open_poolhandle (NULL);
526         if (poolfd < 0) {
527                 closesocket(cryptfd);
528                 errno = ENODEV;
529                 return -1;
530         }
531         /* Finish setting up the registry entry */
532         regent.pfd = poolfd;
533         pthread_mutex_lock (&recvwait);         // Will await unlock by master
534         /* Determine the request ID */
535         if (registry_update (&entry_reqid, &regent) != 0) {
536                 closesocket(cryptfd);
537                 errno = EBUSY;
538                 return -1;
539         }
540         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
541         cmd.pio_reqid = entry_reqid;
542         cmd.pio_cbid = 0;
543         cmd.pio_cmd = PIOC_STARTTLS_V2;
544         memcpy (&cmd.pio_data.pioc_starttls, tlsdata, sizeof (struct pioc_starttls));
545
546 #if TLSPOOL_CTLKEYLEN != 16
547 #  error "Failure on assumption of 16 bytes per ctlkey"
548 #endif
549
550         if (!renegotiate) {
551                 assert (pthread_mutex_lock (&prng_lock) == 0);
552 #if RAND_MAX >= 0xffffffff
553                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
554                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
555                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
556                 * (uint32_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
557 #elif RAND_MAX >= 0xffff
558                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
559                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
560                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
561                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
562                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
563                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
564                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
565                 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
566 #elif RAND_MAX >= 0xff
567                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
568                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 1] = random ();
569                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
570                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 3] = random ();
571                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
572                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 5] = random ();
573                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
574                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 7] = random ();
575                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
576                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 9] = random ();
577                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
578                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [11] = random ();
579                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
580                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [13] = random ();
581                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
582                 * (uint8_t *) &cmd.pio_data.pioc_starttls.ctlkey [15] = random ();
583 #else
584 #  error "Unsuitable random() function due to RAND_MAX value < 0xff"
585 #endif
586                 pthread_mutex_unlock (&prng_lock);
587         }
588 // printf ("DEBUG: ctlkey =");
589 // {int i; for (i=0;i<16;i++) printf (" %02x", cmd.pio_data.pioc_starttls.ctlkey [i]);}
590 // printf ("\n");
591
592         /* Send the request */
593         if (os_sendmsg_command(poolfd, &cmd, renegotiate ? -1 : cryptfd) == -1) {
594                 // Let SIGPIPE be reported as EPIPE
595                 close (cryptfd);
596                 registry_update (&entry_reqid, NULL);
597                 // errno inherited from os_sendmsg_command()
598                 return -1;
599         }
600         sentfd = cryptfd;  /* Close anytime after response and before fn end */
601
602         /* Handle responses until success or error */
603         processing = 1;
604         while (processing) {
605                 //NOTUSED// mh.msg_control = anc;
606                 //NOTUSED// mh.msg_controllen = sizeof (anc);
607                 registry_recvmsg (&regent);
608                 if (sentfd >= 0) {
609                         closesocket(sentfd);
610                 }
611                 sentfd = -1;
612                 switch (cmd.pio_cmd) {
613                 case PIOC_ERROR_V2:
614                         /* Bad luck, we failed */
615                         syslog (LOG_INFO, "TLS Pool error to tlspool_starttls(): %s", cmd.pio_data.pioc_error.message);
616                         registry_update (&entry_reqid, NULL);
617                         errno = cmd.pio_data.pioc_error.tlserrno;
618                         return -1;
619                 case PIOC_STARTTLS_LOCALID_V2:
620                 case PIOC_PLAINTEXT_CONNECT_V2:
621                         if (namedconnect) {
622                                 fprintf (stderr, "Callback to check local id or provide plaintext fd for localid=%s\n", cmd.pio_data.pioc_starttls.localid);
623                                 plainfd = (*namedconnect) (&cmd.pio_data.pioc_starttls, privdata);
624                         } else {
625                                 /* default namedconnect() implementation */
626                                 plainfd = * (int *) privdata;
627                                 if ((plainfd < 0) && (cmd.pio_cmd == PIOC_PLAINTEXT_CONNECT_V2)) {
628                                         plainfd = tlspool_namedconnect_default (&cmd.pio_data.pioc_starttls, privdata);
629                                 }
630                         }
631                         if (plainfd == -1) {
632                                 cmd.pio_cmd = PIOC_ERROR_V2;
633                                 cmd.pio_data.pioc_error.tlserrno = errno;
634                         }
635                         /* We may now have a value to send in plainfd */
636                         /* Now supply plainfd in the callback response */
637                         sentfd = plainfd;
638                         if (os_sendmsg_command(poolfd, &cmd, plainfd) == -1) {
639                                 // Let SIGPIPE be reported as EPIPE
640                                 if (sentfd >= 0) {
641                                         closesocket(sentfd);
642                                         sentfd = -1;
643                                 }
644                                 registry_update (&entry_reqid, NULL);
645                                 // errno inherited from np_send_command()
646                                 return -1;
647                         }
648                         break;  // Loop around and try again
649                 case PIOC_STARTTLS_V2:
650                         /* Wheee!!! we're done */
651                         processing = 0;
652                         break;
653                 default:
654                         /* V2 protocol error */
655                         registry_update (&entry_reqid, NULL);
656                         errno = EPROTO;
657                         return -1;
658                 }
659         }
660
661         /* Close the now-duplicated or now-erradicated plaintext fd */
662
663         memcpy (tlsdata, &cmd.pio_data.pioc_starttls, sizeof (struct pioc_starttls));
664 // 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]);
665         registry_update (&entry_reqid, NULL);
666         return 0;
667 }
668
669
670 /* The library function to send a control connection command, notably
671  * TLSPOOL_CONTROL_DETACH and TLSPOOL_CONTROL_REATTACH.
672  *
673  * This function returns zero on success, and -1 on failure.  In case of
674  * failure, errno will be set.
675  */
676 int _tlspool_control_command (int cmdcode, uint8_t *ctlkey) {
677         struct tlspool_command cmd;
678         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
679         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
680         int entry_reqid = -1;
681         int retval;
682
683         /* Prepare command structure */
684         poolfd = tlspool_open_poolhandle (NULL);
685         if (poolfd < 0) {
686                 errno = ENODEV;
687                 return -1;
688         }
689         /* Finish setting up the registry entry */
690         regent.pfd = poolfd;
691         pthread_mutex_lock (&recvwait);         // Will await unlock by master
692         /* Determine the request ID */
693         if (registry_update (&entry_reqid, &regent) != 0) {
694                 errno = EBUSY;
695                 return -1;
696         }
697         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
698         cmd.pio_reqid = entry_reqid;
699         cmd.pio_cbid = 0;
700         cmd.pio_cmd = cmdcode;
701         memcpy (&cmd.pio_data.pioc_control.ctlkey, ctlkey, TLSPOOL_CTLKEYLEN);
702 // 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]);
703         if (os_sendmsg_command (poolfd, &cmd, -1) == -1) {
704                 // Let SIGPIPE be reported as EPIPE
705                 registry_update (&entry_reqid, NULL);
706                 // errno inherited from os_sendmsg_command()
707                 return -1;
708         }
709         /* Receive the response */
710         registry_recvmsg (&regent);
711         switch (cmd.pio_cmd) {
712         case PIOC_SUCCESS_V2:
713                 retval = 0;
714                 break;
715         case PIOC_ERROR_V2:
716                 retval = -1;
717                 errno = cmd.pio_data.pioc_error.tlserrno;
718                 break;
719         default:
720                 errno = EPROTO;
721                 retval = -1;
722                 break;
723         }
724         return retval;
725 }
726
727 /* Generate a pseudo-random sequence based on session cryptographic keys.
728  *
729  * In the case of TLS, this adheres to RFC 5705; other protocols may or
730  * may not support a similar mechanism, in which case an error is returned.
731  *
732  * This leans on access privileges to an existing connection at a meta-level,
733  * for which we use the customary ctlkey verification mechanism introduced with
734  * tlspool_starttls ().  Note that random material may be used for security
735  * purposes, such as finding the same session key for both sides deriving from
736  * prior key negotiation; the protection of a ctlkey for such applications is
737  * important.
738  *
739  * The inputs to this function must adhere to the following restrictions:
740  *  - label must not be a NULL pointer, but opt_ctxvalue may be set to NULL
741  *    to bypass the use of a context value.  Note that passing an empty string
742  *    in opt_ctxvalue is different from not providing the string at all by
743  *    setting it to NULL.
744  *  - label  and  opt_ctxvalue  (if non-NULL) refer to ASCII strings with
745  *    printable characters, terminated with a NUL character.  The maximum
746  *    string length of each is 254 bytes.
747  *  - prng_len holds the requested number of pseudo-random bytes
748  *  - prng_buf points is a non-NULL pointer to a buffer that can hold
749  *    prng_len bytes.
750  *
751  * If the operation succeeds, then prng_buf holds prng_len bytes of random
752  * material, and zero is returned.  If the operation fails, then prng_buf
753  * is filled with zero bytes (to make it stand out as a rather rare case of
754  * a random byte string) and -1 is returned.
755  *
756  * Note a few restrictions to the generality of this function, as a result of
757  * the underlying packet format for the communication with the TLS Pool; but
758  * the dimensions have been choosen such that these restrictions would not
759  * typically be a problem in practice:
760  *  - it constrains the string lengths of label and opt_ctxvalue
761  *  - it constrains prng_len to a maximum value of TLSPOOL_PRNGBUFLEN
762  *
763  * The TLS Pool may limit certain TLS PRNG labels, in adherence to the
764  * IANA-maintained TLS Exporter Label Registry.  It additionally supports
765  * the EXPERIMENTAL label prefix specified in RFC 5705.
766  *
767  * Be advised that the maximum size of buffer may increase in future releases.
768  * So, be sure to use TLSPOOL_PRNGBUFLEN which holds the header-file defined
769  * size.
770  */
771 int tlspool_prng (char *label,
772                 uint16_t ctxvalue_len, uint8_t *opt_ctxvalue,
773                 uint16_t prng_len, uint8_t *prng_buf,
774                 uint8_t *ctlkey) {
775         struct tlspool_command cmd;
776         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
777         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
778         int entry_reqid = -1;
779         int poolfd = -1;
780         memset (prng_buf, 0, prng_len);
781
782         /* Sanity checks */
783         if ((prng_len > TLSPOOL_PRNGBUFLEN) ||
784                         (label == NULL) || (strlen (label) > 254) ||
785                         ((opt_ctxvalue != NULL) &&
786                                 ((ctxvalue_len > 254) ||
787                                         (strlen (label) + ctxvalue_len > TLSPOOL_PRNGBUFLEN - TLSPOOL_CTLKEYLEN)))) {
788                 errno = EINVAL;
789                 return -1;
790         }
791
792         /* Prepare command structure */
793         poolfd = tlspool_open_poolhandle (NULL);
794         if (poolfd < 0) {
795                 errno = ENODEV;
796                 return -1;
797         }
798         /* Finish setting up the registry entry */
799         regent.pfd = poolfd;
800         pthread_mutex_lock (&recvwait);         // Will await unlock by master
801         /* Determine the request ID */
802         if (registry_update (&entry_reqid, &regent) != 0) {
803                 errno = EBUSY;
804                 return -1;
805         }
806         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
807         cmd.pio_reqid = entry_reqid;
808         cmd.pio_cbid = 0;
809         cmd.pio_cmd = PIOC_PRNG_V2;
810         cmd.pio_data.pioc_prng.prng_len = prng_len;
811         memcpy (cmd.pio_data.pioc_prng.buffer, ctlkey, TLSPOOL_CTLKEYLEN);
812         cmd.pio_data.pioc_prng.in1_len = strlen (label);
813         memcpy (cmd.pio_data.pioc_prng.buffer + TLSPOOL_CTLKEYLEN, label, cmd.pio_data.pioc_prng.in1_len);
814         if (opt_ctxvalue != NULL) {
815                 cmd.pio_data.pioc_prng.in2_len = ctxvalue_len;
816                 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);
817         } else {
818                 cmd.pio_data.pioc_prng.in2_len = -1;
819         }
820         if (os_sendmsg_command (poolfd, &cmd, -1) == -1) {
821                 // Let SIGPIPE be reported as EPIPE
822                 registry_update (&entry_reqid, NULL);
823                 // errno inherited from sendmsg()
824                 return -1;
825         }
826         /* Await response and process it */
827         registry_recvmsg (&regent);
828         registry_update (&entry_reqid, NULL);
829         switch (cmd.pio_cmd) {
830         case PIOC_ERROR_V2:
831                 /* Bad luck, we failed */
832                 syslog (LOG_INFO, "TLS Pool error to tlspool_prng(): %s", cmd.pio_data.pioc_error.message);
833                 errno = cmd.pio_data.pioc_error.tlserrno;
834                 return -1;
835         case PIOC_PRNG_V2:
836                 /* Wheee!!! we're done */
837                 memcpy (prng_buf, cmd.pio_data.pioc_prng.buffer, prng_len);
838                 return 0;
839         default:
840                 /* V2 protocol error */
841                 errno = EPROTO;
842                 return -1;
843         }
844 }
845
846 /* Check or retrieve information from the TLS Pool.  Use kind_info to select
847  * the kind of information, with a PIOK_INFO_xxx tag from <tlspool/commands.h>.
848  *
849  * The amount of data will not exceed TLSPOOL_INFOBUFLEN, and you should
850  * provide a buffer that can hold at least that number of bytes.  In addition,
851  * you should provide a pointer to a length.  Initialise this length to ~0
852  * to perform a query.  Any other length indicates a match, including the
853  * value 0 for a match with an empty string.
854  *
855  * You should provide the ctlkey from the tlspool_starttls() exchange to
856  * be able to reference the connection that you intend to query.
857  *
858  * This function returns zero on success, and -1 on failure.  In case of
859  * failure, errno will be set.  Specifically useful to know is that errno
860  * is set to E_TLSPOOL_INFOKIND_UNKNOWN when the TLS Pool has no code to
861  * provide the requested information (and so its current version will not
862  * provide it to any query) and to E_TLSPOOL_INFO_NOT_FOUND when the
863  * TLS Pool cannot answer the info query for other reasons, such as not
864  * having the information available in the current connection.
865  * 
866  * The error ENOSYS is returned when the TLS Pool has no implementation
867  * for the query you made.
868  */
869 int tlspool_info (uint32_t info_kind,
870                         uint8_t infobuf [TLSPOOL_INFOBUFLEN], uint16_t *infolenptr,
871                         uint8_t *ctlkey) {
872         struct tlspool_command cmd;
873         pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
874         struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
875         int entry_reqid = -1;
876         int poolfd = -1;
877         /* Sanity check */
878         if ((*infolenptr > TLSPOOL_INFOBUFLEN) && (*infolenptr != 0xffff)) {
879                 errno = EINVAL;
880                 return -1;
881         }
882         /* Prepare command structure */
883         poolfd = tlspool_open_poolhandle (NULL);
884         if (poolfd < 0) {
885                 errno = ENODEV;
886                 return -1;
887         }
888         /* Finish setting up the registry entry */
889         regent.pfd = poolfd;
890         pthread_mutex_lock (&recvwait);         // Will await unlock by master
891         /* Determine the request ID */
892         if (registry_update (&entry_reqid, &regent) != 0) {
893                 errno = EBUSY;
894                 return -1;
895         }
896         /* Construct the command message */
897         memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
898         cmd.pio_reqid = entry_reqid;
899         cmd.pio_cbid = 0;
900         cmd.pio_cmd = PIOC_INFO_V2;
901         cmd.pio_data.pioc_info.info_kind = info_kind;
902         cmd.pio_data.pioc_info.len = *infolenptr;
903         memcpy (cmd.pio_data.pioc_info.ctlkey, ctlkey, TLSPOOL_CTLKEYLEN);
904         if ((*infolenptr > 0) && (*infolenptr < TLSPOOL_INFOBUFLEN)) {
905                 memcpy (cmd.pio_data.pioc_info.buffer, infobuf, *infolenptr);
906         }
907         /* Send the command message */
908         if (os_sendmsg_command (poolfd, &cmd, -1) == -1) {
909                 // Let SIGPIPE be reported as EPIPE
910                 registry_update (&entry_reqid, NULL);
911                 // errno inherited from sendmsg()
912                 return -1;
913         }
914         /* Await response and process it */
915         registry_recvmsg (&regent);
916         registry_update (&entry_reqid, NULL);
917         switch (cmd.pio_cmd) {
918         case PIOC_ERROR_V2:
919                 /* Bad luck, we failed */
920                 syslog (LOG_INFO, "TLS Pool error to tlspool_info(): %s", cmd.pio_data.pioc_error.message);
921                 errno = cmd.pio_data.pioc_error.tlserrno;
922                 return -1;
923         case PIOC_INFO_V2:
924                 /* Wheee!!! we're done */
925                 *infolenptr = cmd.pio_data.pioc_info.len;
926                 if ((*infolenptr > 0) && (*infolenptr < TLSPOOL_INFOBUFLEN)) {
927                         memcpy (infobuf, cmd.pio_data.pioc_info.buffer, *infolenptr);
928                 }
929                 return 0;
930         default:
931                 /* V2 protocol error */
932                 errno = EPROTO;
933                 return -1;
934         }
935 }
936