WvStreams
wvsslstream.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 */
5#define OPENSSL_NO_KRB5
6#include "wvsslstream.h"
7#include "wvx509mgr.h"
8#include "wvcrypto.h"
9#include "wvlistener.h"
10#include "wvstrutils.h"
11#include "wvmoniker.h"
12#include "wvlinkerhack.h"
13#include <openssl/ssl.h>
14#include <openssl/err.h>
15#include <assert.h>
16
17#ifndef _WIN32
18# if HAVE_ARGZ_H
19# include <argz.h>
20# else
21# if HAVE_ERRNO_H
22# include <errno.h>
23# endif
24# endif
25#else
26#undef errno
27#define errno GetLastError()
28#undef EAGAIN
29#define EAGAIN WSAEWOULDBLOCK
30#endif
31
32WV_LINK(WvSSLStream);
33
34static IWvStream *creator(WvStringParm s, IObject *_obj)
35{
36 return new WvSSLStream(IWvStream::create(s, _obj), NULL, 0, false);
37}
38
39static IWvStream *screator(WvStringParm s, IObject *_obj)
40{
41 return new WvSSLStream(IWvStream::create(s, _obj),
43 0, true);
44}
45
47{
48 WvX509Mgr *m;
49 WvString s;
50
51 /* Kind of necessary; the WvX509Mgr object here is meant to be passed into
52 * a WvSSLStream, which will addRef() the object. Thus, once the stream
53 * has been created, we need to release() it here, so that once the stream
54 * itself falls into oblivion, we have no hanging references.
55 */
57 { WVRELEASE(m); }
58};
59
60static WvTclParseValues *parse_wvtcl_sslcert(WvStringParm s)
61{
62 /* The idea here is that we've got s, which is a TclStyle string of the
63 * format (without the quotes, of course, but escaped):
64 * "PEM-encoded SSL cert" "PEM-encoded private RSA key" "connection moniker"
65 */
67 wvtcl_decode(l, s);
68 if (l.count() > 3 || l.count() < 2)
69 return NULL; /* we fscked up, no clue how to recover */
70 // in the case of '2', 'obj' had better be set to the calling function
71
73 p->m = new WvX509Mgr;
74 p->m->decode(WvX509::CertPEM, *l.first());
75 l.unlink_first();
76 p->m->decode(WvRSAKey::RsaPEM, *l.first());
77 l.unlink_first();
78 if (!p->m->test()) { /* RSA key and certificate don't match up?? */
79 delete p;
80 return NULL;
81 }
82
83 if (l.count())
84 p->s = *l.first();
85
86 return p;
87}
88
89static IWvStream *sslcertcreator(WvStringParm s, IObject *_obj)
90{
91 WvTclParseValues *p = parse_wvtcl_sslcert(s);
92 if (!p) {
93 WVRELEASE(_obj);
94 return NULL;
95 }
96
97 WvSSLStream *ret = new WvSSLStream(IWvStream::create(p->s, _obj), p->m,
98 0, false);
99 delete p;
100 return ret;
101}
102
103static IWvStream *sslcertscreator(WvStringParm s, IObject *_obj)
104{
105 WvTclParseValues *p = parse_wvtcl_sslcert(s);
106 if (!p) {
107 WVRELEASE(_obj);
108 return NULL;
109 }
110
111 WvSSLStream *ret = new WvSSLStream(IWvStream::create(p->s, _obj), p->m,
112 0, true);
113 delete p;
114 return ret;
115}
116
117static WvMoniker<IWvStream> reg("ssl", creator);
118static WvMoniker<IWvStream> sreg("sslserv", screator);
119static WvMoniker<IWvStream> sslcertreg("sslcert", sslcertcreator);
120static WvMoniker<IWvStream> sslcertsreg("sslcertserv", sslcertscreator);
121
122static IWvListener *listener(WvStringParm s, IObject *obj)
123{
124 IWvListener *l = IWvListener::create(s, obj);
125 if (l)
126 l->addwrap(wv::bind(&IWvStream::create, "sslserv", _1));
127 return l;
128}
129
130static IWvListener *sslcertlistener(WvStringParm s, IObject *obj)
131{
133 wvtcl_decode(li, s);
134 WvString connmoniker;
135
136 if (li.count() == 3) {
137 // We have a connection moniker as well as SSL information
138 connmoniker = *li.last();
139 li.unlink(li.last());
140 } else if (li.count() != 2) {
141 // something went very wrong
142 WVRELEASE(obj);
143 return NULL;
144 }
145
146 IWvListener *l = IWvListener::create(connmoniker, obj);
147 if (l)
148 l->addwrap(wv::bind(&IWvStream::create,
149 WvString("sslcertserv:%s", wvtcl_encode(li)), _1));
150 return l;
151}
152
153static WvMoniker<IWvListener> lreg("ssl", listener);
154static WvMoniker<IWvListener> lsslcertreg("sslcert", sslcertlistener);
155
156#define MAX_BOUNCE_AMOUNT (16384) // 1 SSLv3/TLSv1 record
157
158static int ssl_stream_count = 0;
159
160static int wv_verify_cb(int preverify_ok, X509_STORE_CTX *ctx)
161{
162 // This is just returns true, since what we really want
163 // is for the WvSSLValidateCallback to do this work
164 return 1;
165}
166
167WvSSLGlobalValidateCallback WvSSLStream::global_vcb = 0;
168
170 WvSSLValidateCallback _vcb, bool _is_server) :
171 WvStreamClone(_slave),
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)
175{
176 x509 = _x509;
177 if (x509)
178 x509->addRef(); // openssl may keep a pointer to this object
179
180 vcb = _vcb;
181 if (!vcb && global_vcb)
182 vcb = wv::bind(global_vcb, _1, this);;
183
184 is_server = _is_server;
185 ctx = NULL;
186 ssl = NULL;
187 //meth = NULL;
188 sslconnected = ssl_stop_read = ssl_stop_write = false;
189
190 wvssl_init();
191
192 if (x509 && !x509->isok())
193 {
194 seterr("Certificate + key pair invalid.");
195 return;
196 }
197
198 if (is_server && !x509)
199 {
200 seterr("Certificate not available: server mode not possible!");
201 return;
202 }
203
204 if (is_server)
205 {
206 debug("Configured algorithms and methods for server mode.\n");
207
208 ctx = SSL_CTX_new(SSLv23_server_method());
209 if (!ctx)
210 {
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!");
215 return;
216 }
217
218 // Allow SSL Writes to only write part of a request...
219 SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
220
221 // Tell SSL to use 128 bit or better ciphers - this appears to
222 // be necessary for some reason... *sigh*
223 SSL_CTX_set_cipher_list(ctx, "HIGH");
224
225 // Enable the workarounds for broken clients and servers
226 // and disable the insecure SSLv2 protocol
227 SSL_CTX_set_options(ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
228
229 if (!x509->bind_ssl(ctx))
230 {
231 seterr("Unable to bind Certificate to SSL Context!");
232 return;
233 }
234
235 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
236 wv_verify_cb);
237
238 debug("Server mode ready.\n");
239 }
240 else
241 {
242 debug("Configured algorithms and methods for client mode.\n");
243
244 ctx = SSL_CTX_new(SSLv23_client_method());
245 if (!ctx)
246 {
247 seterr("Can't get SSL context!");
248 return;
249 }
250 if (x509 && !x509->bind_ssl(ctx))
251 {
252 seterr("Unable to bind Certificate to SSL Context!");
253 return;
254 }
255 }
256
257 //SSL_CTX_set_read_ahead(ctx, 1);
258
259 ERR_clear_error();
260 ssl = SSL_new(ctx);
261 if (!ssl)
262 {
263 seterr("Can't create SSL object!");
264 return;
265 }
266
267 // If we set this, it seems we always verify the client... security hole,
268 // no? Well, if we don't set it, the server doesn't even ask the client
269 // for a certificate, so, ya know, it's not actually any more secure.
270 // Client doesn't need this (unless vcb is set), since it always asks the
271 // server for a cert anyway
272 if (!!vcb || is_server)
273 SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
274 wv_verify_cb);
275
276 connect_wants.readable = true;
277 connect_wants.writable = true; // force ssl initiation ASAP
278 connect_wants.isexception = false;
279 debug("SSL stream initialized.\n");
280}
281
282
284{
285 close();
286
287 debug("Deleting SSL connection.\n");
288 if (geterr())
289 debug("Error was: %s\n", errstr());
290
291 WVRELEASE(x509);
292 wvssl_free();
293}
294
295
296void WvSSLStream::printerr(WvStringParm func)
297{
298 unsigned long l = ERR_get_error();
299 char buf[121]; // man ERR_error_string says must be > 120.
300
301 while (l)
302 {
303 ERR_error_string(l, buf);
304 debug("%s error: %s\n", func, buf);
305 l = ERR_get_error();
306 }
307}
308
309
310size_t WvSSLStream::uread(void *buf, size_t len)
311{
312 if (!sslconnected)
313 return 0;
314 if (len == 0) return 0;
315
316 // if SSL buffers stuff on its own, select() may not wake us up
317 // the next time around unless we're sure there is nothing left
318 read_pending = true;
319
320 size_t total = 0;
321 for (;;)
322 {
323 // handle SSL_read quirk
324 if (read_bouncebuf.used() != 0)
325 {
326 // copy out cached data
327 size_t amount = len < read_bouncebuf.used() ?
328 len : read_bouncebuf.used();
329 read_bouncebuf.move(buf, amount);
330
331 // locate next chunk in buffer
332 len -= amount;
333 total += amount;
334 if (len == 0)
335 {
336 read_pending = false;
337 break;
338 }
339 buf = (unsigned char *)buf + amount;
340
341 // FIXME: this shouldn't be necessary, but it resolves weird
342 // problems when the other end disconnects in the middle of
343 // SSL negotiation, but only on emakela's machine. I don't
344 // know why. -- apenwarr (2004/02/10)
345 break;
346 }
347
348 // attempt to read
349 read_bouncebuf.zap(); // force use of same position in buffer
350 size_t avail = read_bouncebuf.free();
351 unsigned char *data = read_bouncebuf.alloc(avail);
352
353 ERR_clear_error();
354 int result = SSL_read(ssl, data, avail);
355 // debug("<< SSL_read result %s for %s bytes (wanted %s)\n",
356 // result, avail, len);
357 if (result <= 0)
358 {
359 error_t err = errno;
360 read_bouncebuf.unalloc(avail);
361 int sslerrcode = SSL_get_error(ssl, result);
362 switch (sslerrcode)
363 {
364 case SSL_ERROR_WANT_READ:
365 debug("<< SSL_read() needs to wait for writable.\n");
366 break; // wait for later
367 case SSL_ERROR_WANT_WRITE:
368 debug("<< SSL_read() needs to wait for readable.\n");
369 break; // wait for later
370
371 case SSL_ERROR_NONE:
372 break; // no error, but can't make progress
373
374 case SSL_ERROR_ZERO_RETURN:
375 debug("<< EOF: zero return\n");
376
377 // don't do this if we're returning nonzero!
378 // (SSL has no way to do a one-way shutdown, so if SSL
379 // detects a read problem, it's also a write problem.)
380 if (!total) { noread(); nowrite(); }
381 break;
382
383 case SSL_ERROR_SYSCALL:
384 if (!err)
385 {
386 if (result == 0)
387 {
388 debug("<< EOF: syscall error "
389 "(%s/%s, %s/%s) total=%s\n",
390 stop_read, stop_write,
391 isok(), cloned && cloned->isok(), total);
392
393 // don't do this if we're returning nonzero!
394 // (SSL has no way to do a one-way shutdown, so
395 // if SSL detects a read problem, it's also a
396 // write problem.)
397 if (!total) { noread(); nowrite(); }
398 }
399 }
400 else
401 {
402 debug("<< SSL_read() err=%s (%s)\n",
403 err, strerror(err));
404 seterr_both(err, WvString("SSL read: %s",
405 strerror(err)));
406 }
407 break;
408
409 default:
410 printerr("SSL_read");
411 seterr("SSL read error #%s", sslerrcode);
412 break;
413 }
414 read_pending = false;
415 break; // wait for next iteration
416 }
417 // debug("<< read result was %s\n", result);
418
419 if (result < 0)
420 result = 0;
421 read_bouncebuf.unalloc(avail - result);
422 }
423
424 // debug("<< read %s bytes (%s, %s)\n",
425 // total, isok(), cloned && cloned->isok());
426 return total;
427}
428
429
430size_t WvSSLStream::uwrite(const void *buf, size_t len)
431{
432 if (!sslconnected)
433 {
434 debug(">> writing, but not connected yet (%s); enqueue.\n", getwfd());
435 unconnected_buf.put(buf, len);
436 return len;
437 }
438
439 if (len == 0) return 0;
440
441// debug(">> I want to write %s bytes.\n", len);
442
443 size_t total = 0;
444
445 // eat any data that was precached and already written
446 if (write_eat >= len)
447 {
448 write_eat -= len;
449 total = len;
450 len = 0;
451 }
452 else
453 {
454 buf = (const unsigned char *)buf + write_eat;
455 total = write_eat;
456 len -= write_eat;
457 write_eat = 0;
458 }
459
460 // FIXME: WOW!!! Ummm... hope this never spins...
461 //
462 for (;;)
463 {
464 // handle SSL_write quirk
465 if (write_bouncebuf.used() == 0)
466 {
467 if (len == 0) break;
468
469 // copy new data into the bounce buffer only if empty
470 // if it were not empty, then SSL_write probably returned
471 // SSL_ERROR_WANT_WRITE on the previous call and we
472 // must invoke it with precisely the same arguments
473 size_t amount = len < write_bouncebuf.free() ?
474 len : write_bouncebuf.free();
475 write_bouncebuf.put(buf, amount);
476 // note: we don't adjust the total yet...
477 } // otherwise we use what we cached last time in bounce buffer
478
479 // attempt to write
480 size_t used = write_bouncebuf.used();
481 const unsigned char *data = write_bouncebuf.get(used);
482
483 ERR_clear_error();
484 int result = SSL_write(ssl, data, used);
485 // debug("<< SSL_write result %s for %s bytes\n",
486 // result, used);
487 if (result <= 0)
488 {
489 int sslerrcode = SSL_get_error(ssl, result);
490 write_bouncebuf.unget(used);
491 switch (sslerrcode)
492 {
493 case SSL_ERROR_WANT_READ:
494 debug(">> SSL_write() needs to wait for readable.\n");
495 break; // wait for later
496 case SSL_ERROR_WANT_WRITE:
497 // debug(">> SSL_write() needs to wait for writable.\n");
498 break; // wait for later
499
500 case SSL_ERROR_SYSCALL:
501 debug(">> ERROR: SSL_write() failed on socket error.\n");
502 seterr(WvString("SSL write error: %s", strerror(errno)));
503 break;
504
505 // This case can cause truncated web pages... give more info
506 case SSL_ERROR_SSL:
507 debug(">> ERROR: SSL_write() failed on internal error.\n");
508 seterr(WvString("SSL write error: %s",
509 ERR_error_string(ERR_get_error(), NULL)));
510 break;
511
512 case SSL_ERROR_NONE:
513 break; // no error, but can't make progress
514
515 case SSL_ERROR_ZERO_RETURN:
516 debug(">> SSL_write zero return: EOF\n");
517 close(); // EOF
518 break;
519
520 default:
521 printerr("SSL_write");
522 seterr(WvString("SSL write error #%s", sslerrcode));
523 break;
524 }
525 break; // wait for next iteration
526 }
527 else
528 assert((size_t)result == used);
529 write_bouncebuf.zap(); // force use of same position in buffer
530
531 // locate next chunk to be written
532 // note: we assume that initial contents of buf and of the
533 // bouncebuf match since if we got SSL_ERROR_WANT_WRITE
534 // we did not claim to actually have written the chunk
535 // that we cached so we will have gotten it again here
536 if (size_t(result) >= len)
537 {
538 // if we cached more previously than we were given, claim
539 // we wrote what we got and remember to eat the rest later
540 write_eat = result - len;
541 total += len;
542 break;
543 }
544 total += size_t(result);
545 len -= size_t(result);
546 buf = (const unsigned char *)buf + size_t(result);
547 }
548
549 //debug(">> wrote %s bytes\n", total);
550 return total;
551}
552
554{
555 debug("Closing SSL connection (ok=%s,sr=%s,sw=%s,child=%s).\n",
556 isok(), stop_read, stop_write, cloned && cloned->isok());
557
558 if (ssl)
559 {
560 ERR_clear_error();
561 SSL_shutdown(ssl);
562 SSL_free(ssl);
563 ssl = NULL;
564 sslconnected = false;
565 }
566
568
569 if (ctx)
570 {
571 SSL_CTX_free(ctx);
572 ctx = NULL;
573 }
574}
575
576
578{
579 return ssl && WvStreamClone::isok();
580}
581
582
584{
585 // WARNING: openssl always needs two-way socket communications even for
586 // one-way encrypted communications, so we don't pass noread/nowrite
587 // along to the child stream. This should be mostly okay, though,
588 // because we'll still send it close() once we have both noread() and
589 // nowrite().
590 ssl_stop_read = true;
591 if (ssl_stop_write)
592 {
595 }
596}
597
598
600{
601 // WARNING: see note in noread()
602 ssl_stop_write = true;
603 if (ssl_stop_read)
604 {
607 }
608}
609
610
612{
613 SelectRequest oldwant = si.wants;
614 bool oldinherit = si.inherit_request;
615 if (!sslconnected)
616 {
617 si.wants = connect_wants;
618 si.inherit_request = true; // ignore force_select() until connected
619 }
620
621 // the SSL library might be keeping its own internal buffers
622 // or we might have left buffered data behind deliberately
623 if (si.wants.readable && (read_pending || read_bouncebuf.used()))
624 {
625 // debug("pre_select: try reading again immediately.\n");
626 si.msec_timeout = 0;
627 si.inherit_request = oldinherit;
628 si.wants = oldwant;
629 return;
630 }
631
633 si.inherit_request = oldinherit;
634 si.wants = oldwant;
635}
636
637
639{
640 SelectRequest oldwant = si.wants;
641 bool oldinherit = si.inherit_request;
642
643 if (!sslconnected)
644 {
645 si.wants = connect_wants;
646 si.inherit_request = true; // ignore force_select() until connected
647 }
648
649 bool result = WvStreamClone::post_select(si);
650 si.wants = oldwant;
651 si.inherit_request = oldinherit;
652
653 // SSL takes a few round trips to
654 // initialize itself, and we mustn't block in the constructor, so keep
655 // trying here... it is also turning into a rather cool place
656 // to do the validation of the connection ;)
657 if (!sslconnected && cloned && cloned->isok() && result)
658 {
659 debug("!sslconnected in post_select (r=%s/%s, w=%s/%s, t=%s)\n",
660 cloned->isreadable(), si.wants.readable,
661 cloned->iswritable(), si.wants.writable,
662 si.msec_timeout);
663
664 connect_wants.writable = false;
665
666 // for ssl streams to work, we have to be cloning a stream that
667 // actually uses a single, valid fd.
668 WvFDStream *fdstream = static_cast<WvFDStream*>(cloned);
669 int fd = fdstream->getfd();
670 assert(fd >= 0);
671 ERR_clear_error();
672 SSL_set_fd(ssl, fd);
673// debug("SSL connected on fd %s.\n", fd);
674
675 int err;
676
677 if (is_server)
678 {
679 // If we are a server, get ready to accept an incoming SSL
680 // connection
681 err = SSL_accept(ssl);
682 }
683 else
684 err = SSL_connect(ssl);
685
686 if (err < 0)
687 {
688 if (errno == EAGAIN)
689 debug("Still waiting for SSL negotiation.\n");
690 else if (!errno)
691 {
692 printerr(is_server ? "SSL_accept" : "SSL_connect");
693 seterr(WvString("SSL negotiation failed (%s)!", err));
694 }
695 else
696 {
697 printerr(is_server ? "SSL_accept" : "SSL_connect");
698 seterr(errno);
699 }
700 }
701 else // We're connected, so let's do some checks ;)
702 {
703 debug("SSL connection using cipher %s.\n", SSL_get_cipher(ssl));
704
705 WvX509 *peercert = new WvX509(SSL_get_peer_certificate(ssl));
706 //Should we try to validate before storing, or not?
707 if (peercert->isok() && peercert->validate())
708 setattr("peercert", peercert->encode(WvX509::CertPEM));
709 if (!!vcb)
710 {
711 debug("SSL Peer is: %s\n", peercert->get_subject());
712 if (peercert->isok() && peercert->validate() && vcb(peercert))
713 {
714 setconnected(true);
715 debug("SSL finished negotiating - certificate is valid.\n");
716 }
717 else
718 {
719 if (!peercert->isok())
720 seterr("Peer cert: %s", peercert->errstr());
721 else
722 seterr("Peer certificate is invalid!");
723 }
724 }
725 else
726 {
727 setconnected(true);
728 debug("SSL finished negotiating "
729 "- certificate validation disabled.\n");
730 }
731 WVRELEASE(peercert);
732 }
733
734 return false;
735 }
736
737 if ((si.wants.readable || readcb)
738 && (read_pending || read_bouncebuf.used()))
739 result = true;
740
741 return result;
742}
743
744
745void WvSSLStream::setconnected(bool conn)
746{
747 sslconnected = conn;
748 if (conn) write(unconnected_buf);
749}
750
The basic interface which is included by all other XPLC interfaces and objects.
Definition: IObject.h:65
virtual unsigned int addRef()=0
Indicate you are using this object.
virtual void addwrap(IWvListenerWrapper _wrapper)=0
Add a wrapper function for this stream: something that accept() will call to possibly wrap the stream...
virtual bool isreadable()=0
Returns true if the stream is readable.
virtual bool iswritable()=0
Returns true if the stream is writable (without using the outbuf).
virtual bool isok() const =0
By default, returns true if geterr() == 0.
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
void unget(size_t count)
Ungets exactly the specified number of elements by returning them to the buffer for subsequent reads.
Definition: wvbufbase.h:177
void unalloc(size_t count)
Unallocates exactly the specified number of elements by removing them from the buffer and releasing t...
Definition: wvbufbase.h:421
size_t free() const
Returns the number of elements that the buffer can currently accept for writing.
Definition: wvbufbase.h:353
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
Definition: wvbufbase.h:379
void zap()
Clears the buffer.
Definition: wvbufbase.h:257
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
static WvString strerror(int errnum)
A replacement for the operating system ::strerror() function that can map more kinds of error strings...
Definition: wverror.cc:91
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition: wvstring.h:94
Base class for streams built on Unix file descriptors.
Definition: wvfdstream.h:21
int getfd() const
Returns the Unix file descriptor for reading and writing.
Definition: wvfdstream.h:81
size_t count() const
Returns the number of elements in the list.
Definition: wvlinklist.cc:24
A linked list container class.
Definition: wvlinklist.h:198
void unlink_first()
Unlinks the first element from the list.
Definition: wvlinklist.h:312
T * first() const
Returns a pointer to the first element in the linked list.
Definition: wvlinklist.h:241
T * last() const
Returns a pointer to the last element in the linked list.
Definition: wvlinklist.h:251
void unlink(T *data)
Unlinks the specified element from the list.
Definition: wvlinklist.h:303
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:57
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:62
SSL Stream, handles SSLv2, SSLv3, and TLS Methods - If you want it to be a server,...
Definition: wvsslstream.h:36
virtual void close()
Close this stream.
Definition: wvsslstream.cc:553
SSL_CTX * ctx
SSL Context - used to create SSL Object.
Definition: wvsslstream.h:72
virtual bool isok() const
return true if the stream is actually usable right now
Definition: wvsslstream.cc:577
virtual size_t uwrite(const void *buf, size_t len)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
Definition: wvsslstream.cc:430
virtual ~WvSSLStream()
Cleans up everything (calls close + frees up the SSL Objects used)
Definition: wvsslstream.cc:283
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
Definition: wvsslstream.cc:611
virtual void nowrite()
Shuts down the writing side of the stream.
Definition: wvsslstream.cc:599
SSL * ssl
Main SSL Object - after SSL_set_fd() we make all calls through the connection through here.
Definition: wvsslstream.h:78
WvSSLStream(IWvStream *_slave, WvX509Mgr *_x509=NULL, WvSSLValidateCallback _vcb=0, bool _is_server=false)
Start an SSL connection on the stream _slave.
Definition: wvsslstream.cc:169
virtual size_t uread(void *buf, size_t len)
unbuffered I/O functions; these ignore the buffer, which is handled by read().
Definition: wvsslstream.cc:310
virtual void noread()
Shuts down the reading side of the stream.
Definition: wvsslstream.cc:583
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
Definition: wvsslstream.cc:638
WvStreamClone simply forwards all requests to the "cloned" stream.
Definition: wvstreamclone.h:24
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
virtual void close()
Close this stream.
virtual bool isok() const
return true if the stream is actually usable right now
virtual void noread()
Shuts down the reading side of the stream.
virtual void nowrite()
Shuts down the writing side of the stream.
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
bool stop_read
True if noread()/nowrite()/close() have been called, respectively.
Definition: wvstream.h:57
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
Definition: wvstream.cc:532
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Definition: wvstream.cc:451
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330
virtual void decode(const WvX509::DumpMode mode, WvStringParm encoded)
Load the information from the format requested by mode into the class - this overwrites the certifica...
Definition: wvx509mgr.cc:664
bool bind_ssl(SSL_CTX *ctx)
Avoid a lot of ugliness by having it so that we are binding to the SSL context, and not the other way...
Definition: wvx509mgr.cc:200
bool test() const
Test to make sure that a certificate and a keypair go together.
Definition: wvx509mgr.cc:217
virtual bool isok() const
Says if this certificate+key pair is good for use.
Definition: wvx509mgr.cc:172
X509 Class to handle certificates and their related functions.
Definition: wvx509.h:42
virtual WvString errstr() const
Returns an error string if isok() is not true.
Definition: wvx509.cc:1297
WvString get_subject() const
get and set the Subject field of the certificate
Definition: wvx509.cc:624
bool validate(WvX509 *cacert=NULL) const
Function to verify the validity of a certificate that has been placed in cert.
Definition: wvx509.cc:359
WvString encode(const DumpMode mode) const
Return the information requested by mode.
Definition: wvx509.cc:441
virtual bool isok() const
Is the certificate object valid?
Definition: wvx509.cc:1285
the data structure used by pre_select()/post_select() and internally by select().
Definition: iwvstream.h:50
A SelectRequest is a convenient way to remember what we want to do to a particular stream: read from ...
Definition: iwvstream.h:34
Various little string functions.
WvString fqdomainname()
Get the fqdn of the local host, using gethostbyname() and gethostname()
Definition: strutils.cc:893
WvString encode_hostname_as_DN(WvStringParm hostname)
Example: encode_hostname_as_DN("www.fizzle.com") will result in dc=www,dc=fizzle,dc=com,...
Definition: strutils.cc:444
WvString wvtcl_encode(WvList< WvString > &l, const WvStringMask &nasties=WVTCL_NASTY_SPACES, const WvStringMask &splitchars=WVTCL_SPLITCHARS)
encode a tcl-style list.
Definition: wvtclstring.cc:221
void wvtcl_decode(WvList< WvString > &l, WvStringParm _s, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
split a tcl-style list.
Definition: wvtclstring.cc:386