1 /*=============================================================================
2                                  socket_openssl.c
3 ===============================================================================
4   This is the implementation of TChanSwitch and TChannel
5   for an SSL (Secure Sockets Layer) connection based on an OpenSSL
6   connection object -- what you create with SSL_new().
7 =============================================================================*/
8 
9 #include "xmlrpc_config.h"
10 
11 #include <stdlib.h>
12 #include <assert.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <sys/socket.h>
18 #include <sys/time.h>
19 #include <netinet/in.h>
20 #include <netinet/tcp.h>
21 #include <netdb.h>
22 #include <arpa/inet.h>
23 #include <errno.h>
24 
25 #include <openssl/ssl.h>
26 #include <openssl/err.h>
27 #include <openssl/rand.h>
28 
29 #include "xmlrpc-c/util_int.h"
30 #include "xmlrpc-c/string_int.h"
31 #include "bool.h"
32 #include "mallocvar.h"
33 #include "trace.h"
34 #include "chanswitch.h"
35 #include "channel.h"
36 #include "socket.h"
37 #include "xmlrpc-c/abyss.h"
38 #include "xmlrpc-c/abyss_openssl.h"
39 
40 #include "sockutil.h"
41 #include "socket_openssl.h"
42 
43 
44 
45 /* We've seen Openssl from the year 2002 not have SSL_ERROR_WANT_ACCEPT.
46    In 2016, it is defined as a macro.
47 */
48 #ifdef SSL_ERROR_WANT_ACCEPT
49 #define HAVE_SSL_ERROR_WANT_ACCEPT 1
50 #else
51 #define HAVE_SSL_ERROR_WANT_ACCEPT 0
52 #endif
53 
54 
55 
56 static const char *
sslErrorMsg(void)57 sslErrorMsg(void) {
58 /*----------------------------------------------------------------------------
59    The information on the OpenSSL error stack, in human-readable (barely)
60    form.
61 -----------------------------------------------------------------------------*/
62     const char * retval;
63     bool eof;
64 
65     retval = xmlrpc_strdupsol("");
66 
67     for (eof = false; !eof; ) {
68         const char * sourceFileName;
69         int lineNum;
70 
71         int const errCode = ERR_get_error_line(&sourceFileName, &lineNum);
72 
73         if (errCode == 0)
74             eof = true;
75         else {
76             const char * newRetval;
77 
78             xmlrpc_asprintf(&newRetval, "%s %s (%s:%d); ",
79                             retval, ERR_error_string(errCode, NULL),
80                             sourceFileName, lineNum);
81 
82             xmlrpc_strfree(retval);
83 
84             retval = newRetval;
85         }
86     }
87     return retval;
88 }
89 
90 
91 
92 static const char *
sslResultMsg(int const resultCode)93 sslResultMsg(int const resultCode) {
94 /*----------------------------------------------------------------------------
95    English description of a result code such as OpenSSL's SSL_get_error
96    returns.
97 -----------------------------------------------------------------------------*/
98     switch (resultCode) {
99     case SSL_ERROR_NONE:             return "None";
100     case SSL_ERROR_SSL:              return "SSL";
101     case SSL_ERROR_WANT_READ:        return "Want Read";
102     case SSL_ERROR_WANT_WRITE:       return "Want Write";
103     case SSL_ERROR_WANT_X509_LOOKUP: return "Want X509_LOOKUP";
104     case SSL_ERROR_SYSCALL:          return "Syscall";
105     case SSL_ERROR_ZERO_RETURN:      return "Zero Return";
106     case SSL_ERROR_WANT_CONNECT:     return "Want Connect";
107 #if HAVE_SSL_ERROR_WANT_ACCEPT
108     case SSL_ERROR_WANT_ACCEPT:      return "Want Accept";
109 #endif
110     default:                         return "???";
111     }
112 }
113 
114 
115 
116 static void
sslCreate(SSL_CTX * const sslCtxP,SSL ** const sslPP,const char ** const errorP)117 sslCreate(SSL_CTX *     const sslCtxP,
118           SSL **        const sslPP,
119           const char ** const errorP) {
120 
121     *sslPP = SSL_new(sslCtxP);
122 
123     if (!*sslPP) {
124         const char * const sslMsg = sslErrorMsg();
125 
126         xmlrpc_asprintf(errorP, "Failed to create SSL connection "
127                         "object.  SSL_new() failed.  %s", sslMsg);
128         xmlrpc_strfree(sslMsg);
129     } else
130         *errorP = NULL;
131 }
132 
133 
134 
135 static void
sslSetFd(SSL * const sslP,int const acceptedFd,const char ** const errorP)136 sslSetFd(SSL *         const sslP,
137          int           const acceptedFd,
138          const char ** const errorP) {
139 
140     int succeeded;
141 
142     succeeded = SSL_set_fd(sslP, acceptedFd);
143 
144     if (!succeeded) {
145         const char * sslMsg;
146 
147         sslMsg = sslErrorMsg();
148 
149         xmlrpc_asprintf(errorP, "SSL_set_fd(%d) failed.  %s",
150                         acceptedFd, sslMsg);
151 
152         xmlrpc_strfree(sslMsg);
153     } else
154         *errorP = NULL;
155 }
156 
157 
158 
159 static void
traceCipherList(SSL * const sslP)160 traceCipherList(SSL * const sslP) {
161 
162     int priority;
163     bool eof;
164 
165     fprintf(stderr, "SSL object will consider using the following "
166             "ciphers in priority order, if conditions are right to use "
167             "them and the client agrees: ");
168 
169     for (priority = 0, eof = false; !eof; ++priority) {
170         const char * const cipherName = SSL_get_cipher_list(sslP, priority);
171 
172         if (cipherName)
173             fprintf(stderr, "%s ", cipherName);
174         else
175             eof = true;
176     }
177     fprintf(stderr, "\n");
178 }
179 
180 
181 
182 static void
sslAccept(SSL * const sslP,const char ** const errorP)183 sslAccept(SSL *         const sslP,
184           const char ** const errorP) {
185 
186     int rc;
187 
188     if (SwitchTraceIsActive)
189         traceCipherList(sslP);
190 
191     rc = SSL_accept(sslP);
192 
193     if (rc == 1)
194         *errorP = NULL;
195     else {
196         int const resultCode = SSL_get_error(sslP, rc);
197 
198         const char * const errorStack = sslErrorMsg();
199 
200         xmlrpc_asprintf(errorP, "SSL_accept() failed.  rc=%d/%d: %s.  "
201                         "OpenSSL error stack: %s\n",
202                         rc, resultCode, sslResultMsg(resultCode), errorStack);
203 
204         xmlrpc_strfree(errorStack);
205     }
206 }
207 
208 
209 
210 struct ChannelOpenSsl {
211 /*----------------------------------------------------------------------------
212    The properties/state of a TChannel unique to the OpenSSL variety.
213 -----------------------------------------------------------------------------*/
214     int fd;
215         /* File descriptor of the TCP connection underlying the SSL connection
216         */
217     SSL * sslP;
218         /* SSL connection handle */
219     bool userSuppliedSsl;
220         /* The SSL connection belongs to the user; we did not create it. */
221 };
222 
223 
224 
225 void
SocketOpenSslInit(const char ** const errorP)226 SocketOpenSslInit(const char ** const errorP) {
227 
228 	SSL_load_error_strings();
229         /* readable error messages, don't call this if memory is tight */
230 	SSL_library_init();   /* initialize library */
231 
232 	*errorP = NULL;
233 }
234 
235 
236 
237 void
SocketOpenSslTerm(void)238 SocketOpenSslTerm(void) {
239 
240 	ERR_free_strings();
241 
242 }
243 
244 
245 
246 /*=============================================================================
247       TChannel
248 =============================================================================*/
249 
250 static ChannelDestroyImpl channelDestroy;
251 
252 static void
channelDestroy(TChannel * const channelP)253 channelDestroy(TChannel * const channelP) {
254 
255     struct ChannelOpenSsl * const channelOpenSslP = channelP->implP;
256 
257     if (!channelOpenSslP->userSuppliedSsl)
258         SSL_shutdown(channelOpenSslP->sslP);
259 
260     free(channelOpenSslP);
261 }
262 
263 
264 
265 static ChannelWriteImpl channelWrite;
266 
267 static void
channelWrite(TChannel * const channelP,const unsigned char * const buffer,uint32_t const len,bool * const failedP)268 channelWrite(TChannel *            const channelP,
269              const unsigned char * const buffer,
270              uint32_t              const len,
271              bool *                const failedP) {
272 
273     struct ChannelOpenSsl * const channelOpenSslP = channelP->implP;
274 
275     unsigned int bytesLeft;
276     bool error;
277 
278     assert(sizeof(int) >= sizeof(len));
279 
280     for (bytesLeft = len, error = false; bytesLeft > 0 && !error; ) {
281         uint32_t const maxSend = (uint32_t)(-1) >> 1;
282 
283         int rc;
284 
285         rc = SSL_write(channelOpenSslP->sslP, &buffer[len-bytesLeft],
286                        MIN(maxSend, bytesLeft));
287 
288         if (ChannelTraceIsActive) {
289             if (rc <= 0)
290                 fprintf(stderr,
291                         "Abyss socket: SSL_write() failed.  rc=%d/%d",
292                         rc, SSL_get_error(channelOpenSslP->sslP, rc));
293             else
294                 fprintf(stderr, "Abyss socket: sent %u bytes: '%.*s'\n",
295                         rc, rc, &buffer[len-bytesLeft]);
296         }
297         if (rc <= 0)
298             /* 0 means connection closed; < 0 means severe error */
299             error = true;
300         else
301             bytesLeft -= rc;
302     }
303     *failedP = error;
304 }
305 
306 
307 
308 static ChannelReadImpl channelRead;
309 
310 static void
channelRead(TChannel * const channelP,unsigned char * const buffer,uint32_t const bufferSize,uint32_t * const bytesReceivedP,bool * const failedP)311 channelRead(TChannel *      const channelP,
312             unsigned char * const buffer,
313             uint32_t        const bufferSize,
314             uint32_t *      const bytesReceivedP,
315             bool *          const failedP) {
316 
317     struct ChannelOpenSsl * const channelOpenSslP = channelP->implP;
318 
319     int rc;
320     rc = SSL_read(channelOpenSslP->sslP, buffer, bufferSize);
321 
322     if (rc < 0) {
323         *failedP = true;
324         if (ChannelTraceIsActive)
325             fprintf(stderr, "Failed to receive data from OpenSSL connection.  "
326                     "SSL_read() failed with rc %d/%d\n",
327                     rc, SSL_get_error(channelOpenSslP->sslP, rc));
328     } else {
329         *failedP = false;
330         *bytesReceivedP = rc;
331 
332         if (ChannelTraceIsActive)
333             fprintf(stderr, "Abyss channel: read %u bytes: '%.*s'\n",
334                     *bytesReceivedP, (int)(*bytesReceivedP), buffer);
335     }
336 }
337 
338 
339 
340 static ChannelWaitImpl channelWait;
341 
342 static void
channelWait(TChannel * const channelP ATTR_UNUSED,bool const waitForRead ATTR_UNUSED,bool const waitForWrite ATTR_UNUSED,uint32_t const timeoutMs ATTR_UNUSED,bool * const readyToReadP,bool * const readyToWriteP,bool * const failedP)343 channelWait(TChannel * const channelP ATTR_UNUSED,
344             bool       const waitForRead ATTR_UNUSED,
345             bool       const waitForWrite ATTR_UNUSED,
346             uint32_t   const timeoutMs ATTR_UNUSED,
347             bool *     const readyToReadP,
348             bool *     const readyToWriteP,
349             bool *     const failedP) {
350 /*----------------------------------------------------------------------------
351   See socket_unix.c for an explanation of the purpose of this
352   subroutine.
353 
354   We don't actually fulfill that purpose, though, because we don't know
355   how yet.  Instead, we return immediately and hope that if Caller
356   subsequently does a read or write, it blocks until it can do its thing.
357 -----------------------------------------------------------------------------*/
358     if (readyToReadP)
359         *readyToReadP = true;
360     if (readyToWriteP)
361         *readyToWriteP = true;
362     if (failedP)
363         *failedP = false;
364 }
365 
366 
367 
368 static ChannelInterruptImpl channelInterrupt;
369 
370 static void
channelInterrupt(TChannel * const channelP ATTR_UNUSED)371 channelInterrupt(TChannel * const channelP ATTR_UNUSED) {
372 /*----------------------------------------------------------------------------
373   Interrupt any waiting that a thread might be doing in channelWait()
374   now or in the future.
375 -----------------------------------------------------------------------------*/
376 
377     /* This is trivial, since channelWait() doesn't actually wait */
378 }
379 
380 
381 
382 static ChannelFormatPeerInfoImpl channelFormatPeerInfo;
383 
384 static void
channelFormatPeerInfo(TChannel * const channelP,const char ** const peerStringP)385 channelFormatPeerInfo(TChannel *    const channelP,
386                       const char ** const peerStringP) {
387 
388     struct ChannelOpenSsl * const channelOpenSslP = channelP->implP;
389 
390     sockutil_formatPeerInfo(channelOpenSslP->fd, peerStringP);
391 }
392 
393 
394 
395 static struct TChannelVtbl const channelVtbl = {
396     &channelDestroy,
397     &channelWrite,
398     &channelRead,
399     &channelWait,
400     &channelInterrupt,
401     &channelFormatPeerInfo,
402 };
403 
404 
405 
406 static void
getPeerAddrFromSsl(SSL * const sslP,struct sockaddr * const peerAddrRetP,size_t * const peerAddrLenRetP,const char ** const errorP)407 getPeerAddrFromSsl(SSL *             const sslP,
408                    struct sockaddr * const peerAddrRetP,
409                    size_t *          const peerAddrLenRetP,
410                    const char **     const errorP) {
411 /*----------------------------------------------------------------------------
412    From the SSL connection with handle 'sslP', get the address (IP address,
413    normally) of the peer (the Abyss client).
414 -----------------------------------------------------------------------------*/
415     int const sockFd = SSL_get_fd(sslP);
416 
417     struct sockaddr * peerAddrP;
418     size_t peerAddrLen;
419     const char * error;
420 
421     sockutil_getPeerName(sockFd, &peerAddrP, &peerAddrLen, &error);
422 
423     if (error) {
424         xmlrpc_asprintf(errorP, "Could not get identity of client.  %s",
425                         error);
426         xmlrpc_strfree(error);
427     } else {
428         *errorP = NULL;
429         *peerAddrLenRetP = peerAddrLen;
430         *peerAddrRetP    = *peerAddrP;
431 
432         free(peerAddrP);
433     }
434 }
435 
436 
437 
438 static void
makeChannelInfo(struct abyss_openSsl_chaninfo ** const channelInfoPP,SSL * const sslP,const char ** const errorP)439 makeChannelInfo(struct abyss_openSsl_chaninfo ** const channelInfoPP,
440                 SSL *                            const sslP,
441                 const char **                    const errorP) {
442 
443     struct abyss_openSsl_chaninfo * channelInfoP;
444 
445     MALLOCVAR(channelInfoP);
446 
447     if (channelInfoP == NULL)
448         xmlrpc_asprintf(errorP, "Unable to allocate memory");
449     else {
450         channelInfoP->sslP = sslP;
451 
452         getPeerAddrFromSsl(sslP,
453                            &channelInfoP->peerAddr,
454                            &channelInfoP->peerAddrLen,
455                            errorP);
456 
457         if (*errorP)
458             free(channelInfoP);
459         else
460             *channelInfoPP = channelInfoP;
461     }
462 }
463 
464 
465 
466 static void
makeChannelFromSsl(SSL * const sslP,bool const userSuppliedSsl,TChannel ** const channelPP,const char ** const errorP)467 makeChannelFromSsl(SSL *         const sslP,
468                    bool          const userSuppliedSsl,
469                    TChannel **   const channelPP,
470                    const char ** const errorP) {
471 
472     struct ChannelOpenSsl * channelOpenSslP;
473 
474     MALLOCVAR(channelOpenSslP);
475 
476     if (channelOpenSslP == NULL)
477         xmlrpc_asprintf(errorP, "Unable to allocate memory for OpenSSL "
478                         "socket descriptor");
479     else {
480         TChannel * channelP;
481 
482         channelOpenSslP->sslP = sslP;
483         channelOpenSslP->userSuppliedSsl = userSuppliedSsl;
484 
485         /* This should be ok as far as I can tell */
486         ChannelCreate(&channelVtbl, channelOpenSslP, &channelP);
487 
488         if (channelP == NULL)
489             xmlrpc_asprintf(errorP, "Unable to allocate memory for "
490                             "channel descriptor.");
491         else {
492             *channelPP = channelP;
493             *errorP = NULL;
494         }
495         if (*errorP)
496             free(channelOpenSslP);
497     }
498 }
499 
500 
501 
502 void
ChannelOpenSslCreateSsl(SSL * const sslP,TChannel ** const channelPP,struct abyss_openSsl_chaninfo ** const channelInfoPP,const char ** const errorP)503 ChannelOpenSslCreateSsl(SSL *                            const sslP,
504                         TChannel **                      const channelPP,
505                         struct abyss_openSsl_chaninfo ** const channelInfoPP,
506                         const char **                    const errorP) {
507 
508     assert(sslP);
509 
510     makeChannelInfo(channelInfoPP, sslP, errorP);
511     if (!*errorP) {
512         bool const userSuppliedTrue = true;
513 
514         makeChannelFromSsl(sslP, userSuppliedTrue, channelPP, errorP);
515 
516         if (*errorP) {
517             free(*channelInfoPP);
518         }
519     }
520 }
521 
522 
523 
524 /*=============================================================================
525       TChanSwitch
526 =============================================================================*/
527 
528 struct ChanSwitchOpenSsl {
529 /*----------------------------------------------------------------------------
530    The properties/state of a TChanSwitch uniqe to the OpenSSL variety.
531 
532    Note that OpenSSL deals only in connected sockets, so this switch
533    doesn't really have anything to do with OpenSSL except that it
534    creates OpenSSL TChannels.  The switch is just a POSIX listening
535    socket, and is almost identical to the Abyss Unix channel switch.
536 -----------------------------------------------------------------------------*/
537     int listenFd;
538         /* File descriptor of the POSIX socket (such as is created by
539            socket() in the C library) for the listening socket.
540         */
541     bool userSuppliedFd;
542         /* The file descriptor and associated POSIX socket belong to the
543            user; we did not create it.
544         */
545     SSL_CTX * sslCtxP;
546         /* The context in which we create all our OpenSSL connections */
547 
548     sockutil_InterruptPipe interruptPipe;
549         /* We use this to interrupt a wait for the next client to arrive */
550 };
551 
552 
553 
554 static SwitchDestroyImpl chanSwitchDestroy;
555 
556 static void
chanSwitchDestroy(TChanSwitch * const chanSwitchP)557 chanSwitchDestroy(TChanSwitch * const chanSwitchP) {
558 
559     struct ChanSwitchOpenSsl * const chanSwitchOpenSslP = chanSwitchP->implP;
560 
561     sockutil_interruptPipeTerm(chanSwitchOpenSslP->interruptPipe);
562 
563     if (!chanSwitchOpenSslP->userSuppliedFd)
564         close(chanSwitchOpenSslP->listenFd);
565 
566     free(chanSwitchOpenSslP);
567 }
568 
569 
570 
571 static SwitchListenImpl chanSwitchListen;
572 
573 static void
chanSwitchListen(TChanSwitch * const chanSwitchP,uint32_t const backlog,const char ** const errorP)574 chanSwitchListen(TChanSwitch * const chanSwitchP,
575                  uint32_t      const backlog,
576                  const char ** const errorP) {
577 
578     struct ChanSwitchOpenSsl * const chanSwitchOpenSslP = chanSwitchP->implP;
579 
580     sockutil_listen(chanSwitchOpenSslP->listenFd, backlog, errorP);
581 }
582 
583 
584 
585 static void
createSslFromAcceptedConn(int const acceptedFd,SSL_CTX * const sslCtxP,SSL ** const sslPP,const char ** const errorP)586 createSslFromAcceptedConn(int           const acceptedFd,
587                           SSL_CTX *     const sslCtxP,
588                           SSL **        const sslPP,
589                           const char ** const errorP) {
590 
591     SSL * sslP;
592     const char * error;
593 
594     sslCreate(sslCtxP, &sslP, &error);
595 
596     if (error) {
597         xmlrpc_asprintf(errorP, "Failed to create SSL connection "
598                         "object.  %s", error);
599         xmlrpc_strfree(error);
600     } else {
601         const char * error;
602 
603         sslSetFd(sslP, acceptedFd, &error);
604 
605         if (error) {
606             xmlrpc_asprintf(errorP, "Failed to set file descriptor for SSL "
607                             "connection.  %s", error);
608             xmlrpc_strfree(error);
609         } else {
610             const char * error;
611 
612             sslAccept(sslP, &error);
613 
614             if (error) {
615                 xmlrpc_asprintf(errorP,
616                                 "Failed to set up SSL communication on "
617                                 "working TCP connection.  %s", error);
618                 xmlrpc_strfree(error);
619             } else
620                 *errorP = NULL;
621         }
622         if (*errorP)
623             SSL_free(sslP);
624         else {
625             *sslPP = sslP;
626         }
627     }
628 }
629 
630 
631 
632 static void
createChannelFromAcceptedConn(int const acceptedFd,SSL_CTX * const sslCtxP,TChannel ** const channelPP,void ** const channelInfoPP,const char ** const errorP)633 createChannelFromAcceptedConn(int             const acceptedFd,
634                               SSL_CTX *       const sslCtxP,
635                               TChannel **     const channelPP,
636                               void **         const channelInfoPP,
637                               const char **   const errorP) {
638 
639     struct ChannelOpenSsl * channelOpenSslP;
640 
641     MALLOCVAR(channelOpenSslP);
642 
643     if (!channelOpenSslP)
644         xmlrpc_asprintf(errorP, "Unable to allocate memory");
645     else {
646         SSL * sslP;
647         const char * error;
648 
649         createSslFromAcceptedConn(acceptedFd, sslCtxP, &sslP, &error);
650 
651         if (error) {
652             xmlrpc_asprintf(errorP, "Failed to create an OpenSSL connection "
653                             "from the accepted TCP connection.  %s", error);
654             xmlrpc_strfree(error);
655         } else {
656             struct abyss_openSsl_chaninfo * channelInfoP;
657 
658             makeChannelInfo(&channelInfoP, sslP, errorP);
659             if (!*errorP) {
660                 bool const userSuppliedFalse = false;
661 
662                 makeChannelFromSsl(sslP, userSuppliedFalse,
663                                    channelPP, errorP);
664 
665                 if (*errorP)
666                     free(channelInfoP);
667                 else
668                     *channelInfoPP = channelInfoP;
669             }
670             if (*errorP)
671                 SSL_free(sslP);
672             else
673                 channelOpenSslP->sslP = sslP;
674         }
675         if (*errorP)
676             free(channelOpenSslP);
677     }
678 }
679 
680 
681 
682 static SwitchAcceptImpl  chanSwitchAccept;
683 
684 static void
chanSwitchAccept(TChanSwitch * const chanSwitchP,TChannel ** const channelPP,void ** const channelInfoPP,const char ** const errorP)685 chanSwitchAccept(TChanSwitch * const chanSwitchP,
686                  TChannel **   const channelPP,
687                  void **       const channelInfoPP,
688                  const char ** const errorP) {
689 /*----------------------------------------------------------------------------
690    Accept a connection via the channel switch *chanSwitchP.  Return as
691    *channelPP the channel for the accepted connection.
692 
693    If no connection is waiting at *chanSwitchP, wait until one is.
694 
695    If we receive a signal while waiting, return immediately with
696    *channelPP == NULL.
697 -----------------------------------------------------------------------------*/
698     struct ChanSwitchOpenSsl * const chanSwitchOpenSslP = chanSwitchP->implP;
699 
700     bool interrupted;
701     TChannel * channelP;
702 
703     interrupted = false; /* Haven't been interrupted yet */
704     channelP    = NULL;  /* No connection yet */
705     *errorP     = NULL;  /* No error yet */
706 
707     while (!channelP && !*errorP && !interrupted) {
708         struct sockaddr peerAddr;
709         socklen_t peerAddrLen;
710         int rc;
711 
712         peerAddrLen = sizeof(peerAddr);  /* initial value */
713 
714         rc = accept(chanSwitchOpenSslP->listenFd, &peerAddr, &peerAddrLen);
715 
716         if (rc >= 0) {
717             int const acceptedFd = rc;
718 
719             const char * error;
720 
721             createChannelFromAcceptedConn(
722                 acceptedFd, chanSwitchOpenSslP->sslCtxP,
723                 &channelP, channelInfoPP, &error);
724 
725             if (error) {
726                 close(acceptedFd);
727 
728                 if (SwitchTraceIsActive)
729                     fprintf(stderr,
730                             "Failed to create a channel from the "
731                             "TCP connection we accepted.  %s.  "
732                             "Closing TCP connection, waiting for the "
733                             "next one\n", error);
734                 xmlrpc_strfree(error);
735             }
736         } else if (errno == EINTR)
737             interrupted = true;
738         else
739             xmlrpc_asprintf(errorP, "accept() failed, errno = %d (%s)",
740                             errno, strerror(errno));
741     }
742     *channelPP = channelP;
743 }
744 
745 
746 
747 static SwitchInterruptImpl chanSwitchInterrupt;
748 
749 static void
chanSwitchInterrupt(TChanSwitch * const chanSwitchP)750 chanSwitchInterrupt(TChanSwitch * const chanSwitchP) {
751 /*----------------------------------------------------------------------------
752   Interrupt any waiting that a thread might be doing in chanSwitchAccept()
753   now or in the future.
754 
755   TODO: Make a way to reset this so that future chanSwitchAccept()s can once
756   again wait.
757 -----------------------------------------------------------------------------*/
758     struct ChanSwitchOpenSsl * const chanSwitchOpenSslP = chanSwitchP->implP;
759 
760     unsigned char const zero[1] = {0u};
761 
762     write(chanSwitchOpenSslP->interruptPipe.interruptorFd,
763           &zero, sizeof(zero));
764 }
765 
766 
767 
768 static struct TChanSwitchVtbl const chanSwitchVtbl = {
769     &chanSwitchDestroy,
770     &chanSwitchListen,
771     &chanSwitchAccept,
772     &chanSwitchInterrupt,
773 };
774 
775 
776 
777 static void
createChanSwitch(int const fd,bool const userSuppliedFd,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)778 createChanSwitch(int            const fd,
779                  bool           const userSuppliedFd,
780                  SSL_CTX *      const sslCtxP,
781                  TChanSwitch ** const chanSwitchPP,
782                  const char **  const errorP) {
783 
784     struct ChanSwitchOpenSsl * chanSwitchOpenSslP;
785 
786     assert(!sockutil_connected(fd));
787 
788     if (SwitchTraceIsActive)
789         fprintf(stderr, "Creating OpenSSL-based channel switch\n");
790 
791     MALLOCVAR(chanSwitchOpenSslP);
792 
793     if (chanSwitchOpenSslP == NULL)
794         xmlrpc_asprintf(errorP, "unable to allocate memory for OpenSSL "
795                         "channel switch descriptor.");
796     else {
797         TChanSwitch * chanSwitchP;
798 
799         chanSwitchOpenSslP->sslCtxP = sslCtxP;
800 
801         chanSwitchOpenSslP->listenFd = fd;
802         chanSwitchOpenSslP->userSuppliedFd = userSuppliedFd;
803 
804         sockutil_interruptPipeInit(&chanSwitchOpenSslP->interruptPipe, errorP);
805 
806         if (!*errorP) {
807             ChanSwitchCreate(&chanSwitchVtbl, chanSwitchOpenSslP,
808                              &chanSwitchP);
809             if (*errorP)
810                 sockutil_interruptPipeTerm(chanSwitchOpenSslP->interruptPipe);
811 
812             if (chanSwitchP == NULL)
813                 xmlrpc_asprintf(errorP, "Unable to allocate memory for "
814                                 "channel switch descriptor");
815             else {
816                 *chanSwitchPP = chanSwitchP;
817                 *errorP = NULL;
818             }
819         }
820         if (*errorP)
821             free(chanSwitchOpenSslP);
822     }
823 }
824 
825 
826 
827 static void
switchCreateIpV4Port(unsigned short const portNumber,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)828 switchCreateIpV4Port(unsigned short const portNumber,
829                      SSL_CTX *      const sslCtxP,
830                      TChanSwitch ** const chanSwitchPP,
831                      const char **  const errorP) {
832 /*----------------------------------------------------------------------------
833    Create a POSIX-socket-based channel switch for an IPv4 endpoint.
834 
835    Set the socket's local address so that a subsequent "listen" will listen on
836    all interfaces, port number 'portNumber'.
837 -----------------------------------------------------------------------------*/
838     int rc;
839     rc = socket(PF_INET, SOCK_STREAM, 0);
840     if (rc < 0)
841         xmlrpc_asprintf(errorP, "socket() failed with errno %d (%s)",
842                         errno, strerror(errno));
843     else {
844         int const socketFd = rc;
845 
846         sockutil_setSocketOptions(socketFd, errorP);
847         if (!*errorP) {
848             sockutil_bindSocketToPortInet(socketFd, portNumber, errorP);
849 
850             if (!*errorP) {
851                 bool const userSupplied = false;
852                 createChanSwitch(socketFd, userSupplied, sslCtxP,
853                                  chanSwitchPP, errorP);
854             }
855         }
856         if (*errorP)
857             close(socketFd);
858     }
859 }
860 
861 
862 
863 static void
switchCreateIpV6Port(unsigned short const portNumber,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)864 switchCreateIpV6Port(unsigned short const portNumber,
865                      SSL_CTX *      const sslCtxP,
866                      TChanSwitch ** const chanSwitchPP,
867                      const char **  const errorP) {
868 /*----------------------------------------------------------------------------
869   Same as switchCreateIpV4Port(), except for IPv6.
870 -----------------------------------------------------------------------------*/
871     int rc;
872     rc = socket(PF_INET6, SOCK_STREAM, 0);
873     if (rc < 0)
874         xmlrpc_asprintf(errorP, "socket() failed with errno %d (%s)",
875                         errno, strerror(errno));
876     else {
877         int const socketFd = rc;
878 
879         sockutil_setSocketOptions(socketFd, errorP);
880         if (!*errorP) {
881             sockutil_bindSocketToPortInet6(socketFd, portNumber, errorP);
882 
883             if (!*errorP) {
884                 bool const userSupplied = false;
885                 createChanSwitch(socketFd, userSupplied, sslCtxP,
886                                  chanSwitchPP, errorP);
887             }
888         }
889         if (*errorP)
890             close(socketFd);
891     }
892 }
893 
894 
895 
896 void
ChanSwitchOpenSslCreate(int const protocolFamily,const struct sockaddr * const sockAddrP,socklen_t const sockAddrLen,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)897 ChanSwitchOpenSslCreate(int                     const protocolFamily,
898                         const struct sockaddr * const sockAddrP,
899                         socklen_t               const sockAddrLen,
900                         SSL_CTX *               const sslCtxP,
901                         TChanSwitch **          const chanSwitchPP,
902                         const char **           const errorP) {
903 
904     int rc;
905     rc = socket(protocolFamily, SOCK_STREAM, 0);
906     if (rc < 0)
907         xmlrpc_asprintf(errorP, "socket() failed with errno %d (%s)",
908                         errno, strerror(errno));
909     else {
910         int const socketFd = rc;
911 
912         if (SwitchTraceIsActive)
913             fprintf(stderr, "Created socket for protocol family %d\n",
914                     protocolFamily);
915 
916         sockutil_setSocketOptions(socketFd, errorP);
917         if (!*errorP) {
918             sockutil_bindSocketToPort(socketFd, sockAddrP, sockAddrLen,
919                                       errorP);
920 
921             if (!*errorP) {
922                 bool const userSupplied = false;
923                 createChanSwitch(socketFd, userSupplied, sslCtxP,
924                                  chanSwitchPP, errorP);
925             }
926         }
927         if (*errorP)
928             close(socketFd);
929     }
930 
931 }
932 
933 
934 
935 void
ChanSwitchOpenSslCreateIpV4Port(unsigned short const portNumber,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)936 ChanSwitchOpenSslCreateIpV4Port(unsigned short const portNumber,
937                                 SSL_CTX *      const sslCtxP,
938                                 TChanSwitch ** const chanSwitchPP,
939                                 const char **  const errorP) {
940 
941     switchCreateIpV4Port(portNumber, sslCtxP, chanSwitchPP, errorP);
942 }
943 
944 
945 
946 void
ChanSwitchOpenSslCreateIpV6Port(unsigned short const portNumber,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)947 ChanSwitchOpenSslCreateIpV6Port(unsigned short const portNumber,
948                                 SSL_CTX *      const sslCtxP,
949                                 TChanSwitch ** const chanSwitchPP,
950                                 const char **  const errorP) {
951 
952     switchCreateIpV6Port(portNumber, sslCtxP, chanSwitchPP, errorP);
953 }
954 
955 
956 
957 void
ChanSwitchOpenSslCreateFd(int const fd,SSL_CTX * const sslCtxP,TChanSwitch ** const chanSwitchPP,const char ** const errorP)958 ChanSwitchOpenSslCreateFd(int            const fd,
959                           SSL_CTX *      const sslCtxP,
960                           TChanSwitch ** const chanSwitchPP,
961                           const char **  const errorP) {
962 
963     if (sockutil_connected(fd))
964         xmlrpc_asprintf(errorP,
965                         "Socket (file descriptor %d) is in connected "
966                         "state.", fd);
967     else {
968         bool const userSupplied = true;
969         createChanSwitch(fd, userSupplied, sslCtxP, chanSwitchPP, errorP);
970     }
971 }
972 
973 
974