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. */
7 /* ANSI C standard includes */
22 #include <sys/types.h>
24 #include <netinet/in_systm.h>
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
27 #include <netinet/tcp.h>
30 #include <arpa/inet.h>
32 #include <sys/resource.h>
33 #include <sys/socket.h>
44 #define S_ADDR_TYPE u_long
47 typedef unsigned char uschar;
50 #define US (unsigned char *)
57 static int sigalrm_seen = 0;
60 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
61 latter needs a whole pile of tables. */
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>
71 # if OPENSSL_VERSION_NUMBER < 0x0090806fL && !defined(DISABLE_OCSP) && !defined(OPENSSL_NO_TLSEXT)
72 # warning "OpenSSL library version too old; define DISABLE_OCSP in Makefile"
76 # include <openssl/ocsp.h>
83 # include <gnutls/gnutls.h>
84 # include <gnutls/x509.h>
85 # if GNUTLS_VERSION_NUMBER >= 0x030103
87 # include <gnutls/ocsp.h>
89 # ifndef GNUTLS_NO_EXTENSIONS
90 # define GNUTLS_NO_EXTENSIONS 0
95 /* Local static variables for GNUTLS */
97 static gnutls_dh_params_t dh_params = NULL;
99 static gnutls_certificate_credentials_t x509_cred = NULL;
100 static gnutls_session_t tls_session = NULL;
102 static int ssl_session_timeout = 200;
104 /* Priorities for TLS algorithms to use. */
106 #if GNUTLS_VERSION_NUMBER < 0x030400
107 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
109 static const int kx_priority[16] = {
115 static int default_cipher_priority[16] = {
116 GNUTLS_CIPHER_AES_256_CBC,
117 GNUTLS_CIPHER_AES_128_CBC,
118 GNUTLS_CIPHER_3DES_CBC,
119 GNUTLS_CIPHER_ARCFOUR_128,
122 static const int mac_priority[16] = {
127 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
130 #endif /*HAVE_GNUTLS*/
135 char * ocsp_stapling = NULL;
139 /*************************************************
140 * SIGALRM handler - crash out *
141 *************************************************/
144 sigalrm_handler_crash(int sig)
146 sig = sig; /* Keep picky compilers happy */
147 printf("\nClient timed out\n");
152 /*************************************************
153 * SIGALRM handler - set flag *
154 *************************************************/
157 sigalrm_handler_flag(int sig)
159 sig = sig; /* Keep picky compilers happy */
165 /****************************************************************************/
166 /****************************************************************************/
171 setup_verify(BIO *bp, char *CAfile, char *CApath)
175 if(!(store = X509_STORE_new())) goto end;
176 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
177 if (lookup == NULL) goto end;
179 if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
180 BIO_printf(bp, "Error loading file %s\n", CAfile);
183 } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
185 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
186 if (lookup == NULL) goto end;
188 if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
189 BIO_printf(bp, "Error loading directory %s\n", CApath);
192 } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
197 X509_STORE_free(store);
203 static STACK_OF(X509) *
204 cert_stack_from_store(X509_STORE * store)
206 STACK_OF(X509_OBJECT) * roots= store->objs;
207 STACK_OF(X509) * sk = sk_X509_new_null();
210 for(i = sk_X509_OBJECT_num(roots) - 1; i >= 0; i--)
212 X509_OBJECT * tmp_obj= sk_X509_OBJECT_value(roots, i);
213 if(tmp_obj->type == X509_LU_X509)
215 X509 * x = tmp_obj->data.x509;
223 cert_stack_free(STACK_OF(X509) * sk)
225 while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
231 tls_client_stapling_cb(SSL *s, void *arg)
233 const unsigned char *p;
238 X509_STORE *store = NULL;
242 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
243 /*BIO_printf(arg, "OCSP response: ");*/
246 BIO_printf(arg, "no response received\n");
249 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
251 BIO_printf(arg, "response parse error\n");
252 BIO_dump_indent(arg, (char *)p, len, 4);
255 if(!(bs = OCSP_response_get1_basic(rsp)))
257 BIO_printf(arg, "error parsing response\n");
262 CAfile = ocsp_stapling;
263 if(!(store = setup_verify(arg, CAfile, NULL)))
265 BIO_printf(arg, "error in cert setup\n");
269 sk = cert_stack_from_store(store);
271 /* OCSP_basic_verify takes a "store" arg, but does not
272 use it for the chain verification, which is all we do
273 when OCSP_NOVERIFY is set. The content from the wire
274 (in "bs") and a cert-stack "sk" are all that is used. */
276 if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
278 BIO_printf(arg, "Response Verify Failure\n");
279 ERR_print_errors(arg);
283 BIO_printf(arg, "Response verify OK\n");
286 X509_STORE_free(store);
292 /*************************************************
293 * Start an OpenSSL TLS session *
294 *************************************************/
297 tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
300 static const unsigned char *sid_ctx = US"exim";
302 RAND_load_file("client.c", -1); /* Not *very* random! */
304 *ssl = SSL_new (ctx);
305 SSL_set_session_id_context(*ssl, sid_ctx, strlen(CS sid_ctx));
306 SSL_set_fd (*ssl, sock);
307 SSL_set_connect_state(*ssl);
312 SSL_CTX_set_tlsext_status_cb(ctx, tls_client_stapling_cb);
313 SSL_CTX_set_tlsext_status_arg(ctx, BIO_new_fp(stdout, BIO_NOCLOSE));
314 SSL_set_tlsext_status_type(*ssl, TLSEXT_STATUSTYPE_ocsp);
318 signal(SIGALRM, sigalrm_handler_flag);
321 rc = SSL_connect (*ssl);
326 printf("SSL_connect timed out\n");
332 ERR_print_errors_fp(stdout);
336 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
341 /*************************************************
342 * SSL Information callback *
343 *************************************************/
346 info_callback(SSL *s, int where, int ret)
350 printf("SSL info: %s\n", SSL_state_string_long(s));
355 /****************************************************************************/
356 /****************************************************************************/
360 /*************************************************
361 * Handle GnuTLS error *
362 *************************************************/
364 /* Called from lots of places when errors occur before actually starting to do
365 the TLS handshake, that is, while the session is still in clear.
369 err a GnuTLS error number, or 0 if local error
371 Returns: doesn't - it dies
375 gnutls_error(uschar *prefix, int err)
377 fprintf(stderr, "GnuTLS connection error: %s:", prefix);
378 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
379 fprintf(stderr, "\n");
385 /*************************************************
386 * Setup up DH parameters *
387 *************************************************/
389 /* For the test suite, the parameters should always be available in the spool
398 uschar filename[200];
401 /* Initialize the data structures for holding the parameters */
403 ret = gnutls_dh_params_init(&dh_params);
404 if (ret < 0) gnutls_error(US"init dh_params", ret);
406 /* Open the cache file for reading and if successful, read it and set up the
409 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
412 fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
416 if (fstat(fd, &statbuf) < 0)
419 return gnutls_error(US"TLS cache stat failed", 0);
422 m.size = statbuf.st_size;
423 m.data = malloc(m.size);
425 return gnutls_error(US"memory allocation failed", 0);
426 if (read(fd, m.data, m.size) != m.size)
427 return gnutls_error(US"TLS cache read failed", 0);
430 ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
431 if (ret < 0) return gnutls_error(US"DH params import", ret);
438 /*************************************************
439 * Initialize for GnuTLS *
440 *************************************************/
444 certificate certificate file
445 privatekey private key file
449 tls_init(uschar *certificate, uschar *privatekey)
453 rc = gnutls_global_init();
454 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
456 /* Read D-H parameters from the cache file. */
460 /* Create the credentials structure */
462 rc = gnutls_certificate_allocate_credentials(&x509_cred);
463 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
465 /* Set the certificate and private keys */
467 if (certificate != NULL)
469 rc = gnutls_certificate_set_x509_key_file(x509_cred, CS certificate,
470 CS privatekey, GNUTLS_X509_FMT_PEM);
471 if (rc < 0) gnutls_error("gnutls_certificate", rc);
474 /* Associate the parameters with the x509 credentials structure. */
476 gnutls_certificate_set_dh_params(x509_cred, dh_params);
478 /* set the CA info for server-cert verify */
480 gnutls_certificate_set_x509_trust_file(x509_cred, ocsp_stapling,
481 GNUTLS_X509_FMT_PEM);
486 /*************************************************
487 * Initialize a single GNUTLS session *
488 *************************************************/
490 static gnutls_session_t
491 tls_session_init(void)
493 gnutls_session_t session;
495 gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);
497 #if GNUTLS_VERSION_NUMBER < 0x030400
498 gnutls_cipher_set_priority(session, default_cipher_priority);
499 gnutls_compression_set_priority(session, comp_priority);
500 gnutls_kx_set_priority(session, kx_priority);
501 gnutls_protocol_set_priority(session, protocol_priority);
502 gnutls_mac_set_priority(session, mac_priority);
504 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
506 gnutls_set_default_priority(session);
507 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
510 gnutls_dh_set_prime_bits(session, DH_BITS);
511 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
518 /****************************************************************************/
519 /****************************************************************************/
524 /*************************************************
526 *************************************************/
528 const char * const HELP_MESSAGE = "\n\
536 [-tn] n seconds timeout\n\
539 [<outgoing interface>]\n\
544 int main(int argc, char **argv)
546 struct sockaddr *s_ptr;
547 struct sockaddr_in s_in4;
548 char *interface = NULL;
549 char *address = NULL;
550 char *certfile = NULL;
551 char *keyfile = NULL;
554 int host_af, port, s_len, rc, sock, save_errno;
557 int sent_starttls = 0;
558 int tls_on_connect = 0;
562 struct sockaddr_in6 s_in6;
570 unsigned char outbuffer[10240];
571 unsigned char inbuffer[10240];
572 unsigned char *inptr = inbuffer;
574 *inptr = 0; /* Buffer empty */
578 while (argc >= argi + 1 && argv[argi][0] == '-')
580 if (strcmp(argv[argi], "-help") == 0 ||
581 strcmp(argv[argi], "--help") == 0 ||
582 strcmp(argv[argi], "-h") == 0)
587 if (strcmp(argv[argi], "-tls-on-connect") == 0)
593 else if (strcmp(argv[argi], "-ocsp") == 0)
595 if (argc < ++argi + 1)
597 fprintf(stderr, "Missing required certificate file for ocsp option\n");
600 ocsp_stapling = argv[argi++];
604 else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
606 tmplong = strtol(argv[argi]+2, &end, 10);
607 if (end == argv[argi]+2 || *end)
609 fprintf(stderr, "Failed to parse seconds from option <%s>\n",
613 if (tmplong > 10000L)
615 fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
621 fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
624 timeout = (int) tmplong;
629 fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
634 /* Mandatory 1st arg is IP address */
638 fprintf(stderr, "No IP address given\n");
642 address = argv[argi++];
643 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
645 /* Mandatory 2nd arg is port */
649 fprintf(stderr, "No port number given\n");
653 port = atoi(argv[argi++]);
655 /* Optional next arg is interface */
658 (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
659 interface = argv[argi++];
661 /* Any more arguments are the name of a certificate file and key file */
663 if (argc > argi) certfile = argv[argi++];
664 if (argc > argi) keyfile = argv[argi++];
668 /* For an IPv6 address, use an IPv6 sockaddr structure. */
670 if (host_af == AF_INET6)
672 s_ptr = (struct sockaddr *)&s_in6;
673 s_len = sizeof(s_in6);
678 /* For an IPv4 address, use an IPv4 sockaddr structure,
679 even on an IPv6 system. */
682 s_ptr = (struct sockaddr *)&s_in4;
683 s_len = sizeof(s_in4);
686 printf("Connecting to %s port %d ... ", address, port);
688 sock = socket(host_af, SOCK_STREAM, 0);
691 printf("socket creation failed: %s\n", strerror(errno));
695 /* Bind to a specific interface if requested. On an IPv6 system, this has
696 to be of the same family as the address we are calling. On an IPv4 system the
697 test is redundant, but it keeps the code tidier. */
699 if (interface != NULL)
701 int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
703 if (interface_af == host_af)
707 /* Set up for IPv6 binding */
709 if (host_af == AF_INET6)
711 memset(&s_in6, 0, sizeof(s_in6));
712 s_in6.sin6_family = AF_INET6;
714 if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
716 printf("Unable to parse \"%s\"", interface);
723 /* Set up for IPv4 binding */
726 memset(&s_in4, 0, sizeof(s_in4));
727 s_in4.sin_family = AF_INET;
729 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
734 if (bind(sock, s_ptr, s_len) < 0)
736 printf("Unable to bind outgoing SMTP call to %s: %s",
737 interface, strerror(errno));
743 /* Set up a remote IPv6 address */
746 if (host_af == AF_INET6)
748 memset(&s_in6, 0, sizeof(s_in6));
749 s_in6.sin6_family = AF_INET6;
750 s_in6.sin6_port = htons(port);
751 if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
753 printf("Unable to parse \"%s\"", address);
760 /* Set up a remote IPv4 address */
763 memset(&s_in4, 0, sizeof(s_in4));
764 s_in4.sin_family = AF_INET;
765 s_in4.sin_port = htons(port);
766 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
769 /* SIGALRM handler crashes out */
771 signal(SIGALRM, sigalrm_handler_crash);
773 rc = connect(sock, s_ptr, s_len);
777 /* A failure whose error code is "Interrupted system call" is in fact
778 an externally applied timeout if the signal handler has been run. */
783 printf("connect failed: %s\n", strerror(save_errno));
787 printf("connected\n");
790 /* --------------- Set up for OpenSSL --------------- */
794 SSL_load_error_strings();
796 ctx = SSL_CTX_new(SSLv23_method());
799 printf ("SSL_CTX_new failed\n");
803 if (certfile != NULL)
805 if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
807 printf("SSL_CTX_use_certificate_file failed\n");
810 printf("Certificate file = %s\n", certfile);
815 if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
817 printf("SSL_CTX_use_PrivateKey_file failed\n");
820 printf("Key file = %s\n", keyfile);
823 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
824 SSL_CTX_set_timeout(ctx, 200);
825 SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
829 /* --------------- Set up for GnuTLS --------------- */
832 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
833 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
834 tls_init(certfile, keyfile);
835 tls_session = tls_session_init();
838 gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
840 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)sock);
842 /* When the server asks for a certificate and the client does not have one,
843 there is a SIGPIPE error in the gnutls_handshake() function for some reason
844 that is not understood. As luck would have it, this has never hit Exim itself
845 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
848 signal(SIGPIPE, SIG_IGN);
851 /* ---------------------------------------------- */
854 /* Start TLS session if configured to do so without STARTTLS */
859 printf("Attempting to start TLS\n");
862 tls_active = tls_start(sock, &ssl, ctx);
868 sigalrm_seen = FALSE;
871 rc = gnutls_handshake(tls_session);
872 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
873 tls_active = rc >= 0;
876 if (!tls_active) printf("%s\n", gnutls_strerror(rc));
881 printf("Failed to start TLS\n");
882 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
883 else if ( ocsp_stapling
884 && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
885 printf("Failed to verify certificate status\n");
888 printf("Succeeded in starting TLS\n");
892 while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL)
894 int n = (int)strlen(CS outbuffer);
896 /* Strip trailing newline */
897 if (outbuffer[n-1] == '\n') outbuffer[--n] = 0;
899 /* Expect incoming */
901 if ( strncmp(CS outbuffer, "???", 3) == 0
902 && (outbuffer[3] == ' ' || outbuffer[3] == '*')
905 unsigned char *lineptr;
906 unsigned exp_eof = outbuffer[3] == '*';
908 printf("%s\n", outbuffer);
910 if (*inptr == 0) /* Refill input buffer */
915 rc = SSL_read (ssl, inbuffer, sizeof(inbuffer) - 1);
918 rc = gnutls_record_recv(tls_session, CS inbuffer, sizeof(inbuffer) - 1);
924 rc = read(sock, inbuffer, sizeof(inbuffer));
930 printf("Read error %s\n", strerror(errno));
936 printf("Expected EOF read\n");
941 printf("Enexpected EOF read\n");
947 printf("Expected EOF not read\n");
959 while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
963 if (*inptr == '\n') inptr++;
966 printf("<<< %s\n", lineptr);
967 if (strncmp(CS lineptr, CS outbuffer + 4, (int)strlen(CS outbuffer) - 4) != 0)
969 printf("\n******** Input mismatch ********\n");
976 if (lineptr[0] == '2')
981 printf("Attempting to start TLS\n");
985 tls_active = tls_start(sock, &ssl, ctx);
991 sigalrm_seen = FALSE;
994 rc = gnutls_handshake(tls_session);
995 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
996 tls_active = rc >= 0;
999 if (!tls_active) printf("%s\n", gnutls_strerror(rc));
1005 printf("Failed to start TLS\n");
1009 else if (ocsp_stapling)
1011 if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
1013 printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
1016 else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
1018 printf("Bad certificate\n");
1022 else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1024 printf("Failed to verify certificate status\n");
1026 gnutls_datum_t stapling;
1027 gnutls_ocsp_resp_t resp;
1028 gnutls_datum_t printed;
1029 if ( (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
1030 && (rc= gnutls_ocsp_resp_init(&resp)) == 0
1031 && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
1032 && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
1035 fprintf(stderr, "%.4096s", printed.data);
1036 gnutls_free(printed.data);
1039 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
1047 printf("Succeeded in starting TLS\n");
1049 else printf("Abandoning TLS start attempt\n");
1055 /* Wait for a bit before proceeding */
1057 else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
1059 printf("%s\n", outbuffer);
1060 sleep(atoi(CS outbuffer + 4));
1063 /* Send outgoing, but barf if unconsumed incoming */
1067 unsigned char *escape;
1071 printf("Unconsumed input: %s", inptr);
1072 printf(" About to send: %s\n", outbuffer);
1080 if (strcmp(CS outbuffer, "stoptls") == 0 ||
1081 strcmp(CS outbuffer, "STOPTLS") == 0)
1085 printf("STOPTLS read when TLS not active\n");
1088 printf("Shutting down TLS encryption\n");
1096 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1097 gnutls_deinit(tls_session);
1099 gnutls_global_deinit();
1106 /* Remember that we sent STARTTLS */
1108 sent_starttls = (strcmp(CS outbuffer, "starttls") == 0 ||
1109 strcmp(CS outbuffer, "STARTTLS") == 0);
1111 /* Fudge: if the command is "starttls_wait", we send the starttls bit,
1112 but we haven't set the flag, so that there is no negotiation. This is for
1113 testing the server's timeout. */
1115 if (strcmp(CS outbuffer, "starttls_wait") == 0)
1122 printf(">>> %s\n", outbuffer);
1123 strcpy(CS outbuffer + n, "\r\n");
1125 /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
1127 while ((escape = US strstr(CS outbuffer, "\\r")) != NULL)
1130 memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2);
1134 while ((escape = US strstr(CS outbuffer, "\\n")) != NULL)
1137 memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2);
1147 rc = SSL_write (ssl, outbuffer, n + 2);
1150 rc = gnutls_record_send(tls_session, CS outbuffer, n + 2);
1153 printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
1160 rc = write(sock, outbuffer, n + 2);
1166 printf("Write error: %s\n", strerror(errno));
1172 printf("End of script\n");
1173 shutdown(sock, SHUT_WR);
1174 while ((rc = read(sock, inbuffer, sizeof(inbuffer))) > 0) ;
1180 /* End of client.c */