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