1 /* A little hacked up program that makes a TCP/IP call and reads a script to
2 drive it, for testing Exim server code running as a daemon. It's got a bit
3 messy with the addition of support for either OpenSSL or GnuTLS. The code for
4 those was hacked out of Exim itself, then code for OpenSSL OCSP stapling was
5 ripped from the openssl ocsp and s_client utilities. */
7 /* ANSI C standard includes */
22 #include <sys/types.h>
24 #include <netinet/in_systm.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27 #include <netinet/tcp.h>
30 #include <arpa/inet.h>
32 #include <sys/resource.h>
33 #include <sys/socket.h>
44 #define S_ADDR_TYPE u_long
47 typedef unsigned char uschar;
50 #define US (unsigned char *)
57 static int sigalrm_seen = 0;
60 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
61 latter needs a whole pile of tables. */
64 # include <openssl/crypto.h>
65 # include <openssl/x509.h>
66 # include <openssl/pem.h>
67 # include <openssl/ssl.h>
68 # include <openssl/err.h>
69 # include <openssl/rand.h>
71 # if OPENSSL_VERSION_NUMBER < 0x0090806fL && !defined(DISABLE_OCSP) && !defined(OPENSSL_NO_TLSEXT)
72 # warning "OpenSSL library version too old; define DISABLE_OCSP in Makefile"
76 # include <openssl/ocsp.h>
83 # include <gnutls/gnutls.h>
84 # include <gnutls/x509.h>
85 # if GNUTLS_VERSION_NUMBER >= 0x030103
87 # include <gnutls/ocsp.h>
89 # ifndef GNUTLS_NO_EXTENSIONS
90 # define GNUTLS_NO_EXTENSIONS 0
95 /* Local static variables for GNUTLS */
97 static gnutls_dh_params_t dh_params = NULL;
99 static gnutls_certificate_credentials_t x509_cred = NULL;
100 static gnutls_session_t tls_session = NULL;
102 static int ssl_session_timeout = 200;
104 /* Priorities for TLS algorithms to use. */
106 # if GNUTLS_VERSION_NUMBER < 0x030400
107 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
109 static const int kx_priority[16] = {
115 static int default_cipher_priority[16] = {
116 GNUTLS_CIPHER_AES_256_CBC,
117 GNUTLS_CIPHER_AES_128_CBC,
118 GNUTLS_CIPHER_3DES_CBC,
119 GNUTLS_CIPHER_ARCFOUR_128,
122 static const int mac_priority[16] = {
127 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
130 #endif /*HAVE_GNUTLS*/
135 char * ocsp_stapling = NULL;
136 char * pri_string = NULL;
140 /*************************************************
141 * SIGALRM handler - crash out *
142 *************************************************/
145 sigalrm_handler_crash(int sig)
147 sig = sig; /* Keep picky compilers happy */
148 printf("\nClient timed out\n");
153 /*************************************************
154 * SIGALRM handler - set flag *
155 *************************************************/
158 sigalrm_handler_flag(int sig)
160 sig = sig; /* Keep picky compilers happy */
166 /****************************************************************************/
167 /****************************************************************************/
170 # ifndef DISABLE_OCSP
172 static STACK_OF(X509) *
173 chain_from_pem_file(const uschar * file)
179 if (!(sk = sk_X509_new_null())) return NULL;
180 if (!(bp = BIO_new_file(CS file, "r"))) return NULL;
181 while ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)))
190 cert_stack_free(STACK_OF(X509) * sk)
192 while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
198 tls_client_stapling_cb(SSL *s, void *arg)
200 const unsigned char *p;
207 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
208 /*BIO_printf(arg, "OCSP response: ");*/
211 BIO_printf(arg, "no response received\n");
214 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
216 BIO_printf(arg, "response parse error\n");
217 BIO_dump_indent(arg, (char *)p, len, 4);
220 if(!(bs = OCSP_response_get1_basic(rsp)))
222 BIO_printf(arg, "error parsing response\n");
227 if (!(sk = chain_from_pem_file((const uschar *)ocsp_stapling)))
229 BIO_printf(arg, "error in cert setup\n");
233 /* OCSP_basic_verify takes a "store" arg, but does not
234 use it for the chain verification, which is all we do
235 when OCSP_NOVERIFY is set. The content from the wire
236 (in "bs") and a cert-stack "sk" are all that is used. */
238 if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
240 BIO_printf(arg, "Response Verify Failure\n");
241 ERR_print_errors(arg);
245 BIO_printf(arg, "Response verify OK\n");
250 # endif /*DISABLE_OCSP*/
253 /*************************************************
254 * Start an OpenSSL TLS session *
255 *************************************************/
258 tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
261 static const unsigned char *sid_ctx = US"exim";
263 RAND_load_file("client.c", -1); /* Not *very* random! */
265 *ssl = SSL_new (ctx);
266 SSL_set_session_id_context(*ssl, sid_ctx, strlen(CS sid_ctx));
267 SSL_set_fd (*ssl, sock);
268 SSL_set_connect_state(*ssl);
273 SSL_CTX_set_tlsext_status_cb(ctx, tls_client_stapling_cb);
274 SSL_CTX_set_tlsext_status_arg(ctx, BIO_new_fp(stdout, BIO_NOCLOSE));
275 SSL_set_tlsext_status_type(*ssl, TLSEXT_STATUSTYPE_ocsp);
279 signal(SIGALRM, sigalrm_handler_flag);
282 rc = SSL_connect (*ssl);
287 printf("SSL_connect timed out\n");
293 ERR_print_errors_fp(stdout);
297 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
302 /*************************************************
303 * SSL Information callback *
304 *************************************************/
307 info_callback(SSL *s, int where, int ret)
311 printf("SSL info: %s\n", SSL_state_string_long(s));
316 /****************************************************************************/
317 /****************************************************************************/
321 /*************************************************
322 * Handle GnuTLS error *
323 *************************************************/
325 /* Called from lots of places when errors occur before actually starting to do
326 the TLS handshake, that is, while the session is still in clear.
330 err a GnuTLS error number, or 0 if local error
332 Returns: doesn't - it dies
336 gnutls_error(uschar *prefix, int err)
338 fprintf(stderr, "GnuTLS connection error: %s:", prefix);
339 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
340 fprintf(stderr, "\n");
346 /*************************************************
347 * Setup up DH parameters *
348 *************************************************/
350 /* For the test suite, the parameters should always be available in the spool
359 uschar filename[200];
362 /* Initialize the data structures for holding the parameters */
364 ret = gnutls_dh_params_init(&dh_params);
365 if (ret < 0) gnutls_error(US"init dh_params", ret);
367 /* Open the cache file for reading and if successful, read it and set up the
370 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
373 fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
377 if (fstat(fd, &statbuf) < 0)
380 return gnutls_error(US"TLS cache stat failed", 0);
383 m.size = statbuf.st_size;
384 m.data = malloc(m.size);
386 return gnutls_error(US"memory allocation failed", 0);
387 if (read(fd, m.data, m.size) != m.size)
388 return gnutls_error(US"TLS cache read failed", 0);
391 ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
392 if (ret < 0) return gnutls_error(US"DH params import", ret);
399 /*************************************************
400 * Initialize for GnuTLS *
401 *************************************************/
405 certificate certificate file
406 privatekey private key file
410 tls_init(uschar *certificate, uschar *privatekey)
414 rc = gnutls_global_init();
415 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
417 /* Read D-H parameters from the cache file. */
421 /* Create the credentials structure */
423 rc = gnutls_certificate_allocate_credentials(&x509_cred);
424 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
426 /* Set the certificate and private keys */
428 if (certificate != NULL)
430 rc = gnutls_certificate_set_x509_key_file(x509_cred, CS certificate,
431 CS privatekey, GNUTLS_X509_FMT_PEM);
432 if (rc < 0) gnutls_error(US"gnutls_certificate", rc);
435 /* Associate the parameters with the x509 credentials structure. */
437 gnutls_certificate_set_dh_params(x509_cred, dh_params);
439 /* set the CA info for server-cert verify */
441 gnutls_certificate_set_x509_trust_file(x509_cred, ocsp_stapling,
442 GNUTLS_X509_FMT_PEM);
447 /*************************************************
448 * Initialize a single GNUTLS session *
449 *************************************************/
451 static gnutls_session_t
452 tls_session_init(void)
454 gnutls_session_t session;
456 gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);
458 # if GNUTLS_VERSION_NUMBER < 0x030400
459 gnutls_cipher_set_priority(session, default_cipher_priority);
460 gnutls_compression_set_priority(session, comp_priority);
461 gnutls_kx_set_priority(session, kx_priority);
462 gnutls_protocol_set_priority(session, protocol_priority);
463 gnutls_mac_set_priority(session, mac_priority);
465 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
469 gnutls_priority_t priority_cache;
472 gnutls_priority_init(&priority_cache, pri_string, &errpos);
473 gnutls_priority_set(session, priority_cache);
476 gnutls_set_default_priority(session);
477 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
480 gnutls_dh_set_prime_bits(session, DH_BITS);
481 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
488 /****************************************************************************/
489 /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
492 unescape_buf(unsigned char * buf, int len)
498 for (s = buf; s < buf+len; s++) if (*s == '\\')
502 default: c = s[1]; shift = 1; break;
503 case 'n': c = '\n'; shift = 1; break;
504 case 'r': c = '\r'; shift = 1; break;
507 if (t >= 'A' && t <= 'F') t -= 'A'-'9'-1;
508 else if (t >= 'a' && t <= 'f') t -= 'a'-'9'-1;
512 if (t >= 'A' && t <= 'F') t -= 'A'-'9'-1;
513 else if (t >= 'a' && t <= 'f') t -= 'a'-'9'-1;
520 memmove(s+1, s+shift+1, len-shift);
527 /****************************************************************************/
539 do_file(srv_ctx * srv, FILE * f, int timeout,
540 unsigned char * inbuffer, unsigned bsiz, unsigned char * inptr)
542 unsigned char outbuffer[1024 * 20];
544 while (fgets(CS outbuffer, sizeof(outbuffer), f) != NULL)
546 int n = (int)strlen(CS outbuffer);
550 /* Strip trailing newline */
551 if (outbuffer[n-1] == '\n') outbuffer[--n] = 0;
553 /* Expect incoming */
555 if ( strncmp(CS outbuffer, "???", 3) == 0
556 && (outbuffer[3] == ' ' || outbuffer[3] == '*' || outbuffer[3] == '?')
559 unsigned char *lineptr;
560 unsigned exp_eof = outbuffer[3] == '*';
561 unsigned resp_optional = outbuffer[3] == '?';
563 printf("%s\n", outbuffer);
564 n = unescape_buf(outbuffer, n);
567 if (*inptr == 0) /* Refill input buffer */
574 rc = SSL_read(srv->ssl, inbuffer, bsiz - 1);
576 switch (error = SSL_get_error(srv->ssl, rc))
578 case SSL_ERROR_ZERO_RETURN:
580 case SSL_ERROR_SYSCALL:
581 printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); break;
584 printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); break;
585 SSL_shutdown(srv->ssl);
587 srv->tls_active = FALSE;
590 printf("SSL error code %d\n", error);
595 rc = gnutls_record_recv(tls_session, CS inbuffer, bsiz - 1);
599 rc = read(srv->sock, inbuffer, bsiz);
604 printf("Read error %s\n", strerror(errno));
610 printf("Expected EOF read\n");
613 else if (resp_optional)
614 continue; /* next scriptline */
617 printf("Unexpected EOF read\n");
623 printf("Expected EOF not read\n");
635 while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
639 if (*inptr == '\n') inptr++;
642 if (strncmp(CS lineptr, CS outbuffer + 4, n - 4) != 0)
645 inptr = lineptr; /* consume scriptline, not inputline */
650 printf("<<< %s\n", lineptr);
651 printf("\n******** Input mismatch ********\n");
655 /* input matched script */
658 goto nextinput; /* consume inputline, not scriptline */
660 printf("<<< %s\n", lineptr);
663 if (srv->sent_starttls)
665 if (lineptr[0] == '2')
669 printf("Attempting to start TLS\n");
673 srv->tls_active = tls_start(srv->sock, &srv->ssl, srv->ctx);
679 sigalrm_seen = FALSE;
682 rc = gnutls_handshake(tls_session);
683 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
684 srv->tls_active = rc >= 0;
687 if (!srv->tls_active) printf("%s\n", gnutls_strerror(rc));
691 if (!srv->tls_active)
693 printf("Failed to start TLS\n");
697 else if (ocsp_stapling)
699 if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
701 printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
704 else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
706 printf("Bad certificate\n");
710 else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
712 printf("Failed to verify certificate status\n");
714 gnutls_datum_t stapling;
715 gnutls_ocsp_resp_t resp;
716 gnutls_datum_t printed;
717 if ( (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
718 && (rc= gnutls_ocsp_resp_init(&resp)) == 0
719 && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
720 && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
723 fprintf(stderr, "%.4096s", printed.data);
724 gnutls_free(printed.data);
727 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
735 printf("Succeeded in starting TLS\n");
737 else printf("Abandoning TLS start attempt\n");
739 srv->sent_starttls = 0;
743 /* Wait for a bit before proceeding */
745 else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
747 printf("%s\n", outbuffer);
748 sleep(atoi(CS outbuffer + 4));
751 /* Stack new input file */
753 else if (strncmp(CS outbuffer, "<<< ", 4) == 0)
756 if (!(new_f = fopen((const char *)outbuffer+4 , "r")))
758 printf("Unable to open '%s': %s", inptr, strerror(errno));
761 do_file(srv, new_f, timeout, inbuffer, bsiz, inptr);
765 /* Send line outgoing, but barf if unconsumed incoming */
769 unsigned char * out = outbuffer;
771 if (strncmp(CS outbuffer, ">>> ", 4) == 0)
780 printf("Unconsumed input: %s", inptr);
781 printf(" About to send: %s\n", out);
789 if (strcmp(CS out, "stoptls") == 0 ||
790 strcmp(CS out, "STOPTLS") == 0)
792 if (!srv->tls_active)
794 printf("STOPTLS read when TLS not active\n");
797 printf("Shutting down TLS encryption\n");
800 SSL_shutdown(srv->ssl);
805 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
806 gnutls_deinit(tls_session);
808 gnutls_global_deinit();
815 /* Remember that we sent STARTTLS */
817 srv->sent_starttls = (strcmp(CS out, "starttls") == 0 ||
818 strcmp(CS out, "STARTTLS") == 0);
820 /* Fudge: if the command is "starttls_wait", we send the starttls bit,
821 but we haven't set the flag, so that there is no negotiation. This is for
822 testing the server's timeout. */
824 if (strcmp(CS out, "starttls_wait") == 0)
831 printf(">>> %s\n", out);
834 strcpy(CS out + n, "\r\n");
838 n = unescape_buf(out, n);
846 rc = SSL_write (srv->ssl, out, n);
849 if ((rc = gnutls_record_send(tls_session, CS out, n)) < 0)
851 printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
857 rc = write(srv->sock, out, n);
862 printf("Write error: %s\n", strerror(errno));
872 /*************************************************
874 *************************************************/
876 const char * const HELP_MESSAGE = "\n\
884 [-p priority-string]\n"
888 [-tn] n seconds timeout\n\
891 [<outgoing interface>]\n\
897 main(int argc, char **argv)
899 struct sockaddr *s_ptr;
900 struct sockaddr_in s_in4;
901 char *interface = NULL;
902 char *address = NULL;
903 char *certfile = NULL;
904 char *keyfile = NULL;
907 int host_af, port, s_len, rc, save_errno;
909 int tls_on_connect = 0;
913 struct sockaddr_in6 s_in6;
918 unsigned char inbuffer[10240];
919 unsigned char *inptr = inbuffer;
921 *inptr = 0; /* Buffer empty */
923 srv.sent_starttls = 0;
927 while (argc >= argi + 1 && argv[argi][0] == '-')
929 if (strcmp(argv[argi], "-help") == 0 ||
930 strcmp(argv[argi], "--help") == 0 ||
931 strcmp(argv[argi], "-h") == 0)
936 if (strcmp(argv[argi], "-tls-on-connect") == 0)
942 else if (strcmp(argv[argi], "-ocsp") == 0)
944 if (argc < ++argi + 1)
946 fprintf(stderr, "Missing required certificate file for ocsp option\n");
949 ocsp_stapling = argv[argi++];
952 else if (strcmp(argv[argi], "-p") == 0)
954 if (argc < ++argi + 1)
956 fprintf(stderr, "Missing priority string\n");
959 pri_string = argv[argi++];
964 else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
966 tmplong = strtol(argv[argi]+2, &end, 10);
967 if (end == argv[argi]+2 || *end)
969 fprintf(stderr, "Failed to parse seconds from option <%s>\n",
973 if (tmplong > 10000L)
975 fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
981 fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
984 timeout = (int) tmplong;
989 fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
994 /* Mandatory 1st arg is IP address */
998 fprintf(stderr, "No IP address given\n");
1002 address = argv[argi++];
1003 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
1005 /* Mandatory 2nd arg is port */
1009 fprintf(stderr, "No port number given\n");
1013 port = atoi(argv[argi++]);
1015 /* Optional next arg is interface */
1018 (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
1019 interface = argv[argi++];
1021 /* Any more arguments are the name of a certificate file and key file */
1023 if (argc > argi) certfile = argv[argi++];
1024 if (argc > argi) keyfile = argv[argi++];
1028 /* For an IPv6 address, use an IPv6 sockaddr structure. */
1030 if (host_af == AF_INET6)
1032 s_ptr = (struct sockaddr *)&s_in6;
1033 s_len = sizeof(s_in6);
1038 /* For an IPv4 address, use an IPv4 sockaddr structure,
1039 even on an IPv6 system. */
1042 s_ptr = (struct sockaddr *)&s_in4;
1043 s_len = sizeof(s_in4);
1046 printf("Connecting to %s port %d ... ", address, port);
1048 srv.sock = socket(host_af, SOCK_STREAM, 0);
1051 printf("socket creation failed: %s\n", strerror(errno));
1055 /* Bind to a specific interface if requested. On an IPv6 system, this has
1056 to be of the same family as the address we are calling. On an IPv4 system the
1057 test is redundant, but it keeps the code tidier. */
1059 if (interface != NULL)
1061 int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
1063 if (interface_af == host_af)
1067 /* Set up for IPv6 binding */
1069 if (host_af == AF_INET6)
1071 memset(&s_in6, 0, sizeof(s_in6));
1072 s_in6.sin6_family = AF_INET6;
1073 s_in6.sin6_port = 0;
1074 if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
1076 printf("Unable to parse \"%s\"", interface);
1083 /* Set up for IPv4 binding */
1086 memset(&s_in4, 0, sizeof(s_in4));
1087 s_in4.sin_family = AF_INET;
1089 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
1094 if (bind(srv.sock, s_ptr, s_len) < 0)
1096 printf("Unable to bind outgoing SMTP call to %s: %s",
1097 interface, strerror(errno));
1103 /* Set up a remote IPv6 address */
1106 if (host_af == AF_INET6)
1108 memset(&s_in6, 0, sizeof(s_in6));
1109 s_in6.sin6_family = AF_INET6;
1110 s_in6.sin6_port = htons(port);
1111 if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
1113 printf("Unable to parse \"%s\"", address);
1120 /* Set up a remote IPv4 address */
1123 memset(&s_in4, 0, sizeof(s_in4));
1124 s_in4.sin_family = AF_INET;
1125 s_in4.sin_port = htons(port);
1126 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
1129 /* SIGALRM handler crashes out */
1131 signal(SIGALRM, sigalrm_handler_crash);
1133 rc = connect(srv.sock, s_ptr, s_len);
1137 /* A failure whose error code is "Interrupted system call" is in fact
1138 an externally applied timeout if the signal handler has been run. */
1143 printf("connect failed: %s\n", strerror(save_errno));
1147 printf("connected\n");
1150 /* --------------- Set up for OpenSSL --------------- */
1154 SSL_load_error_strings();
1156 if (!(srv.ctx = SSL_CTX_new(SSLv23_method())))
1158 printf ("SSL_CTX_new failed\n");
1164 if (!SSL_CTX_use_certificate_file(srv.ctx, certfile, SSL_FILETYPE_PEM))
1166 printf("SSL_CTX_use_certificate_file failed\n");
1169 printf("Certificate file = %s\n", certfile);
1174 if (!SSL_CTX_use_PrivateKey_file(srv.ctx, keyfile, SSL_FILETYPE_PEM))
1176 printf("SSL_CTX_use_PrivateKey_file failed\n");
1179 printf("Key file = %s\n", keyfile);
1182 SSL_CTX_set_session_cache_mode(srv.ctx, SSL_SESS_CACHE_BOTH);
1183 SSL_CTX_set_timeout(srv.ctx, 200);
1184 SSL_CTX_set_info_callback(srv.ctx, (void (*)())info_callback);
1188 /* --------------- Set up for GnuTLS --------------- */
1191 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
1192 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
1193 tls_init(US certfile, US keyfile);
1194 tls_session = tls_session_init();
1197 gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
1199 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)srv.sock);
1201 /* When the server asks for a certificate and the client does not have one,
1202 there is a SIGPIPE error in the gnutls_handshake() function for some reason
1203 that is not understood. As luck would have it, this has never hit Exim itself
1204 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
1207 signal(SIGPIPE, SIG_IGN);
1210 /* ---------------------------------------------- */
1213 /* Start TLS session if configured to do so without STARTTLS */
1218 printf("Attempting to start TLS\n");
1221 srv.tls_active = tls_start(srv.sock, &srv.ssl, srv.ctx);
1227 sigalrm_seen = FALSE;
1230 rc = gnutls_handshake(tls_session);
1231 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
1232 srv.tls_active = rc >= 0;
1235 if (!srv.tls_active) printf("%s\n", gnutls_strerror(rc));
1239 if (!srv.tls_active)
1240 printf("Failed to start TLS\n");
1241 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
1242 else if ( ocsp_stapling
1243 && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1244 printf("Failed to verify certificate status\n");
1247 printf("Succeeded in starting TLS\n");
1251 do_file(&srv, stdin, timeout, inbuffer, sizeof(inbuffer), inptr);
1253 printf("End of script\n");
1254 shutdown(srv.sock, SHUT_WR);
1255 if (fcntl(srv.sock, F_SETFL, O_NONBLOCK) == 0)
1256 while (read(srv.sock, inbuffer, sizeof(inbuffer)) > 0) ;
1262 /* End of client.c */