version 1.7.3.0
[socat.git] / xio-openssl.c
blob665430de8fe768d5facae035244edc2e2c5878a0
1 /* source: xio-openssl.c */
2 /* Copyright Gerhard Rieger */
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 <openssl/conf.h>
10 #include <openssl/x509v3.h>
12 #include "xioopen.h"
14 #include "xio-fd.h"
15 #include "xio-socket.h" /* _xioopen_connect() */
16 #include "xio-listen.h"
17 #include "xio-ipapp.h"
18 #include "xio-openssl.h"
20 /* the openssl library requires a file descriptor for external communications.
21 so our best effort is to provide any possible kind of un*x file descriptor
22 (not only tcp, but also pipes, stdin, files...)
23 for tcp we want to provide support for socks and proxy.
24 read and write functions must use the openssl crypt versions.
25 but currently only plain tcp4 is implemented.
28 /* Linux: "man 3 ssl" */
30 /* generate a simple openssl server for testing:
31 1) generate a private key
32 openssl genrsa -out server.key 1024
33 2) generate a self signed cert
34 openssl req -new -key server.key -x509 -days 3653 -out server.crt
35 enter fields...
36 3) generate the pem file
37 cat server.key server.crt >server.pem
38 openssl s_server (listens on 4433/tcp)
41 /* static declaration of ssl's open function */
42 static int xioopen_openssl_connect(int argc, const char *argv[], struct opt *opts,
43 int xioflags, xiofile_t *fd, unsigned groups,
44 int dummy1, int dummy2, int dummy3);
46 /* static declaration of ssl's open function */
47 static int xioopen_openssl_listen(int argc, const char *argv[], struct opt *opts,
48 int xioflags, xiofile_t *fd, unsigned groups,
49 int dummy1, int dummy2, int dummy3);
50 static int openssl_SSL_ERROR_SSL(int level, const char *funcname);
51 static int openssl_handle_peer_certificate(struct single *xfd,
52 const char *peername,
53 bool opt_ver,
54 int level);
55 static int xioSSL_set_fd(struct single *xfd, int level);
56 static int xioSSL_connect(struct single *xfd, const char *opt_commonname, bool opt_ver, int level);
57 static int openssl_delete_cert_info(void);
60 /* description record for ssl connect */
61 const struct addrdesc addr_openssl = {
62 "openssl", /* keyword for selecting this address type in xioopen calls
63 (canonical or main name) */
64 3, /* data flow directions this address supports on API layer:
65 1..read, 2..write, 3..both */
66 xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
67 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.
68 You might have to specify a new group in xioopts.h */
69 0, /* an integer passed to xioopen_openssl; makes it possible to
70 use the same xioopen_openssl function for slightly different
71 address types. */
72 0, /* like previous argument */
73 0 /* like previous arguments, but pointer type.
74 No trailing comma or semicolon! */
75 HELP(":<host>:<port>") /* a text displayed from xio help function.
76 No trailing comma or semicolon!
77 only generates this text if WITH_HELP is != 0 */
78 } ;
80 #if WITH_LISTEN
81 /* description record for ssl listen */
82 const struct addrdesc addr_openssl_listen = {
83 "openssl-listen", /* keyword for selecting this address type in xioopen calls
84 (canonical or main name) */
85 3, /* data flow directions this address supports on API layer:
86 1..read, 2..write, 3..both */
87 xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
88 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.
89 You might have to specify a new group in xioopts.h */
90 0, /* an integer passed to xioopen_openssl_listen; makes it possible to
91 use the same xioopen_openssl_listen function for slightly different
92 address types. */
93 0, /* like previous argument */
94 0 /* like previous arguments, but pointer type.
95 No trailing comma or semicolon! */
96 HELP(":<port>") /* a text displayed from xio help function.
97 No trailing comma or semicolon!
98 only generates this text if WITH_HELP is != 0 */
99 } ;
100 #endif /* WITH_LISTEN */
102 /* both client and server */
103 const struct optdesc opt_openssl_cipherlist = { "openssl-cipherlist", "ciphers", OPT_OPENSSL_CIPHERLIST, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
104 const struct optdesc opt_openssl_method = { "openssl-method", "method", OPT_OPENSSL_METHOD, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
105 const struct optdesc opt_openssl_verify = { "openssl-verify", "verify", OPT_OPENSSL_VERIFY, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
106 const struct optdesc opt_openssl_certificate = { "openssl-certificate", "cert", OPT_OPENSSL_CERTIFICATE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
107 const struct optdesc opt_openssl_key = { "openssl-key", "key", OPT_OPENSSL_KEY, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
108 const struct optdesc opt_openssl_dhparam = { "openssl-dhparam", "dh", OPT_OPENSSL_DHPARAM, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
109 const struct optdesc opt_openssl_cafile = { "openssl-cafile", "cafile", OPT_OPENSSL_CAFILE, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
110 const struct optdesc opt_openssl_capath = { "openssl-capath", "capath", OPT_OPENSSL_CAPATH, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
111 const struct optdesc opt_openssl_egd = { "openssl-egd", "egd", OPT_OPENSSL_EGD, GROUP_OPENSSL, PH_SPEC, TYPE_FILENAME, OFUNC_SPEC };
112 const struct optdesc opt_openssl_pseudo = { "openssl-pseudo", "pseudo", OPT_OPENSSL_PSEUDO, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
113 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
114 const struct optdesc opt_openssl_compress = { "openssl-compress", "compress", OPT_OPENSSL_COMPRESS, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
115 #endif
116 #if WITH_FIPS
117 const struct optdesc opt_openssl_fips = { "openssl-fips", "fips", OPT_OPENSSL_FIPS, GROUP_OPENSSL, PH_SPEC, TYPE_BOOL, OFUNC_SPEC };
118 #endif
119 const struct optdesc opt_openssl_commonname = { "openssl-commonname", "cn", OPT_OPENSSL_COMMONNAME, GROUP_OPENSSL, PH_SPEC, TYPE_STRING, OFUNC_SPEC };
122 /* If FIPS is compiled in, we need to track if the user asked for FIPS mode.
123 * On forks, the FIPS mode must be reset by a disable, then enable since
124 * FIPS tracks the process ID that initializes things.
125 * If FIPS is not compiled in, no tracking variable is needed
126 * and we make the reset code compile out. This keeps the
127 * rest of the code below free of FIPS related #ifs
129 #if WITH_FIPS
130 static bool xio_openssl_fips = false;
131 int xio_reset_fips_mode(void) {
132 if (xio_openssl_fips) {
133 if(!sycFIPS_mode_set(0) || !sycFIPS_mode_set(1)) {
134 ERR_load_crypto_strings();
135 ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
136 Error("Failed to reset OpenSSL FIPS mode");
137 xio_openssl_fips = false;
138 return -1;
141 return 0;
143 #else
144 #define xio_reset_fips_mode() 0
145 #endif
147 static void openssl_conn_loginfo(SSL *ssl) {
148 Notice1("SSL connection using %s", SSL_get_cipher(ssl));
150 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
152 const COMP_METHOD *comp, *expansion;
154 comp = sycSSL_get_current_compression(ssl);
155 expansion = sycSSL_get_current_expansion(ssl);
157 Notice1("SSL connection compression \"%s\"",
158 comp?sycSSL_COMP_get_name(comp):"none");
159 Notice1("SSL connection expansion \"%s\"",
160 expansion?sycSSL_COMP_get_name(expansion):"none");
162 #endif
165 /* the open function for OpenSSL client */
166 static int
167 xioopen_openssl_connect(int argc,
168 const char *argv[], /* the arguments in the address string */
169 struct opt *opts,
170 int xioflags, /* is the open meant for reading (0),
171 writing (1), or both (2) ? */
172 xiofile_t *xxfd, /* a xio file descriptor structure,
173 already allocated */
174 unsigned groups, /* the matching address groups... */
175 int dummy1, /* first transparent integer value from
176 addr_openssl */
177 int dummy2, /* second transparent integer value from
178 addr_openssl */
179 int dummy3) /* transparent pointer value from
180 addr_openssl */
182 struct single *xfd = &xxfd->stream;
183 struct opt *opts0 = NULL;
184 const char *hostname, *portname;
185 int pf = PF_UNSPEC;
186 int ipproto = IPPROTO_TCP;
187 int socktype = SOCK_STREAM;
188 bool dofork = false;
189 union sockaddr_union us_sa, *us = &us_sa;
190 union sockaddr_union them_sa, *them = &them_sa;
191 socklen_t uslen = sizeof(us_sa);
192 socklen_t themlen = sizeof(them_sa);
193 bool needbind = false;
194 bool lowport = false;
195 int level;
196 SSL_CTX* ctx;
197 bool opt_ver = true; /* verify peer certificate */
198 char *opt_cert = NULL; /* file name of client certificate */
199 const char *opt_commonname = NULL; /* for checking peer certificate */
200 int result;
202 if (!(xioflags & XIO_MAYCONVERT)) {
203 Error("address with data processing not allowed here");
204 return STAT_NORETRY;
206 xfd->flags |= XIO_DOESCONVERT;
208 if (argc != 3) {
209 Error1("%s: 2 parameters required", argv[0]);
210 return STAT_NORETRY;
212 hostname = argv[1];
213 portname = argv[2];
214 if (hostname[0] == '\0') {
215 /* we catch this explicitely because empty commonname (peername) disables
216 commonName check of peer certificate */
217 Error1("%s: empty host name", argv[0]);
218 return STAT_NORETRY;
221 xfd->howtoend = END_SHUTDOWN;
222 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
223 applyopts(-1, opts, PH_INIT);
225 retropt_bool(opts, OPT_FORK, &dofork);
227 retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
228 retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
230 if (opt_commonname == NULL) {
231 opt_commonname = hostname;
234 result =
235 _xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
236 if (result != STAT_OK) return STAT_NORETRY;
238 result =
239 _xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
240 xfd->para.socket.ip.res_opts[1],
241 xfd->para.socket.ip.res_opts[0],
242 them, &themlen, us, &uslen,
243 &needbind, &lowport, socktype);
244 if (result != STAT_OK) return STAT_NORETRY;
246 if (xioopts.logopt == 'm') {
247 Info("starting connect loop, switching to syslog");
248 diag_set('y', xioopts.syslogfac); xioopts.logopt = 'y';
249 } else {
250 Info("starting connect loop");
253 do { /* loop over failed connect and SSL handshake attempts */
255 #if WITH_RETRY
256 if (xfd->forever || xfd->retry) {
257 level = E_INFO;
258 } else
259 #endif /* WITH_RETRY */
260 level = E_ERROR;
262 /* this cannot fork because we retrieved fork option above */
263 result =
264 _xioopen_connect(xfd,
265 needbind?(struct sockaddr *)us:NULL, uslen,
266 (struct sockaddr *)them, themlen,
267 opts, pf, socktype, ipproto, lowport, level);
268 switch (result) {
269 case STAT_OK: break;
270 #if WITH_RETRY
271 case STAT_RETRYLATER:
272 case STAT_RETRYNOW:
273 if (xfd->forever || xfd->retry) {
274 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
275 if (result == STAT_RETRYLATER) {
276 Nanosleep(&xfd->intervall, NULL);
278 --xfd->retry;
279 continue;
281 return STAT_NORETRY;
282 #endif /* WITH_RETRY */
283 default:
284 return result;
287 /*! isn't this too early? */
288 if ((result = _xio_openlate(xfd, opts)) < 0) {
289 return result;
292 result = _xioopen_openssl_connect(xfd, opt_ver, opt_commonname, ctx, level);
293 switch (result) {
294 case STAT_OK: break;
295 #if WITH_RETRY
296 case STAT_RETRYLATER:
297 case STAT_RETRYNOW:
298 if (xfd->forever || xfd->retry) {
299 Close(xfd->fd);
300 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
301 if (result == STAT_RETRYLATER) {
302 Nanosleep(&xfd->intervall, NULL);
304 --xfd->retry;
305 continue;
307 #endif /* WITH_RETRY */
308 default: return STAT_NORETRY;
311 if (dofork) {
312 xiosetchilddied(); /* set SIGCHLD handler */
315 #if WITH_RETRY
316 if (dofork) {
317 pid_t pid;
318 int level = E_ERROR;
319 if (xfd->forever || xfd->retry) {
320 level = E_WARN;
322 while ((pid = xio_fork(false, level)) < 0) {
323 if (xfd->forever || --xfd->retry) {
324 Nanosleep(&xfd->intervall, NULL); continue;
326 return STAT_RETRYLATER;
329 if (pid == 0) { /* child process */
330 xfd->forever = false; xfd->retry = 0;
331 break;
334 /* parent process */
335 Close(xfd->fd);
336 sycSSL_free(xfd->para.openssl.ssl);
337 xfd->para.openssl.ssl = NULL;
338 /* with and without retry */
339 Nanosleep(&xfd->intervall, NULL);
340 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
341 continue; /* with next socket() bind() connect() */
343 #endif /* WITH_RETRY */
344 break;
345 } while (true); /* drop out on success */
347 openssl_conn_loginfo(xfd->para.openssl.ssl);
349 /* fill in the fd structure */
350 return STAT_OK;
354 /* this function is typically called within the OpenSSL client fork/retry loop.
355 xfd must be of type DATA_OPENSSL, and its fd must be set with a valid file
356 descriptor. this function then performs all SSL related step to make a valid
357 SSL connection from an FD and a CTX. */
358 int _xioopen_openssl_connect(struct single *xfd,
359 bool opt_ver,
360 const char *opt_commonname,
361 SSL_CTX *ctx,
362 int level) {
363 SSL *ssl;
364 unsigned long err;
365 int result;
367 /* create a SSL object */
368 if ((ssl = sycSSL_new(ctx)) == NULL) {
369 if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
370 while (err = ERR_get_error()) {
371 Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
373 /*Error("SSL_new()");*/
374 return STAT_RETRYLATER;
376 xfd->para.openssl.ssl = ssl;
378 result = xioSSL_set_fd(xfd, level);
379 if (result != STAT_OK) {
380 sycSSL_free(xfd->para.openssl.ssl);
381 xfd->para.openssl.ssl = NULL;
382 return result;
385 result = xioSSL_connect(xfd, opt_commonname, opt_ver, level);
386 if (result != STAT_OK) {
387 sycSSL_free(xfd->para.openssl.ssl);
388 xfd->para.openssl.ssl = NULL;
389 return result;
392 result = openssl_handle_peer_certificate(xfd, opt_commonname,
393 opt_ver, level);
394 if (result != STAT_OK) {
395 sycSSL_free(xfd->para.openssl.ssl);
396 xfd->para.openssl.ssl = NULL;
397 return result;
400 return STAT_OK;
404 #if WITH_LISTEN
406 static int
407 xioopen_openssl_listen(int argc,
408 const char *argv[], /* the arguments in the address string */
409 struct opt *opts,
410 int xioflags, /* is the open meant for reading (0),
411 writing (1), or both (2) ? */
412 xiofile_t *xxfd, /* a xio file descriptor structure,
413 already allocated */
414 unsigned groups, /* the matching address groups... */
415 int dummy1, /* first transparent integer value from
416 addr_openssl */
417 int dummy2, /* second transparent integer value from
418 addr_openssl */
419 int dummy3) /* transparent pointer value from
420 addr_openssl */
422 struct single *xfd = &xxfd->stream;
423 const char *portname;
424 struct opt *opts0 = NULL;
425 union sockaddr_union us_sa, *us = &us_sa;
426 socklen_t uslen = sizeof(us_sa);
427 int pf;
428 int socktype = SOCK_STREAM;
429 int ipproto = IPPROTO_TCP;
430 /*! lowport? */
431 int level;
432 SSL_CTX* ctx;
433 bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
434 char *opt_cert = NULL; /* file name of server certificate */
435 const char *opt_commonname = NULL; /* for checking peer certificate */
436 int result;
438 if (!(xioflags & XIO_MAYCONVERT)) {
439 Error("address with data processing not allowed here");
440 return STAT_NORETRY;
442 xfd->flags |= XIO_DOESCONVERT;
444 if (argc != 2) {
445 Error1("%s: 1 parameter required", argv[0]);
446 return STAT_NORETRY;
449 #if WITH_IP4 && WITH_IP6
450 pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
451 #elif WITH_IP6
452 pf = PF_INET6;
453 #else
454 pf = PF_INET;
455 #endif
457 portname = argv[1];
459 xfd->howtoend = END_SHUTDOWN;
460 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
461 applyopts(-1, opts, PH_INIT);
463 retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
464 if (opt_cert == NULL) {
465 Warn("no certificate given; consider option \"cert\"");
468 retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
470 applyopts(-1, opts, PH_EARLY);
472 result =
473 _xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx);
474 if (result != STAT_OK) return STAT_NORETRY;
476 if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
477 xfd->para.socket.ip.res_opts[1],
478 xfd->para.socket.ip.res_opts[0],
479 us, &uslen, socktype)
480 != STAT_OK) {
481 return STAT_NORETRY;
484 xfd->addr = &addr_openssl_listen;
485 xfd->dtype = XIODATA_OPENSSL;
487 while (true) { /* loop over failed attempts */
489 #if WITH_RETRY
490 if (xfd->forever || xfd->retry) {
491 level = E_INFO;
492 } else
493 #endif /* WITH_RETRY */
494 level = E_ERROR;
496 /* tcp listen; this can fork() for us; it only returns on error or on
497 successful establishment of tcp connection */
498 result = _xioopen_listen(xfd, xioflags,
499 (struct sockaddr *)us, uslen,
500 opts, pf, socktype, IPPROTO_TCP,
501 #if WITH_RETRY
502 (xfd->retry||xfd->forever)?E_INFO:E_ERROR
503 #else
504 E_ERROR
505 #endif /* WITH_RETRY */
507 /*! not sure if we should try again on retry/forever */
508 switch (result) {
509 case STAT_OK: break;
510 #if WITH_RETRY
511 case STAT_RETRYLATER:
512 case STAT_RETRYNOW:
513 if (xfd->forever || xfd->retry) {
514 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
515 if (result == STAT_RETRYLATER) {
516 Nanosleep(&xfd->intervall, NULL);
518 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
519 --xfd->retry;
520 continue;
522 return STAT_NORETRY;
523 #endif /* WITH_RETRY */
524 default:
525 return result;
528 result = _xioopen_openssl_listen(xfd, opt_ver, opt_commonname, ctx, level);
529 switch (result) {
530 case STAT_OK: break;
531 #if WITH_RETRY
532 case STAT_RETRYLATER:
533 case STAT_RETRYNOW:
534 if (xfd->forever || xfd->retry) {
535 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
536 if (result == STAT_RETRYLATER) {
537 Nanosleep(&xfd->intervall, NULL);
539 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
540 --xfd->retry;
541 continue;
543 return STAT_NORETRY;
544 #endif /* WITH_RETRY */
545 default:
546 return result;
549 openssl_conn_loginfo(xfd->para.openssl.ssl);
550 break;
552 } /* drop out on success */
554 /* fill in the fd structure */
556 return STAT_OK;
560 int _xioopen_openssl_listen(struct single *xfd,
561 bool opt_ver,
562 const char *opt_commonname,
563 SSL_CTX *ctx,
564 int level) {
565 char error_string[120];
566 unsigned long err;
567 int errint, ret;
569 /* create an SSL object */
570 if ((xfd->para.openssl.ssl = sycSSL_new(ctx)) == NULL) {
571 if (ERR_peek_error() == 0) Msg(level, "SSL_new() failed");
572 while (err = ERR_get_error()) {
573 Msg1(level, "SSL_new(): %s", ERR_error_string(err, NULL));
575 /*Error("SSL_new()");*/
576 return STAT_NORETRY;
579 /* assign the network connection to the SSL object */
580 if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
581 if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed");
582 while (err = ERR_get_error()) {
583 Msg2(level, "SSL_set_fd(, %d): %s",
584 xfd->fd, ERR_error_string(err, NULL));
588 #if WITH_DEBUG
590 int i = 0;
591 const char *ciphers = NULL;
592 Debug("available ciphers:");
593 do {
594 ciphers = SSL_get_cipher_list(xfd->para.openssl.ssl, i);
595 if (ciphers == NULL) break;
596 Debug2("CIPHERS pri=%d: %s", i, ciphers);
597 ++i;
598 } while (1);
600 #endif /* WITH_DEBUG */
602 /* connect via SSL by performing handshake */
603 if ((ret = sycSSL_accept(xfd->para.openssl.ssl)) <= 0) {
604 /*if (ERR_peek_error() == 0) Msg(level, "SSL_accept() failed");*/
605 errint = SSL_get_error(xfd->para.openssl.ssl, ret);
606 switch (errint) {
607 case SSL_ERROR_NONE:
608 Msg(level, "ok"); break;
609 case SSL_ERROR_ZERO_RETURN:
610 Msg(level, "connection closed (wrong version number?)"); break;
611 case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE:
612 case SSL_ERROR_WANT_CONNECT:
613 case SSL_ERROR_WANT_X509_LOOKUP:
614 Msg(level, "nonblocking operation did not complete"); break; /*!*/
615 case SSL_ERROR_SYSCALL:
616 if (ERR_peek_error() == 0) {
617 if (ret == 0) {
618 Msg(level, "SSL_accept(): socket closed by peer");
619 } else if (ret == -1) {
620 Msg1(level, "SSL_accept(): %s", strerror(errno));
622 } else {
623 Msg(level, "I/O error"); /*!*/
624 while (err = ERR_get_error()) {
625 ERR_error_string_n(err, error_string, sizeof(error_string));
626 Msg4(level, "SSL_accept(): %s / %s / %s / %s", error_string,
627 ERR_lib_error_string(err), ERR_func_error_string(err),
628 ERR_reason_error_string(err));
630 /* Msg1(level, "SSL_accept(): %s", ERR_error_string(e, buf));*/
632 break;
633 case SSL_ERROR_SSL:
634 /*ERR_print_errors_fp(stderr);*/
635 openssl_SSL_ERROR_SSL(level, "SSL_accept");
636 break;
637 default:
638 Msg(level, "unknown error");
641 return STAT_RETRYLATER;
644 if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, E_ERROR/*!*/) < 0) {
645 return STAT_NORETRY;
648 return STAT_OK;
651 #endif /* WITH_LISTEN */
654 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
655 /* In OpenSSL 0.9.7 compression methods could be added using
656 * SSL_COMP_add_compression_method(3), but the implemntation is not compatible
657 * with the standard (RFC3749).
659 static int openssl_setup_compression(SSL_CTX *ctx, char *method)
661 STACK_OF(SSL_COMP)* comp_methods;
663 assert(method);
665 /* Getting the stack of compression methods has the intended side-effect of
666 * initializing the SSL library's compression part.
668 comp_methods = SSL_COMP_get_compression_methods();
669 if (!comp_methods) {
670 Info("OpenSSL built without compression support");
671 return STAT_OK;
674 if (strcasecmp(method, "auto") == 0) {
675 Info("Using default OpenSSL compression");
676 return STAT_OK;
679 if (strcasecmp(method, "none") == 0) {
680 /* Disable compression */
681 #ifdef SSL_OP_NO_COMPRESSION
682 Info("Disabling OpenSSL compression");
683 SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
684 #else
685 /* SSL_OP_NO_COMPRESSION was only introduced in OpenSSL 0.9.9 (released
686 * as 1.0.0). Removing all compression methods is a work-around for
687 * earlier versions of OpenSSL, but it affects all SSL connections.
689 Info("Disabling OpenSSL compression globally");
690 sk_SSL_COMP_zero(comp_methods);
691 #endif
692 return STAT_OK;
695 /* zlib compression in OpenSSL before version 0.9.8e-beta1 uses the libc's
696 * default malloc/free instead of the ones passed to OpenSSL. Should socat
697 * ever use custom malloc/free functions for OpenSSL, this must be taken
698 * into consideration. See OpenSSL bug #1468.
701 Error1("openssl-compress=\"%s\": unknown compression method", method);
702 return STAT_NORETRY;
704 #endif
708 _xioopen_openssl_prepare(struct opt *opts,
709 struct single *xfd,/* a xio file descriptor
710 structure, already allocated
712 bool server, /* SSL client: false */
713 bool *opt_ver,
714 const char *opt_cert,
715 SSL_CTX **ctx)
717 bool opt_fips = false;
718 const SSL_METHOD *method = NULL;
719 char *me_str = NULL; /* method string */
720 char *ci_str = "HIGH:-NULL:-PSK:-aNULL"; /* cipher string */
721 char *opt_key = NULL; /* file name of client private key */
722 char *opt_dhparam = NULL; /* file name of DH params */
723 char *opt_cafile = NULL; /* certificate authority file */
724 char *opt_capath = NULL; /* certificate authority directory */
725 char *opt_egd = NULL; /* entropy gathering daemon socket path */
726 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
727 char *opt_compress = NULL; /* compression method */
728 #endif
729 bool opt_pseudo = false; /* use pseudo entropy if nothing else */
730 unsigned long err;
731 int result;
733 xfd->addr = &addr_openssl;
734 xfd->dtype = XIODATA_OPENSSL;
736 retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
737 retropt_string(opts, OPT_OPENSSL_METHOD, &me_str);
738 retropt_string(opts, OPT_OPENSSL_CIPHERLIST, &ci_str);
739 retropt_bool(opts, OPT_OPENSSL_VERIFY, opt_ver);
740 retropt_string(opts, OPT_OPENSSL_CAFILE, &opt_cafile);
741 retropt_string(opts, OPT_OPENSSL_CAPATH, &opt_capath);
742 retropt_string(opts, OPT_OPENSSL_KEY, &opt_key);
743 retropt_string(opts, OPT_OPENSSL_DHPARAM, &opt_dhparam);
744 retropt_string(opts, OPT_OPENSSL_EGD, &opt_egd);
745 retropt_bool(opts,OPT_OPENSSL_PSEUDO, &opt_pseudo);
746 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
747 retropt_string(opts, OPT_OPENSSL_COMPRESS, &opt_compress);
748 #endif
749 #if WITH_FIPS
750 if (opt_fips) {
751 if (!sycFIPS_mode_set(1)) {
752 ERR_load_crypto_strings();
753 ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
754 Error("Failed to set FIPS mode");
755 } else {
756 xio_openssl_fips = true;
759 #endif
761 openssl_delete_cert_info();
763 OpenSSL_add_all_algorithms();
764 OpenSSL_add_all_ciphers();
765 OpenSSL_add_all_digests();
766 sycSSL_load_error_strings();
768 /* OpenSSL preparation */
769 sycSSL_library_init();
771 /*! actions_to_seed_PRNG();*/
773 if (!server) {
774 if (me_str != NULL) {
775 if (false) {
776 ; /* for canonical reasons */
777 #if HAVE_SSLv2_client_method
778 } else if (!strcasecmp(me_str, "SSL2")) {
779 method = sycSSLv2_client_method();
780 #endif
781 #if HAVE_SSLv3_client_method
782 } else if (!strcasecmp(me_str, "SSL3")) {
783 method = sycSSLv3_client_method();
784 #endif
785 #if HAVE_SSLv23_client_method
786 } else if (!strcasecmp(me_str, "SSL23")) {
787 method = sycSSLv23_client_method();
788 #endif
789 #if HAVE_TLSv1_client_method
790 } else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
791 method = sycTLSv1_client_method();
792 #endif
793 #if HAVE_TLSv1_1_client_method
794 } else if (!strcasecmp(me_str, "TLS1.1")) {
795 method = sycTLSv1_1_client_method();
796 #endif
797 #if HAVE_TLSv1_2_client_method
798 } else if (!strcasecmp(me_str, "TLS1.2")) {
799 method = sycTLSv1_2_client_method();
800 #endif
801 #if HAVE_DTLSv1_client_method
802 } else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
803 method = sycDTLSv1_client_method();
804 #endif
805 } else {
806 Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
808 } else {
809 #if HAVE_SSLv23_client_method
810 method = sycSSLv23_client_method();
811 #elif HAVE_TLSv1_2_client_method
812 method = sycTLSv1_2_client_method();
813 #elif HAVE_TLSv1_1_client_method
814 method = sycTLSv1_1_client_method();
815 #elif HAVE_TLSv1_client_method
816 method = sycTLSv1_client_method();
817 #elif HAVE_SSLv3_client_method
818 method = sycSSLv3_client_method();
819 #elif HAVE_SSLv2_client_method
820 method = sycSSLv2_client_method();
821 #else
822 # error "OpenSSL does not seem to provide client methods"
823 #endif
825 } else /* server */ {
826 if (me_str != 0) {
827 if (false) {
828 ; /* for canonical reasons */
830 #if HAVE_SSLv2_server_method
831 } else if (!strcasecmp(me_str, "SSL2")) {
832 method = sycSSLv2_server_method();
833 #endif
834 #if HAVE_SSLv3_server_method
835 } else if (!strcasecmp(me_str, "SSL3")) {
836 method = sycSSLv3_server_method();
837 #endif
838 #if HAVE_SSLv23_server_method
839 } else if (!strcasecmp(me_str, "SSL23")) {
840 method = sycSSLv23_server_method();
841 #endif
842 #if HAVE_TLSv1_server_method
843 } else if (!strcasecmp(me_str, "TLS1") || !strcasecmp(me_str, "TLS1.0")) {
844 method = sycTLSv1_server_method();
845 #endif
846 #if HAVE_TLSv1_1_server_method
847 } else if (!strcasecmp(me_str, "TLS1.1")) {
848 method = sycTLSv1_1_server_method();
849 #endif
850 #if HAVE_TLSv1_2_server_method
851 } else if (!strcasecmp(me_str, "TLS1.2")) {
852 method = sycTLSv1_2_server_method();
853 #endif
854 #if HAVE_DTLSv1_server_method
855 } else if (!strcasecmp(me_str, "DTLS") || !strcasecmp(me_str, "DTLS1")) {
856 method = sycDTLSv1_server_method();
857 #endif
858 } else {
859 Error1("openssl-method=\"%s\": method unknown or not provided by library", me_str);
861 } else {
862 #if HAVE_SSLv23_server_method
863 method = sycSSLv23_server_method();
864 #elif HAVE_TLSv1_2_server_method
865 method = sycTLSv1_2_server_method();
866 #elif HAVE_TLSv1_1_server_method
867 method = sycTLSv1_1_server_method();
868 #elif HAVE_TLSv1_server_method
869 method = sycTLSv1_server_method();
870 #elif HAVE_SSLv3_server_method
871 method = sycSSLv3_server_method();
872 #elif HAVE_SSLv2_server_method
873 method = sycSSLv2_server_method();
874 #else
875 # error "OpenSSL does not seem to provide client methods"
876 #endif
880 if (opt_egd) {
881 sycRAND_egd(opt_egd);
884 if (opt_pseudo) {
885 long int randdata;
886 /* initialize libc random from actual microseconds */
887 struct timeval tv;
888 struct timezone tz;
889 tz.tz_minuteswest = 0;
890 tz.tz_dsttime = 0;
891 if ((result = Gettimeofday(&tv, &tz)) < 0) {
892 Warn2("gettimeofday(%p, {0,0}): %s", &tv, strerror(errno));
894 srandom(tv.tv_sec*1000000+tv.tv_usec);
896 while (!RAND_status()) {
897 randdata = random();
898 Debug2("RAND_seed(0x{%lx}, "F_Zu")",
899 randdata, sizeof(randdata));
900 RAND_seed(&randdata, sizeof(randdata));
904 if ((*ctx = sycSSL_CTX_new(method)) == NULL) {
905 if (ERR_peek_error() == 0) Error("SSL_CTX_new()");
906 while (err = ERR_get_error()) {
907 Error1("SSL_CTX_new(): %s", ERR_error_string(err, NULL));
910 /*ERR_clear_error;*/
911 return STAT_RETRYLATER;
915 static unsigned char dh1024_p[] = {
916 0xCC,0x17,0xF2,0xDC,0x96,0xDF,0x59,0xA4,0x46,0xC5,0x3E,0x0E,
917 0xB8,0x26,0x55,0x0C,0xE3,0x88,0xC1,0xCE,0xA7,0xBC,0xB3,0xBF,
918 0x16,0x94,0xD8,0xA9,0x45,0xA2,0xCE,0xA9,0x5B,0x22,0x25,0x5F,
919 0x92,0x59,0x94,0x1C,0x22,0xBF,0xCB,0xC8,0xC8,0x57,0xCB,0xBF,
920 0xBC,0x0E,0xE8,0x40,0xF9,0x87,0x03,0xBF,0x60,0x9B,0x08,0xC6,
921 0x8E,0x99,0xC6,0x05,0xFC,0x00,0xD6,0x6D,0x90,0xA8,0xF5,0xF8,
922 0xD3,0x8D,0x43,0xC8,0x8F,0x7A,0xBD,0xBB,0x28,0xAC,0x04,0x69,
923 0x4A,0x0B,0x86,0x73,0x37,0xF0,0x6D,0x4F,0x04,0xF6,0xF5,0xAF,
924 0xBF,0xAB,0x8E,0xCE,0x75,0x53,0x4D,0x7F,0x7D,0x17,0x78,0x0E,
925 0x12,0x46,0x4A,0xAF,0x95,0x99,0xEF,0xBC,0xA6,0xC5,0x41,0x77,
926 0x43,0x7A,0xB9,0xEC,0x8E,0x07,0x3C,0x6D,
928 static unsigned char dh1024_g[] = {
929 0x02,
931 DH *dh;
932 unsigned long err;
934 if ((dh = DH_new()) == NULL) {
935 while (err = ERR_get_error()) {
936 Warn1("DH_new(): %s",
937 ERR_error_string(err, NULL));
939 Error("DH_new() failed");
940 } else {
941 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
942 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
943 if ((dh->p == NULL) || (dh->g == NULL)) {
944 while (err = ERR_get_error()) {
945 Warn1("BN_bin2bn(): %s",
946 ERR_error_string(err, NULL));
948 Error("BN_bin2bn() failed");
949 } else {
950 if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
951 while (err = ERR_get_error()) {
952 Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
953 ERR_error_string(err, NULL));
955 Error2("SSL_CTX_set_tmp_dh(%p, %p) failed", *ctx, dh);
957 /*! OPENSSL_free(dh->p,g)? doc does not tell so */
959 DH_free(dh);
963 #if defined(EC_KEY) /* not on Openindiana 5.11 */
965 /* see http://openssl.6102.n7.nabble.com/Problem-with-cipher-suite-ECDHE-ECDSA-AES256-SHA384-td42229.html */
966 int nid;
967 EC_KEY *ecdh;
969 #if 0
970 nid = OBJ_sn2nid(ECDHE_CURVE);
971 if (nid == NID_undef) {
972 Error("openssl: failed to set ECDHE parameters");
973 return -1;
975 #endif
976 nid = NID_X9_62_prime256v1;
977 ecdh = EC_KEY_new_by_curve_name(nid);
978 if (NULL == ecdh) {
979 Error("openssl: failed to set ECDHE parameters");
980 return -1;
983 SSL_CTX_set_tmp_ecdh(*ctx, ecdh);
985 #endif /* !defined(EC_KEY) */
987 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
988 if (opt_compress) {
989 int result;
990 result = openssl_setup_compression(*ctx, opt_compress);
991 if (result != STAT_OK) {
992 return result;
995 #endif
997 if (opt_cafile != NULL || opt_capath != NULL) {
998 if (sycSSL_CTX_load_verify_locations(*ctx, opt_cafile, opt_capath) != 1) {
999 int result;
1001 if ((result =
1002 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_CTX_load_verify_locations"))
1003 != STAT_OK) {
1004 /*! free ctx */
1005 return STAT_RETRYLATER;
1008 #ifdef HAVE_SSL_CTX_set_default_verify_paths
1009 } else {
1010 SSL_CTX_set_default_verify_paths(*ctx);
1011 #endif
1014 if (opt_cert) {
1015 BIO *bio;
1016 DH *dh;
1018 if (sycSSL_CTX_use_certificate_chain_file(*ctx, opt_cert) <= 0) {
1019 /*! trace functions */
1020 /*0 ERR_print_errors_fp(stderr);*/
1021 if (ERR_peek_error() == 0)
1022 Error2("SSL_CTX_use_certificate_file(%p, \"%s\", SSL_FILETYPE_PEM) failed",
1023 *ctx, opt_cert);
1024 while (err = ERR_get_error()) {
1025 Error1("SSL_CTX_use_certificate_file(): %s",
1026 ERR_error_string(err, NULL));
1028 return STAT_RETRYLATER;
1031 if (sycSSL_CTX_use_PrivateKey_file(*ctx, opt_key?opt_key:opt_cert, SSL_FILETYPE_PEM) <= 0) {
1032 /*ERR_print_errors_fp(stderr);*/
1033 openssl_SSL_ERROR_SSL(E_ERROR/*!*/, "SSL_CTX_use_PrivateKey_file");
1034 return STAT_RETRYLATER;
1037 if (opt_dhparam == NULL) {
1038 opt_dhparam = (char *)opt_cert;
1040 if ((bio = sycBIO_new_file(opt_dhparam, "r")) == NULL) {
1041 Warn2("BIO_new_file(\"%s\", \"r\"): %s",
1042 opt_dhparam, strerror(errno));
1043 } else {
1044 if ((dh = sycPEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) {
1045 Info1("PEM_read_bio_DHparams(%p, NULL, NULL, NULL): error", bio);
1046 } else {
1047 BIO_free(bio);
1048 if (sycSSL_CTX_set_tmp_dh(*ctx, dh) <= 0) {
1049 while (err = ERR_get_error()) {
1050 Warn3("SSL_CTX_set_tmp_dh(%p, %p): %s", *ctx, dh,
1051 ERR_error_string(err, NULL));
1053 Error2("SSL_CTX_set_tmp_dh(%p, %p): error", *ctx, dh);
1059 /* set pre ssl-connect options */
1060 /* SSL_CIPHERS */
1061 if (ci_str != NULL) {
1062 if (sycSSL_CTX_set_cipher_list(*ctx, ci_str) <= 0) {
1063 if (ERR_peek_error() == 0)
1064 Error1("SSL_set_cipher_list(, \"%s\") failed", ci_str);
1065 while (err = ERR_get_error()) {
1066 Error2("SSL_set_cipher_list(, \"%s\"): %s",
1067 ci_str, ERR_error_string(err, NULL));
1069 /*Error("SSL_new()");*/
1070 return STAT_RETRYLATER;
1074 if (*opt_ver) {
1075 sycSSL_CTX_set_verify(*ctx,
1076 SSL_VERIFY_PEER| SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1077 NULL);
1078 } else {
1079 sycSSL_CTX_set_verify(*ctx,
1080 SSL_VERIFY_NONE,
1081 NULL);
1084 return STAT_OK;
1088 /* analyses an OpenSSL error condition, prints the appropriate messages with
1089 severity 'level' and returns one of STAT_OK, STAT_RETRYLATER, or
1090 STAT_NORETRY */
1091 static int openssl_SSL_ERROR_SSL(int level, const char *funcname) {
1092 unsigned long e;
1093 char buf[120]; /* this value demanded by "man ERR_error_string" */
1094 int stat = STAT_OK;
1096 while (e = ERR_get_error()) {
1097 Debug1("ERR_get_error(): %lx", e);
1098 if (e == ((ERR_LIB_RAND<<24)|
1099 (RAND_F_SSLEAY_RAND_BYTES<<12)|
1100 (RAND_R_PRNG_NOT_SEEDED)) /*0x24064064*/) {
1101 Error("too few entropy; use options \"egd\" or \"pseudo\"");
1102 stat = STAT_NORETRY;
1103 } else {
1104 Msg2(level, "%s(): %s", funcname, ERR_error_string(e, buf));
1105 stat = level==E_ERROR ? STAT_NORETRY : STAT_RETRYLATER;
1108 return stat;
1111 static const char *openssl_verify_messages[] = {
1112 /* 0 */ "ok",
1113 /* 1 */ NULL,
1114 /* 2 */ "unable to get issuer certificate",
1115 /* 3 */ "unable to get certificate CRL",
1116 /* 4 */ "unable to decrypt certificate's signature",
1117 /* 5 */ "unable to decrypt CRL's signature",
1118 /* 6 */ "unable to decode issuer public key",
1119 /* 7 */ "certificate signature failure",
1120 /* 8 */ "CRL signature failure",
1121 /* 9 */ "certificate is not yet valid",
1122 /* 10 */ "certificate has expired",
1123 /* 11 */ "CRL is not yet valid",
1124 /* 12 */ "CRL has expired",
1125 /* 13 */ "format error in certificate's notBefore field",
1126 /* 14 */ "format error in certificate's notAfter field",
1127 /* 15 */ "format error in CRL's lastUpdate field",
1128 /* 16 */ "format error in CRL's nextUpdate field",
1129 /* 17 */ "out of memory",
1130 /* 18 */ "self signed certificate",
1131 /* 19 */ "self signed certificate in certificate chain",
1132 /* 20 */ "unable to get local issuer certificate",
1133 /* 21 */ "unable to verify the first certificate",
1134 /* 22 */ "certificate chain too long",
1135 /* 23 */ "certificate revoked",
1136 /* 24 */ "invalid CA certificate",
1137 /* 25 */ "path length constraint exceeded",
1138 /* 26 */ "unsupported certificate purpose",
1139 /* 27 */ "certificate not trusted",
1140 /* 28 */ "certificate rejected",
1141 /* 29 */ "subject issuer mismatch",
1142 /* 30 */ "authority and subject key identifier mismatch",
1143 /* 31 */ "authority and issuer serial number mismatch",
1144 /* 32 */ "key usage does not include certificate signing",
1145 /* 33 */ NULL,
1146 /* 34 */ NULL,
1147 /* 35 */ NULL,
1148 /* 36 */ NULL,
1149 /* 37 */ NULL,
1150 /* 38 */ NULL,
1151 /* 39 */ NULL,
1152 /* 40 */ NULL,
1153 /* 41 */ NULL,
1154 /* 42 */ NULL,
1155 /* 43 */ NULL,
1156 /* 44 */ NULL,
1157 /* 45 */ NULL,
1158 /* 46 */ NULL,
1159 /* 47 */ NULL,
1160 /* 48 */ NULL,
1161 /* 49 */ NULL,
1162 /* 50 */ "application verification failure",
1166 /* delete all environment variables whose name begins with SOCAT_OPENSSL_
1167 resp. <progname>_OPENSSL_ */
1168 static int openssl_delete_cert_info(void) {
1169 # define XIO_ENVNAMELEN 256
1170 const char *progname;
1171 char envprefix[XIO_ENVNAMELEN];
1172 char envname[XIO_ENVNAMELEN];
1173 size_t i, l;
1174 const char **entry;
1176 progname = diag_get_string('p');
1177 envprefix[0] = '\0'; strncat(envprefix, progname, XIO_ENVNAMELEN-1);
1178 l = strlen(envprefix);
1179 for (i = 0; i < l; ++i) envprefix[i] = toupper(envprefix[i]);
1180 strncat(envprefix+l, "_OPENSSL_", XIO_ENVNAMELEN-l-1);
1182 #if HAVE_VAR_ENVIRON
1183 entry = (const char **)environ;
1184 while (*entry != NULL) {
1185 if (!strncmp(*entry, envprefix, strlen(envprefix))) {
1186 const char *eq = strchr(*entry, '=');
1187 if (eq == NULL) eq = *entry + strlen(*entry);
1188 envname[0] = '\0'; strncat(envname, *entry, eq-*entry);
1189 Unsetenv(envname);
1190 } else {
1191 ++entry;
1194 #endif /* HAVE_VAR_ENVIRON */
1195 return 0;
1198 /* read in the "name" information (from field "issuer" or "subject") and
1199 create environment variable with complete info, eg:
1200 SOCAT_OPENSSL_X509_SUBJECT */
1201 static int openssl_setenv_cert_name(const char *field, X509_NAME *name) {
1202 BIO *bio = BIO_new(BIO_s_mem());
1203 char *buf = NULL, *str;
1204 size_t len;
1205 X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE&~ASN1_STRFLGS_ESC_MSB); /* rc not documented */
1206 len = BIO_get_mem_data (bio, &buf);
1207 if ((str = Malloc(len+1)) == NULL) {
1208 BIO_free(bio);
1209 return -1;
1211 memcpy(str, buf, len);
1212 str[len] = '\0';
1213 Info2("SSL peer cert %s: \"%s\"", field, buf);
1214 xiosetenv2("OPENSSL_X509", field, str, 1, NULL);
1215 free(str);
1216 BIO_free(bio);
1217 return 0;
1220 /* read in the "name" information (from field "issuer" or "subject") and
1221 create environment variables with the fields, eg:
1222 SOCAT_OPENSSL_X509_COMMONNAME
1224 static int openssl_setenv_cert_fields(const char *field, X509_NAME *name) {
1225 int n, i;
1226 n = X509_NAME_entry_count(name);
1227 /* extract fields of cert name */
1228 for (i = 0; i < n; ++i) {
1229 X509_NAME_ENTRY *entry;
1230 ASN1_OBJECT *obj;
1231 ASN1_STRING *data;
1232 unsigned char *text;
1233 int nid;
1234 entry = X509_NAME_get_entry(name, i);
1235 obj = X509_NAME_ENTRY_get_object(entry);
1236 data = X509_NAME_ENTRY_get_data(entry);
1237 nid = OBJ_obj2nid(obj);
1238 text = ASN1_STRING_data(data);
1239 Debug3("SSL peer cert %s entry: %s=\"%s\"", (field[0]?field:"subject"), OBJ_nid2ln(nid), text);
1240 if (field != NULL && field[0] != '\0') {
1241 xiosetenv3("OPENSSL_X509", field, OBJ_nid2ln(nid), (const char *)text, 2, " // ");
1242 } else {
1243 xiosetenv2("OPENSSL_X509", OBJ_nid2ln(nid), (const char *)text, 2, " // ");
1246 return 0;
1249 /* compares the peername used/provided by the client to cn as extracted from
1250 the peer certificate.
1251 supports wildcard cn like *.domain which matches domain and
1252 host.domain
1253 returns true on match */
1254 static bool openssl_check_name(const char *cn, const char *peername) {
1255 const char *dotp;
1256 if (peername == NULL) {
1257 Info1("commonName \"%s\": no peername", cn);
1258 return false;
1259 } else if (peername[0] == '\0') {
1260 Info1("commonName \"%s\": matched by empty peername", cn);
1261 return true;
1263 if (! (cn[0] == '*' && cn[1] == '.')) {
1264 /* normal server name - this is simple */
1265 Debug1("commonName \"%s\" has no wildcard", cn);
1266 if (strcmp(cn, peername) == 0) {
1267 Debug2("commonName \"%s\" matches peername \"%s\"", cn, peername);
1268 return true;
1269 } else {
1270 Info2("commonName \"%s\" does not match peername \"%s\"", cn, peername);
1271 return false;
1274 /* wildcard cert */
1275 Debug1("commonName \"%s\" is a wildcard name", cn);
1276 /* case: just the base domain */
1277 if (strcmp(cn+2, peername) == 0) {
1278 Debug2("wildcard commonName \"%s\" matches base domain \"%s\"", cn, peername);
1279 return true;
1281 /* case: subdomain; only one level! */
1282 dotp = strchr(peername, '.');
1283 if (dotp == NULL) {
1284 Info2("peername \"%s\" is not a subdomain, thus is not matched by wildcard commonName \"%s\"",
1285 peername, cn);
1286 return false;
1288 if (strcmp(cn+1, dotp) != 0) {
1289 Info2("commonName \"%s\" does not match subdomain peername \"%s\"", cn, peername);
1290 return false;
1292 Debug2("commonName \"%s\" matches subdomain peername \"%s\"", cn, peername);
1293 return true;
1296 /* retrieves the commonName field and compares it to the peername
1297 returns true on match, false otherwise */
1298 static bool openssl_check_peername(X509_NAME *name, const char *peername) {
1299 int ind = -1;
1300 X509_NAME_ENTRY *entry;
1301 ASN1_STRING *data;
1302 unsigned char *text;
1303 ind = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
1304 if (ind < 0) {
1305 Info("no COMMONNAME field in peer certificate");
1306 return false;
1308 entry = X509_NAME_get_entry(name, ind);
1309 data = X509_NAME_ENTRY_get_data(entry);
1310 text = ASN1_STRING_data(data);
1311 return openssl_check_name((const char *)text, peername);
1314 /* retrieves certificate provided by peer, sets env vars containing
1315 certificates field values, and checks peername if provided by
1316 calling function */
1317 /* parts of this code were copied from Gene Spaffords C/C++ Secure Programming at Etutorials.org:
1318 http://etutorials.org/Programming/secure+programming/Chapter+10.+Public+Key+Infrastructure/10.8+Adding+Hostname+Checking+to+Certificate+Verification/
1319 The code examples in this tutorial do not seem to have explicit license restrictions.
1321 static int openssl_handle_peer_certificate(struct single *xfd,
1322 const char *peername,
1323 bool opt_ver, int level) {
1324 X509 *peer_cert;
1325 X509_NAME *subjectname, *issuername;
1326 /*ASN1_TIME not_before, not_after;*/
1327 int extcount, i, ok = 0;
1328 int status;
1330 if ((peer_cert = SSL_get_peer_certificate(xfd->para.openssl.ssl)) == NULL) {
1331 if (opt_ver) {
1332 Msg(level, "no peer certificate");
1333 status = STAT_RETRYLATER;
1334 } else {
1335 Notice("no peer certificate and no check");
1336 status = STAT_OK;
1338 return status;
1341 /* verify peer certificate (trust, signature, validity dates) */
1342 if (opt_ver) {
1343 long verify_result;
1344 if ((verify_result = sycSSL_get_verify_result(xfd->para.openssl.ssl)) != X509_V_OK) {
1345 const char *message = NULL;
1346 if (verify_result >= 0 &&
1347 (size_t)verify_result <
1348 sizeof(openssl_verify_messages)/sizeof(char*)) {
1349 message = openssl_verify_messages[verify_result];
1351 if (message) {
1352 Msg1(level, "%s", message);
1353 } else {
1354 Msg1(level, "rejected peer certificate with error %ld", verify_result);
1356 status = STAT_RETRYLATER;
1357 X509_free(peer_cert);
1358 return STAT_RETRYLATER;
1360 Info("peer certificate is trusted");
1363 /* set env vars from cert's subject and issuer values */
1364 if ((subjectname = X509_get_subject_name(peer_cert)) != NULL) {
1365 openssl_setenv_cert_name("subject", subjectname);
1366 openssl_setenv_cert_fields("", subjectname);
1367 /*! I'd like to provide dates too; see
1368 http://markmail.org/message/yi4vspp7aeu3xwtu#query:+page:1+mid:jhnl4wklif3pgzqf+state:results */
1370 if ((issuername = X509_get_issuer_name(peer_cert)) != NULL) {
1371 openssl_setenv_cert_name("issuer", issuername);
1374 /* check peername against cert's subjectAltName DNS entries */
1375 /* this code is based on example from Gerhard Gappmeier in
1376 http://openssl.6102.n7.nabble.com/How-to-extract-subjectAltName-td17236.html
1378 if ((extcount = X509_get_ext_count(peer_cert)) > 0) {
1379 for (i = 0; !ok && i < extcount; ++i) {
1380 const char *extstr;
1381 X509_EXTENSION *ext;
1382 const X509V3_EXT_METHOD *meth;
1383 ext = X509_get_ext(peer_cert, i);
1384 extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
1385 if (!strcasecmp(extstr, "subjectAltName")) {
1386 void *names;
1387 if (!(meth = X509V3_EXT_get(ext))) break;
1388 names = X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
1389 if (names) {
1390 int numalts;
1391 int i;
1393 /* get amount of alternatives, RFC2459 claims there MUST be at least one, but we don't depend on it... */
1394 numalts = sk_GENERAL_NAME_num ( names );
1395 /* loop through all alternatives */
1396 for ( i=0; ( i<numalts ); i++ ) {
1397 /* get a handle to alternative name number i */
1398 const GENERAL_NAME *pName = sk_GENERAL_NAME_value (names, i );
1399 unsigned char *pBuffer;
1400 switch ( pName->type ) {
1402 case GEN_DNS:
1403 ASN1_STRING_to_UTF8(&pBuffer,
1404 pName->d.ia5);
1405 xiosetenv("OPENSSL_X509V3_SUBJECTALTNAME_DNS", (char *)pBuffer, 2, " // ");
1406 if (peername != NULL &&
1407 openssl_check_name((char *)pBuffer, /*const char*/peername)) {
1408 ok = 1;
1410 OPENSSL_free(pBuffer);
1411 break;
1413 default: continue;
1421 if (!opt_ver) {
1422 Notice("option openssl-verify disabled, no check of certificate");
1423 X509_free(peer_cert);
1424 return STAT_OK;
1426 if (peername == NULL || peername[0] == '\0') {
1427 Notice("trusting certificate, no check of commonName");
1428 X509_free(peer_cert);
1429 return STAT_OK;
1431 if (ok) {
1432 Notice("trusting certificate, commonName matches");
1433 X509_free(peer_cert);
1434 return STAT_OK;
1437 /* here: all envs set; opt_ver, cert verified, no subjAltName match -> check subject CN */
1438 if (!openssl_check_peername(/*X509_NAME*/subjectname, /*const char*/peername)) {
1439 Error("certificate is valid but its commonName does not match hostname");
1440 status = STAT_NORETRY;
1441 } else {
1442 Notice("trusting certificate, commonName matches");
1443 status = STAT_OK;
1445 X509_free(peer_cert);
1446 return status;
1449 static int xioSSL_set_fd(struct single *xfd, int level) {
1450 unsigned long err;
1452 /* assign a network connection to the SSL object */
1453 if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
1454 Msg(level, "SSL_set_fd() failed");
1455 while (err = ERR_get_error()) {
1456 Msg2(level, "SSL_set_fd(, %d): %s",
1457 xfd->fd, ERR_error_string(err, NULL));
1459 return STAT_RETRYLATER;
1461 return STAT_OK;
1465 /* ...
1466 in case of an error condition, this function check forever and retry
1467 options and ev. sleeps an interval. It returns NORETRY when the caller
1468 should not retry for any reason. */
1469 static int xioSSL_connect(struct single *xfd, const char *opt_commonname,
1470 bool opt_ver, int level) {
1471 char error_string[120];
1472 int errint, status, ret;
1473 unsigned long err;
1475 /* connect via SSL by performing handshake */
1476 if ((ret = sycSSL_connect(xfd->para.openssl.ssl)) <= 0) {
1477 /*if (ERR_peek_error() == 0) Msg(level, "SSL_connect() failed");*/
1478 errint = SSL_get_error(xfd->para.openssl.ssl, ret);
1479 switch (errint) {
1480 case SSL_ERROR_NONE:
1481 /* this is not an error, but I dare not continue for security reasons*/
1482 Msg(level, "ok");
1483 status = STAT_RETRYLATER;
1484 case SSL_ERROR_ZERO_RETURN:
1485 Msg(level, "connection closed (wrong version number?)");
1486 status = STAT_RETRYLATER;
1487 break;
1488 case SSL_ERROR_WANT_READ:
1489 case SSL_ERROR_WANT_WRITE:
1490 case SSL_ERROR_WANT_CONNECT:
1491 case SSL_ERROR_WANT_X509_LOOKUP:
1492 Msg(level, "nonblocking operation did not complete");
1493 status = STAT_RETRYLATER;
1494 break; /*!*/
1495 case SSL_ERROR_SYSCALL:
1496 if (ERR_peek_error() == 0) {
1497 if (ret == 0) {
1498 Msg(level, "SSL_connect(): socket closed by peer");
1499 } else if (ret == -1) {
1500 Msg1(level, "SSL_connect(): %s", strerror(errno));
1502 } else {
1503 Msg(level, "I/O error"); /*!*/
1504 while (err = ERR_get_error()) {
1505 ERR_error_string_n(err, error_string, sizeof(error_string));
1506 Msg4(level, "SSL_connect(): %s / %s / %s / %s", error_string,
1507 ERR_lib_error_string(err), ERR_func_error_string(err),
1508 ERR_reason_error_string(err));
1511 status = STAT_RETRYLATER;
1512 break;
1513 case SSL_ERROR_SSL:
1514 status = openssl_SSL_ERROR_SSL(level, "SSL_connect");
1515 if (openssl_handle_peer_certificate(xfd, opt_commonname, opt_ver, level/*!*/) < 0) {
1516 return STAT_RETRYLATER;
1518 break;
1519 default:
1520 Msg(level, "unknown error");
1521 status = STAT_RETRYLATER;
1522 break;
1524 return status;
1526 return STAT_OK;
1529 /* on result < 0: errno is set (at least to EIO) */
1530 ssize_t xioread_openssl(struct single *pipe, void *buff, size_t bufsiz) {
1531 unsigned long err;
1532 char error_string[120];
1533 int _errno = EIO; /* if we have no better idea about nature of error */
1534 int errint, ret;
1536 ret = sycSSL_read(pipe->para.openssl.ssl, buff, bufsiz);
1537 if (ret < 0) {
1538 errint = SSL_get_error(pipe->para.openssl.ssl, ret);
1539 switch (errint) {
1540 case SSL_ERROR_NONE:
1541 /* this is not an error, but I dare not continue for security reasons*/
1542 Error("ok");
1543 break;
1544 case SSL_ERROR_ZERO_RETURN:
1545 Error("connection closed by peer");
1546 break;
1547 case SSL_ERROR_WANT_READ:
1548 case SSL_ERROR_WANT_WRITE:
1549 case SSL_ERROR_WANT_CONNECT:
1550 case SSL_ERROR_WANT_X509_LOOKUP:
1551 Info("nonblocking operation did not complete");
1552 errno = EAGAIN;
1553 return -1;
1554 case SSL_ERROR_SYSCALL:
1555 if (ERR_peek_error() == 0) {
1556 if (ret == 0) {
1557 Error("SSL_read(): socket closed by peer");
1558 } else if (ret == -1) {
1559 _errno = errno;
1560 Error1("SSL_read(): %s", strerror(errno));
1562 } else {
1563 Error("I/O error"); /*!*/
1564 while (err = ERR_get_error()) {
1565 ERR_error_string_n(err, error_string, sizeof(error_string));
1566 Error4("SSL_read(): %s / %s / %s / %s", error_string,
1567 ERR_lib_error_string(err), ERR_func_error_string(err),
1568 ERR_reason_error_string(err));
1571 break;
1572 case SSL_ERROR_SSL:
1573 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
1574 break;
1575 default:
1576 Error("unknown error");
1577 break;
1579 errno = _errno;
1580 return -1;
1582 return ret;
1585 ssize_t xiopending_openssl(struct single *pipe) {
1586 int bytes = sycSSL_pending(pipe->para.openssl.ssl);
1587 return bytes;
1590 /* on result < 0: errno is set (at least to EIO) */
1591 ssize_t xiowrite_openssl(struct single *pipe, const void *buff, size_t bufsiz) {
1592 unsigned long err;
1593 char error_string[120];
1594 int _errno = EIO; /* if we have no better idea about nature of error */
1595 int errint, ret;
1597 ret = sycSSL_write(pipe->para.openssl.ssl, buff, bufsiz);
1598 if (ret < 0) {
1599 errint = SSL_get_error(pipe->para.openssl.ssl, ret);
1600 switch (errint) {
1601 case SSL_ERROR_NONE:
1602 /* this is not an error, but I dare not continue for security reasons*/
1603 Error("ok");
1604 case SSL_ERROR_ZERO_RETURN:
1605 Error("connection closed by peer");
1606 break;
1607 case SSL_ERROR_WANT_READ:
1608 case SSL_ERROR_WANT_WRITE:
1609 case SSL_ERROR_WANT_CONNECT:
1610 case SSL_ERROR_WANT_X509_LOOKUP:
1611 Error("nonblocking operation did not complete");
1612 break; /*!*/
1613 case SSL_ERROR_SYSCALL:
1614 if (ERR_peek_error() == 0) {
1615 if (ret == 0) {
1616 Error("SSL_write(): socket closed by peer");
1617 } else if (ret == -1) {
1618 _errno = errno;
1619 Error1("SSL_write(): %s", strerror(errno));
1621 } else {
1622 Error("I/O error"); /*!*/
1623 while (err = ERR_get_error()) {
1624 ERR_error_string_n(err, error_string, sizeof(error_string));
1625 Error4("SSL_write(): %s / %s / %s / %s", error_string,
1626 ERR_lib_error_string(err), ERR_func_error_string(err),
1627 ERR_reason_error_string(err));
1630 break;
1631 case SSL_ERROR_SSL:
1632 openssl_SSL_ERROR_SSL(E_ERROR, "SSL_connect");
1633 break;
1634 default:
1635 Error("unknown error");
1636 break;
1638 errno = _errno;
1639 return -1;
1641 return ret;
1645 #endif /* WITH_OPENSSL */