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 
32 WV_LINK(WvSSLStream);
33 
34 static IWvStream *creator(WvStringParm s, IObject *_obj)
35 {
36  return new WvSSLStream(IWvStream::create(s, _obj), NULL, 0, false);
37 }
38 
39 static 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 
60 static 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 
89 static 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 
103 static 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 
117 static WvMoniker<IWvStream> reg("ssl", creator);
118 static WvMoniker<IWvStream> sreg("sslserv", screator);
119 static WvMoniker<IWvStream> sslcertreg("sslcert", sslcertcreator);
120 static WvMoniker<IWvStream> sslcertsreg("sslcertserv", sslcertscreator);
121 
122 static 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 
130 static IWvListener *sslcertlistener(WvStringParm s, IObject *obj)
131 {
132  WvList<WvString> li;
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 
153 static WvMoniker<IWvListener> lreg("ssl", listener);
154 static WvMoniker<IWvListener> lsslcertreg("sslcert", sslcertlistener);
155 
156 #define MAX_BOUNCE_AMOUNT (16384) // 1 SSLv3/TLSv1 record
157 
158 static int ssl_stream_count = 0;
159 
160 static 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 
167 WvSSLGlobalValidateCallback 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 
296 void 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 
310 size_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 
430 size_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 
577 bool WvSSLStream::isok() const
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 
745 void WvSSLStream::setconnected(bool conn)
746 {
747  sslconnected = conn;
748  if (conn) write(unconnected_buf);
749 }
750 
WvBufBaseCommonImpl::get
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
WvStream::write
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
Definition: wvstream.cc:532
fqdomainname
WvString fqdomainname()
Get the fqdn of the local host, using gethostbyname() and gethostname()
Definition: strutils.cc:893
IWvListener::addwrap
virtual void addwrap(IWvListenerWrapper _wrapper)=0
Add a wrapper function for this stream: something that accept() will call to possibly wrap the stream...
WvSSLStream::uwrite
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
IWvStream::isreadable
virtual bool isreadable()=0
Returns true if the stream is readable.
WvBufBaseCommonImpl::unget
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
WvSSLStream::pre_select
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
Definition: wvsslstream.cc:611
WvList::last
T * last() const
Returns a pointer to the last element in the linked list.
Definition: wvlinklist.h:251
WvX509
X509 Class to handle certificates and their related functions.
Definition: wvx509.h:41
WvBufBaseCommonImpl::alloc
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
Definition: wvbufbase.h:379
WvBufBaseCommonImpl::unalloc
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
IWvStream::iswritable
virtual bool iswritable()=0
Returns true if the stream is writable (without using the outbuf).
WvStreamClone::close
virtual void close()
Close this stream.
Definition: wvstreamclone.cc:83
WvBufBaseCommonImpl::free
size_t free() const
Returns the number of elements that the buffer can currently accept for writing.
Definition: wvbufbase.h:353
WvSSLStream
SSL Stream, handles SSLv2, SSLv3, and TLS Methods - If you want it to be a server,...
Definition: wvsslstream.h:35
WvList::unlink
void unlink(T *data)
Unlinks the specified element from the list.
Definition: wvlinklist.h:303
WvX509Mgr::bind_ssl
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
WvErrorBase::strerror
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
IWvStream
Definition: iwvstream.h:24
WvList::first
T * first() const
Returns a pointer to the first element in the linked list.
Definition: wvlinklist.h:241
IWvListener
Definition: iwvlistener.h:16
WvX509::validate
bool validate(WvX509 *cacert=NULL) const
Function to verify the validity of a certificate that has been placed in cert.
Definition: wvx509.cc:359
WvX509::isok
virtual bool isok() const
Is the certificate object valid?
Definition: wvx509.cc:1285
WvStreamClone::noread
virtual void noread()
Shuts down the reading side of the stream.
Definition: wvstreamclone.cc:61
WvX509::errstr
virtual WvString errstr() const
Returns an error string if isok() is not true.
Definition: wvx509.cc:1297
encode_hostname_as_DN
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
WvX509Mgr::isok
virtual bool isok() const
Says if this certificate+key pair is good for use.
Definition: wvx509mgr.cc:172
WvStream::seterr
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
Definition: wvstream.cc:451
WvSSLStream::WvSSLStream
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
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvLog
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:56
wvtcl_encode
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
wvstrutils.h
IWvStream::SelectInfo
the data structure used by pre_select()/post_select() and internally by select().
Definition: iwvstream.h:50
WvStreamClone::nowrite
virtual void nowrite()
Shuts down the writing side of the stream.
Definition: wvstreamclone.cc:72
WvMoniker
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:61
WvSSLStream::nowrite
virtual void nowrite()
Shuts down the writing side of the stream.
Definition: wvsslstream.cc:599
WvX509Mgr::decode
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
WvStreamClone
WvStreamClone simply forwards all requests to the "cloned" stream.
Definition: wvstreamclone.h:23
WvSSLStream::uread
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
WvBufBaseCommonImpl::zap
void zap()
Clears the buffer.
Definition: wvbufbase.h:257
WvFdStream::getfd
int getfd() const
Returns the Unix file descriptor for reading and writing.
Definition: wvfdstream.h:81
WvX509Mgr
Definition: wvx509mgr.h:14
IObject
Definition: IObject.h:65
IWvStream::isok
virtual bool isok() const =0
By default, returns true if geterr() == 0.
WvStreamClone::pre_select
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
Definition: wvstreamclone.cc:199
WvStreamClone::geterr
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
Definition: wvstreamclone.cc:149
IWvStream::SelectRequest
A SelectRequest is a convenient way to remember what we want to do to a particular stream: read from ...
Definition: iwvstream.h:34
WvStreamClone::isok
virtual bool isok() const
return true if the stream is actually usable right now
Definition: wvstreamclone.cc:136
WvListBase::count
size_t count() const
Returns the number of elements in the list.
Definition: wvlinklist.cc:24
WvSSLStream::post_select
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
WvFdStream
Base class for streams built on Unix file descriptors.
Definition: wvfdstream.h:20
WvSSLStream::noread
virtual void noread()
Shuts down the reading side of the stream.
Definition: wvsslstream.cc:583
WvBufBaseCommonImpl::used
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
WvSSLStream::ctx
SSL_CTX * ctx
SSL Context - used to create SSL Object.
Definition: wvsslstream.h:72
WvSSLStream::isok
virtual bool isok() const
return true if the stream is actually usable right now
Definition: wvsslstream.cc:577
WvX509Mgr::test
bool test() const
Test to make sure that a certificate and a keypair go together.
Definition: wvx509mgr.cc:217
WvSSLStream::close
virtual void close()
Close this stream.
Definition: wvsslstream.cc:553
WvX509::get_subject
WvString get_subject() const
get and set the Subject field of the certificate
Definition: wvx509.cc:624
wvtcl_decode
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
WvList
A linked list container class.
Definition: wvlinklist.h:197
WvStreamClone::post_select
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
Definition: wvstreamclone.cc:222
IObject::addRef
virtual unsigned int addRef()=0
Indicate you are using this object.
WvTclParseValues
Definition: wvsslstream.cc:46
WvList::unlink_first
void unlink_first()
Unlinks the first element from the list.
Definition: wvlinklist.h:312
WvSSLStream::~WvSSLStream
virtual ~WvSSLStream()
Cleans up everything (calls close + frees up the SSL Objects used)
Definition: wvsslstream.cc:283
WvStream::stop_read
bool stop_read
True if noread()/nowrite()/close() have been called, respectively.
Definition: wvstream.h:57
WvX509::encode
WvString encode(const DumpMode mode) const
Return the information requested by mode.
Definition: wvx509.cc:441
WvSSLStream::ssl
SSL * ssl
Main SSL Object - after SSL_set_fd() we make all calls through the connection through here.
Definition: wvsslstream.h:78