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));
585 printf("%s\nTLS terminated\n", ERR_error_string(ERR_get_error(), NULL));
586 SSL_shutdown(srv->ssl);
588 srv->tls_active = FALSE;
589 { /* OpenSSL leaves it in restartsys mode */
590 struct sigaction act = {.sa_handler = sigalrm_handler_flag, .sa_flags = 0};
592 sigaction(SIGALRM, &act, NULL);
597 printf("SSL error code %d\n", error);
601 rc = gnutls_record_recv(tls_session, CS inbuffer, bsiz - 1);
605 rc = read(srv->sock, inbuffer, bsiz);
610 if (errno == EINTR && sigalrm_seen && resp_optional)
611 continue; /* next scriptline */
612 printf("Read error %s\n", strerror(errno));
618 printf("Expected EOF read\n");
621 else if (resp_optional)
622 continue; /* next scriptline */
625 printf("Unexpected EOF read\n");
631 printf("Expected EOF not read\n");
643 while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
647 if (*inptr == '\n') inptr++;
650 if (strncmp(CS lineptr, CS outbuffer + 4, n - 4) != 0)
653 inptr = lineptr; /* consume scriptline, not inputline */
658 printf("<<< %s\n", lineptr);
659 printf("\n******** Input mismatch ********\n");
663 /* input matched script */
666 goto nextinput; /* consume inputline, not scriptline */
668 printf("<<< %s\n", lineptr);
671 if (srv->sent_starttls)
673 if (lineptr[0] == '2')
677 printf("Attempting to start TLS\n");
681 srv->tls_active = tls_start(srv->sock, &srv->ssl, srv->ctx);
687 sigalrm_seen = FALSE;
690 rc = gnutls_handshake(tls_session);
691 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
692 srv->tls_active = rc >= 0;
695 if (!srv->tls_active) printf("%s\n", gnutls_strerror(rc));
699 if (!srv->tls_active)
701 printf("Failed to start TLS\n");
705 else if (ocsp_stapling)
707 if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
709 printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
712 else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
714 printf("Bad certificate\n");
718 else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
720 printf("Failed to verify certificate status\n");
722 gnutls_datum_t stapling;
723 gnutls_ocsp_resp_t resp;
724 gnutls_datum_t printed;
725 if ( (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
726 && (rc= gnutls_ocsp_resp_init(&resp)) == 0
727 && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
728 && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
731 fprintf(stderr, "%.4096s", printed.data);
732 gnutls_free(printed.data);
735 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
743 printf("Succeeded in starting TLS\n");
745 else printf("Abandoning TLS start attempt\n");
747 srv->sent_starttls = 0;
751 /* Wait for a bit before proceeding */
753 else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
755 printf("%s\n", outbuffer);
756 sleep(atoi(CS outbuffer + 4));
759 /* Stack new input file */
761 else if (strncmp(CS outbuffer, "<<< ", 4) == 0)
764 if (!(new_f = fopen((const char *)outbuffer+4 , "r")))
766 printf("Unable to open '%s': %s", inptr, strerror(errno));
769 do_file(srv, new_f, timeout, inbuffer, bsiz, inptr);
773 /* Send line outgoing, but barf if unconsumed incoming */
777 unsigned char * out = outbuffer;
779 if (strncmp(CS outbuffer, ">>> ", 4) == 0)
788 printf("Unconsumed input: %s", inptr);
789 printf(" About to send: %s\n", out);
797 if (strcmp(CS out, "stoptls") == 0 ||
798 strcmp(CS out, "STOPTLS") == 0)
800 if (!srv->tls_active)
802 printf("STOPTLS read when TLS not active\n");
805 printf("Shutting down TLS encryption\n");
808 SSL_shutdown(srv->ssl);
813 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
814 gnutls_deinit(tls_session);
816 gnutls_global_deinit();
823 /* Remember that we sent STARTTLS */
825 srv->sent_starttls = (strcmp(CS out, "starttls") == 0 ||
826 strcmp(CS out, "STARTTLS") == 0);
828 /* Fudge: if the command is "starttls_wait", we send the starttls bit,
829 but we haven't set the flag, so that there is no negotiation. This is for
830 testing the server's timeout. */
832 if (strcmp(CS out, "starttls_wait") == 0)
839 printf(">>> %s\n", out);
842 strcpy(CS out + n, "\r\n");
846 n = unescape_buf(out, n);
854 rc = SSL_write (srv->ssl, out, n);
857 if ((rc = gnutls_record_send(tls_session, CS out, n)) < 0)
859 printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
865 rc = write(srv->sock, out, n);
870 printf("Write error: %s\n", strerror(errno));
880 /*************************************************
882 *************************************************/
884 const char * const HELP_MESSAGE = "\n\
892 [-p priority-string]\n"
896 [-tn] n seconds timeout\n\
899 [<outgoing interface>]\n\
905 main(int argc, char **argv)
907 struct sockaddr *s_ptr;
908 struct sockaddr_in s_in4;
909 char *interface = NULL;
910 char *address = NULL;
911 char *certfile = NULL;
912 char *keyfile = NULL;
915 int host_af, port, s_len, rc, save_errno;
917 int tls_on_connect = 0;
921 struct sockaddr_in6 s_in6;
926 unsigned char inbuffer[10240];
927 unsigned char *inptr = inbuffer;
929 *inptr = 0; /* Buffer empty */
931 srv.sent_starttls = 0;
935 while (argc >= argi + 1 && argv[argi][0] == '-')
937 if (strcmp(argv[argi], "-help") == 0 ||
938 strcmp(argv[argi], "--help") == 0 ||
939 strcmp(argv[argi], "-h") == 0)
944 if (strcmp(argv[argi], "-tls-on-connect") == 0)
950 else if (strcmp(argv[argi], "-ocsp") == 0)
952 if (argc < ++argi + 1)
954 fprintf(stderr, "Missing required certificate file for ocsp option\n");
957 ocsp_stapling = argv[argi++];
960 else if (strcmp(argv[argi], "-p") == 0)
962 if (argc < ++argi + 1)
964 fprintf(stderr, "Missing priority string\n");
967 pri_string = argv[argi++];
972 else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
974 tmplong = strtol(argv[argi]+2, &end, 10);
975 if (end == argv[argi]+2 || *end)
977 fprintf(stderr, "Failed to parse seconds from option <%s>\n",
981 if (tmplong > 10000L)
983 fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
989 fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
992 timeout = (int) tmplong;
997 fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
1002 /* Mandatory 1st arg is IP address */
1006 fprintf(stderr, "No IP address given\n");
1010 address = argv[argi++];
1011 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
1013 /* Mandatory 2nd arg is port */
1017 fprintf(stderr, "No port number given\n");
1021 port = atoi(argv[argi++]);
1023 /* Optional next arg is interface */
1026 (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
1027 interface = argv[argi++];
1029 /* Any more arguments are the name of a certificate file and key file */
1031 if (argc > argi) certfile = argv[argi++];
1032 if (argc > argi) keyfile = argv[argi++];
1036 /* For an IPv6 address, use an IPv6 sockaddr structure. */
1038 if (host_af == AF_INET6)
1040 s_ptr = (struct sockaddr *)&s_in6;
1041 s_len = sizeof(s_in6);
1046 /* For an IPv4 address, use an IPv4 sockaddr structure,
1047 even on an IPv6 system. */
1050 s_ptr = (struct sockaddr *)&s_in4;
1051 s_len = sizeof(s_in4);
1054 printf("Connecting to %s port %d ... ", address, port);
1056 srv.sock = socket(host_af, SOCK_STREAM, 0);
1059 printf("socket creation failed: %s\n", strerror(errno));
1063 /* Bind to a specific interface if requested. On an IPv6 system, this has
1064 to be of the same family as the address we are calling. On an IPv4 system the
1065 test is redundant, but it keeps the code tidier. */
1067 if (interface != NULL)
1069 int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
1071 if (interface_af == host_af)
1075 /* Set up for IPv6 binding */
1077 if (host_af == AF_INET6)
1079 memset(&s_in6, 0, sizeof(s_in6));
1080 s_in6.sin6_family = AF_INET6;
1081 s_in6.sin6_port = 0;
1082 if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
1084 printf("Unable to parse \"%s\"", interface);
1091 /* Set up for IPv4 binding */
1094 memset(&s_in4, 0, sizeof(s_in4));
1095 s_in4.sin_family = AF_INET;
1097 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
1102 if (bind(srv.sock, s_ptr, s_len) < 0)
1104 printf("Unable to bind outgoing SMTP call to %s: %s",
1105 interface, strerror(errno));
1111 /* Set up a remote IPv6 address */
1114 if (host_af == AF_INET6)
1116 memset(&s_in6, 0, sizeof(s_in6));
1117 s_in6.sin6_family = AF_INET6;
1118 s_in6.sin6_port = htons(port);
1119 if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
1121 printf("Unable to parse \"%s\"", address);
1128 /* Set up a remote IPv4 address */
1131 memset(&s_in4, 0, sizeof(s_in4));
1132 s_in4.sin_family = AF_INET;
1133 s_in4.sin_port = htons(port);
1134 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
1137 /* SIGALRM handler crashes out */
1139 signal(SIGALRM, sigalrm_handler_crash);
1141 rc = connect(srv.sock, s_ptr, s_len);
1145 /* A failure whose error code is "Interrupted system call" is in fact
1146 an externally applied timeout if the signal handler has been run. */
1151 printf("connect failed: %s\n", strerror(save_errno));
1155 printf("connected\n");
1158 /* --------------- Set up for OpenSSL --------------- */
1162 SSL_load_error_strings();
1164 if (!(srv.ctx = SSL_CTX_new(SSLv23_method())))
1166 printf ("SSL_CTX_new failed\n");
1172 if (!SSL_CTX_use_certificate_file(srv.ctx, certfile, SSL_FILETYPE_PEM))
1174 printf("SSL_CTX_use_certificate_file failed\n");
1177 printf("Certificate file = %s\n", certfile);
1182 if (!SSL_CTX_use_PrivateKey_file(srv.ctx, keyfile, SSL_FILETYPE_PEM))
1184 printf("SSL_CTX_use_PrivateKey_file failed\n");
1187 printf("Key file = %s\n", keyfile);
1190 SSL_CTX_set_session_cache_mode(srv.ctx, SSL_SESS_CACHE_BOTH);
1191 SSL_CTX_set_timeout(srv.ctx, 200);
1192 SSL_CTX_set_info_callback(srv.ctx, (void (*)())info_callback);
1196 /* --------------- Set up for GnuTLS --------------- */
1199 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
1200 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
1201 tls_init(US certfile, US keyfile);
1202 tls_session = tls_session_init();
1205 gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
1207 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)srv.sock);
1209 /* When the server asks for a certificate and the client does not have one,
1210 there is a SIGPIPE error in the gnutls_handshake() function for some reason
1211 that is not understood. As luck would have it, this has never hit Exim itself
1212 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
1215 signal(SIGPIPE, SIG_IGN);
1218 /* ---------------------------------------------- */
1221 /* Start TLS session if configured to do so without STARTTLS */
1226 printf("Attempting to start TLS\n");
1229 srv.tls_active = tls_start(srv.sock, &srv.ssl, srv.ctx);
1235 sigalrm_seen = FALSE;
1238 rc = gnutls_handshake(tls_session);
1239 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
1240 srv.tls_active = rc >= 0;
1243 if (!srv.tls_active) printf("%s\n", gnutls_strerror(rc));
1247 if (!srv.tls_active)
1248 printf("Failed to start TLS\n");
1249 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
1250 else if ( ocsp_stapling
1251 && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1252 printf("Failed to verify certificate status\n");
1255 printf("Succeeded in starting TLS\n");
1259 do_file(&srv, stdin, timeout, inbuffer, sizeof(inbuffer), inptr);
1261 printf("End of script\n");
1262 shutdown(srv.sock, SHUT_WR);
1263 if (fcntl(srv.sock, F_SETFL, O_NONBLOCK) == 0)
1264 while (read(srv.sock, inbuffer, sizeof(inbuffer)) > 0) ;
1270 /* End of client.c */