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