Testsuite: variances for OpenSSL 1.1.1
[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 #include <netinet/tcp.h>
28
29 #include <netdb.h>
30 #include <arpa/inet.h>
31 #include <sys/time.h>
32 #include <sys/resource.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <utime.h>
38
39 #ifdef AF_INET6
40 #define HAVE_IPV6 1
41 #endif
42
43 #ifndef S_ADDR_TYPE
44 #define S_ADDR_TYPE u_long
45 #endif
46
47 typedef unsigned char uschar;
48
49 #define CS   (char *)
50 #define US   (unsigned char *)
51
52 #define FALSE         0
53 #define TRUE          1
54
55
56
57 static int sigalrm_seen = 0;
58
59
60 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
61 latter needs a whole pile of tables. */
62 #ifdef HAVE_OPENSSL
63 # define HAVE_TLS
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>
70
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"
73 #  define DISABLE_OCSP
74 # endif
75 # ifndef DISABLE_OCSP
76 #  include <openssl/ocsp.h>
77 # endif
78 #endif
79
80
81 #ifdef HAVE_GNUTLS
82 # define HAVE_TLS
83 # include <gnutls/gnutls.h>
84 # include <gnutls/x509.h>
85 # if GNUTLS_VERSION_NUMBER >= 0x030103
86 #  define HAVE_OCSP
87 #  include <gnutls/ocsp.h>
88 # endif
89 # ifndef GNUTLS_NO_EXTENSIONS
90 #  define GNUTLS_NO_EXTENSIONS 0
91 # endif
92
93 # define DH_BITS      768
94
95 /* Local static variables for GNUTLS */
96
97 static gnutls_dh_params_t dh_params = NULL;
98
99 static gnutls_certificate_credentials_t x509_cred = NULL;
100 static gnutls_session_t tls_session = NULL;
101
102 static int  ssl_session_timeout = 200;
103
104 /* Priorities for TLS algorithms to use. */
105
106 # if GNUTLS_VERSION_NUMBER < 0x030400
107 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
108
109 static const int kx_priority[16] = {
110   GNUTLS_KX_RSA,
111   GNUTLS_KX_DHE_DSS,
112   GNUTLS_KX_DHE_RSA,
113   0 };
114
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,
120   0 };
121
122 static const int mac_priority[16] = {
123   GNUTLS_MAC_SHA,
124   GNUTLS_MAC_MD5,
125   0 };
126
127 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
128 # endif
129
130 #endif  /*HAVE_GNUTLS*/
131
132
133
134 #ifdef HAVE_TLS
135 char * ocsp_stapling = NULL;
136 char * pri_string = NULL;
137 #endif
138
139
140 /*************************************************
141 *            SIGALRM handler - crash out         *
142 *************************************************/
143
144 static void
145 sigalrm_handler_crash(int sig)
146 {
147 sig = sig;    /* Keep picky compilers happy */
148 printf("\nClient timed out\n");
149 exit(99);
150 }
151
152
153 /*************************************************
154 *            SIGALRM handler - set flag          *
155 *************************************************/
156
157 static void
158 sigalrm_handler_flag(int sig)
159 {
160 sig = sig;    /* Keep picky compilers happy */
161 sigalrm_seen = 1;
162 }
163
164
165
166 /****************************************************************************/
167 /****************************************************************************/
168
169 #ifdef HAVE_OPENSSL
170 # ifndef DISABLE_OCSP
171
172 static STACK_OF(X509) *
173 chain_from_pem_file(const uschar * file)
174 {
175 BIO * bp;
176 X509 * x;
177 STACK_OF(X509) * sk;
178
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)))
182   sk_X509_push(sk, x);
183 BIO_free(bp);
184 return sk;
185 }
186
187
188
189 static void
190 cert_stack_free(STACK_OF(X509) * sk)
191 {
192 while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
193 sk_X509_free(sk);
194 }
195
196
197 static int
198 tls_client_stapling_cb(SSL *s, void *arg)
199 {
200 const unsigned char *p;
201 int len;
202 OCSP_RESPONSE *rsp;
203 OCSP_BASICRESP *bs;
204 STACK_OF(X509) * sk;
205 int ret = 1;
206
207 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
208 /*BIO_printf(arg, "OCSP response: ");*/
209 if (!p)
210         {
211         BIO_printf(arg, "no response received\n");
212         return 1;
213         }
214 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
215         {
216         BIO_printf(arg, "response parse error\n");
217         BIO_dump_indent(arg, (char *)p, len, 4);
218         return 0;
219         }
220 if(!(bs = OCSP_response_get1_basic(rsp)))
221   {
222   BIO_printf(arg, "error parsing response\n");
223   return 0;
224   }
225
226
227 if (!(sk = chain_from_pem_file((const uschar *)ocsp_stapling)))
228   {
229   BIO_printf(arg, "error in cert setup\n");
230   return 0;
231   }
232
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. */
237
238 if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
239   {
240   BIO_printf(arg, "Response Verify Failure\n");
241   ERR_print_errors(arg);
242   ret = 0;
243   }
244 else
245   BIO_printf(arg, "Response verify OK\n");
246
247 cert_stack_free(sk);
248 return ret;
249 }
250 # endif /*DISABLE_OCSP*/
251
252
253 /*************************************************
254 *         Start an OpenSSL TLS session           *
255 *************************************************/
256
257 int
258 tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
259 {
260 int rc;
261 static const unsigned char *sid_ctx = US"exim";
262
263 RAND_load_file("client.c", -1);   /* Not *very* random! */
264
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);
269
270 #ifndef DISABLE_OCSP
271 if (ocsp_stapling)
272   {
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);
276   }
277 #endif
278
279 signal(SIGALRM, sigalrm_handler_flag);
280 sigalrm_seen = 0;
281 alarm(5);
282 rc = SSL_connect (*ssl);
283 alarm(0);
284
285 if (sigalrm_seen)
286   {
287   printf("SSL_connect timed out\n");
288   return 0;
289   }
290
291 if (rc <= 0)
292   {
293   ERR_print_errors_fp(stdout);
294   return 0;
295   }
296
297 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
298 return 1;
299 }
300
301
302 /*************************************************
303 *           SSL Information callback             *
304 *************************************************/
305
306 static void
307 info_callback(SSL *s, int where, int ret)
308 {
309 where = where;
310 ret = ret;
311 printf("SSL info: %s\n", SSL_state_string_long(s));
312 }
313 #endif
314
315
316 /****************************************************************************/
317 /****************************************************************************/
318
319
320 #ifdef HAVE_GNUTLS
321 /*************************************************
322 *            Handle GnuTLS error                 *
323 *************************************************/
324
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.
327
328 Argument:
329   prefix    prefix text
330   err       a GnuTLS error number, or 0 if local error
331
332 Returns:    doesn't - it dies
333 */
334
335 static void
336 gnutls_error(uschar *prefix, int err)
337 {
338 fprintf(stderr, "GnuTLS connection error: %s:", prefix);
339 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
340 fprintf(stderr, "\n");
341 exit(98);
342 }
343
344
345
346 /*************************************************
347 *             Setup up DH parameters             *
348 *************************************************/
349
350 /* For the test suite, the parameters should always be available in the spool
351 directory. */
352
353 static void
354 init_dh(void)
355 {
356 int fd;
357 int ret;
358 gnutls_datum_t m;
359 uschar filename[200];
360 struct stat statbuf;
361
362 /* Initialize the data structures for holding the parameters */
363
364 ret = gnutls_dh_params_init(&dh_params);
365 if (ret < 0) gnutls_error(US"init dh_params", ret);
366
367 /* Open the cache file for reading and if successful, read it and set up the
368 parameters. */
369
370 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
371 if (fd < 0)
372   {
373   fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
374   exit(97);
375   }
376
377 if (fstat(fd, &statbuf) < 0)
378   {
379   (void)close(fd);
380   return gnutls_error(US"TLS cache stat failed", 0);
381   }
382
383 m.size = statbuf.st_size;
384 m.data = malloc(m.size);
385 if (m.data == NULL)
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);
389 (void)close(fd);
390
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);
393 free(m.data);
394 }
395
396
397
398
399 /*************************************************
400 *            Initialize for GnuTLS               *
401 *************************************************/
402
403 /*
404 Arguments:
405   certificate     certificate file
406   privatekey      private key file
407 */
408
409 static void
410 tls_init(uschar *certificate, uschar *privatekey)
411 {
412 int rc;
413
414 rc = gnutls_global_init();
415 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
416
417 /* Read D-H parameters from the cache file. */
418
419 init_dh();
420
421 /* Create the credentials structure */
422
423 rc = gnutls_certificate_allocate_credentials(&x509_cred);
424 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
425
426 /* Set the certificate and private keys */
427
428 if (certificate != NULL)
429   {
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);
433   }
434
435 /* Associate the parameters with the x509 credentials structure. */
436
437 gnutls_certificate_set_dh_params(x509_cred, dh_params);
438
439 /* set the CA info for server-cert verify */
440 if (ocsp_stapling)
441   gnutls_certificate_set_x509_trust_file(x509_cred, ocsp_stapling,
442         GNUTLS_X509_FMT_PEM);
443 }
444
445
446
447 /*************************************************
448 *        Initialize a single GNUTLS session      *
449 *************************************************/
450
451 static gnutls_session_t
452 tls_session_init(void)
453 {
454 gnutls_session_t session;
455
456 gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);
457
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);
464
465 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
466 # else
467 if (pri_string)
468   {
469   gnutls_priority_t priority_cache;
470   const char * errpos;
471
472   gnutls_priority_init(&priority_cache, pri_string, &errpos);
473   gnutls_priority_set(session, priority_cache);
474   }
475 else
476   gnutls_set_default_priority(session);
477 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
478 # endif
479
480 gnutls_dh_set_prime_bits(session, DH_BITS);
481 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
482
483 return session;
484 }
485 #endif
486
487
488 /****************************************************************************/
489 /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
490
491 static int
492 unescape_buf(unsigned char * buf, int len)
493 {
494 unsigned char * s;
495 unsigned char c, t;
496 unsigned shift;
497
498 for (s = buf; s < buf+len; s++) if (*s == '\\')
499   {
500   switch (s[1])
501     {
502     default:    c = s[1]; shift = 1; break;
503     case 'n':   c = '\n'; shift = 1; break;
504     case 'r':   c = '\r'; shift = 1; break;
505     case 'x':
506                 t = s[2];
507                 if (t >= 'A' && t <= 'F') t -= 'A'-'9'-1;
508                 else if (t >= 'a' && t <= 'f') t -= 'a'-'9'-1;
509                 t -= '0';
510                 c = (t<<4) & 0xf0;
511                 t = s[3];
512                 if (t >= 'A' && t <= 'F') t -= 'A'-'9'-1;
513                 else if (t >= 'a' && t <= 'f') t -= 'a'-'9'-1;
514                 t -= '0';
515                 c |= t & 0xf;
516                 shift = 3;
517                 break;
518     }
519   *s = c;
520   memmove(s+1, s+shift+1, len-shift);
521   len -= shift;
522   }
523 return len;
524 }
525
526
527 /****************************************************************************/
528 typedef struct {
529   int   sock;
530   int   tls_active;
531 #ifdef HAVE_OPENSSL
532   SSL_CTX * ctx;
533   SSL * ssl;
534 #endif
535   int   sent_starttls;
536 } srv_ctx;
537
538 static void
539 do_file(srv_ctx * srv, FILE * f, int timeout,
540   unsigned char * inbuffer, unsigned bsiz, unsigned char * inptr)
541 {
542 unsigned char outbuffer[1024 * 20];
543
544 while (fgets(CS outbuffer, sizeof(outbuffer), f) != NULL)
545   {
546   int n = (int)strlen(CS outbuffer);
547   int crlf = 1;
548   int rc;
549
550   /* Strip trailing newline */
551   if (outbuffer[n-1] == '\n') outbuffer[--n] = 0;
552
553   /* Expect incoming */
554
555   if (  strncmp(CS outbuffer, "???", 3) == 0
556      && (outbuffer[3] == ' ' || outbuffer[3] == '*' || outbuffer[3] == '?')
557      )
558     {
559     unsigned char *lineptr;
560     unsigned exp_eof = outbuffer[3] == '*';
561     unsigned resp_optional = outbuffer[3] == '?';
562
563     printf("%s\n", outbuffer);
564     n = unescape_buf(outbuffer, n);
565
566 nextinput:
567     if (*inptr == 0)   /* Refill input buffer */
568       {
569       alarm(timeout);
570       if (srv->tls_active)
571         {
572 #ifdef HAVE_OPENSSL
573         int error;
574         rc = SSL_read(srv->ssl, inbuffer, bsiz - 1);
575         if (rc <= 0)
576           switch (error = SSL_get_error(srv->ssl, rc))
577             {
578             case SSL_ERROR_ZERO_RETURN:
579               break;
580             case SSL_ERROR_SYSCALL:
581               printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
582               rc = -1;
583               break;
584             case SSL_ERROR_SSL:
585               printf("%s\nTLS terminated\n", ERR_error_string(ERR_get_error(), NULL));
586               SSL_shutdown(srv->ssl);
587               SSL_free(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};
591               sigalrm_seen = 1;
592               sigaction(SIGALRM, &act, NULL);
593               }
594               *inptr = 0;
595               goto nextinput;
596             default:
597               printf("SSL error code %d\n", error);
598             }
599 #endif
600 #ifdef HAVE_GNUTLS
601         rc = gnutls_record_recv(tls_session, CS inbuffer, bsiz - 1);
602 #endif
603         }
604       else
605         rc = read(srv->sock, inbuffer, bsiz);
606       alarm(0);
607
608       if (rc < 0)
609         {
610         if (errno == EINTR && sigalrm_seen && resp_optional)
611           continue;     /* next scriptline */
612         printf("Read error %s\n", strerror(errno));
613         exit(81);
614         }
615       else if (rc == 0)
616         if (exp_eof)
617           {
618           printf("Expected EOF read\n");
619           continue;
620           }
621         else if (resp_optional)
622           continue;     /* next scriptline */
623         else
624           {
625           printf("Unexpected EOF read\n");
626           close(srv->sock);
627           exit(80);
628           }
629       else if (exp_eof)
630         {
631         printf("Expected EOF not read\n");
632         close(srv->sock);
633         exit(74);
634         }
635       else
636         {
637         inbuffer[rc] = 0;
638         inptr = inbuffer;
639         }
640       }
641
642     lineptr = inptr;
643     while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
644     if (*inptr != 0)
645       {
646       *inptr++ = 0;
647       if (*inptr == '\n') inptr++;
648       }
649
650     if (strncmp(CS lineptr, CS outbuffer + 4, n - 4) != 0)
651       if (resp_optional)
652         {
653         inptr = lineptr;        /* consume scriptline, not inputline */
654         continue;
655         }
656       else
657         {
658         printf("<<< %s\n", lineptr);
659         printf("\n******** Input mismatch ********\n");
660         exit(79);
661         }
662
663     /* input matched script */
664
665     if (resp_optional)
666       goto nextinput;           /* consume inputline, not scriptline */
667
668     printf("<<< %s\n", lineptr);
669
670     #ifdef HAVE_TLS
671     if (srv->sent_starttls)
672       {
673       if (lineptr[0] == '2')
674         {
675         unsigned int verify;
676
677         printf("Attempting to start TLS\n");
678         fflush(stdout);
679
680         #ifdef HAVE_OPENSSL
681         srv->tls_active = tls_start(srv->sock, &srv->ssl, srv->ctx);
682         #endif
683
684         #ifdef HAVE_GNUTLS
685           {
686           int rc;
687           sigalrm_seen = FALSE;
688           alarm(timeout);
689           do {
690             rc = gnutls_handshake(tls_session);
691           } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
692           srv->tls_active = rc >= 0;
693           alarm(0);
694
695           if (!srv->tls_active) printf("%s\n", gnutls_strerror(rc));
696           }
697         #endif
698
699         if (!srv->tls_active)
700           {
701           printf("Failed to start TLS\n");
702           fflush(stdout);
703           }
704         #ifdef HAVE_GNUTLS
705         else if (ocsp_stapling)
706           {
707           if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
708             {
709             printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
710             fflush(stdout);
711             }
712           else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
713             {
714             printf("Bad certificate\n");
715             fflush(stdout);
716             }
717           #ifdef HAVE_OCSP
718           else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
719             {
720             printf("Failed to verify certificate status\n");
721               {
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
729                  )
730                 {
731                 fprintf(stderr, "%.4096s", printed.data);
732                 gnutls_free(printed.data);
733                 }
734               else
735                 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
736               }
737             fflush(stdout);
738             }
739           #endif
740           }
741         #endif
742         else
743           printf("Succeeded in starting TLS\n");
744         }
745       else printf("Abandoning TLS start attempt\n");
746       }
747     srv->sent_starttls = 0;
748     #endif
749     }
750
751   /* Wait for a bit before proceeding */
752
753   else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
754     {
755     printf("%s\n", outbuffer);
756     sleep(atoi(CS outbuffer + 4));
757     }
758
759   /* Stack new input file */
760
761   else if (strncmp(CS outbuffer, "<<< ", 4) == 0)
762     {
763     FILE * new_f;
764     if (!(new_f = fopen((const char *)outbuffer+4 , "r")))
765       {
766       printf("Unable to open '%s': %s", inptr, strerror(errno));
767       exit(74);
768       }
769     do_file(srv, new_f, timeout, inbuffer, bsiz, inptr);
770     }
771
772
773   /* Send line outgoing, but barf if unconsumed incoming */
774
775   else
776     {
777     unsigned char * out = outbuffer;
778
779     if (strncmp(CS outbuffer, ">>> ", 4) == 0)
780       {
781       crlf = 0;
782       out += 4;
783       n -= 4;
784       }
785
786     if (*inptr != 0)
787       {
788       printf("Unconsumed input: %s", inptr);
789       printf("   About to send: %s\n", out);
790       exit(78);
791       }
792
793     #ifdef HAVE_TLS
794
795     /* Shutdown TLS */
796
797     if (strcmp(CS out, "stoptls") == 0 ||
798         strcmp(CS out, "STOPTLS") == 0)
799       {
800       if (!srv->tls_active)
801         {
802         printf("STOPTLS read when TLS not active\n");
803         exit(77);
804         }
805       printf("Shutting down TLS encryption\n");
806
807       #ifdef HAVE_OPENSSL
808       SSL_shutdown(srv->ssl);
809       SSL_free(srv->ssl);
810       #endif
811
812       #ifdef HAVE_GNUTLS
813       gnutls_bye(tls_session, GNUTLS_SHUT_WR);
814       gnutls_deinit(tls_session);
815       tls_session = NULL;
816       gnutls_global_deinit();
817       #endif
818
819       srv->tls_active = 0;
820       continue;
821       }
822
823     /* Remember that we sent STARTTLS */
824
825     srv->sent_starttls = (strcmp(CS out, "starttls") == 0 ||
826                      strcmp(CS out, "STARTTLS") == 0);
827
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. */
831
832     if (strcmp(CS out, "starttls_wait") == 0)
833       {
834       out[8] = 0;
835       n = 8;
836       }
837     #endif
838
839     printf(">>> %s\n", out);
840     if (crlf)
841       {
842       strcpy(CS out + n, "\r\n");
843       n += 2;
844       }
845
846     n = unescape_buf(out, n);
847
848     /* OK, do it */
849
850     alarm(timeout);
851     if (srv->tls_active)
852       {
853       #ifdef HAVE_OPENSSL
854         rc = SSL_write (srv->ssl, out, n);
855       #endif
856       #ifdef HAVE_GNUTLS
857         if ((rc = gnutls_record_send(tls_session, CS out, n)) < 0)
858           {
859           printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
860           exit(76);
861           }
862       #endif
863       }
864     else
865       rc = write(srv->sock, out, n);
866     alarm(0);
867
868     if (rc < 0)
869       {
870       printf("Write error: %s\n", strerror(errno));
871       exit(75);
872       }
873     }
874   }
875 }
876
877
878
879
880 /*************************************************
881 *                 Main Program                   *
882 *************************************************/
883
884 const char * const HELP_MESSAGE = "\n\
885 Usage: client\n"
886 #ifdef HAVE_TLS
887 "\
888           [-tls-on-connect]\n\
889           [-ocsp]\n"
890 # ifdef HAVE_GNUTLS
891 "\
892           [-p priority-string]\n"
893 # endif
894 #endif
895 "\
896           [-tn] n seconds timeout\n\
897           <IP address>\n\
898           <port>\n\
899           [<outgoing interface>]\n\
900           [<cert file>]\n\
901           [<key file>]\n\
902 \n";
903
904 int
905 main(int argc, char **argv)
906 {
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;
913 char *end = NULL;
914 int argi = 1;
915 int host_af, port, s_len, rc, save_errno;
916 int timeout = 5;
917 int tls_on_connect = 0;
918 long tmplong;
919
920 #if HAVE_IPV6
921 struct sockaddr_in6 s_in6;
922 #endif
923
924 srv_ctx srv;
925
926 unsigned char inbuffer[10240];
927 unsigned char *inptr = inbuffer;
928
929 *inptr = 0;   /* Buffer empty */
930 srv.tls_active = 0;
931 srv.sent_starttls = 0;
932
933 /* Options */
934
935 while (argc >= argi + 1 && argv[argi][0] == '-')
936   {
937   if (strcmp(argv[argi], "-help") == 0 ||
938       strcmp(argv[argi], "--help") == 0 ||
939       strcmp(argv[argi], "-h") == 0)
940     {
941     puts(HELP_MESSAGE);
942     exit(0);
943     }
944   if (strcmp(argv[argi], "-tls-on-connect") == 0)
945     {
946     tls_on_connect = 1;
947     argi++;
948     }
949 #ifdef HAVE_TLS
950   else if (strcmp(argv[argi], "-ocsp") == 0)
951     {
952     if (argc < ++argi + 1)
953       {
954       fprintf(stderr, "Missing required certificate file for ocsp option\n");
955       exit(96);
956       }
957     ocsp_stapling = argv[argi++];
958     }
959 # ifdef HAVE_GNUTLS
960   else if (strcmp(argv[argi], "-p") == 0)
961     {
962     if (argc < ++argi + 1)
963       {
964       fprintf(stderr, "Missing priority string\n");
965       exit(96);
966       }
967     pri_string = argv[argi++];
968     }
969 #endif
970
971 #endif
972   else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
973     {
974     tmplong = strtol(argv[argi]+2, &end, 10);
975     if (end == argv[argi]+2 || *end)
976       {
977       fprintf(stderr, "Failed to parse seconds from option <%s>\n",
978         argv[argi]);
979       exit(95);
980       }
981     if (tmplong > 10000L)
982       {
983       fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
984         tmplong);
985       exit(94);
986       }
987     if (tmplong < 0L)
988       {
989       fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
990       exit(93);
991       }
992     timeout = (int) tmplong;
993     argi++;
994     }
995   else
996     {
997     fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
998     exit(92);
999     }
1000   }
1001
1002 /* Mandatory 1st arg is IP address */
1003
1004 if (argc < argi+1)
1005   {
1006   fprintf(stderr, "No IP address given\n");
1007   exit(91);
1008   }
1009
1010 address = argv[argi++];
1011 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
1012
1013 /* Mandatory 2nd arg is port */
1014
1015 if (argc < argi+1)
1016   {
1017   fprintf(stderr, "No port number given\n");
1018   exit(90);
1019   }
1020
1021 port = atoi(argv[argi++]);
1022
1023 /* Optional next arg is interface */
1024
1025 if (argc > argi &&
1026   (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
1027     interface = argv[argi++];
1028
1029 /* Any more arguments are the name of a certificate file and key file */
1030
1031 if (argc > argi) certfile = argv[argi++];
1032 if (argc > argi) keyfile = argv[argi++];
1033
1034
1035 #if HAVE_IPV6
1036 /* For an IPv6 address, use an IPv6 sockaddr structure. */
1037
1038 if (host_af == AF_INET6)
1039   {
1040   s_ptr = (struct sockaddr *)&s_in6;
1041   s_len = sizeof(s_in6);
1042   }
1043 else
1044 #endif
1045
1046 /* For an IPv4 address, use an IPv4 sockaddr structure,
1047 even on an IPv6 system. */
1048
1049   {
1050   s_ptr = (struct sockaddr *)&s_in4;
1051   s_len = sizeof(s_in4);
1052   }
1053
1054 printf("Connecting to %s port %d ... ", address, port);
1055
1056 srv.sock = socket(host_af, SOCK_STREAM, 0);
1057 if (srv.sock < 0)
1058   {
1059   printf("socket creation failed: %s\n", strerror(errno));
1060   exit(89);
1061   }
1062
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. */
1066
1067 if (interface != NULL)
1068   {
1069   int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
1070
1071   if (interface_af == host_af)
1072     {
1073     #if HAVE_IPV6
1074
1075     /* Set up for IPv6 binding */
1076
1077     if (host_af == AF_INET6)
1078       {
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)
1083         {
1084         printf("Unable to parse \"%s\"", interface);
1085         exit(88);
1086         }
1087       }
1088     else
1089     #endif
1090
1091     /* Set up for IPv4 binding */
1092
1093       {
1094       memset(&s_in4, 0, sizeof(s_in4));
1095       s_in4.sin_family = AF_INET;
1096       s_in4.sin_port = 0;
1097       s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
1098       }
1099
1100     /* Bind */
1101
1102     if (bind(srv.sock, s_ptr, s_len) < 0)
1103       {
1104       printf("Unable to bind outgoing SMTP call to %s: %s",
1105         interface, strerror(errno));
1106       exit(87);
1107       }
1108     }
1109   }
1110
1111 /* Set up a remote IPv6 address */
1112
1113 #if HAVE_IPV6
1114 if (host_af == AF_INET6)
1115   {
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)
1120     {
1121     printf("Unable to parse \"%s\"", address);
1122     exit(86);
1123     }
1124   }
1125 else
1126 #endif
1127
1128 /* Set up a remote IPv4 address */
1129
1130   {
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);
1135   }
1136
1137 /* SIGALRM handler crashes out */
1138
1139 signal(SIGALRM, sigalrm_handler_crash);
1140 alarm(timeout);
1141 rc = connect(srv.sock, s_ptr, s_len);
1142 save_errno = errno;
1143 alarm(0);
1144
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. */
1147
1148 if (rc < 0)
1149   {
1150   close(srv.sock);
1151   printf("connect failed: %s\n", strerror(save_errno));
1152   exit(85);
1153   }
1154
1155 printf("connected\n");
1156
1157
1158 /* --------------- Set up for OpenSSL --------------- */
1159
1160 #ifdef HAVE_OPENSSL
1161 SSL_library_init();
1162 SSL_load_error_strings();
1163
1164 if (!(srv.ctx = SSL_CTX_new(SSLv23_method())))
1165   {
1166   printf ("SSL_CTX_new failed\n");
1167   exit(84);
1168   }
1169
1170 if (certfile)
1171   {
1172   if (!SSL_CTX_use_certificate_file(srv.ctx, certfile, SSL_FILETYPE_PEM))
1173     {
1174     printf("SSL_CTX_use_certificate_file failed\n");
1175     exit(83);
1176     }
1177   printf("Certificate file = %s\n", certfile);
1178   }
1179
1180 if (keyfile)
1181   {
1182   if (!SSL_CTX_use_PrivateKey_file(srv.ctx, keyfile, SSL_FILETYPE_PEM))
1183     {
1184     printf("SSL_CTX_use_PrivateKey_file failed\n");
1185     exit(82);
1186     }
1187   printf("Key file = %s\n", keyfile);
1188   }
1189
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);
1193 #endif
1194
1195
1196 /* --------------- Set up for GnuTLS --------------- */
1197
1198 #ifdef HAVE_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();
1203 #ifdef HAVE_OCSP
1204 if (ocsp_stapling)
1205   gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
1206 #endif
1207 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)srv.sock);
1208
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
1213 one wants. */
1214
1215 signal(SIGPIPE, SIG_IGN);
1216 #endif
1217
1218 /* ---------------------------------------------- */
1219
1220
1221 /* Start TLS session if configured to do so without STARTTLS */
1222
1223 #ifdef HAVE_TLS
1224 if (tls_on_connect)
1225   {
1226   printf("Attempting to start TLS\n");
1227
1228 #ifdef HAVE_OPENSSL
1229   srv.tls_active = tls_start(srv.sock, &srv.ssl, srv.ctx);
1230 #endif
1231
1232 #ifdef HAVE_GNUTLS
1233   {
1234   int rc;
1235   sigalrm_seen = FALSE;
1236   alarm(timeout);
1237   do {
1238     rc = gnutls_handshake(tls_session);
1239   } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
1240   srv.tls_active = rc >= 0;
1241   alarm(0);
1242
1243   if (!srv.tls_active) printf("%s\n", gnutls_strerror(rc));
1244   }
1245 #endif
1246
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");
1253 #endif
1254   else
1255     printf("Succeeded in starting TLS\n");
1256   }
1257 #endif
1258
1259 do_file(&srv, stdin, timeout, inbuffer, sizeof(inbuffer), inptr);
1260
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) ;
1265 close(srv.sock);
1266
1267 exit(0);
1268 }
1269
1270 /* End of client.c */