add listen-timeout to function as an accept timeout
[socat/sam.git] / xio-openssl.c
blob3bd8178942c0ad1ba581bc36175b5433c737edf5
1 /* source: xio-openssl.c */
2 /* Copyright Gerhard Rieger 2002-2008 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the implementation of the openssl addresses */
7 #include "xiosysincludes.h"
8 #if WITH_OPENSSL /* make this address configure dependend */
9 #include "xioopen.h"
11 #include "xio-fd.h"
12 #include "xio-socket.h" /* _xioopen_connect() */
13 #include "xio-listen.h"
14 #include "xio-ipapp.h"
15 #include "xio-openssl.h"
17 /* the openssl library requires a file descriptor for external communications.
18 so our best effort is to provide any possible kind of un*x file descriptor
19 (not only tcp, but also pipes, stdin, files...)
20 for tcp we want to provide support for socks and proxy.
21 read and write functions must use the openssl crypt versions.
22 but currently only plain tcp4 is implemented.
25 /* Linux: "man 3 ssl" */
27 /* generate a simple openssl server for testing:
28 1) generate a private key
29 openssl genrsa -out server.key 1024
30 2) generate a self signed cert
31 openssl req -new -key server.key -x509 -days 3653 -out server.crt
32 enter fields...
33 3) generate the pem file
34 cat server.key server.crt >server.pem
35 openssl s_server (listens on 4433/tcp)
38 /* static declaration of ssl's open function */
39 static int xioopen_openssl_connect(int argc, const char *argv[], struct opt *opts,
40 int xioflags, xiofile_t *fd, unsigned groups,
41 int dummy1, int dummy2, int dummy3);
43 /* static declaration of ssl's open function */
44 static int xioopen_openssl_listen(int argc, const char *argv[], struct opt *opts,
45 int xioflags, xiofile_t *fd, unsigned groups,
46 int dummy1, int dummy2, int dummy3);
47 static int openssl_SSL_ERROR_SSL(int level, const char *funcname);
48 static int openssl_handle_peer_certificate(struct single *xfd, bool opt_ver,
49 int level);
50 static int xioSSL_set_fd(struct single *xfd, int level);
51 static int xioSSL_connect(struct single *xfd, bool opt_ver, int level);
54 /* description record for ssl connect */
55 const struct addrdesc addr_openssl = {
56 "openssl", /* keyword for selecting this address type in xioopen calls
57 (canonical or main name) */
58 3, /* data flow directions this address supports on API layer:
59 1..read, 2..write, 3..both */
60 xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
61 GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
62 You might have to specify a new group in xioopts.h */
63 0, /* an integer passed to xioopen_openssl; makes it possible to
64 use the same xioopen_openssl function for slightly different
65 address types. */
66 0, /* like previous argument */
67 0 /* like previous arguments, but pointer type.
68 No trailing comma or semicolon! */
69 HELP(":<host>:<port>") /* a text displayed from xio help function.
70 No trailing comma or semicolon!
71 only generates this text if WITH_HELP is != 0 */
72 } ;
74 #if WITH_LISTEN
75 /* description record for ssl listen */
76 const struct addrdesc addr_openssl_listen = {
77 "openssl-listen", /* keyword for selecting this address type in xioopen calls
78 (canonical or main name) */
79 3, /* data flow directions this address supports on API layer:
80 1..read, 2..write, 3..both */
81 xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
82 GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
83 You might have to specify a new group in xioopts.h */
84 0, /* an integer passed to xioopen_openssl_listen; makes it possible to
85 use the same xioopen_openssl_listen function for slightly different
86 address types. */
87 0, /* like previous argument */
88 0 /* like previous arguments, but pointer type.
89 No trailing comma or semicolon! */
90 HELP(":<port>") /* a text displayed from xio help function.
91 No trailing comma or semicolon!
92 only generates this text if WITH_HELP is != 0 */
93 } ;
94 #endif /* WITH_LISTEN */
96 /* both client and server */
97 const struct optdesc opt_openssl_cipherlist = { "openssl-cipherlist", "ciphers", OPT_OPENSSL_CIPHERLIST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
98 const struct optdesc opt_openssl_method = { "openssl-method", "method", OPT_OPENSSL_METHOD, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
99 const struct optdesc opt_openssl_verify = { "openssl-verify", "verify", OPT_OPENSSL_VERIFY, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
100 const struct optdesc opt_openssl_certificate = { "openssl-certificate", "cert", OPT_OPENSSL_CERTIFICATE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
101 const struct optdesc opt_openssl_key = { "openssl-key", "key", OPT_OPENSSL_KEY, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
102 const struct optdesc opt_openssl_dhparam = { "openssl-dhparam", "dh", OPT_OPENSSL_DHPARAM, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
103 const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile", OPT_OPENSSL_CAFILE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
104 const struct optdesc opt_openssl_capath = { "openssl-capath", "capath", OPT_OPENSSL_CAPATH, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
105 const struct optdesc opt_openssl_egd = { "openssl-egd", "egd", OPT_OPENSSL_EGD, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
106 const struct optdesc opt_openssl_pseudo = { "openssl-pseudo", "pseudo", OPT_OPENSSL_PSEUDO, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
107 #if WITH_FIPS
108 const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
109 #endif
112 /* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
113 * On forks, the FIPS mode must be reset by a disable, then enable since
114 * FIPS tracks the process ID that initializes things.
115 * If FIPS is not compiled in, no tracking variable is needed
116 * and we make the reset code compile out. This keeps the
117 * rest of the code below free of FIPS related #ifs
119 #if WITH_FIPS
120 static bool xio_openssl_fips = false;
121 int xio_reset_fips_mode(void) {
122 if (xio_openssl_fips) {
123 if(!sycFIPS_mode_set(0) || !sycFIPS_mode_set(1)) {
124 ERR_load_crypto_strings();
125 ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
126 Error("Failed to reset OpenSSL FIPS mode");
127 xio_openssl_fips = false;
128 return -1;
131 return 0;
133 #else
134 #define xio_reset_fips_mode() 0
135 #endif
137 /* the open function for OpenSSL client */
138 static int
139 xioopen_openssl_connect(int argc,
140 const char *argv[], /* the arguments in the address string */
141 struct opt *opts,
142 int xioflags, /* is the open meant for reading (0),
143 writing (1), or both (2) ? */
144 xiofile_t *xxfd, /* a xio file descriptor structure,
145 already allocated */
146 unsigned groups, /* the matching address groups... */
147 int dummy1, /* first transparent integer value from
148 addr_openssl */
149 int dummy2, /* second transparent integer value from
150 addr_openssl */
151 int dummy3) /* transparent pointer value from
152 addr_openssl */
154 struct single *xfd = &xxfd->stream;
155 struct opt *opts0 = NULL;
156 const char *hostname, *portname;
157 int pf = PF_UNSPEC;
158 int ipproto = IPPROTO_TCP;
159 int socktype = SOCK_STREAM;
160 bool dofork = false;
161 union sockaddr_union us_sa, *us = &us_sa;
162 union sockaddr_union them_sa, *them = &them_sa;
163 socklen_t uslen = sizeof(us_sa);
164 socklen_t themlen = sizeof(them_sa);
165 bool needbind = false;
166 bool lowport = false;
167 int level;
168 SSL_CTX* ctx;
169 bool opt_ver = true; /* verify peer certificate */
170 char *opt_cert = NULL; /* file name of client certificate */
171 int result;
173 if (!(xioflags & XIO_MAYCONVERT)) {
174 Error("address with data processing not allowed here");
175 return STAT_NORETRY;
177 xfd->flags |= XIO_DOESCONVERT;
179 if (argc != 3) {
180 Error1("%s: 2 parameters required", argv[0]);
181 return STAT_NORETRY;
183 hostname = argv[1];
184 portname = argv[2];
186 xfd->howtoend = END_SHUTDOWN;
187 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
188 applyopts(-1, opts, PH_INIT);
190 retropt_bool(opts, OPT_FORK, &dofork);
192 retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
194 result =
195 _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
196 if (result != STAT_OK) return STAT_NORETRY;
198 result =
199 _xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
200 xfd->para.socket.ip.res_opts[1],
201 xfd->para.socket.ip.res_opts[0],
202 them, &themlen, us, &uslen,
203 &needbind, &lowport, socktype);
204 if (result != STAT_OK) return STAT_NORETRY;
206 if (xioopts.logopt == 'm') {
207 Info("starting connect loop, switching to syslog");
208 diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
209 } else {
210 Info("starting connect loop");
213 do { /* loop over failed connect and SSL handshake attempts */
215 #if WITH_RETRY
216 if (xfd->forever || xfd->retry) {
217 level = E_INFO;
218 } else
219 #endif /* WITH_RETRY */
220 level = E_ERROR;
222 /* this cannot fork because we retrieved fork option above */
223 result =
224 _xioopen_connect(xfd,
225 needbind?(struct sockaddr *)us:NULL, sizeof(*us),
226 (struct sockaddr *)them, themlen,
227 opts, pf, socktype, ipproto, lowport, level);
228 switch (result) {
229 case STAT_OK: break;
230 #if WITH_RETRY
231 case STAT_RETRYLATER:
232 case STAT_RETRYNOW:
233 if (xfd->forever || xfd->retry) {
234 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
235 if (result == STAT_RETRYLATER) {
236 Nanosleep(&xfd->intervall, NULL);
238 --xfd->retry;
239 continue;
241 return STAT_NORETRY;
242 #endif /* WITH_RETRY */
243 default:
244 return result;
247 /*! isn't this too early? */
248 if ((result = _xio_openlate(xfd, opts)) < 0) {
249 return result;
252 result = _xioopen_openssl_connect(xfd, opt_ver, ctx, level);
253 switch (result) {
254 case STAT_OK: break;
255 #if WITH_RETRY
256 case STAT_RETRYLATER:
257 case STAT_RETRYNOW:
258 if (xfd->forever || xfd->retry) {
259 Close(xfd->fd);
260 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
261 if (result == STAT_RETRYLATER) {
262 Nanosleep(&xfd->intervall, NULL);
264 --xfd->retry;
265 continue;
267 #endif /* WITH_RETRY */
268 default: return STAT_NORETRY;
271 if (dofork) {
272 xiosetchilddied(); /* set SIGCHLD handler */
275 #if WITH_RETRY
276 if (dofork) {
277 pid_t pid;
278 int level = E_ERROR;
279 if (xfd->forever || xfd->retry) {
280 level = E_WARN;
282 while ((pid = xio_fork(false, level)) < 0) {
283 if (xfd->forever || --xfd->retry) {
284 Nanosleep(&xfd->intervall, NULL); continue;
286 return STAT_RETRYLATER;
289 if (pid == 0) { /* child process */
290 xfd->forever = false; xfd->retry = 0;
291 break;
294 /* parent process */
295 Close(xfd->fd);
296 sycSSL_free(xfd->para.openssl.ssl);
297 xfd->para.openssl.ssl = NULL;
298 /* with and without retry */
299 Nanosleep(&xfd->intervall, NULL);
300 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
301 continue; /* with next socket() bind() connect() */
303 #endif /* WITH_RETRY */
304 break;
305 } while (true); /* drop out on success */
307 Notice1("SSL connection using %s", SSL_get_cipher(xfd->para.openssl.ssl));
309 /* fill in the fd structure */
310 return STAT_OK;
314 /* this function is typically called within the OpenSSL client fork/retry loop.
315 xfd must be of type DATA_OPENSSL, and its fd must be set with a valid file
316 descriptor. this function then performs all SSL related step to make a valid
317 SSL connection from an FD and a CTX. */
318 int _xioopen_openssl_connect(struct single *xfd,
319 bool opt_ver,
320 SSL_CTX *ctx,
321 int level) {
322 SSL *ssl;
323 unsigned long err;
324 int result;
326 /* create a SSL object */
327 if ((ssl = sycSSL_new(ctx)) == NULL) {
328 if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
329 while (err = ERR_get_error()) {
330 Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
332 /*Error("SSL_new()");*/
333 return STAT_RETRYLATER;
335 xfd->para.openssl.ssl = ssl;
337 result = xioSSL_set_fd(xfd, level);
338 if (result != STAT_OK) {
339 sycSSL_free(xfd->para.openssl.ssl);
340 xfd->para.openssl.ssl = NULL;
341 return result;
344 result = xioSSL_connect(xfd, opt_ver, level);
345 if (result != STAT_OK) {
346 sycSSL_free(xfd->para.openssl.ssl);
347 xfd->para.openssl.ssl = NULL;
348 return result;
351 result = openssl_handle_peer_certificate(xfd, opt_ver, level);
352 if (result != STAT_OK) {
353 sycSSL_free(xfd->para.openssl.ssl);
354 xfd->para.openssl.ssl = NULL;
355 return result;
358 return STAT_OK;
362 #if WITH_LISTEN
364 static int
365 xioopen_openssl_listen(int argc,
366 const char *argv[], /* the arguments in the address string */
367 struct opt *opts,
368 int xioflags, /* is the open meant for reading (0),
369 writing (1), or both (2) ? */
370 xiofile_t *xxfd, /* a xio file descriptor structure,
371 already allocated */
372 unsigned groups, /* the matching address groups... */
373 int dummy1, /* first transparent integer value from
374 addr_openssl */
375 int dummy2, /* second transparent integer value from
376 addr_openssl */
377 int dummy3) /* transparent pointer value from
378 addr_openssl */
380 struct single *xfd = &xxfd->stream;
381 const char *portname;
382 struct opt *opts0 = NULL;
383 union sockaddr_union us_sa, *us = &us_sa;
384 socklen_t uslen = sizeof(us_sa);
385 int pf;
386 int socktype = SOCK_STREAM;
387 int ipproto = IPPROTO_TCP;
388 /*! lowport? */
389 int level;
390 SSL_CTX* ctx;
391 bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
392 char *opt_cert = NULL; /* file name of server certificate */
393 int result;
395 if (!(xioflags & XIO_MAYCONVERT)) {
396 Error("address with data processing not allowed here");
397 return STAT_NORETRY;
399 xfd->flags |= XIO_DOESCONVERT;
401 if (argc != 2) {
402 Error1("%s: 1 parameter required", argv[0]);
403 return STAT_NORETRY;
406 #if WITH_IP4 && WITH_IP6
407 pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
408 #elif WITH_IP6
409 pf = PF_INET6;
410 #else
411 pf = PF_INET;
412 #endif
414 portname = argv[1];
416 xfd->howtoend = END_SHUTDOWN;
417 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
418 applyopts(-1, opts, PH_INIT);
420 retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
421 if (opt_cert == NULL) {
422 Warn("no certificate given; consider option \"cert\"");
425 applyopts(-1, opts, PH_EARLY);
427 result =
428 _xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx);
429 if (result != STAT_OK) return STAT_NORETRY;
431 if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
432 xfd->para.socket.ip.res_opts[1],
433 xfd->para.socket.ip.res_opts[0],
434 us, &uslen, socktype)
435 != STAT_OK) {
436 return STAT_NORETRY;
439 xfd->addr = &addr_openssl_listen;
440 xfd->dtype = XIODATA_OPENSSL;
442 while (true) { /* loop over failed attempts */
444 #if WITH_RETRY
445 if (xfd->forever || xfd->retry) {
446 level = E_INFO;
447 } else
448 #endif /* WITH_RETRY */
449 level = E_ERROR;
451 /* tcp listen; this can fork() for us; it only returns on error or on
452 successful establishment of tcp connection */
453 result = _xioopen_listen(xfd, xioflags,
454 (struct sockaddr *)us, uslen,
455 opts, pf, socktype, IPPROTO_TCP,
456 #if WITH_RETRY
457 (xfd->retry||xfd->forever)?E_INFO:E_ERROR
458 #else
459 E_ERROR
460 #endif /* WITH_RETRY */
462 /*! not sure if we should try again on retry/forever */
463 switch (result) {
464 case STAT_OK: break;
465 #if WITH_RETRY
466 case STAT_RETRYLATER:
467 case STAT_RETRYNOW:
468 if (xfd->forever || xfd->retry) {
469 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
470 if (result == STAT_RETRYLATER) {
471 Nanosleep(&xfd->intervall, NULL);
473 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
474 --xfd->retry;
475 continue;
477 return STAT_NORETRY;
478 #endif /* WITH_RETRY */
479 default:
480 return result;
483 result = _xioopen_openssl_listen(xfd, opt_ver, ctx, level);
484 switch (result) {
485 case STAT_OK: break;
486 #if WITH_RETRY
487 case STAT_RETRYLATER:
488 case STAT_RETRYNOW:
489 if (xfd->forever || xfd->retry) {
490 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
491 if (result == STAT_RETRYLATER) {
492 Nanosleep(&xfd->intervall, NULL);
494 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
495 --xfd->retry;
496 continue;
498 return STAT_NORETRY;
499 #endif /* WITH_RETRY */
500 default:
501 return result;
504 Notice1("SSL connection using %s",
505 SSL_get_cipher(xfd->para.openssl.ssl));
506 break;
508 } /* drop out on success */
510 /* fill in the fd structure */
512 return STAT_OK;
516 int _xioopen_openssl_listen(struct single *xfd,
517 bool opt_ver,
518 SSL_CTX *ctx,
519 int level) {
520 char error_string[120];
521 unsigned long err;
522 int errint, ret;
524 /* create an SSL object */
525 if ((xfd->para.openssl.ssl = sycSSL_new(ctx)) == NULL) {
526 if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
527 while (err = ERR_get_error()) {
528 Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
530 /*Error("SSL_new()");*/
531 return STAT_NORETRY;
534 /* assign the network connection to the SSL object */
535 if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
536 if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed");
537 while (err = ERR_get_error()) {
538 Msg2(level, "SSL_set_fd(, %d): %s",
539 xfd->fd, ERR_error_string(err, NULL));
543 #if WITH_DEBUG
545 int i = 0;
546 const char *ciphers = NULL;
547 Debug("available ciphers:");
548 do {
549 ciphers = SSL_get_cipher_list(xfd->para.openssl.ssl, i);
550 if (ciphers == NULL) break;
551 Debug2("CIPHERS pri=%d: %s", i, ciphers);
552 ++i;
553 } while (1);
555 #endif /* WITH_DEBUG */
557 /* connect via SSL by performing handshake */
558 if ((ret = sycSSL_accept(xfd->para.openssl.ssl)) <= 0) {
559 /*if (ERR_peek_error() == 0) Msg(level, "SSL_accept() failed");*/
560 errint = SSL_get_error(xfd->para.openssl.ssl, ret);
561 switch (errint) {
562 case SSL_ERROR_NONE:
563 Msg(level, "ok"); break;
564 case SSL_ERROR_ZERO_RETURN:
565 Msg(level, "connection closed (wrong version number?)"); break;
566 case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE:
567 case SSL_ERROR_WANT_CONNECT:
568 case SSL_ERROR_WANT_X509_LOOKUP:
569 Msg(level, "nonblocking operation did not complete"); break; /*!*/
570 case SSL_ERROR_SYSCALL:
571 if (ERR_peek_error() == 0) {
572 if (ret == 0) {
573 Msg(level, "SSL_accept(): socket closed by peer");
574 } else if (ret == -1) {
575 Msg1(level, "SSL_accept(): %s", strerror(errno));
577 } else {
578 Msg(level, "I/O error"); /*!*/
579 while (err = ERR_get_error()) {
580 ERR_error_string_n(err, error_string, sizeof(error_string));
581 Msg4(level, "SSL_accept(): %s / %s / %s / %s", error_string,
582 ERR_lib_error_string(err), ERR_func_error_string(err),
583 ERR_reason_error_string(err));
585 /* Msg1(level, "SSL_connect(): %s", ERR_error_string(e, buf));*/
587 break;
588 case SSL_ERROR_SSL:
589 /*ERR_print_errors_fp(stderr);*/
590 openssl_SSL_ERROR_SSL(level, "SSL_accept");
591 break;
592 default:
593 Msg(level, "unknown error");
596 return STAT_RETRYLATER;
599 if (openssl_handle_peer_certificate(xfd, opt_ver, E_ERROR/*!*/) < 0) {
600 return STAT_NORETRY;
603 return STAT_OK;
606 #endif /* WITH_LISTEN */
610 _xioopen_openssl_prepare(struct opt *opts,
611 struct single *xfd,/* a xio file descriptor
612 structure, already allocated
614 bool server, /* SSL client: false */
615 bool *opt_ver,
616 const char *opt_cert,
617 SSL_CTX **ctx)
619 bool opt_fips = false;
620 SSL_METHOD *method;
621 char *me_str = NULL; /* method string */
622 char *ci_str = NULL; /* cipher string */
623 char *opt_key = NULL; /* file name of client private key */
624 char *opt_dhparam = NULL; /* file name of DH params */
625 char *opt_cafile = NULL; /* certificate authority file */
626 char *opt_capath = NULL; /* certificate authority directory */
627 char *opt_egd = NULL; /* entropy gathering daemon socket path */
628 bool opt_pseudo = false; /* use pseudo entropy if nothing else */
629 unsigned long err;
630 int result;
632 xfd->addr = &addr_openssl;
633 xfd->dtype = XIODATA_OPENSSL;
635 retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
636 retropt_string(opts, OPT_OPENSSL_METHOD, &me_str);
637 retropt_string(opts, OPT_OPENSSL_CIPHERLIST, &ci_str);
638 retropt_bool(opts, OPT_OPENSSL_VERIFY, opt_ver);
639 retropt_string(opts, OPT_OPENSSL_CAFILE, &opt_cafile);
640 retropt_string(opts, OPT_OPENSSL_CAPATH, &opt_capath);
641 retropt_string(opts, OPT_OPENSSL_KEY, &opt_key);
642 retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam);
643 retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd);
644 retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo);
646 #if WITH_FIPS
647 if (opt_fips) {
648 if (!sycFIPS_mode_set(1)) {
649 ERR_load_crypto_strings();
650 ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
651 Error("Failed to set FIPS mode");
652 } else {
653 xio_openssl_fips = true;
656 #endif
658 OpenSSL_add_all_algorithms();
659 OpenSSL_add_all_ciphers();
660 OpenSSL_add_all_digests();
661 sycSSL_load_error_strings();
663 /* OpenSSL preparation */
664 sycSSL_library_init();
666 /*! actions_to_seed_PRNG();*/
668 if (!server) {
669 if (me_str != 0) {
670 if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
671 method = sycSSLv2_client_method();
672 } else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
673 method = sycSSLv3_client_method();
674 } else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
675 !strcasecmp(me_str, "SSL")) {
676 method = sycSSLv23_client_method();
677 } else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
678 !strcasecmp(me_str, "TLS")) {
679 method = sycTLSv1_client_method();
680 } else {
681 Error1("openssl-method=\"%s\": unknown method", me_str);
682 method = sycSSLv23_client_method()/*!*/;
684 } else {
685 method = sycSSLv23_client_method()/*!*/;
687 } else /* server */ {
688 if (me_str != 0) {
689 if (!strcasecmp(me_str, "SSLv2") || !strcasecmp(me_str, "SSL2")) {
690 method = sycSSLv2_server_method();
691 } else if (!strcasecmp(me_str, "SSLv3") || !strcasecmp(me_str, "SSL3")) {
692 method = sycSSLv3_server_method();
693 } else if (!strcasecmp(me_str, "SSLv23") || !strcasecmp(me_str, "SSL23") ||
694 !strcasecmp(me_str, "SSL")) {
695 method = sycSSLv23_server_method();
696 } else if (!strcasecmp(me_str, "TLSv1") || !strcasecmp(me_str, "TLS1") ||
697 !strcasecmp(me_str, "TLS")) {
698 method = sycTLSv1_server_method();
699 } else {
700 Error1("openssl-method=\"%s\": unknown method", me_str);
701 method = sycSSLv23_server_method()/*!*/;
703 } else {
704 method = sycSSLv23_server_method()/*!*/;
708 if (opt_egd) {
709 sycRAND_egd(opt_egd);
712 if (opt_pseudo) {
713 long int randdata;
714 /* initialize libc random from actual microseconds */
715 struct timeval tv;
716 struct timezone tz;
717 tz.tz_minuteswest = 0;
718 tz.tz_dsttime = 0;
719 if ((result = Gettimeofday(&tv, &tz)) < 0) {
720 Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
722 srandom(tv.tv_sec*1000000+tv.tv_usec);
724 while (!RAND_status()) {
725 randdata = random();
726 Debug2("RAND_seed(0x{%lx}, "F_Zu")",
727 randdata, sizeof(randdata));
728 RAND_seed(&randdata, sizeof(randdata));
732 if ((*ctx = sycSSL_CTX_new(method)) == NULL) {
733 if (ERR_peek_error() == 0) Error("SSL_CTX_new()");
734 while (err = ERR_get_error()) {
735 Error1("SSL_CTX_new(): %s", ERR_error_string(err, NULL));
738 /*ERR_clear_error;*/
739 return STAT_RETRYLATER;
742 if (opt_cafile != NULL || opt_capath != NULL) {
743 if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
744 int result;
746 if ((result =
747 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_CTX_load_verify_locations"))
748 != STAT_OK) {
749 /*! free ctx */
750 return STAT_RETRYLATER;
755 if (opt_cert) {
756 BIO *bio;
757 DH *dh;
759 if (sycSSL_CTX_use_certificate_chain_file(*ctx, opt_cert) <= 0) {
760 /*! trace functions */
761 /*0 ERR_print_errors_fp(stderr);*/
762 if (ERR_peek_error() == 0)
763 Error2("SSL_CTX_use_certificate_file(%p, \"%s\", SSL_FILETYPE_PEM) failed",
764 *ctx, opt_cert);
765 while (err = ERR_get_error()) {
766 Error1("SSL_CTX_use_certificate_file(): %s",
767 ERR_error_string(err, NULL));
769 return STAT_RETRYLATER;
772 if (sycSSL_CTX_use_PrivateKey_file(*ctx, opt_key?opt_key:opt_cert, SSL_FILETYPE_PEM) <= 0) {
773 /*ERR_print_errors_fp(stderr);*/
774 openssl_SSL_ERROR_SSL(E_ERROR/*!*/, "SSL_CTX_use_PrivateKey_file");
775 return STAT_RETRYLATER;
778 if (opt_dhparam == NULL) {
779 opt_dhparam = (char *)opt_cert;
781 if ((bio = sycBIO_new_file(opt_dhparam, "r")) == NULL) {
782 Warn2("BIO_new_file(\"%s\", \"r\"): %s",
783 opt_dhparam, strerror(errno));
784 } else {
785 if ((dh = sycPEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) {
786 Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio);
787 } else {
788 BIO_free(bio);
789 if (sycSSL_CTX_set_tmp_dh(*ctx, dh) == 0) {
790 Error2("SSL_CTX_set_tmp_dh(%p, %p): error", ctx, dh);
796 /* set pre ssl-connect options */
797 /* SSL_CIPHERS */
798 if (ci_str != NULL) {
799 if (sycSSL_CTX_set_cipher_list(*ctx, ci_str) <= 0) {
800 if (ERR_peek_error() == 0)
801 Error1("SSL_set_cipher_list(, \"%s\") failed", ci_str);
802 while (err = ERR_get_error()) {
803 Error2("SSL_set_cipher_list(, \"%s\"): %s",
804 ci_str, ERR_error_string(err, NULL));
806 /*Error("SSL_new()");*/
807 return STAT_RETRYLATER;
811 if (*opt_ver) {
812 sycSSL_CTX_set_verify(*ctx,
813 SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
814 NULL);
815 } else {
816 sycSSL_CTX_set_verify(*ctx,
817 SSL_VERIFY_NONE,
818 NULL);
821 return STAT_OK;
825 /* analyses an OpenSSL error condition, prints the appropriate messages with
826 severity 'level' and returns one of STAT_OK, STAT_RETRYLATER, or
827 STAT_NORETRY */
828 static int openssl_SSL_ERROR_SSL(int level, const char *funcname) {
829 unsigned long e;
830 char buf[120]; /* this value demanded by "man ERR_error_string" */
832 e = ERR_get_error();
833 Debug1("ERR_get_error(): %lx", e);
834 if (e == ((ERR_LIB_RAND<<24)|
835 (RAND_F_SSLEAY_RAND_BYTES<<12)|
836 (RAND_R_PRNG_NOT_SEEDED)) /*0x24064064*/) {
837 Error("too few entropy; use options \"egd\" or \"pseudo\"");
838 return STAT_NORETRY;
839 } else {
840 Msg2(level, "%s(): %s", funcname, ERR_error_string(e, buf));
841 return level==E_ERROR ? STAT_NORETRY : STAT_RETRYLATER;
843 return STAT_OK;
846 static const char *openssl_verify_messages[] = {
847 /* 0 */ "ok",
848 /* 1 */ NULL,
849 /* 2 */ "unable to get issuer certificate",
850 /* 3 */ "unable to get certificate CRL",
851 /* 4 */ "unable to decrypt certificate's signature",
852 /* 5 */ "unable to decrypt CRL's signature",
853 /* 6 */ "unable to decode issuer public key",
854 /* 7 */ "certificate signature failure",
855 /* 8 */ "CRL signature failure",
856 /* 9 */ "certificate is not yet valid",
857 /* 10 */ "certificate has expired",
858 /* 11 */ "CRL is not yet valid",
859 /* 12 */ "CRL has expired",
860 /* 13 */ "format error in certificate's notBefore field",
861 /* 14 */ "format error in certificate's notAfter field",
862 /* 15 */ "format error in CRL's lastUpdate field",
863 /* 16 */ "format error in CRL's nextUpdate field",
864 /* 17 */ "out of memory",
865 /* 18 */ "self signed certificate",
866 /* 19 */ "self signed certificate in certificate chain",
867 /* 20 */ "unable to get local issuer certificate",
868 /* 21 */ "unable to verify the first certificate",
869 /* 22 */ "certificate chain too long",
870 /* 23 */ "certificate revoked",
871 /* 24 */ "invalid CA certificate",
872 /* 25 */ "path length constraint exceeded",
873 /* 26 */ "unsupported certificate purpose",
874 /* 27 */ "certificate not trusted",
875 /* 28 */ "certificate rejected",
876 /* 29 */ "subject issuer mismatch",
877 /* 30 */ "authority and subject key identifier mismatch",
878 /* 31 */ "authority and issuer serial number mismatch",
879 /* 32 */ "key usage does not include certificate signing",
880 /* 33 */ NULL,
881 /* 34 */ NULL,
882 /* 35 */ NULL,
883 /* 36 */ NULL,
884 /* 37 */ NULL,
885 /* 38 */ NULL,
886 /* 39 */ NULL,
887 /* 40 */ NULL,
888 /* 41 */ NULL,
889 /* 42 */ NULL,
890 /* 43 */ NULL,
891 /* 44 */ NULL,
892 /* 45 */ NULL,
893 /* 46 */ NULL,
894 /* 47 */ NULL,
895 /* 48 */ NULL,
896 /* 49 */ NULL,
897 /* 50 */ "application verification failure",
900 static int openssl_handle_peer_certificate(struct single *xfd,
901 bool opt_ver, int level) {
902 X509 *peer_cert;
903 char *str;
904 char buff[2048]; /* hold peer certificate */
905 int status;
907 /* SSL_CTX_add_extra_chain_cert
908 SSL_get_verify_result
910 if ((peer_cert = SSL_get_peer_certificate(xfd->para.openssl.ssl)) != NULL) {
911 Debug("peer certificate:");
912 if ((str = X509_NAME_oneline(X509_get_subject_name(peer_cert), buff, sizeof(buff))) != NULL)
913 Debug1("\tsubject: %s", str); /*free (str); SIGSEGV*/
914 if ((str = X509_NAME_oneline(X509_get_issuer_name(peer_cert), buff, sizeof(buff))) != NULL)
915 Debug1("\tissuer: %s", str); /*free (str); SIGSEGV*/
918 if (peer_cert) {
919 if (opt_ver) {
920 long verify_result;
921 if ((verify_result = sycSSL_get_verify_result(xfd->para.openssl.ssl)) == X509_V_OK) {
922 Info("accepted peer certificate");
923 status = STAT_OK;
924 } else {
925 const char *message = NULL;
926 if (verify_result >= 0 &&
927 (size_t)verify_result <
928 sizeof(openssl_verify_messages)/sizeof(char*))
930 message = openssl_verify_messages[verify_result];
932 if (message) {
933 Msg1(level, "%s", message);
934 } else {
935 Msg1(level, "rejected peer certificate with error %ld", verify_result);
937 status = STAT_RETRYLATER;
939 } else {
940 Notice("no check of certificate");
941 status = STAT_OK;
943 } else {
944 if (opt_ver) {
945 Msg(level, "no peer certificate");
946 status = STAT_RETRYLATER;
947 } else {
948 Notice("no peer certificate and no check");
949 status = STAT_OK;
953 X509_free(peer_cert);
954 return status;
957 static int xioSSL_set_fd(struct single *xfd, int level) {
958 unsigned long err;
960 /* assign a network connection to the SSL object */
961 if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
962 Msg(level, "SSL_set_fd() failed");
963 while (err = ERR_get_error()) {
964 Msg2(level, "SSL_set_fd(, %d): %s",
965 xfd->fd, ERR_error_string(err, NULL));
967 return STAT_RETRYLATER;
969 return STAT_OK;
973 /* ...
974 in case of an error condition, this function check forever and retry
975 options and ev. sleeps an interval. It returns NORETRY when the caller
976 should not retry for any reason. */
977 static int xioSSL_connect(struct single *xfd, bool opt_ver, int level) {
978 char error_string[120];
979 int errint, status, ret;
980 unsigned long err;
982 /* connect via SSL by performing handshake */
983 if ((ret = sycSSL_connect(xfd->para.openssl.ssl)) <= 0) {
984 /*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
985 errint = SSL_get_error(xfd->para.openssl.ssl, ret);
986 switch (errint) {
987 case SSL_ERROR_NONE:
988 /* this is not an error, but I dare not continue for security reasons*/
989 Msg(level, "ok");
990 status = STAT_RETRYLATER;
991 case SSL_ERROR_ZERO_RETURN:
992 Msg(level, "connection closed (wrong version number?)");
993 status = STAT_RETRYLATER;
994 break;
995 case SSL_ERROR_WANT_READ:
996 case SSL_ERROR_WANT_WRITE:
997 case SSL_ERROR_WANT_CONNECT:
998 case SSL_ERROR_WANT_X509_LOOKUP:
999 Msg(level, "nonblocking operation did not complete");
1000 status = STAT_RETRYLATER;
1001 break; /*!*/
1002 case SSL_ERROR_SYSCALL:
1003 if (ERR_peek_error() == 0) {
1004 if (ret == 0) {
1005 Msg(level, "SSL_connect(): socket closed by peer");
1006 } else if (ret == -1) {
1007 Msg1(level, "SSL_connect(): %s", strerror(errno));
1009 } else {
1010 Msg(level, "I/O error"); /*!*/
1011 while (err = ERR_get_error()) {
1012 ERR_error_string_n(err, error_string, sizeof(error_string));
1013 Msg4(level, "SSL_connect(): %s / %s / %s / %s", error_string,
1014 ERR_lib_error_string(err), ERR_func_error_string(err),
1015 ERR_reason_error_string(err));
1018 status = STAT_RETRYLATER;
1019 break;
1020 case SSL_ERROR_SSL:
1021 status = openssl_SSL_ERROR_SSL(level, "SSL_connect");
1022 if (openssl_handle_peer_certificate(xfd, opt_ver, level/*!*/) < 0) {
1023 return STAT_RETRYLATER;
1025 break;
1026 default:
1027 Msg(level, "unknown error");
1028 status = STAT_RETRYLATER;
1029 break;
1031 return status;
1033 return STAT_OK;
1036 /* on result < 0: errno is set (at least to EIO) */
1037 ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
1038 unsigned long err;
1039 char error_string[120];
1040 int _errno = EIO; /* if we have no better idea about nature of error */
1041 int errint, ret;
1043 ret = sycSSL_read(pipe->para.openssl.ssl, buff, bufsiz);
1044 if (ret < 0) {
1045 errint = SSL_get_error(pipe->para.openssl.ssl, ret);
1046 switch (errint) {
1047 case SSL_ERROR_NONE:
1048 /* this is not an error, but I dare not continue for security reasons*/
1049 Error("ok");
1050 case SSL_ERROR_ZERO_RETURN:
1051 Error("connection closed by peer");
1052 break;
1053 case SSL_ERROR_WANT_READ:
1054 case SSL_ERROR_WANT_WRITE:
1055 case SSL_ERROR_WANT_CONNECT:
1056 case SSL_ERROR_WANT_X509_LOOKUP:
1057 Error("nonblocking operation did not complete");
1058 break; /*!*/
1059 case SSL_ERROR_SYSCALL:
1060 if (ERR_peek_error() == 0) {
1061 if (ret == 0) {
1062 Error("SSL_read(): socket closed by peer");
1063 } else if (ret == -1) {
1064 _errno = errno;
1065 Error1("SSL_read(): %s", strerror(errno));
1067 } else {
1068 Error("I/O error"); /*!*/
1069 while (err = ERR_get_error()) {
1070 ERR_error_string_n(err, error_string, sizeof(error_string));
1071 Error4("SSL_read(): %s / %s / %s / %s", error_string,
1072 ERR_lib_error_string(err), ERR_func_error_string(err),
1073 ERR_reason_error_string(err));
1076 break;
1077 case SSL_ERROR_SSL:
1078 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
1079 break;
1080 default:
1081 Error("unknown error");
1082 break;
1084 errno = _errno;
1085 return -1;
1087 return ret;
1090 ssize_t xiopending_openssl(struct single *pipe) {
1091 int bytes = sycSSL_pending(pipe->para.openssl.ssl);
1092 return bytes;
1095 /* on result < 0: errno is set (at least to EIO) */
1096 ssize_t xiowrite_openssl(struct single *pipe, const void *buff, size_t bufsiz) {
1097 unsigned long err;
1098 char error_string[120];
1099 int _errno = EIO; /* if we have no better idea about nature of error */
1100 int errint, ret;
1102 ret = sycSSL_write(pipe->para.openssl.ssl, buff, bufsiz);
1103 if (ret < 0) {
1104 errint = SSL_get_error(pipe->para.openssl.ssl, ret);
1105 switch (errint) {
1106 case SSL_ERROR_NONE:
1107 /* this is not an error, but I dare not continue for security reasons*/
1108 Error("ok");
1109 case SSL_ERROR_ZERO_RETURN:
1110 Error("connection closed by peer");
1111 break;
1112 case SSL_ERROR_WANT_READ:
1113 case SSL_ERROR_WANT_WRITE:
1114 case SSL_ERROR_WANT_CONNECT:
1115 case SSL_ERROR_WANT_X509_LOOKUP:
1116 Error("nonblocking operation did not complete");
1117 break; /*!*/
1118 case SSL_ERROR_SYSCALL:
1119 if (ERR_peek_error() == 0) {
1120 if (ret == 0) {
1121 Error("SSL_write(): socket closed by peer");
1122 } else if (ret == -1) {
1123 _errno = errno;
1124 Error1("SSL_write(): %s", strerror(errno));
1126 } else {
1127 Error("I/O error"); /*!*/
1128 while (err = ERR_get_error()) {
1129 ERR_error_string_n(err, error_string, sizeof(error_string));
1130 Error4("SSL_write(): %s / %s / %s / %s", error_string,
1131 ERR_lib_error_string(err), ERR_func_error_string(err),
1132 ERR_reason_error_string(err));
1135 break;
1136 case SSL_ERROR_SSL:
1137 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
1138 break;
1139 default:
1140 Error("unknown error");
1141 break;
1143 errno = _errno;
1144 return -1;
1146 return ret;
1150 #endif /* WITH_OPENSSL */