1 /* tlspool/libtlspool.c -- Library function for starttls go-get-it */
19 #include <tlspool/starttls.h>
20 #include <tlspool/commands.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/select.h>
29 #include <sys/resource.h>
32 #if !defined(WINDOWS_PORT)
33 #define closesocket(s) close(s)
37 #define PIPE_TIMEOUT 5000
42 #define _tprintf printf
43 #endif /* WINDOWS_PORT */
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.
50 static pthread_mutex_t have_master_lock = PTHREAD_MUTEX_INITIALIZER;
52 static void *master_thread (void *path);
54 static pool_handle_t poolfd = INVALID_POOL_HANDLE; /* Blocked retrieval with tlspool_socket() */
56 static pthread_cond_t updated_poolfd = PTHREAD_COND_INITIALIZER;
58 static pthread_mutex_t prng_lock = PTHREAD_MUTEX_INITIALIZER;
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.
64 int tlspool_pid (char *opt_pidfile) {
71 if (opt_pidfile == NULL) {
72 opt_pidfile = tlspool_configvar (NULL, "daemon_pidfile");
74 if (opt_pidfile == NULL) {
75 opt_pidfile = TLSPOOL_DEFAULT_PIDFILE_PATH;
77 assert (opt_pidfile != NULL);
78 fd = open (opt_pidfile, O_RDONLY);
80 len = read (fd, str_pid, sizeof (str_pid) -1);
82 if ((len > 0) && (len < sizeof (str_pid))) {
84 pid = strtoul (str_pid, &endptr, 10);
85 while ((endptr != NULL) && (isspace (*endptr))) {
88 if ((pid >= 0) && (pid <= INT_MAX) && (!*endptr)) {
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.
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.
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;
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) {
115 path = tlspool_configvar (NULL, "socket_name");
118 path = TLSPOOL_DEFAULT_SOCKET_PATH;
120 assert (path != NULL);
121 fprintf (stderr, "DEBUG: Opening TLS Pool on socket path %s\n", path);
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");
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;
135 pthread_detach (thr);
137 // We need enough randomness to avoid clashing ctlkeys
139 seed = ((unsigned int) time (NULL)) ^ (((unsigned int) me) << 16);
143 // Wait until the master thread signals that it updated the
144 // poolfd, as long as it is invalid.
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);
156 pthread_mutex_unlock (&local_cond_wait);
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.
166 int tlspool_simultaneous_starttls(void) {
169 #else /* WINDOWS_PORT */
170 static int simu = -1;
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
177 simu = rlimit_nofile.rlim_max / 2; // 2 FDs per STARTTLS
180 #endif /* WINDOWS_PORT */
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.
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 */
196 static struct registry_entry **registry;
198 static pthread_mutex_t registry_lock = PTHREAD_MUTEX_INITIALIZER;
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
207 * The return value is 0 on success, or -1 on failure; the most probable
208 * cause for failure is
210 static int registry_update (int *reqid, struct registry_entry *entry) {
211 static int simu = -1;
212 static uint16_t pos = 0;
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");
223 /* Set the entry in the given entry */
225 /* Allocate an entry in the registry */
226 assert (pthread_mutex_lock (®istry_lock) == 0);
229 if (registry [pos] == NULL) {
230 registry [pos] = entry;
239 pthread_mutex_unlock (®istry_lock);
245 if ((*reqid < 0) || (*reqid >= simu)) {
248 /* Remove the entry from the given entry */
249 assert (pthread_mutex_lock (®istry_lock) == 0);
250 registry [*reqid] = NULL; /* may not be atomic */
252 pthread_mutex_unlock (®istry_lock);
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
263 static void registry_flush (pool_handle_t poolfd) {
264 int regid = tlspool_simultaneous_starttls ();
265 assert (pthread_mutex_lock (®istry_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
280 pthread_mutex_unlock (®istry_lock);
284 static pool_handle_t open_named_pipe (LPCTSTR lpszPipename)
287 //struct tlspool_command chBuf;
288 BOOL fSuccess = FALSE;
291 // Try to open a named pipe; wait for it, if necessary.
296 lpszPipename, // pipe name
297 GENERIC_READ | // read and write access
300 NULL, // default security attributes
301 OPEN_EXISTING, // opens existing pipe
302 FILE_FLAG_OVERLAPPED, // overlapped
303 NULL); // no template file
305 // Break if the pipe handle is valid.
306 if (hPipe != INVALID_POOL_HANDLE)
309 // Exit if an error other than ERROR_PIPE_BUSY occurs.
310 if (GetLastError() != ERROR_PIPE_BUSY)
312 _tprintf(TEXT("Could not open pipe. GLE=%d\n"), GetLastError());
313 return INVALID_POOL_HANDLE;
316 // All pipe instances are busy, so wait for 20 seconds.
317 if (!WaitNamedPipe(lpszPipename, 20000))
319 printf("Could not open pipe: 20 second wait timed out.");
320 return INVALID_POOL_HANDLE;
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
332 _tprintf(TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError());
333 return INVALID_POOL_HANDLE;
335 ULONG ServerProcessId;
336 if (GetNamedPipeServerProcessId(hPipe, &ServerProcessId)) {
337 printf("GetNamedPipeServerProcessId: ServerProcessId = %ld\n", ServerProcessId);
339 _tprintf(TEXT("GetNamedPipeServerProcessId failed. GLE=%d\n"), GetLastError());
344 static int np_send_command(struct tlspool_command *cmd) {
345 DWORD cbToWrite, cbWritten;
346 OVERLAPPED overlapped;
349 /* Send the request */
350 // Send a message to the pipe server.
352 cbToWrite = sizeof (struct tlspool_command);
353 _tprintf(TEXT("Sending %d byte cmd\n"), cbToWrite);
355 memset(&overlapped, 0, sizeof(overlapped));
356 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
358 fSuccess = WriteFile(
359 poolfd, // pipe handle
361 cbToWrite, // cmd message length
362 NULL, // bytes written
363 &overlapped); // overlapped
365 if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
367 // printf ("DEBUG: Write I/O pending\n");
368 fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
372 fSuccess = GetOverlappedResult(poolfd, &overlapped, &cbWritten, TRUE);
377 _tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
381 // printf ("DEBUG: Wrote %ld bytes to pipe\n", cbWritten);
383 // printf("DEBUG: Message sent to server, receiving reply as follows:\n");
386 #endif /* WINDOWS_PORT */
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.
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.
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.
404 static void *master_thread (void *path) {
407 struct sockaddr_un sun;
408 //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
410 struct cmsghdr *cmsg;
411 struct msghdr mh = { 0 };
415 struct tlspool_command cmd;
416 //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
417 struct registry_entry *entry;
419 BOOL fSuccess = FALSE;
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;
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);
445 // First, connect to the TLS Pool; upon failure, retry
446 // with 1s, 2s, 4s, 8s, 16s, 32s, 32s, 32s, ... intervals.
448 while (poolfd == INVALID_POOL_HANDLE) {
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) {
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");
463 tlspool_close_poolhandle (newpoolfd);
464 newpoolfd = INVALID_POOL_HANDLE;
467 // printf ("DEBUG: Trying new poolfd %d for path %s\n", poolfd, sun.sun_path);
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);
481 // Wait before repeating, with exponential back-off
482 if (poolfd == INVALID_POOL_HANDLE) {
489 if (usec > 32000000) {
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.
502 OVERLAPPED overlapped;
504 memset(&overlapped, 0, sizeof(overlapped));
505 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
507 // Read from the pipe.
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
515 if (!fSuccess && GetLastError() == ERROR_IO_PENDING )
517 // printf ("DEBUG: Read I/O pending\n");
518 fSuccess = WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0;
522 fSuccess = GetOverlappedResult(poolfd, &overlapped, &cbRead, TRUE);
527 _tprintf(TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError());
530 // printf ("DEBUG: Read %ld bytes from pipe\n", cbRead);
534 iov.iov_len = sizeof (cmd);
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
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));
553 #endif /* WINDOWS_PORT */
555 // Determine where to post the received message
556 entry = registry [cmd.pio_reqid];
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));
568 np_send_command (&cmd);
570 sendmsg (poolfd, &mh, MSG_NOSIGNAL);
573 // printf ("DEBUG: Sent PIOC_ERROR_V2 as callback to TLS Pool\n");
575 // Do not attempt delivery
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);
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");
591 /* Consider handling the message reception interface, if no other thread is
592 * doing that yet. Then, wait until a message has been received.
594 static void registry_recvmsg (struct registry_entry *entry) {
595 static pool_handle_t lastpoolfd = INVALID_POOL_HANDLE;
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);
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);
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.
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.
629 * This function returns zero on success, and -1 on failure. In case of
630 * failure, errno will be set.
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;
639 /* Prepare command structure */
640 poolfd = tlspool_open_poolhandle (NULL);
641 // printf ("DEBUG: poolfd = %d\n", poolfd);
642 if (poolfd == INVALID_POOL_HANDLE) {
646 /* Finish setting up the registry entry */
648 pthread_mutex_lock (&recvwait); // Will await unlock by master
649 /* Determine the request ID */
650 if (registry_update (&entry_reqid, ®ent) != 0) {
654 memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
655 cmd.pio_reqid = entry_reqid;
657 cmd.pio_cmd = PIOC_PING_V2;
658 memcpy (&cmd.pio_data.pioc_ping, pingdata, sizeof (struct pioc_ping));
660 if (np_send_command (&cmd) == -1) {
661 // errno inherited from np_send_command ()
662 registry_update (&entry_reqid, NULL);
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()
674 /* Await response and process it */
675 registry_recvmsg (®ent);
676 registry_update (&entry_reqid, NULL);
677 switch (cmd.pio_cmd) {
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;
684 /* Wheee!!! we're done */
685 memcpy (pingdata, &cmd.pio_data.pioc_ping, sizeof (pingpool_t));
688 /* V2 protocol error */
694 #if defined(WINDOWS_PORT)
695 static int socket_dup_protocol_info(int fd, int pid, LPWSAPROTOCOL_INFOW lpProtocolInfo)
697 if (WSADuplicateSocketW((SOCKET)fd, pid, lpProtocolInfo) == SOCKET_ERROR) {
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.
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.
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.
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.
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.
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.
745 * This function returns zero on success, and -1 on failure. In case of
746 * failure, errno will be set.
748 int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
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;
760 struct cmsghdr *cmsg;
761 struct msghdr mh = { 0 };
762 char anc[CMSG_SPACE(sizeof(int))];
765 int renegotiate = 0 != (tlsdata->flags & PIOF_STARTTLS_RENEGOTIATE);
767 /* Prepare command structure */
768 poolfd = tlspool_open_poolhandle (NULL);
769 if (poolfd == INVALID_POOL_HANDLE) {
770 closesocket(cryptfd);
774 /* Finish setting up the registry entry */
776 pthread_mutex_lock (&recvwait); // Will await unlock by master
777 /* Determine the request ID */
778 if (registry_update (&entry_reqid, ®ent) != 0) {
779 closesocket(cryptfd);
783 memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
784 cmd.pio_reqid = entry_reqid;
786 cmd.pio_cmd = PIOC_STARTTLS_V2;
787 memcpy (&cmd.pio_data.pioc_starttls, tlsdata, sizeof (struct pioc_starttls));
789 #if TLSPOOL_CTLKEYLEN != 16
790 # error "Failure on assumption of 16 bytes per ctlkey"
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 ();
827 # error "Unsuitable random() function due to RAND_MAX value < 0xff"
829 pthread_mutex_unlock (&prng_lock);
831 // printf ("DEBUG: ctlkey =");
832 // {int i; for (i=0;i<16;i++) printf (" %02x", cmd.pio_data.pioc_starttls.ctlkey [i]);}
835 /* Send the request */
838 iov.iov_len = sizeof(cmd);
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)*/) {
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()
868 //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
870 // Send a file handle
871 cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
872 //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
874 #endif /* WINDOWS_PORT */
877 if (np_send_command (&cmd) == -1) {
879 registry_update (&entry_reqid, NULL);
880 // errno inherited from np_send_command ()
884 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
885 // Let SIGPIPE be reported as EPIPE
887 registry_update (&entry_reqid, NULL);
888 // errno inherited from sendmsg()
891 #endif /* WINDOWS_PORT */
892 sentfd = cryptfd; /* Close anytime after response and before fn end */
894 /* Handle responses until success or error */
897 //NOTUSED// mh.msg_control = anc;
898 //NOTUSED// mh.msg_controllen = sizeof (anc);
899 registry_recvmsg (®ent);
904 switch (cmd.pio_cmd) {
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;
911 case PIOC_STARTTLS_LOCALID_V2:
912 case PIOC_PLAINTEXT_CONNECT_V2:
914 plainfd = (*namedconnect) (tlsdata, privdata);
916 /* default namedconnect() implementation */
917 plainfd = * (int *) privdata;
918 if ((plainfd < 0) && (cmd.pio_cmd == PIOC_PLAINTEXT_CONNECT_V2)) {
919 #if !defined(WINDOWS_PORT)
922 // https://github.com/ncm/selectable-socketpair
923 extern int dumb_socketpair(SOCKET socks[2], int make_overlapped);
926 //TODO// Setup for TCP, UDP, SCTP
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 */
935 * (int *) privdata = soxx [1];
937 /* Socketpair failed */
938 // printf("DEBUG: socketpair failed\n");
939 cmd.pio_cmd = PIOC_ERROR_V2;
940 cmd.pio_data.pioc_error.tlserrno = errno;
945 /* We may now have a value to send in plainfd */
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)*/) {
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()
971 //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
973 // Send a file handle
974 cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
975 //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
977 #endif /* WINDOWS_PORT */
980 /* Now supply plainfd in the callback response */
983 if (np_send_command (&cmd) == -1) {
988 registry_update (&entry_reqid, NULL);
989 // errno inherited from np_send_command()
993 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
994 // Let SIGPIPE be reported as EPIPE
999 registry_update (&entry_reqid, NULL);
1000 // errno inherited from sendmsg()
1003 #endif /* WINDOWS_PORT */
1004 break; // Loop around and try again
1005 case PIOC_STARTTLS_V2:
1006 /* Wheee!!! we're done */
1010 /* V2 protocol error */
1011 registry_update (&entry_reqid, NULL);
1017 /* Close the now-duplicated or now-erradicated plaintext fd */
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);
1026 /* The library function to send a control connection command, notably
1027 * TLSPOOL_CONTROL_DETACH and TLSPOOL_CONTROL_REATTACH.
1029 * This function returns zero on success, and -1 on failure. In case of
1030 * failure, errno will be set.
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;
1039 /* Prepare command structure */
1040 poolfd = tlspool_open_poolhandle (NULL);
1041 if (poolfd == INVALID_POOL_HANDLE) {
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, ®ent) != 0) {
1053 memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
1054 cmd.pio_reqid = entry_reqid;
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]);
1061 if (np_send_command (&cmd) == -1) {
1062 registry_update (&entry_reqid, NULL);
1063 // errno inherited from np_send_command ()
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()
1075 /* Receive the response */
1076 registry_recvmsg (®ent);
1077 switch (cmd.pio_cmd) {
1078 case PIOC_SUCCESS_V2:
1083 errno = cmd.pio_data.pioc_error.tlserrno;
1093 /* Generate a pseudo-random sequence based on session cryptographic keys.
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.
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
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
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.
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
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.
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
1137 int tlspool_prng (char *label, char *opt_ctxvalue,
1138 uint16_t prng_len, uint8_t *prng_buf,
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);
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)))) {
1158 /* Prepare command structure */
1159 poolfd = tlspool_open_poolhandle (NULL);
1160 if (poolfd == INVALID_POOL_HANDLE) {
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, ®ent) != 0) {
1172 memset (&cmd, 0, sizeof (cmd)); /* Do not leak old stack info */
1173 cmd.pio_reqid = entry_reqid;
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);
1184 cmd.pio_data.pioc_prng.in2_len = -1;
1188 if (np_send_command (&cmd) == -1) {
1189 // errno inherited from np_send_command ()
1190 registry_update (&entry_reqid, NULL);
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()
1202 /* Await response and process it */
1203 registry_recvmsg (®ent);
1204 registry_update (&entry_reqid, NULL);
1205 switch (cmd.pio_cmd) {
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;
1212 /* Wheee!!! we're done */
1213 memcpy (prng_buf, cmd.pio_data.pioc_prng.buffer, prng_len);
1216 /* V2 protocol error */
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().
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>.
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.
1235 char *tlspool_configvar (char *cfgfile, char *varname) {
1241 struct cfgopt *curopt;
1243 char *retval = NULL;
1245 if (cfgfile == NULL) {
1246 cfgfile = getenv ("TLSPOOL_CFGFILE");
1248 if (cfgfile == NULL) {
1249 cfgfile = TLSPOOL_DEFAULT_CONFIG_PATH;
1252 assert (cfgfile != NULL);
1253 assert (varname != NULL);
1255 cf = fopen (cfgfile, "r");
1257 perror ("Failed to open configuration file");
1262 if (!fgets (line, sizeof (line)-1, cf)) {
1267 perror ("Error while reading configuration file");
1271 linelen = strlen (line);
1276 if (line [linelen-1] == (char) EOF) {
1280 if (line [linelen-1] != '\n') {
1281 fprintf (stderr, "Configuration line too long\n");
1284 line [--linelen] = 0;
1288 if (line [0] == '#') {
1292 while ((*here) && isspace (*here)) {
1299 fprintf (stderr, "Configuration line starts with whitespace:\n%s\n", line);
1302 while ((*here) && (*here != ' ')) {
1306 fprintf (stderr, "Configuration line misses space after keyword:\n%s\n", line);
1310 if (strcmp (varname, line) == 0) {
1311 // Success! We set the return value and end the loop