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