Testsuite: src/client.c: handle long lines read back from the server
[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 unsigned char *inbufferp = inbuffer;
574 for (;;) {
575 if (srv->tls_active)
576 {
577 #ifdef HAVE_OPENSSL
578 int error;
579 DEBUG { printf("call SSL_read\n"); fflush(stdout); }
580 rc = SSL_read(srv->ssl, inbufferp, bsiz - (inbufferp - inbuffer) - 1);
581 DEBUG { printf("SSL_read: %d\n", rc); fflush(stdout); }
582 if (rc <= 0)
583 switch (error = SSL_get_error(srv->ssl, rc))
584 {
585 case SSL_ERROR_ZERO_RETURN:
586 break;
587 case SSL_ERROR_SYSCALL:
588 printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
589 rc = -1;
590 break;
591 case SSL_ERROR_SSL:
592 printf("%s\nTLS terminated\n", ERR_error_string(ERR_get_error(), NULL));
593 SSL_shutdown(srv->ssl);
594 SSL_free(srv->ssl);
595 srv->tls_active = FALSE;
596 { /* OpenSSL leaves it in restartsys mode */
597 struct sigaction act = {.sa_handler = sigalrm_handler_flag, .sa_flags = 0};
598 sigalrm_seen = 1;
599 sigaction(SIGALRM, &act, NULL);
600 }
601 *inptr = 0;
602 DEBUG { printf("go round\n"); fflush(stdout); }
603 goto nextinput;
604 default:
605 printf("SSL error code %d\n", error);
606 }
607 #endif
608 #ifdef HAVE_GNUTLS
609 rc = gnutls_record_recv(tls_session, CS inbufferp, bsiz - (inbufferp - inbuffer) - 1);
610 #endif
611 }
612 else
613 {
614 DEBUG { printf("call read\n"); fflush(stdout); }
615 rc = read(srv->sock, inbufferp, bsiz - (inbufferp - inbuffer) - 1);
616 DEBUG { printf("read: %d\n", rc); fflush(stdout); }
617 }
618
619 if (rc > 0) inbufferp[rc] = '\0';
620 if (rc <= 0 || strchr(inbufferp, '\n')) break;
621 inbufferp += rc;
622 if (inbufferp >= inbuffer + bsiz) {
623 printf("Input buffer overrun, need more than %d bytes input buffer\n", bsiz);
624 exit(73);
625 }
626 DEBUG { printf("read more\n"); }
627 }
628 alarm(0);
629
630 if (rc < 0)
631 {
632 if (errno == EINTR && sigalrm_seen && resp_optional)
633 continue; /* next scriptline */
634 printf("Read error %s\n", strerror(errno));
635 exit(81);
636 }
637 else if (rc == 0)
638 if (exp_eof)
639 {
640 printf("Expected EOF read\n");
641 continue;
642 }
643 else if (resp_optional)
644 continue; /* next scriptline */
645 else
646 {
647 printf("Unexpected EOF read\n");
648 close(srv->sock);
649 exit(80);
650 }
651 else if (exp_eof)
652 {
653 printf("Expected EOF not read\n");
654 close(srv->sock);
655 exit(74);
656 }
657 else
658 inptr = inbuffer;
659 }
660 DEBUG { printf("read: '%s'\n", inptr); fflush(stdout); }
661
662 lineptr = inptr;
663 while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
664 if (*inptr != 0)
665 {
666 *inptr++ = 0;
667 if (*inptr == '\n') inptr++;
668 }
669
670 if (strncmp(CS lineptr, CS outbuffer + 4, n - 4) != 0)
671 if (resp_optional)
672 {
673 inptr = lineptr; /* consume scriptline, not inputline */
674 continue;
675 }
676 else
677 {
678 printf("<<< %s\n", lineptr);
679 printf("\n******** Input mismatch ********\n");
680 exit(79);
681 }
682
683 /* Input matched script. Output the inputline, unless optional */
684 DEBUG { printf("read matched\n"); fflush(stdout); }
685
686 if (!resp_optional)
687 printf("<<< %s\n", lineptr);
688 else
689
690 /* If there is further input after this line, consume inputline but not
691 scriptline in case there are several matching. Nonmatches are dealt with
692 above. */
693
694 if (*inptr != 0)
695 goto nextinput;
696
697 #ifdef HAVE_TLS
698 if (srv->sent_starttls)
699 {
700 if (lineptr[0] == '2')
701 {
702 unsigned int verify;
703
704 printf("Attempting to start TLS\n");
705 fflush(stdout);
706
707 #ifdef HAVE_OPENSSL
708 srv->tls_active = tls_start(srv->sock, &srv->ssl, srv->ctx);
709 #endif
710
711 #ifdef HAVE_GNUTLS
712 {
713 int rc;
714 sigalrm_seen = FALSE;
715 alarm(timeout);
716 do {
717 rc = gnutls_handshake(tls_session);
718 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
719 srv->tls_active = rc >= 0;
720 alarm(0);
721
722 if (!srv->tls_active) printf("%s\n", gnutls_strerror(rc));
723 }
724 #endif
725
726 if (!srv->tls_active)
727 {
728 printf("Failed to start TLS\n");
729 fflush(stdout);
730 }
731 #ifdef HAVE_GNUTLS
732 else if (ocsp_stapling)
733 {
734 if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
735 {
736 printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
737 fflush(stdout);
738 }
739 else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
740 {
741 printf("Bad certificate\n");
742 fflush(stdout);
743 }
744 #ifdef HAVE_OCSP
745 else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
746 {
747 printf("Failed to verify certificate status\n");
748 {
749 gnutls_datum_t stapling;
750 gnutls_ocsp_resp_t resp;
751 gnutls_datum_t printed;
752 if ( (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
753 && (rc= gnutls_ocsp_resp_init(&resp)) == 0
754 && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
755 && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
756 )
757 {
758 fprintf(stderr, "%.4096s", printed.data);
759 gnutls_free(printed.data);
760 }
761 else
762 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
763 }
764 fflush(stdout);
765 }
766 #endif
767 }
768 #endif
769 else
770 printf("Succeeded in starting TLS\n");
771 }
772 else printf("Abandoning TLS start attempt\n");
773 }
774 srv->sent_starttls = 0;
775 #endif
776 }
777
778 /* Wait for a bit before proceeding */
779
780 else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
781 {
782 printf("%s\n", outbuffer);
783 sleep(atoi(CS outbuffer + 4));
784 }
785
786 /* Stack new input file */
787
788 else if (strncmp(CS outbuffer, "<<< ", 4) == 0)
789 {
790 FILE * new_f;
791 if (!(new_f = fopen((const char *)outbuffer+4 , "r")))
792 {
793 printf("Unable to open '%s': %s", inptr, strerror(errno));
794 exit(74);
795 }
796 do_file(srv, new_f, timeout, inbuffer, bsiz, inptr);
797 }
798
799
800 /* Send line outgoing, but barf if unconsumed incoming */
801
802 else
803 {
804 unsigned char * out = outbuffer;
805
806 if (strncmp(CS outbuffer, ">>> ", 4) == 0)
807 {
808 crlf = 0;
809 out += 4;
810 n -= 4;
811 }
812
813 if (*inptr != 0)
814 {
815 printf("Unconsumed input: %s", inptr);
816 printf(" About to send: %s\n", out);
817 exit(78);
818 }
819
820 #ifdef HAVE_TLS
821
822 /* Shutdown TLS */
823
824 if (strcmp(CS out, "stoptls") == 0 ||
825 strcmp(CS out, "STOPTLS") == 0)
826 {
827 if (!srv->tls_active)
828 {
829 printf("STOPTLS read when TLS not active\n");
830 exit(77);
831 }
832 printf("Shutting down TLS encryption\n");
833
834 #ifdef HAVE_OPENSSL
835 SSL_shutdown(srv->ssl);
836 SSL_free(srv->ssl);
837 #endif
838
839 #ifdef HAVE_GNUTLS
840 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
841 gnutls_deinit(tls_session);
842 tls_session = NULL;
843 gnutls_global_deinit();
844 #endif
845
846 srv->tls_active = 0;
847 continue;
848 }
849
850 /* Remember that we sent STARTTLS */
851
852 srv->sent_starttls = (strcmp(CS out, "starttls") == 0 ||
853 strcmp(CS out, "STARTTLS") == 0);
854
855 /* Fudge: if the command is "starttls_wait", we send the starttls bit,
856 but we haven't set the flag, so that there is no negotiation. This is for
857 testing the server's timeout. */
858
859 if (strcmp(CS out, "starttls_wait") == 0)
860 {
861 out[8] = 0;
862 n = 8;
863 }
864 #endif
865
866 printf(">>> %s\n", out);
867 if (crlf)
868 {
869 strcpy(CS out + n, "\r\n");
870 n += 2;
871 }
872
873 n = unescape_buf(out, n);
874
875 /* OK, do it */
876
877 alarm(timeout);
878 if (srv->tls_active)
879 {
880 #ifdef HAVE_OPENSSL
881 rc = SSL_write (srv->ssl, out, n);
882 #endif
883 #ifdef HAVE_GNUTLS
884 if ((rc = gnutls_record_send(tls_session, CS out, n)) < 0)
885 {
886 printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
887 exit(76);
888 }
889 #endif
890 }
891 else
892 rc = write(srv->sock, out, n);
893 alarm(0);
894
895 if (rc < 0)
896 {
897 printf("Write error: %s\n", strerror(errno));
898 exit(75);
899 }
900 }
901 }
902 }
903
904
905
906
907 /*************************************************
908 * Main Program *
909 *************************************************/
910
911 const char * const HELP_MESSAGE = "\n\
912 Usage: client\n"
913 #ifdef HAVE_TLS
914 "\
915 [-tls-on-connect]\n\
916 [-ocsp]\n"
917 # ifdef HAVE_GNUTLS
918 "\
919 [-p priority-string]\n"
920 # endif
921 #endif
922 "\
923 [-tn] n seconds timeout\n\
924 <IP address>\n\
925 <port>\n\
926 [<outgoing interface>]\n\
927 [<cert file>]\n\
928 [<key file>]\n\
929 \n";
930
931 int
932 main(int argc, char **argv)
933 {
934 struct sockaddr *s_ptr;
935 struct sockaddr_in s_in4;
936 char *interface = NULL;
937 char *address = NULL;
938 char *certfile = NULL;
939 char *keyfile = NULL;
940 char *end = NULL;
941 int argi = 1;
942 int host_af, port, s_len, rc, save_errno;
943 int timeout = 5;
944 int tls_on_connect = 0;
945 long tmplong;
946
947 #if HAVE_IPV6
948 struct sockaddr_in6 s_in6;
949 #endif
950
951 srv_ctx srv;
952
953 unsigned char inbuffer[100 * 1024];
954 unsigned char *inptr = inbuffer;
955
956 *inptr = 0; /* Buffer empty */
957 srv.tls_active = 0;
958 srv.sent_starttls = 0;
959
960 /* Options */
961
962 while (argc >= argi + 1 && argv[argi][0] == '-')
963 {
964 if (strcmp(argv[argi], "-help") == 0 ||
965 strcmp(argv[argi], "--help") == 0 ||
966 strcmp(argv[argi], "-h") == 0)
967 {
968 puts(HELP_MESSAGE);
969 exit(0);
970 }
971 if (strcmp(argv[argi], "-tls-on-connect") == 0)
972 {
973 tls_on_connect = 1;
974 argi++;
975 }
976 #ifdef HAVE_TLS
977 else if (strcmp(argv[argi], "-ocsp") == 0)
978 {
979 if (argc < ++argi + 1)
980 {
981 fprintf(stderr, "Missing required certificate file for ocsp option\n");
982 exit(96);
983 }
984 ocsp_stapling = argv[argi++];
985 }
986 # ifdef HAVE_GNUTLS
987 else if (strcmp(argv[argi], "-p") == 0)
988 {
989 if (argc < ++argi + 1)
990 {
991 fprintf(stderr, "Missing priority string\n");
992 exit(96);
993 }
994 pri_string = argv[argi++];
995 }
996 #endif
997
998 #endif
999 else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
1000 {
1001 tmplong = strtol(argv[argi]+2, &end, 10);
1002 if (end == argv[argi]+2 || *end)
1003 {
1004 fprintf(stderr, "Failed to parse seconds from option <%s>\n",
1005 argv[argi]);
1006 exit(95);
1007 }
1008 if (tmplong > 10000L)
1009 {
1010 fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
1011 tmplong);
1012 exit(94);
1013 }
1014 if (tmplong < 0L)
1015 {
1016 fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
1017 exit(93);
1018 }
1019 timeout = (int) tmplong;
1020 argi++;
1021 }
1022 else
1023 {
1024 fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
1025 exit(92);
1026 }
1027 }
1028
1029 /* Mandatory 1st arg is IP address */
1030
1031 if (argc < argi+1)
1032 {
1033 fprintf(stderr, "No IP address given\n");
1034 exit(91);
1035 }
1036
1037 address = argv[argi++];
1038 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
1039
1040 /* Mandatory 2nd arg is port */
1041
1042 if (argc < argi+1)
1043 {
1044 fprintf(stderr, "No port number given\n");
1045 exit(90);
1046 }
1047
1048 port = atoi(argv[argi++]);
1049
1050 /* Optional next arg is interface */
1051
1052 if (argc > argi &&
1053 (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
1054 interface = argv[argi++];
1055
1056 /* Any more arguments are the name of a certificate file and key file */
1057
1058 if (argc > argi) certfile = argv[argi++];
1059 if (argc > argi) keyfile = argv[argi++];
1060
1061
1062 #if HAVE_IPV6
1063 /* For an IPv6 address, use an IPv6 sockaddr structure. */
1064
1065 if (host_af == AF_INET6)
1066 {
1067 s_ptr = (struct sockaddr *)&s_in6;
1068 s_len = sizeof(s_in6);
1069 }
1070 else
1071 #endif
1072
1073 /* For an IPv4 address, use an IPv4 sockaddr structure,
1074 even on an IPv6 system. */
1075
1076 {
1077 s_ptr = (struct sockaddr *)&s_in4;
1078 s_len = sizeof(s_in4);
1079 }
1080
1081 printf("Connecting to %s port %d ... ", address, port);
1082
1083 srv.sock = socket(host_af, SOCK_STREAM, 0);
1084 if (srv.sock < 0)
1085 {
1086 printf("socket creation failed: %s\n", strerror(errno));
1087 exit(89);
1088 }
1089
1090 /* Bind to a specific interface if requested. On an IPv6 system, this has
1091 to be of the same family as the address we are calling. On an IPv4 system the
1092 test is redundant, but it keeps the code tidier. */
1093
1094 if (interface != NULL)
1095 {
1096 int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
1097
1098 if (interface_af == host_af)
1099 {
1100 #if HAVE_IPV6
1101
1102 /* Set up for IPv6 binding */
1103
1104 if (host_af == AF_INET6)
1105 {
1106 memset(&s_in6, 0, sizeof(s_in6));
1107 s_in6.sin6_family = AF_INET6;
1108 s_in6.sin6_port = 0;
1109 if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
1110 {
1111 printf("Unable to parse \"%s\"", interface);
1112 exit(88);
1113 }
1114 }
1115 else
1116 #endif
1117
1118 /* Set up for IPv4 binding */
1119
1120 {
1121 memset(&s_in4, 0, sizeof(s_in4));
1122 s_in4.sin_family = AF_INET;
1123 s_in4.sin_port = 0;
1124 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
1125 }
1126
1127 /* Bind */
1128
1129 if (bind(srv.sock, s_ptr, s_len) < 0)
1130 {
1131 printf("Unable to bind outgoing SMTP call to %s: %s",
1132 interface, strerror(errno));
1133 exit(87);
1134 }
1135 }
1136 }
1137
1138 /* Set up a remote IPv6 address */
1139
1140 #if HAVE_IPV6
1141 if (host_af == AF_INET6)
1142 {
1143 memset(&s_in6, 0, sizeof(s_in6));
1144 s_in6.sin6_family = AF_INET6;
1145 s_in6.sin6_port = htons(port);
1146 if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
1147 {
1148 printf("Unable to parse \"%s\"", address);
1149 exit(86);
1150 }
1151 }
1152 else
1153 #endif
1154
1155 /* Set up a remote IPv4 address */
1156
1157 {
1158 memset(&s_in4, 0, sizeof(s_in4));
1159 s_in4.sin_family = AF_INET;
1160 s_in4.sin_port = htons(port);
1161 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
1162 }
1163
1164 /* SIGALRM handler crashes out */
1165
1166 signal(SIGALRM, sigalrm_handler_crash);
1167 alarm(timeout);
1168 rc = connect(srv.sock, s_ptr, s_len);
1169 save_errno = errno;
1170 alarm(0);
1171
1172 /* A failure whose error code is "Interrupted system call" is in fact
1173 an externally applied timeout if the signal handler has been run. */
1174
1175 if (rc < 0)
1176 {
1177 close(srv.sock);
1178 printf("connect failed: %s\n", strerror(save_errno));
1179 exit(85);
1180 }
1181
1182 printf("connected\n");
1183
1184
1185 /* --------------- Set up for OpenSSL --------------- */
1186
1187 #ifdef HAVE_OPENSSL
1188 SSL_library_init();
1189 SSL_load_error_strings();
1190
1191 if (!(srv.ctx = SSL_CTX_new(SSLv23_method())))
1192 {
1193 printf ("SSL_CTX_new failed\n");
1194 exit(84);
1195 }
1196
1197 if (certfile)
1198 {
1199 if (!SSL_CTX_use_certificate_file(srv.ctx, certfile, SSL_FILETYPE_PEM))
1200 {
1201 printf("SSL_CTX_use_certificate_file failed\n");
1202 exit(83);
1203 }
1204 printf("Certificate file = %s\n", certfile);
1205 }
1206
1207 if (keyfile)
1208 {
1209 if (!SSL_CTX_use_PrivateKey_file(srv.ctx, keyfile, SSL_FILETYPE_PEM))
1210 {
1211 printf("SSL_CTX_use_PrivateKey_file failed\n");
1212 exit(82);
1213 }
1214 printf("Key file = %s\n", keyfile);
1215 }
1216
1217 SSL_CTX_set_session_cache_mode(srv.ctx, SSL_SESS_CACHE_BOTH);
1218 SSL_CTX_set_timeout(srv.ctx, 200);
1219 SSL_CTX_set_info_callback(srv.ctx, (void (*)())info_callback);
1220 #endif
1221
1222
1223 /* --------------- Set up for GnuTLS --------------- */
1224
1225 #ifdef HAVE_GNUTLS
1226 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
1227 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
1228 tls_init(US certfile, US keyfile);
1229 tls_session = tls_session_init();
1230 #ifdef HAVE_OCSP
1231 if (ocsp_stapling)
1232 gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
1233 #endif
1234 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)srv.sock);
1235
1236 /* When the server asks for a certificate and the client does not have one,
1237 there is a SIGPIPE error in the gnutls_handshake() function for some reason
1238 that is not understood. As luck would have it, this has never hit Exim itself
1239 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
1240 one wants. */
1241
1242 signal(SIGPIPE, SIG_IGN);
1243 #endif
1244
1245 /* ---------------------------------------------- */
1246
1247
1248 /* Start TLS session if configured to do so without STARTTLS */
1249
1250 #ifdef HAVE_TLS
1251 if (tls_on_connect)
1252 {
1253 printf("Attempting to start TLS\n");
1254
1255 #ifdef HAVE_OPENSSL
1256 srv.tls_active = tls_start(srv.sock, &srv.ssl, srv.ctx);
1257 #endif
1258
1259 #ifdef HAVE_GNUTLS
1260 {
1261 int rc;
1262 sigalrm_seen = FALSE;
1263 alarm(timeout);
1264 do {
1265 rc = gnutls_handshake(tls_session);
1266 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
1267 srv.tls_active = rc >= 0;
1268 alarm(0);
1269
1270 if (!srv.tls_active) printf("%s\n", gnutls_strerror(rc));
1271 }
1272 #endif
1273
1274 if (!srv.tls_active)
1275 printf("Failed to start TLS\n");
1276 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
1277 else if ( ocsp_stapling
1278 && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1279 printf("Failed to verify certificate status\n");
1280 #endif
1281 else
1282 printf("Succeeded in starting TLS\n");
1283 }
1284 #endif
1285
1286 do_file(&srv, stdin, timeout, inbuffer, sizeof(inbuffer), inptr);
1287
1288 printf("End of script\n");
1289 shutdown(srv.sock, SHUT_WR);
1290 if (fcntl(srv.sock, F_SETFL, O_NONBLOCK) == 0)
1291 while (read(srv.sock, inbuffer, sizeof(inbuffer)) > 0) ;
1292 close(srv.sock);
1293
1294 exit(0);
1295 }
1296
1297 /* End of client.c */