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 
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.
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
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 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
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
T * alloc(size_t count)
Allocates exactly the specified number of elements and returns a pointer to an UNINITIALIZED storage ...
Definition: wvbufbase.h:379
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
void unlink(T *data)
Unlinks the specified element from the list.
Definition: wvlinklist.h:303
T * last() const
Returns a pointer to the last element in the linked list.
Definition: wvlinklist.h:251
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