Testsuite: move dynamic_socket to Exim::Runtest
[exim.git] / test / src / client.c
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. */
6
7 /* ANSI C standard includes */
8
9 #include <ctype.h>
10 #include <signal.h>
11 #include <stdarg.h>
12 #include <stddef.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17
18 /* Unix includes */
19
20 #include <errno.h>
21 #include <dirent.h>
22 #include <sys/types.h>
23
24 #include <netinet/in_systm.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27
28 #include <netdb.h>
29 #include <arpa/inet.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <utime.h>
37
38 #ifdef AF_INET6
39 #define HAVE_IPV6 1
40 #endif
41
42 #ifndef S_ADDR_TYPE
43 #define S_ADDR_TYPE u_long
44 #endif
45
46 typedef unsigned char uschar;
47
48 #define CS   (char *)
49 #define US   (unsigned char *)
50
51 #define FALSE         0
52 #define TRUE          1
53
54
55
56 static int sigalrm_seen = 0;
57
58
59 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
60 latter needs a whole pile of tables. */
61 #ifdef HAVE_OPENSSL
62 # define HAVE_TLS
63 # include <openssl/crypto.h>
64 # include <openssl/x509.h>
65 # include <openssl/pem.h>
66 # include <openssl/ssl.h>
67 # include <openssl/err.h>
68 # include <openssl/rand.h>
69
70 # if OPENSSL_VERSION_NUMBER < 0x0090806fL && !defined(DISABLE_OCSP) && !defined(OPENSSL_NO_TLSEXT)
71 #  warning "OpenSSL library version too old; define DISABLE_OCSP in Makefile"
72 #  define DISABLE_OCSP
73 # endif
74 # ifndef DISABLE_OCSP
75 #  include <openssl/ocsp.h>
76 # endif
77 #endif
78
79
80 #ifdef HAVE_GNUTLS
81 # define HAVE_TLS
82 # include <gnutls/gnutls.h>
83 # include <gnutls/x509.h>
84 # if GNUTLS_VERSION_NUMBER >= 0x030103
85 #  define HAVE_OCSP
86 #  include <gnutls/ocsp.h>
87 # endif
88 # ifndef GNUTLS_NO_EXTENSIONS
89 #  define GNUTLS_NO_EXTENSIONS 0
90 # endif
91
92 # define DH_BITS      768
93
94 /* Local static variables for GNUTLS */
95
96 static gnutls_dh_params_t dh_params = NULL;
97
98 static gnutls_certificate_credentials_t x509_cred = NULL;
99 static gnutls_session_t tls_session = NULL;
100
101 static int  ssl_session_timeout = 200;
102
103 /* Priorities for TLS algorithms to use. */
104
105 #if GNUTLS_VERSION_NUMBER < 0x030400
106 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
107
108 static const int kx_priority[16] = {
109   GNUTLS_KX_RSA,
110   GNUTLS_KX_DHE_DSS,
111   GNUTLS_KX_DHE_RSA,
112   0 };
113
114 static int default_cipher_priority[16] = {
115   GNUTLS_CIPHER_AES_256_CBC,
116   GNUTLS_CIPHER_AES_128_CBC,
117   GNUTLS_CIPHER_3DES_CBC,
118   GNUTLS_CIPHER_ARCFOUR_128,
119   0 };
120
121 static const int mac_priority[16] = {
122   GNUTLS_MAC_SHA,
123   GNUTLS_MAC_MD5,
124   0 };
125
126 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
127 #endif
128
129 #endif  /*HAVE_GNUTLS*/
130
131
132
133 #ifdef HAVE_TLS
134 char * ocsp_stapling = NULL;
135 #endif
136
137
138 /*************************************************
139 *            SIGALRM handler - crash out         *
140 *************************************************/
141
142 static void
143 sigalrm_handler_crash(int sig)
144 {
145 sig = sig;    /* Keep picky compilers happy */
146 printf("\nClient timed out\n");
147 exit(99);
148 }
149
150
151 /*************************************************
152 *            SIGALRM handler - set flag          *
153 *************************************************/
154
155 static void
156 sigalrm_handler_flag(int sig)
157 {
158 sig = sig;    /* Keep picky compilers happy */
159 sigalrm_seen = 1;
160 }
161
162
163
164 /****************************************************************************/
165 /****************************************************************************/
166
167 #ifdef HAVE_OPENSSL
168
169 X509_STORE *
170 setup_verify(BIO *bp, char *CAfile, char *CApath)
171 {
172         X509_STORE *store;
173         X509_LOOKUP *lookup;
174         if(!(store = X509_STORE_new())) goto end;
175         lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
176         if (lookup == NULL) goto end;
177         if (CAfile) {
178                 if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
179                         BIO_printf(bp, "Error loading file %s\n", CAfile);
180                         goto end;
181                 }
182         } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
183
184         lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
185         if (lookup == NULL) goto end;
186         if (CApath) {
187                 if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
188                         BIO_printf(bp, "Error loading directory %s\n", CApath);
189                         goto end;
190                 }
191         } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
192
193         ERR_clear_error();
194         return store;
195         end:
196         X509_STORE_free(store);
197         return NULL;
198 }
199
200
201 #ifndef DISABLE_OCSP
202 static STACK_OF(X509) *
203 cert_stack_from_store(X509_STORE * store)
204 {
205 STACK_OF(X509_OBJECT) * roots= store->objs;
206 STACK_OF(X509) * sk = sk_X509_new_null();
207 int i;
208
209 for(i = sk_X509_OBJECT_num(roots) - 1; i >= 0; i--)
210   {
211   X509_OBJECT * tmp_obj= sk_X509_OBJECT_value(roots, i);
212   if(tmp_obj->type == X509_LU_X509)
213     {
214     X509 * x = tmp_obj->data.x509;
215     sk_X509_push(sk, x);
216     }
217   }
218 return sk;
219 }
220
221 static void
222 cert_stack_free(STACK_OF(X509) * sk)
223 {
224 while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
225 sk_X509_free(sk);
226 }
227
228
229 static int
230 tls_client_stapling_cb(SSL *s, void *arg)
231 {
232 const unsigned char *p;
233 int len;
234 OCSP_RESPONSE *rsp;
235 OCSP_BASICRESP *bs;
236 char *CAfile = NULL;
237 X509_STORE *store = NULL;
238 STACK_OF(X509) * sk;
239 int ret = 1;
240
241 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
242 /*BIO_printf(arg, "OCSP response: ");*/
243 if (!p)
244         {
245         BIO_printf(arg, "no response received\n");
246         return 1;
247         }
248 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
249         {
250         BIO_printf(arg, "response parse error\n");
251         BIO_dump_indent(arg, (char *)p, len, 4);
252         return 0;
253         }
254 if(!(bs = OCSP_response_get1_basic(rsp)))
255   {
256   BIO_printf(arg, "error parsing response\n");
257   return 0;
258   }
259
260
261 CAfile = ocsp_stapling;
262 if(!(store = setup_verify(arg, CAfile, NULL)))
263   {
264   BIO_printf(arg, "error in cert setup\n");
265   return 0;
266   }
267
268 sk = cert_stack_from_store(store);
269
270 /* OCSP_basic_verify takes a "store" arg, but does not
271 use it for the chain verification, which is all we do
272 when OCSP_NOVERIFY is set.  The content from the wire
273 (in "bs") and a cert-stack "sk" are all that is used. */
274
275 if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
276   {
277   BIO_printf(arg, "Response Verify Failure\n");
278   ERR_print_errors(arg);
279   ret = 0;
280   }
281 else
282   BIO_printf(arg, "Response verify OK\n");
283
284 cert_stack_free(sk);
285 X509_STORE_free(store);
286 return ret;
287 }
288 #endif
289
290
291 /*************************************************
292 *         Start an OpenSSL TLS session           *
293 *************************************************/
294
295 int
296 tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
297 {
298 int rc;
299 static const unsigned char *sid_ctx = US"exim";
300
301 RAND_load_file("client.c", -1);   /* Not *very* random! */
302
303 *ssl = SSL_new (ctx);
304 SSL_set_session_id_context(*ssl, sid_ctx, strlen(CS sid_ctx));
305 SSL_set_fd (*ssl, sock);
306 SSL_set_connect_state(*ssl);
307
308 #ifndef DISABLE_OCSP
309 if (ocsp_stapling)
310   {
311   SSL_CTX_set_tlsext_status_cb(ctx, tls_client_stapling_cb);
312   SSL_CTX_set_tlsext_status_arg(ctx, BIO_new_fp(stdout, BIO_NOCLOSE));
313   SSL_set_tlsext_status_type(*ssl, TLSEXT_STATUSTYPE_ocsp);
314   }
315 #endif
316
317 signal(SIGALRM, sigalrm_handler_flag);
318 sigalrm_seen = 0;
319 alarm(5);
320 rc = SSL_connect (*ssl);
321 alarm(0);
322
323 if (sigalrm_seen)
324   {
325   printf("SSL_connect timed out\n");
326   return 0;
327   }
328
329 if (rc <= 0)
330   {
331   ERR_print_errors_fp(stdout);
332   return 0;
333   }
334
335 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
336 return 1;
337 }
338
339
340 /*************************************************
341 *           SSL Information callback             *
342 *************************************************/
343
344 static void
345 info_callback(SSL *s, int where, int ret)
346 {
347 where = where;
348 ret = ret;
349 printf("SSL info: %s\n", SSL_state_string_long(s));
350 }
351 #endif
352
353
354 /****************************************************************************/
355 /****************************************************************************/
356
357
358 #ifdef HAVE_GNUTLS
359 /*************************************************
360 *            Handle GnuTLS error                 *
361 *************************************************/
362
363 /* Called from lots of places when errors occur before actually starting to do
364 the TLS handshake, that is, while the session is still in clear.
365
366 Argument:
367   prefix    prefix text
368   err       a GnuTLS error number, or 0 if local error
369
370 Returns:    doesn't - it dies
371 */
372
373 static void
374 gnutls_error(uschar *prefix, int err)
375 {
376 fprintf(stderr, "GnuTLS connection error: %s:", prefix);
377 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
378 fprintf(stderr, "\n");
379 exit(98);
380 }
381
382
383
384 /*************************************************
385 *             Setup up DH parameters             *
386 *************************************************/
387
388 /* For the test suite, the parameters should always be available in the spool
389 directory. */
390
391 static void
392 init_dh(void)
393 {
394 int fd;
395 int ret;
396 gnutls_datum_t m;
397 uschar filename[200];
398 struct stat statbuf;
399
400 /* Initialize the data structures for holding the parameters */
401
402 ret = gnutls_dh_params_init(&dh_params);
403 if (ret < 0) gnutls_error(US"init dh_params", ret);
404
405 /* Open the cache file for reading and if successful, read it and set up the
406 parameters. */
407
408 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
409 if (fd < 0)
410   {
411   fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
412   exit(97);
413   }
414
415 if (fstat(fd, &statbuf) < 0)
416   {
417   (void)close(fd);
418   return gnutls_error(US"TLS cache stat failed", 0);
419   }
420
421 m.size = statbuf.st_size;
422 m.data = malloc(m.size);
423 if (m.data == NULL)
424   return gnutls_error(US"memory allocation failed", 0);
425 if (read(fd, m.data, m.size) != m.size)
426   return gnutls_error(US"TLS cache read failed", 0);
427 (void)close(fd);
428
429 ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
430 if (ret < 0) return gnutls_error(US"DH params import", ret);
431 free(m.data);
432 }
433
434
435
436
437 /*************************************************
438 *            Initialize for GnuTLS               *
439 *************************************************/
440
441 /*
442 Arguments:
443   certificate     certificate file
444   privatekey      private key file
445 */
446
447 static void
448 tls_init(uschar *certificate, uschar *privatekey)
449 {
450 int rc;
451
452 rc = gnutls_global_init();
453 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
454
455 /* Read D-H parameters from the cache file. */
456
457 init_dh();
458
459 /* Create the credentials structure */
460
461 rc = gnutls_certificate_allocate_credentials(&x509_cred);
462 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
463
464 /* Set the certificate and private keys */
465
466 if (certificate != NULL)
467   {
468   rc = gnutls_certificate_set_x509_key_file(x509_cred, CS certificate,
469     CS privatekey, GNUTLS_X509_FMT_PEM);
470   if (rc < 0) gnutls_error("gnutls_certificate", rc);
471   }
472
473 /* Associate the parameters with the x509 credentials structure. */
474
475 gnutls_certificate_set_dh_params(x509_cred, dh_params);
476
477 /* set the CA info for server-cert verify */
478 if (ocsp_stapling)
479   gnutls_certificate_set_x509_trust_file(x509_cred, ocsp_stapling,
480         GNUTLS_X509_FMT_PEM);
481 }
482
483
484
485 /*************************************************
486 *        Initialize a single GNUTLS session      *
487 *************************************************/
488
489 static gnutls_session_t
490 tls_session_init(void)
491 {
492 gnutls_session_t session;
493
494 gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);
495
496 #if GNUTLS_VERSION_NUMBER < 0x030400
497 gnutls_cipher_set_priority(session, default_cipher_priority);
498 gnutls_compression_set_priority(session, comp_priority);
499 gnutls_kx_set_priority(session, kx_priority);
500 gnutls_protocol_set_priority(session, protocol_priority);
501 gnutls_mac_set_priority(session, mac_priority);
502
503 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
504 #else
505 gnutls_set_default_priority(session);
506 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
507 #endif
508
509 gnutls_dh_set_prime_bits(session, DH_BITS);
510 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
511
512 return session;
513 }
514 #endif
515
516
517 /****************************************************************************/
518 /****************************************************************************/
519
520
521
522
523 /*************************************************
524 *                 Main Program                   *
525 *************************************************/
526
527 const char * const HELP_MESSAGE = "\n\
528 Usage: client\n"
529 #ifdef HAVE_TLS
530 "\
531           [-tls-on-connect]\n\
532           [-ocsp]\n"
533 #endif
534 "\
535           [-tn] n seconds timeout\n\
536           <IP address>\n\
537           <port>\n\
538           [<outgoing interface>]\n\
539           [<cert file>]\n\
540           [<key file>]\n\
541 \n";
542
543 int main(int argc, char **argv)
544 {
545 struct sockaddr *s_ptr;
546 struct sockaddr_in s_in4;
547 char *interface = NULL;
548 char *address = NULL;
549 char *certfile = NULL;
550 char *keyfile = NULL;
551 char *end = NULL;
552 int argi = 1;
553 int host_af, port, s_len, rc, sock, save_errno;
554 int timeout = 5;
555 int tls_active = 0;
556 int sent_starttls = 0;
557 int tls_on_connect = 0;
558 long tmplong;
559
560 #if HAVE_IPV6
561 struct sockaddr_in6 s_in6;
562 #endif
563
564 #ifdef HAVE_OPENSSL
565 SSL_CTX* ctx;
566 SSL*     ssl;
567 #endif
568
569 unsigned char outbuffer[10240];
570 unsigned char inbuffer[10240];
571 unsigned char *inptr = inbuffer;
572
573 *inptr = 0;   /* Buffer empty */
574
575 /* Options */
576
577 while (argc >= argi + 1 && argv[argi][0] == '-')
578   {
579   if (strcmp(argv[argi], "-help") == 0 ||
580       strcmp(argv[argi], "--help") == 0 ||
581       strcmp(argv[argi], "-h") == 0)
582     {
583     puts(HELP_MESSAGE);
584     exit(0);
585     }
586   if (strcmp(argv[argi], "-tls-on-connect") == 0)
587     {
588     tls_on_connect = 1;
589     argi++;
590     }
591 #ifdef HAVE_TLS
592   else if (strcmp(argv[argi], "-ocsp") == 0)
593     {
594     if (argc < ++argi + 1)
595       {
596       fprintf(stderr, "Missing required certificate file for ocsp option\n");
597       exit(96);
598       }
599     ocsp_stapling = argv[argi++];
600     }
601
602 #endif
603   else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
604     {
605     tmplong = strtol(argv[argi]+2, &end, 10);
606     if (end == argv[argi]+2 || *end)
607       {
608       fprintf(stderr, "Failed to parse seconds from option <%s>\n",
609         argv[argi]);
610       exit(95);
611       }
612     if (tmplong > 10000L)
613       {
614       fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
615         tmplong);
616       exit(94);
617       }
618     if (tmplong < 0L)
619       {
620       fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
621       exit(93);
622       }
623     timeout = (int) tmplong;
624     argi++;
625     }
626   else
627     {
628     fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
629     exit(92);
630     }
631   }
632
633 /* Mandatory 1st arg is IP address */
634
635 if (argc < argi+1)
636   {
637   fprintf(stderr, "No IP address given\n");
638   exit(91);
639   }
640
641 address = argv[argi++];
642 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
643
644 /* Mandatory 2nd arg is port */
645
646 if (argc < argi+1)
647   {
648   fprintf(stderr, "No port number given\n");
649   exit(90);
650   }
651
652 port = atoi(argv[argi++]);
653
654 /* Optional next arg is interface */
655
656 if (argc > argi &&
657   (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
658     interface = argv[argi++];
659
660 /* Any more arguments are the name of a certificate file and key file */
661
662 if (argc > argi) certfile = argv[argi++];
663 if (argc > argi) keyfile = argv[argi++];
664
665
666 #if HAVE_IPV6
667 /* For an IPv6 address, use an IPv6 sockaddr structure. */
668
669 if (host_af == AF_INET6)
670   {
671   s_ptr = (struct sockaddr *)&s_in6;
672   s_len = sizeof(s_in6);
673   }
674 else
675 #endif
676
677 /* For an IPv4 address, use an IPv4 sockaddr structure,
678 even on an IPv6 system. */
679
680   {
681   s_ptr = (struct sockaddr *)&s_in4;
682   s_len = sizeof(s_in4);
683   }
684
685 printf("Connecting to %s port %d ... ", address, port);
686
687 sock = socket(host_af, SOCK_STREAM, 0);
688 if (sock < 0)
689   {
690   printf("socket creation failed: %s\n", strerror(errno));
691   exit(89);
692   }
693
694 /* Bind to a specific interface if requested. On an IPv6 system, this has
695 to be of the same family as the address we are calling. On an IPv4 system the
696 test is redundant, but it keeps the code tidier. */
697
698 if (interface != NULL)
699   {
700   int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
701
702   if (interface_af == host_af)
703     {
704     #if HAVE_IPV6
705
706     /* Set up for IPv6 binding */
707
708     if (host_af == AF_INET6)
709       {
710       memset(&s_in6, 0, sizeof(s_in6));
711       s_in6.sin6_family = AF_INET6;
712       s_in6.sin6_port = 0;
713       if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
714         {
715         printf("Unable to parse \"%s\"", interface);
716         exit(88);
717         }
718       }
719     else
720     #endif
721
722     /* Set up for IPv4 binding */
723
724       {
725       memset(&s_in4, 0, sizeof(s_in4));
726       s_in4.sin_family = AF_INET;
727       s_in4.sin_port = 0;
728       s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
729       }
730
731     /* Bind */
732
733     if (bind(sock, s_ptr, s_len) < 0)
734       {
735       printf("Unable to bind outgoing SMTP call to %s: %s",
736         interface, strerror(errno));
737       exit(87);
738       }
739     }
740   }
741
742 /* Set up a remote IPv6 address */
743
744 #if HAVE_IPV6
745 if (host_af == AF_INET6)
746   {
747   memset(&s_in6, 0, sizeof(s_in6));
748   s_in6.sin6_family = AF_INET6;
749   s_in6.sin6_port = htons(port);
750   if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
751     {
752     printf("Unable to parse \"%s\"", address);
753     exit(86);
754     }
755   }
756 else
757 #endif
758
759 /* Set up a remote IPv4 address */
760
761   {
762   memset(&s_in4, 0, sizeof(s_in4));
763   s_in4.sin_family = AF_INET;
764   s_in4.sin_port = htons(port);
765   s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
766   }
767
768 /* SIGALRM handler crashes out */
769
770 signal(SIGALRM, sigalrm_handler_crash);
771 alarm(timeout);
772 rc = connect(sock, s_ptr, s_len);
773 save_errno = errno;
774 alarm(0);
775
776 /* A failure whose error code is "Interrupted system call" is in fact
777 an externally applied timeout if the signal handler has been run. */
778
779 if (rc < 0)
780   {
781   close(sock);
782   printf("connect failed: %s\n", strerror(save_errno));
783   exit(85);
784   }
785
786 printf("connected\n");
787
788
789 /* --------------- Set up for OpenSSL --------------- */
790
791 #ifdef HAVE_OPENSSL
792 SSL_library_init();
793 SSL_load_error_strings();
794
795 ctx = SSL_CTX_new(SSLv23_method());
796 if (ctx == NULL)
797   {
798   printf ("SSL_CTX_new failed\n");
799   exit(84);
800   }
801
802 if (certfile != NULL)
803   {
804   if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
805     {
806     printf("SSL_CTX_use_certificate_file failed\n");
807     exit(83);
808     }
809   printf("Certificate file = %s\n", certfile);
810   }
811
812 if (keyfile != NULL)
813   {
814   if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
815     {
816     printf("SSL_CTX_use_PrivateKey_file failed\n");
817     exit(82);
818     }
819   printf("Key file = %s\n", keyfile);
820   }
821
822 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
823 SSL_CTX_set_timeout(ctx, 200);
824 SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
825 #endif
826
827
828 /* --------------- Set up for GnuTLS --------------- */
829
830 #ifdef HAVE_GNUTLS
831 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
832 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
833 tls_init(certfile, keyfile);
834 tls_session = tls_session_init();
835 #ifdef HAVE_OCSP
836 if (ocsp_stapling)
837   gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
838 #endif
839 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)sock);
840
841 /* When the server asks for a certificate and the client does not have one,
842 there is a SIGPIPE error in the gnutls_handshake() function for some reason
843 that is not understood. As luck would have it, this has never hit Exim itself
844 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
845 one wants. */
846
847 signal(SIGPIPE, SIG_IGN);
848 #endif
849
850 /* ---------------------------------------------- */
851
852
853 /* Start TLS session if configured to do so without STARTTLS */
854
855 #ifdef HAVE_TLS
856 if (tls_on_connect)
857   {
858   printf("Attempting to start TLS\n");
859
860 #ifdef HAVE_OPENSSL
861   tls_active = tls_start(sock, &ssl, ctx);
862 #endif
863
864 #ifdef HAVE_GNUTLS
865   {
866   int rc;
867   sigalrm_seen = FALSE;
868   alarm(timeout);
869   do {
870     rc = gnutls_handshake(tls_session);
871   } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
872   tls_active = rc >= 0;
873   alarm(0);
874
875   if (!tls_active) printf("%s\n", gnutls_strerror(rc));
876   }
877 #endif
878
879   if (!tls_active)
880     printf("Failed to start TLS\n");
881 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
882   else if (  ocsp_stapling
883           && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
884     printf("Failed to verify certificate status\n");
885 #endif
886   else
887     printf("Succeeded in starting TLS\n");
888   }
889 #endif
890
891 while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL)
892   {
893   int n = (int)strlen(CS outbuffer);
894
895   /* Strip trailing newline */
896   if (outbuffer[n-1] == '\n') outbuffer[--n] = 0;
897
898   /* Expect incoming */
899
900   if (strncmp(CS outbuffer, "??? ", 4) == 0)
901     {
902     unsigned char *lineptr;
903     printf("%s\n", outbuffer);
904
905     if (*inptr == 0)   /* Refill input buffer */
906       {
907       if (tls_active)
908         {
909         #ifdef HAVE_OPENSSL
910         rc = SSL_read (ssl, inbuffer, sizeof(inbuffer) - 1);
911         #endif
912         #ifdef HAVE_GNUTLS
913         rc = gnutls_record_recv(tls_session, CS inbuffer, sizeof(inbuffer) - 1);
914         #endif
915         }
916       else
917         {
918         alarm(timeout);
919         rc = read(sock, inbuffer, sizeof(inbuffer));
920         alarm(0);
921         }
922
923       if (rc < 0)
924         {
925         printf("Read error %s\n", strerror(errno));
926         exit(81)  ;
927         }
928       else if (rc == 0)
929         {
930         printf("Unexpected EOF read\n");
931         close(sock);
932         exit(80);
933         }
934       else
935         {
936         inbuffer[rc] = 0;
937         inptr = inbuffer;
938         }
939       }
940
941     lineptr = inptr;
942     while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
943     if (*inptr != 0)
944       {
945       *inptr++ = 0;
946       if (*inptr == '\n') inptr++;
947       }
948
949     printf("<<< %s\n", lineptr);
950     if (strncmp(CS lineptr, CS outbuffer + 4, (int)strlen(CS outbuffer) - 4) != 0)
951       {
952       printf("\n******** Input mismatch ********\n");
953       exit(79);
954       }
955
956     #ifdef HAVE_TLS
957     if (sent_starttls)
958       {
959       if (lineptr[0] == '2')
960         {
961 int rc;
962         unsigned int verify;
963
964         printf("Attempting to start TLS\n");
965         fflush(stdout);
966
967         #ifdef HAVE_OPENSSL
968         tls_active = tls_start(sock, &ssl, ctx);
969         #endif
970
971         #ifdef HAVE_GNUTLS
972           {
973           int rc;
974           sigalrm_seen = FALSE;
975           alarm(timeout);
976           do {
977             rc = gnutls_handshake(tls_session);
978           } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
979           tls_active = rc >= 0;
980           alarm(0);
981
982           if (!tls_active) printf("%s\n", gnutls_strerror(rc));
983           }
984         #endif
985
986         if (!tls_active)
987           {
988           printf("Failed to start TLS\n");
989           fflush(stdout);
990           }
991         #ifdef HAVE_GNUTLS
992         else if (ocsp_stapling)
993           {
994           if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
995             {
996             printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
997             fflush(stdout);
998             }
999           else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
1000             {
1001             printf("Bad certificate\n");
1002             fflush(stdout);
1003             }
1004           #ifdef HAVE_OCSP
1005           else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1006             {
1007             printf("Failed to verify certificate status\n");
1008               {
1009               gnutls_datum_t stapling;
1010               gnutls_ocsp_resp_t resp;
1011               gnutls_datum_t printed;
1012               if (  (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
1013                  && (rc= gnutls_ocsp_resp_init(&resp)) == 0
1014                  && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
1015                  && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
1016                  )
1017                 {
1018                 fprintf(stderr, "%.4096s", printed.data);
1019                 gnutls_free(printed.data);
1020                 }
1021               else
1022                 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
1023               }
1024             fflush(stdout);
1025             }
1026           #endif
1027           }
1028         #endif
1029         else
1030           printf("Succeeded in starting TLS\n");
1031         }
1032       else printf("Abandoning TLS start attempt\n");
1033       }
1034     sent_starttls = 0;
1035     #endif
1036     }
1037
1038   /* Wait for a bit before proceeding */
1039
1040   else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
1041     {
1042     printf("%s\n", outbuffer);
1043     sleep(atoi(CS outbuffer + 4));
1044     }
1045
1046   /* Send outgoing, but barf if unconsumed incoming */
1047
1048   else
1049     {
1050     unsigned char *escape;
1051
1052     if (*inptr != 0)
1053       {
1054       printf("Unconsumed input: %s", inptr);
1055       printf("   About to send: %s\n", outbuffer);
1056       exit(78);
1057       }
1058
1059     #ifdef HAVE_TLS
1060
1061     /* Shutdown TLS */
1062
1063     if (strcmp(CS outbuffer, "stoptls") == 0 ||
1064         strcmp(CS outbuffer, "STOPTLS") == 0)
1065       {
1066       if (!tls_active)
1067         {
1068         printf("STOPTLS read when TLS not active\n");
1069         exit(77);
1070         }
1071       printf("Shutting down TLS encryption\n");
1072
1073       #ifdef HAVE_OPENSSL
1074       SSL_shutdown(ssl);
1075       SSL_free(ssl);
1076       #endif
1077
1078       #ifdef HAVE_GNUTLS
1079       gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1080       gnutls_deinit(tls_session);
1081       tls_session = NULL;
1082       gnutls_global_deinit();
1083       #endif
1084
1085       tls_active = 0;
1086       continue;
1087       }
1088
1089     /* Remember that we sent STARTTLS */
1090
1091     sent_starttls = (strcmp(CS outbuffer, "starttls") == 0 ||
1092                      strcmp(CS outbuffer, "STARTTLS") == 0);
1093
1094     /* Fudge: if the command is "starttls_wait", we send the starttls bit,
1095     but we haven't set the flag, so that there is no negotiation. This is for
1096     testing the server's timeout. */
1097
1098     if (strcmp(CS outbuffer, "starttls_wait") == 0)
1099       {
1100       outbuffer[8] = 0;
1101       n = 8;
1102       }
1103     #endif
1104
1105     printf(">>> %s\n", outbuffer);
1106     strcpy(CS outbuffer + n, "\r\n");
1107
1108     /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
1109
1110     while ((escape = US strstr(CS outbuffer, "\\r")) != NULL)
1111       {
1112       *escape = '\r';
1113       memmove(escape + 1, escape + 2,  (n + 2) - (escape - outbuffer) - 2);
1114       n--;
1115       }
1116
1117     while ((escape = US strstr(CS outbuffer, "\\n")) != NULL)
1118       {
1119       *escape = '\n';
1120       memmove(escape + 1, escape + 2,  (n + 2) - (escape - outbuffer) - 2);
1121       n--;
1122       }
1123
1124     /* OK, do it */
1125
1126     alarm(timeout);
1127     if (tls_active)
1128       {
1129       #ifdef HAVE_OPENSSL
1130         rc = SSL_write (ssl, outbuffer, n + 2);
1131       #endif
1132       #ifdef HAVE_GNUTLS
1133         rc = gnutls_record_send(tls_session, CS outbuffer, n + 2);
1134         if (rc < 0)
1135           {
1136           printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
1137           exit(76);
1138           }
1139       #endif
1140       }
1141     else
1142       {
1143       rc = write(sock, outbuffer, n + 2);
1144       }
1145     alarm(0);
1146
1147     if (rc < 0)
1148       {
1149       printf("Write error: %s\n", strerror(errno));
1150       exit(75);
1151       }
1152     }
1153   }
1154
1155 printf("End of script\n");
1156 shutdown(sock, SHUT_WR);
1157 while ((rc = read(sock, inbuffer, sizeof(inbuffer))) > 0) ;
1158 close(sock);
1159
1160 exit(0);
1161 }
1162
1163 /* End of client.c */