wmbiff: Fix compiler warnings from deprecated gnutls types.
[dockapps.git] / wmbiff / wmbiff / tlsComm.c
bloba99afa883eba82a8d110d0cf58a6a72d7dc68843
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;
41 /* gnutls: specify the priorities to use on the ciphers, key exchange methods,
42 macs and compression methods. */
43 extern const char *tls;
45 /* WARNING: implcitly uses scs to gain access to the mailbox
46 that holds the per-mailbox debug flag. */
47 #define TDM(lvl, args...) DM(scs->pc, lvl, "comm: " args)
49 /* how long to wait for the server to do its thing
50 when we issue it a command (in seconds) */
51 #define EXPECT_TIMEOUT 40
53 /* this is the per-connection state that is maintained for
54 each connection; BIG variables are for ssl (null if not
55 used). */
56 #define BUF_SIZE 1024
57 struct connection_state {
58 int sd;
59 char *name;
60 #ifdef USE_GNUTLS
61 gnutls_session_t tls_state;
62 gnutls_certificate_credentials_t xcred;
63 #else
64 /*@null@ */ void *tls_state;
65 /*@null@ */ void *xcred;
66 #endif
67 char unprocessed[BUF_SIZE];
68 Pop3 pc; /* mailbox handle for debugging messages */
71 /* gotta do our own line buffering, sigh */
72 int getline_from_buffer(char *readbuffer, char *linebuffer,
73 int linebuflen);
74 void handle_gnutls_read_error(int readbytes, struct connection_state *scs);
76 void tlscomm_close(struct connection_state *scs)
78 TDM(DEBUG_INFO, "%s: closing.\n",
79 (scs->name != NULL) ? scs->name : "null");
81 /* not ok to call this more than once */
82 if (scs->tls_state) {
83 #ifdef USE_GNUTLS
84 /* this next line seems capable of hanging... */
85 /* gnutls_bye(scs->tls_state, GNUTLS_SHUT_RDWR); */
86 /* so we'll try just _bye'ing the WR direction, which
87 should send the alert but not wait for a response. */
88 gnutls_bye(scs->tls_state, GNUTLS_SHUT_WR);
89 gnutls_certificate_free_credentials(scs->xcred);
90 gnutls_deinit(scs->tls_state);
91 scs->xcred = NULL;
92 #endif
93 } else {
94 (void) close(scs->sd);
96 scs->sd = -1;
97 scs->tls_state = NULL;
98 scs->xcred = NULL;
99 free(scs->name);
100 scs->name = NULL;
101 free(scs);
104 extern int x_socket(void);
105 extern void ProcessPendingEvents(void);
107 /* this avoids blocking without using non-blocking i/o */
108 static int wait_for_it(int sd, int timeoutseconds)
110 fd_set readfds;
111 struct timeval tv;
112 int ready_descriptors;
113 int maxfd;
114 int xfd;
115 struct timeval time_now;
116 struct timeval time_out;
118 gettimeofday(&time_now, NULL);
119 memcpy(&time_out, &time_now, sizeof(struct timeval));
120 time_out.tv_sec += timeoutseconds;
122 xfd = x_socket();
123 maxfd = max(sd, xfd);
125 do {
126 do {
127 ProcessPendingEvents();
129 gettimeofday(&time_now, NULL);
130 tv.tv_sec = max(time_out.tv_sec - time_now.tv_sec + 1, (time_t) 0); /* sloppy, but bfd */
131 tv.tv_usec = 0;
132 /* select will return if we have X stuff or we have comm stuff on sd */
133 FD_ZERO(&readfds);
134 FD_SET(sd, &readfds);
135 // FD_SET(xfd, &readfds);
136 ready_descriptors = select(maxfd + 1, &readfds, NULL, NULL, &tv);
137 // DMA(DEBUG_INFO,
138 // "select %d/%d returned %d descriptor, %d\n",
139 // sd, timeoutseconds, ready_descriptors, FD_ISSET(sd, &readfds));
141 } while(tv.tv_sec > 0 && (!FD_ISSET(sd, &readfds) || (errno == EINTR && ready_descriptors == -1)));
143 FD_ZERO(&readfds);
144 FD_SET(sd, &readfds);
145 tv.tv_sec = 0; tv.tv_usec = 0;
146 ready_descriptors = select(sd + 1, &readfds, NULL, NULL, &tv);
148 while (ready_descriptors == -1 && errno == EINTR);
149 if (ready_descriptors == 0) {
150 DMA(DEBUG_INFO,
151 "select timed out after %d seconds on socket: %d\n",
152 timeoutseconds, sd);
153 return (0);
154 } else if (ready_descriptors == -1) {
155 DMA(DEBUG_ERROR,
156 "select failed on socket %d: %s\n", sd, strerror(errno));
157 return (0);
159 return (FD_ISSET(sd, &readfds));
162 /* exported for testing */
163 extern int
164 getline_from_buffer(char *readbuffer, char *linebuffer, int linebuflen)
166 char *p, *q;
167 int i;
168 /* find end of line (stopping if linebuflen is too small. */
169 for (p = readbuffer, i = 0;
170 *p != '\n' && *p != '\0' && i < linebuflen - 1; p++, i++);
172 /* gobble \n if it starts the line. */
173 if (*p == '\n') {
174 /* grab the end of line too! and then advance past
175 the newline */
176 i++;
177 p++;
178 } else {
179 /* TODO -- perhaps we should return no line at all
180 here, as it might be incomplete. don't want to
181 break anything though. */
182 DMA(DEBUG_INFO, "expected line doesn't end on its own.\n");
185 if (i != 0) {
186 /* copy a line into the linebuffer */
187 strncpy(linebuffer, readbuffer, (size_t) i);
188 /* sigh, null terminate */
189 linebuffer[i] = '\0';
190 /* shift the rest over; this could be done
191 instead with strcpy... I think. */
192 q = readbuffer;
193 if (*p != '\0') {
194 while (*p != '\0') {
195 *(q++) = *(p++);
198 /* null terminate */
199 *(q++) = *(p++);
200 /* return the length of the line */
202 if (i < 0 || i > linebuflen) {
203 DM((Pop3) NULL, DEBUG_ERROR, "bork bork bork!: %d %d\n", i,
204 linebuflen);
206 return i;
209 /* eat lines, until one starting with prefix is found;
210 this skips 'informational' IMAP responses */
211 /* the correct response to a return value of 0 is almost
212 certainly tlscomm_close(scs): don't _expect() anything
213 unless anything else would represent failure */
215 tlscomm_expect(struct connection_state *scs,
216 const char *prefix, char *linebuf, int buflen)
218 int prefixlen = (int) strlen(prefix);
219 int buffered_bytes = 0;
220 memset(linebuf, 0, buflen);
221 TDM(DEBUG_INFO, "%s: expecting: %s\n", scs->name, prefix);
222 /* if(scs->unprocessed[0]) {
223 TDM(DEBUG_INFO, "%s: buffered: %s\n", scs->name, scs->unprocessed);
224 } */
225 while (scs->unprocessed[0] != '\0'
226 || wait_for_it(scs->sd, EXPECT_TIMEOUT)) {
227 if (scs->unprocessed[buffered_bytes] == '\0') {
228 int thisreadbytes;
229 #ifdef USE_GNUTLS
230 if (scs->tls_state) {
231 /* BUF_SIZE - 1 leaves room for trailing \0 */
232 thisreadbytes =
233 gnutls_read(scs->tls_state,
234 &scs->unprocessed[buffered_bytes],
235 BUF_SIZE - 1 - buffered_bytes);
236 if (thisreadbytes < 0) {
237 handle_gnutls_read_error(thisreadbytes, scs);
238 return 0;
240 } else
241 #endif
243 thisreadbytes =
244 read(scs->sd, &scs->unprocessed[buffered_bytes],
245 BUF_SIZE - 1 - buffered_bytes);
246 if (thisreadbytes < 0) {
247 TDM(DEBUG_ERROR, "%s: error reading: %s\n",
248 scs->name, strerror(errno));
249 return 0;
252 buffered_bytes += thisreadbytes;
253 /* force null termination */
254 scs->unprocessed[buffered_bytes] = '\0';
255 if (buffered_bytes == 0) {
256 return 0; /* bummer */
258 } else {
259 buffered_bytes = strlen(scs->unprocessed);
261 while (buffered_bytes >= prefixlen) {
262 int linebytes;
263 linebytes =
264 getline_from_buffer(scs->unprocessed, linebuf, buflen);
265 if (linebytes == 0) {
266 buffered_bytes = 0;
267 } else {
268 buffered_bytes -= linebytes;
269 if (strncmp(linebuf, prefix, prefixlen) == 0) {
270 TDM(DEBUG_INFO, "%s: got: %*s", scs->name,
271 linebytes, linebuf);
272 return 1; /* got it! */
274 TDM(DEBUG_INFO, "%s: dumped(%d/%d): %.*s", scs->name,
275 linebytes, buffered_bytes, linebytes, linebuf);
279 if (buffered_bytes == -1) {
280 TDM(DEBUG_INFO, "%s: timed out while expecting '%s'\n",
281 scs->name, prefix);
282 } else {
283 TDM(DEBUG_ERROR, "%s: expecting: '%s', saw (%d): %s%s",
284 scs->name, prefix, buffered_bytes, linebuf,
285 /* only print the newline if the linebuf lacks it */
286 (linebuf[strlen(linebuf) - 1] == '\n') ? "\n" : "");
288 return 0; /* wait_for_it failed */
291 int tlscomm_gets(char *buf, int buflen, struct connection_state *scs)
293 return (tlscomm_expect(scs, "", buf, buflen));
296 void tlscomm_printf(struct connection_state *scs, const char *format, ...)
298 va_list args;
299 char buf[1024];
300 int bytes;
301 ssize_t unused __attribute__((unused));
303 if (scs == NULL) {
304 DMA(DEBUG_ERROR, "null connection to tlscomm_printf\n");
305 abort();
307 va_start(args, format);
308 bytes = vsnprintf(buf, 1024, format, args);
309 va_end(args);
311 if (scs->sd != -1) {
312 #ifdef USE_GNUTLS
313 if (scs->tls_state) {
314 int written = gnutls_write(scs->tls_state, buf, bytes);
315 if (written < bytes) {
316 TDM(DEBUG_ERROR,
317 "Error %s prevented writing: %*s\n",
318 gnutls_strerror(written), bytes, buf);
319 return;
321 } else
322 #endif
323 /* Why???? */
324 unused = write(scs->sd, buf, bytes);
325 } else {
326 printf
327 ("warning: tlscomm_printf called with an invalid socket descriptor\n");
328 return;
330 TDM(DEBUG_INFO, "wrote %*s", bytes, buf);
333 /* most of this file only makes sense if using TLS. */
334 #ifdef USE_GNUTLS
335 #include "gnutls-common.h"
337 static void
338 bad_certificate(const struct connection_state *scs, const char *msg)
340 TDM(DEBUG_ERROR, "%s", msg);
341 if (!SkipCertificateCheck) {
342 TDM(DEBUG_ERROR, "to ignore this error, run wmbiff "
343 "with the -skip-certificate-check option\n");
344 exit(1);
348 static void
349 warn_certificate(const struct connection_state *scs, const char *msg)
351 if (!SkipCertificateCheck) {
352 TDM(DEBUG_ERROR, "%s", msg);
353 TDM(DEBUG_ERROR, "to ignore this warning, run wmbiff "
354 "with the -skip-certificate-check option\n");
358 /* a start of a hack at verifying certificates. does not
359 provide any security at all. I'm waiting for either
360 gnutls to make this as easy as it should be, or someone
361 to port Andrew McDonald's gnutls-for-mutt patch.
364 #define CERT_SEP "-----BEGIN"
366 /* this bit is based on read_ca_file() in gnutls */
367 static int tls_compare_certificates(const gnutls_datum_t * peercert)
369 gnutls_datum_t cert;
370 unsigned char *ptr;
371 FILE *fd1;
372 int ret;
373 gnutls_datum_t b64_data;
374 unsigned char *b64_data_data;
375 struct stat filestat;
377 if (stat(certificate_filename, &filestat) == -1)
378 return 0;
380 b64_data.size = filestat.st_size + 1;
381 b64_data_data = (unsigned char *) malloc(b64_data.size);
382 b64_data_data[b64_data.size - 1] = '\0';
383 b64_data.data = b64_data_data;
385 fd1 = fopen(certificate_filename, "r");
386 if (fd1 == NULL) {
387 return 0;
390 b64_data.size = fread(b64_data.data, 1, b64_data.size, fd1);
391 fclose(fd1);
393 do {
394 ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
395 if (ret != 0) {
396 free(b64_data_data);
397 return 0;
400 ptr = (unsigned char *) strstr((char *) b64_data.data, CERT_SEP) + 1;
401 ptr = (unsigned char *) strstr((char *) ptr, CERT_SEP);
403 b64_data.size = b64_data.size - (ptr - b64_data.data);
404 b64_data.data = ptr;
406 if (cert.size == peercert->size) {
407 if (memcmp(cert.data, peercert->data, cert.size) == 0) {
408 /* match found */
409 gnutls_free(cert.data);
410 free(b64_data_data);
411 return 1;
415 gnutls_free(cert.data);
416 } while (ptr != NULL);
418 /* no match found */
419 free(b64_data_data);
420 return 0;
424 static void
425 tls_check_certificate(struct connection_state *scs,
426 const char *remote_hostname)
428 int ret;
429 unsigned int certstat;
430 const gnutls_datum_t *cert_list;
431 unsigned int cert_list_size = 0;
432 gnutls_x509_crt_t cert;
434 if (gnutls_auth_get_type(scs->tls_state) != GNUTLS_CRD_CERTIFICATE) {
435 bad_certificate(scs, "Unable to get certificate from peer.\n");
436 return; /* bad_cert will exit if -skip-certificate-check was not given */
438 ret = gnutls_certificate_verify_peers2(scs->tls_state, &certstat);
440 if (ret < 0) {
441 char errbuf[1024];
443 snprintf(errbuf, 1024, "could not verify certificate: %s (%d).\n",
444 gnutls_strerror(ret), ret);
445 bad_certificate(scs, (ret == GNUTLS_E_NO_CERTIFICATE_FOUND ?
446 "server presented no certificate.\n" :
447 errbuf));
448 return;
449 #ifdef GNUTLS_CERT_CORRUPTED
450 } else if (certstat & GNUTLS_CERT_CORRUPTED) {
451 bad_certificate(scs, "server's certificate is corrupt.\n");
452 #endif
453 } else if (certstat & GNUTLS_CERT_REVOKED) {
454 bad_certificate(scs, "server's certificate has been revoked.\n");
455 } else if (certstat & GNUTLS_CERT_EXPIRED) {
456 bad_certificate(scs, "server's certificate is expired.\n");
457 } else if (certstat & GNUTLS_CERT_INSECURE_ALGORITHM) {
458 warn_certificate(scs, "server's certificate use an insecure algorithm.\n");
459 } else if (certstat & GNUTLS_CERT_INVALID) {
460 if (gnutls_certificate_type_get(scs->tls_state) == GNUTLS_CRT_X509) {
461 /* bad_certificate(scs, "server's certificate is not trusted.\n"
462 "there may be a problem with the certificate stored in your certfile\n"); */
463 } else {
464 bad_certificate(scs,
465 "server's certificate is invalid or not X.509.\n"
466 "there may be a problem with the certificate stored in your certfile\n");
468 #if defined(GNUTLS_CERT_SIGNER_NOT_FOUND)
469 } else if (certstat & GNUTLS_CERT_SIGNER_NOT_FOUND) {
470 TDM(DEBUG_INFO, "server's certificate is not signed.\n");
471 TDM(DEBUG_INFO,
472 "to verify that a certificate is trusted, use the certfile option.\n");
473 #endif
475 #if defined(GNUTLS_CERT_NOT_TRUSTED)
476 } else if (certstat & GNUTLS_CERT_NOT_TRUSTED) {
477 TDM(DEBUG_INFO, "server's certificate is not trusted.\n");
478 TDM(DEBUG_INFO,
479 "to verify that a certificate is trusted, use the certfile option.\n");
480 #endif
483 if (gnutls_x509_crt_init(&cert) < 0) {
484 bad_certificate(scs,
485 "Unable to initialize certificate data structure");
489 /* not checking for not-yet-valid certs... this would make sense
490 if we weren't just comparing to stored ones */
491 cert_list =
492 gnutls_certificate_get_peers(scs->tls_state, &cert_list_size);
494 if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) <
495 0) {
496 bad_certificate(scs, "Error processing certificate data");
499 if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL)) {
500 bad_certificate(scs, "server's certificate has expired.\n");
501 } else if (gnutls_x509_crt_get_activation_time(cert)
502 > time(NULL)) {
503 bad_certificate(scs, "server's certificate is not yet valid.\n");
504 } else {
505 TDM(DEBUG_INFO, "certificate passed time check.\n");
508 if (gnutls_x509_crt_check_hostname(cert, remote_hostname) == 0) {
509 char certificate_hostname[256];
510 size_t buflen = 255;
511 gnutls_x509_crt_get_dn(cert, certificate_hostname, &buflen);
512 /* gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); */
513 TDM(DEBUG_INFO,
514 "server's certificate (%s) does not match its hostname (%s).\n",
515 certificate_hostname, remote_hostname);
516 bad_certificate(scs,
517 "server's certificate does not match its hostname.\n");
518 } else {
519 if ((scs->pc)->debug >= DEBUG_INFO) {
520 char certificate_hostname[256];
521 size_t buflen = 255;
522 gnutls_x509_crt_get_dn(cert, certificate_hostname, &buflen);
523 /* gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); */
524 TDM(DEBUG_INFO,
525 "server's certificate (%s) matched its hostname (%s).\n",
526 certificate_hostname, remote_hostname);
530 if (certificate_filename != NULL &&
531 tls_compare_certificates(&cert_list[0]) == 0) {
532 bad_certificate(scs,
533 "server's certificate was not found in the certificate file.\n");
536 gnutls_x509_crt_deinit(cert);
538 TDM(DEBUG_INFO, "certificate check ok.\n");
539 return;
542 struct connection_state *initialize_gnutls(int sd, char *name, Pop3 pc,
543 const char *remote_hostname)
545 static int gnutls_initialized;
546 int zok;
547 struct connection_state *scs = malloc(sizeof(struct connection_state));
548 memset(scs, 0, sizeof(struct connection_state)); /* clears the unprocessed buffer */
550 scs->pc = pc;
552 assert(sd >= 0);
554 if (gnutls_initialized == 0) {
555 assert(gnutls_global_init() == 0);
556 gnutls_initialized = 1;
559 assert(gnutls_init(&scs->tls_state, GNUTLS_CLIENT) == 0);
561 const char *err_pos;
562 if (GNUTLS_E_SUCCESS != gnutls_priority_set_direct(scs->tls_state, tls, &err_pos)) {
563 DMA(DEBUG_ERROR,
564 "Unable to set the priorities to use on the ciphers, "
565 "key exchange methods, macs and/or compression methods.\n"
566 "See 'tls' parameter in config file: '%s'.\n",
567 err_pos);
568 exit(1);
571 /* no client private key */
572 if (gnutls_certificate_allocate_credentials(&scs->xcred) < 0) {
573 DMA(DEBUG_ERROR, "gnutls memory error\n");
574 exit(1);
577 /* certfile seems to work. */
578 if (certificate_filename != NULL) {
579 if (!exists(certificate_filename)) {
580 DMA(DEBUG_ERROR,
581 "Certificate file (certfile=) %s not found.\n",
582 certificate_filename);
583 exit(1);
585 zok = gnutls_certificate_set_x509_trust_file(scs->xcred,
586 (char *)
587 certificate_filename,
588 GNUTLS_X509_FMT_PEM);
589 if (zok < 0) {
590 DMA(DEBUG_ERROR,
591 "GNUTLS did not like your certificate file %s (%d).\n",
592 certificate_filename, zok);
593 gnutls_perror(zok);
594 exit(1);
598 gnutls_cred_set(scs->tls_state, GNUTLS_CRD_CERTIFICATE,
599 scs->xcred);
600 gnutls_transport_set_ptr(scs->tls_state,
601 (gnutls_transport_ptr_t) sd);
602 do {
603 zok = gnutls_handshake(scs->tls_state);
605 while (zok == GNUTLS_E_INTERRUPTED || zok == GNUTLS_E_AGAIN);
607 tls_check_certificate(scs, remote_hostname);
610 if (zok < 0) {
611 TDM(DEBUG_ERROR, "%s: Handshake failed\n", name);
612 TDM(DEBUG_ERROR, "%s: This may be a problem in gnutls, "
613 "which is under development\n", name);
614 TDM(DEBUG_ERROR,
615 "%s: This copy of wmbiff was compiled with \n"
616 " gnutls version %s.\n", name, LIBGNUTLS_VERSION);
617 gnutls_perror(zok);
618 if (scs->pc->u.pop_imap.serverPort != 143 /* starttls */ ) {
619 TDM(DEBUG_ERROR,
620 "%s: Please run 'gnutls-cli-debug -p %d %s' to test ssl directly.\n"
621 " That tool provides a lower-level test of gnutls with your server.\n",
622 name, scs->pc->u.pop_imap.serverPort, remote_hostname);
624 gnutls_deinit(scs->tls_state);
625 free(scs);
626 return (NULL);
627 } else {
628 TDM(DEBUG_INFO, "%s: Handshake was completed\n", name);
629 if (scs->pc->debug >= DEBUG_INFO)
630 print_info(scs->tls_state, remote_hostname);
631 scs->sd = sd;
632 scs->name = name;
634 return (scs);
637 /* moved down here, to keep from interrupting the flow with
638 verbose error crap */
639 void handle_gnutls_read_error(int readbytes, struct connection_state *scs)
641 if (gnutls_error_is_fatal(readbytes) == 1) {
642 TDM(DEBUG_ERROR,
643 "%s: Received corrupted data(%d) - server has terminated the connection abnormally\n",
644 scs->name, readbytes);
645 } else {
646 if (readbytes == GNUTLS_E_WARNING_ALERT_RECEIVED
647 || readbytes == GNUTLS_E_FATAL_ALERT_RECEIVED)
648 TDM(DEBUG_ERROR, "* Received alert [%d]\n",
649 gnutls_alert_get(scs->tls_state));
650 if (readbytes == GNUTLS_E_REHANDSHAKE)
651 TDM(DEBUG_ERROR, "* Received HelloRequest message\n");
653 TDM(DEBUG_ERROR,
654 "%s: gnutls error reading: %s\n",
655 scs->name, gnutls_strerror(readbytes));
658 #else
659 /* declare stubs when tls isn't compiled in */
660 struct connection_state *initialize_gnutls(UNUSED(int sd),
661 UNUSED(char *name),
662 UNUSED(Pop3 pc),
663 UNUSED(const char
664 *remote_hostname))
666 DM(pc, DEBUG_ERROR,
667 "FATAL: tried to initialize ssl when ssl wasn't compiled in.\n");
668 exit(EXIT_FAILURE);
670 #endif
672 /* either way: */
673 struct connection_state *initialize_unencrypted(int sd,
674 /*@only@ */ char *name,
675 Pop3 pc)
677 struct connection_state *ret = malloc(sizeof(struct connection_state));
678 assert(sd >= 0);
679 assert(ret != NULL);
680 memset(ret, 0, sizeof(struct connection_state)); /* clears the unprocessed buffer */
681 ret->sd = sd;
682 ret->name = name;
683 ret->tls_state = NULL;
684 ret->xcred = NULL;
685 ret->pc = pc;
686 return (ret);
689 /* bad seed connections that can't be setup */
690 /*@only@*/
691 struct connection_state *initialize_blacklist( /*@only@ */ char *name)
693 struct connection_state *ret = malloc(sizeof(struct connection_state));
694 assert(ret != NULL);
695 ret->sd = -1;
696 ret->name = name;
697 ret->tls_state = NULL;
698 ret->xcred = NULL;
699 ret->pc = NULL;
700 return (ret);
704 int tlscomm_is_blacklisted(const struct connection_state *scs)
706 return (scs != NULL && scs->sd == -1);
709 /* vim:set ts=4: */
711 * Local Variables:
712 * tab-width: 4
713 * c-indent-level: 4
714 * c-basic-offset: 4
715 * End: