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