05e6dd8e32b2e2f294d5333cc1b13c9982d99eb2
[dockapps.git] / wmbiff / wmbiff / tlsComm.c
blob05e6dd8e32b2e2f294d5333cc1b13c9982d99eb2
1 /* tlsComm.c - primitive routines to aid TLS communication
2 within wmbiff, without rewriting each mailbox access
3 scheme. These functions hide whether the underlying
4 transport is encrypted.
6 Neil Spring (nspring@cs.washington.edu) */
8 /* TODO: handle "* BYE" internally? */
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 #endif
13 #include <stdarg.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <assert.h>
22 #ifdef HAVE_GNUTLS_GNUTLS_H
23 #define USE_GNUTLS
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
26 #include <sys/stat.h>
27 #endif
28 #ifdef USE_DMALLOC
29 #include <dmalloc.h>
30 #endif
32 #include "tlsComm.h"
34 #include "Client.h" /* debugging messages */
36 /* if non-null, set to a file for certificate verification */
37 extern const char *certificate_filename;
38 /* if set, don't fail when dealing with a bad certificate.
39 (continue to whine, though, as bad certs should be fixed) */
40 extern int SkipCertificateCheck;
42 /* WARNING: implcitly uses scs to gain access to the mailbox
43 that holds the per-mailbox debug flag. */
44 #define TDM(lvl, args...) DM(scs->pc, lvl, "comm: " args)
46 /* how long to wait for the server to do its thing
47 when we issue it a command (in seconds) */
48 #define EXPECT_TIMEOUT 40
50 /* this is the per-connection state that is maintained for
51 each connection; BIG variables are for ssl (null if not
52 used). */
53 #define BUF_SIZE 1024
54 struct connection_state {
55 int sd;
56 char *name;
57 #ifdef USE_GNUTLS
58 gnutls_session tls_state;
59 gnutls_certificate_credentials xcred;
60 #else
61 /*@null@ */ void *tls_state;
62 /*@null@ */ void *xcred;
63 #endif
64 char unprocessed[BUF_SIZE];
65 Pop3 pc; /* mailbox handle for debugging messages */
68 /* gotta do our own line buffering, sigh */
69 int getline_from_buffer(char *readbuffer, char *linebuffer,
70 int linebuflen);
71 void handle_gnutls_read_error(int readbytes, struct connection_state *scs);
73 void tlscomm_close(struct connection_state *scs)
75 TDM(DEBUG_INFO, "%s: closing.\n",
76 (scs->name != NULL) ? scs->name : "null");
78 /* not ok to call this more than once */
79 if (scs->tls_state) {
80 #ifdef USE_GNUTLS
81 /* this next line seems capable of hanging... */
82 /* gnutls_bye(scs->tls_state, GNUTLS_SHUT_RDWR); */
83 /* so we'll try just _bye'ing the WR direction, which
84 should send the alert but not wait for a response. */
85 gnutls_bye(scs->tls_state, GNUTLS_SHUT_WR);
86 gnutls_certificate_free_credentials(scs->xcred);
87 gnutls_deinit(scs->tls_state);
88 scs->xcred = NULL;
89 #endif
90 } else {
91 (void) close(scs->sd);
93 scs->sd = -1;
94 scs->tls_state = NULL;
95 scs->xcred = NULL;
96 free(scs->name);
97 scs->name = NULL;
98 free(scs);
101 extern int x_socket(void);
102 extern void ProcessPendingEvents(void);
104 /* this avoids blocking without using non-blocking i/o */
105 static int wait_for_it(int sd, int timeoutseconds)
107 fd_set readfds;
108 struct timeval tv;
109 int ready_descriptors;
110 int maxfd;
111 int xfd;
112 struct timeval time_now;
113 struct timeval time_out;
115 gettimeofday(&time_now, NULL);
116 memcpy(&time_out, &time_now, sizeof(struct timeval));
117 time_out.tv_sec += timeoutseconds;
119 xfd = x_socket();
120 maxfd = max(sd, xfd);
122 do {
123 do {
124 ProcessPendingEvents();
126 gettimeofday(&time_now, NULL);
127 tv.tv_sec = max(time_out.tv_sec - time_now.tv_sec + 1, (time_t) 0); /* sloppy, but bfd */
128 tv.tv_usec = 0;
129 /* select will return if we have X stuff or we have comm stuff on sd */
130 FD_ZERO(&readfds);
131 FD_SET(sd, &readfds);
132 // FD_SET(xfd, &readfds);
133 ready_descriptors = select(maxfd + 1, &readfds, NULL, NULL, &tv);
134 // DMA(DEBUG_INFO,
135 // "select %d/%d returned %d descriptor, %d\n",
136 // sd, timeoutseconds, ready_descriptors, FD_ISSET(sd, &readfds));
138 } while(tv.tv_sec > 0 && (!FD_ISSET(sd, &readfds) || (errno == EINTR && ready_descriptors == -1)));
140 FD_ZERO(&readfds);
141 FD_SET(sd, &readfds);
142 tv.tv_sec = 0; tv.tv_usec = 0;
143 ready_descriptors = select(sd + 1, &readfds, NULL, NULL, &tv);
145 while (ready_descriptors == -1 && errno == EINTR);
146 if (ready_descriptors == 0) {
147 DMA(DEBUG_INFO,
148 "select timed out after %d seconds on socket: %d\n",
149 timeoutseconds, sd);
150 return (0);
151 } else if (ready_descriptors == -1) {
152 DMA(DEBUG_ERROR,
153 "select failed on socket %d: %s\n", sd, strerror(errno));
154 return (0);
156 return (FD_ISSET(sd, &readfds));
159 /* exported for testing */
160 extern int
161 getline_from_buffer(char *readbuffer, char *linebuffer, int linebuflen)
163 char *p, *q;
164 int i;
165 /* find end of line (stopping if linebuflen is too small. */
166 for (p = readbuffer, i = 0;
167 *p != '\n' && *p != '\0' && i < linebuflen - 1; p++, i++);
169 /* gobble \n if it starts the line. */
170 if (*p == '\n') {
171 /* grab the end of line too! and then advance past
172 the newline */
173 i++;
174 p++;
175 } else {
176 /* TODO -- perhaps we should return no line at all
177 here, as it might be incomplete. don't want to
178 break anything though. */
179 DMA(DEBUG_INFO, "expected line doesn't end on its own.\n");
182 if (i != 0) {
183 /* copy a line into the linebuffer */
184 strncpy(linebuffer, readbuffer, (size_t) i);
185 /* sigh, null terminate */
186 linebuffer[i] = '\0';
187 /* shift the rest over; this could be done
188 instead with strcpy... I think. */
189 q = readbuffer;
190 if (*p != '\0') {
191 while (*p != '\0') {
192 *(q++) = *(p++);
195 /* null terminate */
196 *(q++) = *(p++);
197 /* return the length of the line */
199 if (i < 0 || i > linebuflen) {
200 DM((Pop3) NULL, DEBUG_ERROR, "bork bork bork!: %d %d\n", i,
201 linebuflen);
203 return i;
206 /* eat lines, until one starting with prefix is found;
207 this skips 'informational' IMAP responses */
208 /* the correct response to a return value of 0 is almost
209 certainly tlscomm_close(scs): don't _expect() anything
210 unless anything else would represent failure */
212 tlscomm_expect(struct connection_state *scs,
213 const char *prefix, char *linebuf, int buflen)
215 int prefixlen = (int) strlen(prefix);
216 int buffered_bytes = 0;
217 memset(linebuf, 0, buflen);
218 TDM(DEBUG_INFO, "%s: expecting: %s\n", scs->name, prefix);
219 /* if(scs->unprocessed[0]) {
220 TDM(DEBUG_INFO, "%s: buffered: %s\n", scs->name, scs->unprocessed);
221 } */
222 while (scs->unprocessed[0] != '\0'
223 || wait_for_it(scs->sd, EXPECT_TIMEOUT)) {
224 if (scs->unprocessed[buffered_bytes] == '\0') {
225 int thisreadbytes;
226 #ifdef USE_GNUTLS
227 if (scs->tls_state) {
228 /* BUF_SIZE - 1 leaves room for trailing \0 */
229 thisreadbytes =
230 gnutls_read(scs->tls_state,
231 &scs->unprocessed[buffered_bytes],
232 BUF_SIZE - 1 - buffered_bytes);
233 if (thisreadbytes < 0) {
234 handle_gnutls_read_error(thisreadbytes, scs);
235 return 0;
237 } else
238 #endif
240 thisreadbytes =
241 read(scs->sd, &scs->unprocessed[buffered_bytes],
242 BUF_SIZE - 1 - buffered_bytes);
243 if (thisreadbytes < 0) {
244 TDM(DEBUG_ERROR, "%s: error reading: %s\n",
245 scs->name, strerror(errno));
246 return 0;
249 buffered_bytes += thisreadbytes;
250 /* force null termination */
251 scs->unprocessed[buffered_bytes] = '\0';
252 if (buffered_bytes == 0) {
253 return 0; /* bummer */
255 } else {
256 buffered_bytes = strlen(scs->unprocessed);
258 while (buffered_bytes >= prefixlen) {
259 int linebytes;
260 linebytes =
261 getline_from_buffer(scs->unprocessed, linebuf, buflen);
262 if (linebytes == 0) {
263 buffered_bytes = 0;
264 } else {
265 buffered_bytes -= linebytes;
266 if (strncmp(linebuf, prefix, prefixlen) == 0) {
267 TDM(DEBUG_INFO, "%s: got: %*s", scs->name,
268 linebytes, linebuf);
269 return 1; /* got it! */
271 TDM(DEBUG_INFO, "%s: dumped(%d/%d): %.*s", scs->name,
272 linebytes, buffered_bytes, linebytes, linebuf);
276 if (buffered_bytes == -1) {
277 TDM(DEBUG_INFO, "%s: timed out while expecting '%s'\n",
278 scs->name, prefix);
279 } else {
280 TDM(DEBUG_ERROR, "%s: expecting: '%s', saw (%d): %s%s",
281 scs->name, prefix, buffered_bytes, linebuf,
282 /* only print the newline if the linebuf lacks it */
283 (linebuf[strlen(linebuf) - 1] == '\n') ? "\n" : "");
285 return 0; /* wait_for_it failed */
288 int tlscomm_gets(char *buf, int buflen, struct connection_state *scs)
290 return (tlscomm_expect(scs, "", buf, buflen));
293 void tlscomm_printf(struct connection_state *scs, const char *format, ...)
295 va_list args;
296 char buf[1024];
297 int bytes;
298 ssize_t unused __attribute__((unused));
300 if (scs == NULL) {
301 DMA(DEBUG_ERROR, "null connection to tlscomm_printf\n");
302 abort();
304 va_start(args, format);
305 bytes = vsnprintf(buf, 1024, format, args);
306 va_end(args);
308 if (scs->sd != -1) {
309 #ifdef USE_GNUTLS
310 if (scs->tls_state) {
311 int written = gnutls_write(scs->tls_state, buf, bytes);
312 if (written < bytes) {
313 TDM(DEBUG_ERROR,
314 "Error %s prevented writing: %*s\n",
315 gnutls_strerror(written), bytes, buf);
316 return;
318 } else
319 #endif
320 /* Why???? */
321 unused = write(scs->sd, buf, bytes);
322 } else {
323 printf
324 ("warning: tlscomm_printf called with an invalid socket descriptor\n");
325 return;
327 TDM(DEBUG_INFO, "wrote %*s", bytes, buf);
330 /* most of this file only makes sense if using TLS. */
331 #ifdef USE_GNUTLS
332 #include "gnutls-common.h"
334 static void
335 bad_certificate(const struct connection_state *scs, const char *msg)
337 TDM(DEBUG_ERROR, "%s", msg);
338 if (!SkipCertificateCheck) {
339 TDM(DEBUG_ERROR, "to ignore this error, run wmbiff "
340 "with the -skip-certificate-check option\n");
341 exit(1);
345 /* a start of a hack at verifying certificates. does not
346 provide any security at all. I'm waiting for either
347 gnutls to make this as easy as it should be, or someone
348 to port Andrew McDonald's gnutls-for-mutt patch.
351 #define CERT_SEP "-----BEGIN"
353 /* this bit is based on read_ca_file() in gnutls */
354 static int tls_compare_certificates(const gnutls_datum * peercert)
356 gnutls_datum cert;
357 unsigned char *ptr;
358 FILE *fd1;
359 int ret;
360 gnutls_datum b64_data;
361 unsigned char *b64_data_data;
362 struct stat filestat;
364 if (stat(certificate_filename, &filestat) == -1)
365 return 0;
367 b64_data.size = filestat.st_size + 1;
368 b64_data_data = (unsigned char *) malloc(b64_data.size);
369 b64_data_data[b64_data.size - 1] = '\0';
370 b64_data.data = b64_data_data;
372 fd1 = fopen(certificate_filename, "r");
373 if (fd1 == NULL) {
374 return 0;
377 b64_data.size = fread(b64_data.data, 1, b64_data.size, fd1);
378 fclose(fd1);
380 do {
381 ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
382 if (ret != 0) {
383 free(b64_data_data);
384 return 0;
387 ptr = (unsigned char *) strstr((char *) b64_data.data, CERT_SEP) + 1;
388 ptr = (unsigned char *) strstr((char *) ptr, CERT_SEP);
390 b64_data.size = b64_data.size - (ptr - b64_data.data);
391 b64_data.data = ptr;
393 if (cert.size == peercert->size) {
394 if (memcmp(cert.data, peercert->data, cert.size) == 0) {
395 /* match found */
396 gnutls_free(cert.data);
397 free(b64_data_data);
398 return 1;
402 gnutls_free(cert.data);
403 } while (ptr != NULL);
405 /* no match found */
406 free(b64_data_data);
407 return 0;
411 static void
412 tls_check_certificate(struct connection_state *scs,
413 const char *remote_hostname)
415 int certstat;
416 const gnutls_datum *cert_list;
417 unsigned int cert_list_size = 0;
418 gnutls_x509_crt cert;
420 if (gnutls_auth_get_type(scs->tls_state) != GNUTLS_CRD_CERTIFICATE) {
421 bad_certificate(scs, "Unable to get certificate from peer.\n");
422 return; /* bad_cert will exit if -skip-certificate-check was not given */
424 certstat = gnutls_certificate_verify_peers(scs->tls_state);
425 if (certstat == GNUTLS_E_NO_CERTIFICATE_FOUND) {
426 bad_certificate(scs, "server presented no certificate.\n");
427 #ifdef GNUTLS_CERT_CORRUPTED
428 } else if (certstat & GNUTLS_CERT_CORRUPTED) {
429 bad_certificate(scs, "server's certificate is corrupt.\n");
430 #endif
431 } else if (certstat & GNUTLS_CERT_REVOKED) {
432 bad_certificate(scs, "server's certificate has been revoked.\n");
433 } else if (certstat & GNUTLS_CERT_INVALID) {
434 if (gnutls_certificate_type_get(scs->tls_state) == GNUTLS_CRT_X509) {
435 /* bad_certificate(scs, "server's certificate is not trusted.\n"
436 "there may be a problem with the certificate stored in your certfile\n"); */
437 } else {
438 bad_certificate(scs,
439 "server's certificate is invalid or not X.509.\n"
440 "there may be a problem with the certificate stored in your certfile\n");
442 #if defined(GNUTLS_CERT_SIGNER_NOT_FOUND)
443 } else if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND) {
444 TDM(DEBUG_INFO, "server's certificate is not signed.\n");
445 TDM(DEBUG_INFO,
446 "to verify that a certificate is trusted, use the certfile option.\n");
447 #endif
449 #if defined(GNUTLS_CERT_NOT_TRUSTED)
450 } else if (certstat & GNUTLS_CERT_NOT_TRUSTED) {
451 TDM(DEBUG_INFO, "server's certificate is not trusted.\n");
452 TDM(DEBUG_INFO,
453 "to verify that a certificate is trusted, use the certfile option.\n");
454 #endif
457 if (gnutls_x509_crt_init(&cert) < 0) {
458 bad_certificate(scs,
459 "Unable to initialize certificate data structure");
463 /* not checking for not-yet-valid certs... this would make sense
464 if we weren't just comparing to stored ones */
465 cert_list =
466 gnutls_certificate_get_peers(scs->tls_state, &cert_list_size);
468 if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) <
469 0) {
470 bad_certificate(scs, "Error processing certificate data");
473 if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) {
474 bad_certificate(scs, "server's certificate has expired.\n");
475 } else if (gnutls_x509_crt_get_activation_time(cert)
476 > time(NULL)) {
477 bad_certificate(scs, "server's certificate is not yet valid.\n");
478 } else {
479 TDM(DEBUG_INFO, "certificate passed time check.\n");
482 if (gnutls_x509_crt_check_hostname(cert, remote_hostname) == 0) {
483 char certificate_hostname[256];
484 size_t buflen = 255;
485 gnutls_x509_crt_get_dn(cert, certificate_hostname, &buflen);
486 /* gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); */
487 TDM(DEBUG_INFO,
488 "server's certificate (%s) does not match its hostname (%s).\n",
489 certificate_hostname, remote_hostname);
490 bad_certificate(scs,
491 "server's certificate does not match its hostname.\n");
492 } else {
493 if ((scs->pc)->debug >= DEBUG_INFO) {
494 char certificate_hostname[256];
495 size_t buflen = 255;
496 gnutls_x509_crt_get_dn(cert, certificate_hostname, &buflen);
497 /* gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); */
498 TDM(DEBUG_INFO,
499 "server's certificate (%s) matched its hostname (%s).\n",
500 certificate_hostname, remote_hostname);
504 if (certificate_filename != NULL &&
505 tls_compare_certificates(&cert_list[0]) == 0) {
506 bad_certificate(scs,
507 "server's certificate was not found in the certificate file.\n");
510 gnutls_x509_crt_deinit(cert);
512 TDM(DEBUG_INFO, "certificate check ok.\n");
513 return;
516 struct connection_state *initialize_gnutls(int sd, char *name, Pop3 pc,
517 const char *remote_hostname)
519 static int gnutls_initialized;
520 int zok;
521 struct connection_state *scs = malloc(sizeof(struct connection_state));
522 memset(scs, 0, sizeof(struct connection_state)); /* clears the unprocessed buffer */
524 scs->pc = pc;
526 assert(sd >= 0);
528 if (gnutls_initialized == 0) {
529 assert(gnutls_global_init() == 0);
530 gnutls_initialized = 1;
533 assert(gnutls_init(&scs->tls_state, GNUTLS_CLIENT) == 0);
535 const int protocols[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
536 const int ciphers[] =
537 { GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC,
538 GNUTLS_CIPHER_RIJNDAEL_256_CBC,
539 GNUTLS_CIPHER_ARCFOUR, 0
541 const int compress[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
542 const int key_exch[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS,
543 GNUTLS_KX_DHE_RSA, 0
545 /* mutt with gnutls doesn't use kx_srp or kx_anon_dh */
546 const int mac[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
547 assert(gnutls_protocol_set_priority(scs->tls_state, protocols) ==
549 assert(gnutls_cipher_set_priority(scs->tls_state, ciphers) == 0);
550 assert(gnutls_compression_set_priority(scs->tls_state, compress) ==
552 assert(gnutls_kx_set_priority(scs->tls_state, key_exch) == 0);
553 assert(gnutls_mac_set_priority(scs->tls_state, mac) == 0);
554 /* no client private key */
555 if (gnutls_certificate_allocate_credentials(&scs->xcred) < 0) {
556 DMA(DEBUG_ERROR, "gnutls memory error\n");
557 exit(1);
560 /* certfile seems to work. */
561 if (certificate_filename != NULL) {
562 if (!exists(certificate_filename)) {
563 DMA(DEBUG_ERROR,
564 "Certificate file (certfile=) %s not found.\n",
565 certificate_filename);
566 exit(1);
568 zok = gnutls_certificate_set_x509_trust_file(scs->xcred,
569 (char *)
570 certificate_filename,
571 GNUTLS_X509_FMT_PEM);
572 if (zok < 0) {
573 DMA(DEBUG_ERROR,
574 "GNUTLS did not like your certificate file %s (%d).\n",
575 certificate_filename, zok);
576 gnutls_perror(zok);
577 exit(1);
581 gnutls_cred_set(scs->tls_state, GNUTLS_CRD_CERTIFICATE,
582 scs->xcred);
583 gnutls_transport_set_ptr(scs->tls_state,
584 (gnutls_transport_ptr) sd);
585 do {
586 zok = gnutls_handshake(scs->tls_state);
588 while (zok == GNUTLS_E_INTERRUPTED || zok == GNUTLS_E_AGAIN);
590 tls_check_certificate(scs, remote_hostname);
593 if (zok < 0) {
594 TDM(DEBUG_ERROR, "%s: Handshake failed\n", name);
595 TDM(DEBUG_ERROR, "%s: This may be a problem in gnutls, "
596 "which is under development\n", name);
597 TDM(DEBUG_ERROR,
598 "%s: This copy of wmbiff was compiled with \n"
599 " gnutls version %s.\n", name, LIBGNUTLS_VERSION);
600 gnutls_perror(zok);
601 if (scs->pc->u.pop_imap.serverPort != 143 /* starttls */ ) {
602 TDM(DEBUG_ERROR,
603 "%s: Please run 'gnutls-cli-debug -p %d %s' to test ssl directly.\n"
604 " That tool provides a lower-level test of gnutls with your server.\n",
605 name, scs->pc->u.pop_imap.serverPort, remote_hostname);
607 gnutls_deinit(scs->tls_state);
608 free(scs);
609 return (NULL);
610 } else {
611 TDM(DEBUG_INFO, "%s: Handshake was completed\n", name);
612 if (scs->pc->debug >= DEBUG_INFO)
613 print_info(scs->tls_state, remote_hostname);
614 scs->sd = sd;
615 scs->name = name;
617 return (scs);
620 /* moved down here, to keep from interrupting the flow with
621 verbose error crap */
622 void handle_gnutls_read_error(int readbytes, struct connection_state *scs)
624 if (gnutls_error_is_fatal(readbytes) == 1) {
625 TDM(DEBUG_ERROR,
626 "%s: Received corrupted data(%d) - server has terminated the connection abnormally\n",
627 scs->name, readbytes);
628 } else {
629 if (readbytes == GNUTLS_E_WARNING_ALERT_RECEIVED
630 || readbytes == GNUTLS_E_FATAL_ALERT_RECEIVED)
631 TDM(DEBUG_ERROR, "* Received alert [%d]\n",
632 gnutls_alert_get(scs->tls_state));
633 if (readbytes == GNUTLS_E_REHANDSHAKE)
634 TDM(DEBUG_ERROR, "* Received HelloRequest message\n");
636 TDM(DEBUG_ERROR,
637 "%s: gnutls error reading: %s\n",
638 scs->name, gnutls_strerror(readbytes));
641 #else
642 /* declare stubs when tls isn't compiled in */
643 struct connection_state *initialize_gnutls(UNUSED(int sd),
644 UNUSED(char *name),
645 UNUSED(Pop3 pc),
646 UNUSED(const char
647 *remote_hostname))
649 DM(pc, DEBUG_ERROR,
650 "FATAL: tried to initialize ssl when ssl wasn't compiled in.\n");
651 exit(EXIT_FAILURE);
653 #endif
655 /* either way: */
656 struct connection_state *initialize_unencrypted(int sd,
657 /*@only@ */ char *name,
658 Pop3 pc)
660 struct connection_state *ret = malloc(sizeof(struct connection_state));
661 assert(sd >= 0);
662 assert(ret != NULL);
663 memset(ret, 0, sizeof(struct connection_state)); /* clears the unprocessed buffer */
664 ret->sd = sd;
665 ret->name = name;
666 ret->tls_state = NULL;
667 ret->xcred = NULL;
668 ret->pc = pc;
669 return (ret);
672 /* bad seed connections that can't be setup */
673 /*@only@*/
674 struct connection_state *initialize_blacklist( /*@only@ */ char *name)
676 struct connection_state *ret = malloc(sizeof(struct connection_state));
677 assert(ret != NULL);
678 ret->sd = -1;
679 ret->name = name;
680 ret->tls_state = NULL;
681 ret->xcred = NULL;
682 ret->pc = NULL;
683 return (ret);
687 int tlscomm_is_blacklisted(const struct connection_state *scs)
689 return (scs != NULL && scs->sd == -1);
692 /* vim:set ts=4: */
694 * Local Variables:
695 * tab-width: 4
696 * c-indent-level: 4
697 * c-basic-offset: 4
698 * End: