5 #define OPENSSL_NO_KRB5
6 #include "wvsslstream.h"
9 #include "wvlistener.h"
11 #include "wvmoniker.h"
12 #include "wvlinkerhack.h"
13 #include <openssl/ssl.h>
14 #include <openssl/err.h>
27 #define errno GetLastError()
29 #define EAGAIN WSAEWOULDBLOCK
36 return new WvSSLStream(IWvStream::create(s, _obj), NULL, 0,
false);
126 l->
addwrap(wv::bind(&IWvStream::create,
"sslserv", _1));
136 if (li.
count() == 3) {
138 connmoniker = *li.
last();
140 }
else if (li.
count() != 2) {
146 IWvListener *l = IWvListener::create(connmoniker, obj);
148 l->
addwrap(wv::bind(&IWvStream::create,
156 #define MAX_BOUNCE_AMOUNT (16384) // 1 SSLv3/TLSv1 record
158 static int ssl_stream_count = 0;
160 static int wv_verify_cb(
int preverify_ok, X509_STORE_CTX *ctx)
167 WvSSLGlobalValidateCallback WvSSLStream::global_vcb = 0;
170 WvSSLValidateCallback _vcb,
bool _is_server) :
172 debug(
WvString(
"WvSSLStream %s", ++ssl_stream_count),
WvLog::Debug5),
173 write_bouncebuf(MAX_BOUNCE_AMOUNT), write_eat(0),
174 read_bouncebuf(MAX_BOUNCE_AMOUNT), read_pending(false)
181 if (!vcb && global_vcb)
182 vcb = wv::bind(global_vcb, _1,
this);;
184 is_server = _is_server;
188 sslconnected = ssl_stop_read = ssl_stop_write =
false;
192 if (x509 && !x509->
isok())
194 seterr(
"Certificate + key pair invalid.");
198 if (is_server && !x509)
200 seterr(
"Certificate not available: server mode not possible!");
206 debug(
"Configured algorithms and methods for server mode.\n");
208 ctx = SSL_CTX_new(SSLv23_server_method());
211 ERR_print_errors_fp(stderr);
212 debug(
"Can't get SSL context! Error: %s\n",
213 ERR_reason_error_string(ERR_get_error()));
214 seterr(
"Can't get SSL context!");
219 SSL_CTX_set_mode(
ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
223 SSL_CTX_set_cipher_list(
ctx,
"HIGH");
227 SSL_CTX_set_options(
ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
231 seterr(
"Unable to bind Certificate to SSL Context!");
235 SSL_CTX_set_verify(
ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
238 debug(
"Server mode ready.\n");
242 debug(
"Configured algorithms and methods for client mode.\n");
244 ctx = SSL_CTX_new(SSLv23_client_method());
247 seterr(
"Can't get SSL context!");
252 seterr(
"Unable to bind Certificate to SSL Context!");
263 seterr(
"Can't create SSL object!");
272 if (!!vcb || is_server)
273 SSL_set_verify(
ssl, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
276 connect_wants.readable =
true;
277 connect_wants.writable =
true;
278 connect_wants.isexception =
false;
279 debug(
"SSL stream initialized.\n");
287 debug(
"Deleting SSL connection.\n");
289 debug(
"Error was: %s\n", errstr());
298 unsigned long l = ERR_get_error();
303 ERR_error_string(l, buf);
304 debug(
"%s error: %s\n", func, buf);
314 if (len == 0)
return 0;
324 if (read_bouncebuf.
used() != 0)
327 size_t amount = len < read_bouncebuf.
used() ?
328 len : read_bouncebuf.
used();
329 read_bouncebuf.move(buf, amount);
336 read_pending =
false;
339 buf = (
unsigned char *)buf + amount;
349 read_bouncebuf.
zap();
350 size_t avail = read_bouncebuf.
free();
351 unsigned char *data = read_bouncebuf.
alloc(avail);
354 int result = SSL_read(
ssl, data, avail);
361 int sslerrcode = SSL_get_error(
ssl, result);
364 case SSL_ERROR_WANT_READ:
365 debug(
"<< SSL_read() needs to wait for writable.\n");
367 case SSL_ERROR_WANT_WRITE:
368 debug(
"<< SSL_read() needs to wait for readable.\n");
374 case SSL_ERROR_ZERO_RETURN:
375 debug(
"<< EOF: zero return\n");
383 case SSL_ERROR_SYSCALL:
388 debug(
"<< EOF: syscall error "
389 "(%s/%s, %s/%s) total=%s\n",
391 isok(), cloned && cloned->
isok(), total);
402 debug(
"<< SSL_read() err=%s (%s)\n",
404 seterr_both(err,
WvString(
"SSL read: %s",
410 printerr(
"SSL_read");
411 seterr(
"SSL read error #%s", sslerrcode);
414 read_pending =
false;
421 read_bouncebuf.
unalloc(avail - result);
434 debug(
">> writing, but not connected yet (%s); enqueue.\n", getwfd());
435 unconnected_buf.put(buf, len);
439 if (len == 0)
return 0;
446 if (write_eat >= len)
454 buf = (
const unsigned char *)buf + write_eat;
465 if (write_bouncebuf.
used() == 0)
473 size_t amount = len < write_bouncebuf.
free() ?
474 len : write_bouncebuf.
free();
475 write_bouncebuf.put(buf, amount);
480 size_t used = write_bouncebuf.
used();
481 const unsigned char *data = write_bouncebuf.
get(used);
484 int result = SSL_write(
ssl, data, used);
489 int sslerrcode = SSL_get_error(
ssl, result);
490 write_bouncebuf.
unget(used);
493 case SSL_ERROR_WANT_READ:
494 debug(
">> SSL_write() needs to wait for readable.\n");
496 case SSL_ERROR_WANT_WRITE:
500 case SSL_ERROR_SYSCALL:
501 debug(
">> ERROR: SSL_write() failed on socket error.\n");
507 debug(
">> ERROR: SSL_write() failed on internal error.\n");
509 ERR_error_string(ERR_get_error(), NULL)));
515 case SSL_ERROR_ZERO_RETURN:
516 debug(
">> SSL_write zero return: EOF\n");
521 printerr(
"SSL_write");
528 assert((
size_t)result == used);
529 write_bouncebuf.
zap();
536 if (
size_t(result) >= len)
540 write_eat = result - len;
544 total += size_t(result);
545 len -= size_t(result);
546 buf = (
const unsigned char *)buf +
size_t(result);
555 debug(
"Closing SSL connection (ok=%s,sr=%s,sw=%s,child=%s).\n",
564 sslconnected =
false;
590 ssl_stop_read =
true;
602 ssl_stop_write =
true;
614 bool oldinherit = si.inherit_request;
617 si.wants = connect_wants;
618 si.inherit_request =
true;
623 if (si.wants.readable && (read_pending || read_bouncebuf.
used()))
627 si.inherit_request = oldinherit;
633 si.inherit_request = oldinherit;
641 bool oldinherit = si.inherit_request;
645 si.wants = connect_wants;
646 si.inherit_request =
true;
651 si.inherit_request = oldinherit;
657 if (!sslconnected && cloned && cloned->
isok() && result)
659 debug(
"!sslconnected in post_select (r=%s/%s, w=%s/%s, t=%s)\n",
664 connect_wants.writable =
false;
669 int fd = fdstream->
getfd();
681 err = SSL_accept(
ssl);
684 err = SSL_connect(
ssl);
689 debug(
"Still waiting for SSL negotiation.\n");
692 printerr(is_server ?
"SSL_accept" :
"SSL_connect");
697 printerr(is_server ?
"SSL_accept" :
"SSL_connect");
703 debug(
"SSL connection using cipher %s.\n", SSL_get_cipher(
ssl));
708 setattr(
"peercert", peercert->
encode(WvX509::CertPEM));
711 debug(
"SSL Peer is: %s\n", peercert->
get_subject());
712 if (peercert->
isok() && peercert->
validate() && vcb(peercert))
715 debug(
"SSL finished negotiating - certificate is valid.\n");
719 if (!peercert->
isok())
722 seterr(
"Peer certificate is invalid!");
728 debug(
"SSL finished negotiating "
729 "- certificate validation disabled.\n");
737 if ((si.wants.readable || readcb)
738 && (read_pending || read_bouncebuf.
used()))
745 void WvSSLStream::setconnected(
bool conn)
748 if (conn)
write(unconnected_buf);