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>
29 #include <arpa/inet.h>
31 #include <sys/resource.h>
32 #include <sys/socket.h>
43 #define S_ADDR_TYPE u_long
46 typedef unsigned char uschar;
49 #define US (unsigned char *)
56 static int sigalrm_seen = 0;
59 /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The
60 latter needs a whole pile of tables. */
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>
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"
75 # include <openssl/ocsp.h>
82 # include <gnutls/gnutls.h>
83 # include <gnutls/x509.h>
84 # if GNUTLS_VERSION_NUMBER >= 0x030103
86 # include <gnutls/ocsp.h>
88 # ifndef GNUTLS_NO_EXTENSIONS
89 # define GNUTLS_NO_EXTENSIONS 0
94 /* Local static variables for GNUTLS */
96 static gnutls_dh_params_t dh_params = NULL;
98 static gnutls_certificate_credentials_t x509_cred = NULL;
99 static gnutls_session_t tls_session = NULL;
101 static int ssl_session_timeout = 200;
103 /* Priorities for TLS algorithms to use. */
105 #if GNUTLS_VERSION_NUMBER < 0x030400
106 static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
108 static const int kx_priority[16] = {
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,
121 static const int mac_priority[16] = {
126 static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
129 #endif /*HAVE_GNUTLS*/
134 char * ocsp_stapling = NULL;
138 /*************************************************
139 * SIGALRM handler - crash out *
140 *************************************************/
143 sigalrm_handler_crash(int sig)
145 sig = sig; /* Keep picky compilers happy */
146 printf("\nClient timed out\n");
151 /*************************************************
152 * SIGALRM handler - set flag *
153 *************************************************/
156 sigalrm_handler_flag(int sig)
158 sig = sig; /* Keep picky compilers happy */
164 /****************************************************************************/
165 /****************************************************************************/
170 setup_verify(BIO *bp, char *CAfile, char *CApath)
174 if(!(store = X509_STORE_new())) goto end;
175 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
176 if (lookup == NULL) goto end;
178 if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
179 BIO_printf(bp, "Error loading file %s\n", CAfile);
182 } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
184 lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
185 if (lookup == NULL) goto end;
187 if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
188 BIO_printf(bp, "Error loading directory %s\n", CApath);
191 } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
196 X509_STORE_free(store);
202 static STACK_OF(X509) *
203 cert_stack_from_store(X509_STORE * store)
205 STACK_OF(X509_OBJECT) * roots= store->objs;
206 STACK_OF(X509) * sk = sk_X509_new_null();
209 for(i = sk_X509_OBJECT_num(roots) - 1; i >= 0; i--)
211 X509_OBJECT * tmp_obj= sk_X509_OBJECT_value(roots, i);
212 if(tmp_obj->type == X509_LU_X509)
214 X509 * x = tmp_obj->data.x509;
222 cert_stack_free(STACK_OF(X509) * sk)
224 while (sk_X509_num(sk) > 0) (void) sk_X509_pop(sk);
230 tls_client_stapling_cb(SSL *s, void *arg)
232 const unsigned char *p;
237 X509_STORE *store = NULL;
241 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
242 /*BIO_printf(arg, "OCSP response: ");*/
245 BIO_printf(arg, "no response received\n");
248 if(!(rsp = d2i_OCSP_RESPONSE(NULL, &p, len)))
250 BIO_printf(arg, "response parse error\n");
251 BIO_dump_indent(arg, (char *)p, len, 4);
254 if(!(bs = OCSP_response_get1_basic(rsp)))
256 BIO_printf(arg, "error parsing response\n");
261 CAfile = ocsp_stapling;
262 if(!(store = setup_verify(arg, CAfile, NULL)))
264 BIO_printf(arg, "error in cert setup\n");
268 sk = cert_stack_from_store(store);
270 /* OCSP_basic_verify takes a "store" arg, but does not
271 use it for the chain verification, which is all we do
272 when OCSP_NOVERIFY is set. The content from the wire
273 (in "bs") and a cert-stack "sk" are all that is used. */
275 if(OCSP_basic_verify(bs, sk, NULL, OCSP_NOVERIFY) <= 0)
277 BIO_printf(arg, "Response Verify Failure\n");
278 ERR_print_errors(arg);
282 BIO_printf(arg, "Response verify OK\n");
285 X509_STORE_free(store);
291 /*************************************************
292 * Start an OpenSSL TLS session *
293 *************************************************/
296 tls_start(int sock, SSL **ssl, SSL_CTX *ctx)
299 static const unsigned char *sid_ctx = US"exim";
301 RAND_load_file("client.c", -1); /* Not *very* random! */
303 *ssl = SSL_new (ctx);
304 SSL_set_session_id_context(*ssl, sid_ctx, strlen(CS sid_ctx));
305 SSL_set_fd (*ssl, sock);
306 SSL_set_connect_state(*ssl);
311 SSL_CTX_set_tlsext_status_cb(ctx, tls_client_stapling_cb);
312 SSL_CTX_set_tlsext_status_arg(ctx, BIO_new_fp(stdout, BIO_NOCLOSE));
313 SSL_set_tlsext_status_type(*ssl, TLSEXT_STATUSTYPE_ocsp);
317 signal(SIGALRM, sigalrm_handler_flag);
320 rc = SSL_connect (*ssl);
325 printf("SSL_connect timed out\n");
331 ERR_print_errors_fp(stdout);
335 printf("SSL connection using %s\n", SSL_get_cipher (*ssl));
340 /*************************************************
341 * SSL Information callback *
342 *************************************************/
345 info_callback(SSL *s, int where, int ret)
349 printf("SSL info: %s\n", SSL_state_string_long(s));
354 /****************************************************************************/
355 /****************************************************************************/
359 /*************************************************
360 * Handle GnuTLS error *
361 *************************************************/
363 /* Called from lots of places when errors occur before actually starting to do
364 the TLS handshake, that is, while the session is still in clear.
368 err a GnuTLS error number, or 0 if local error
370 Returns: doesn't - it dies
374 gnutls_error(uschar *prefix, int err)
376 fprintf(stderr, "GnuTLS connection error: %s:", prefix);
377 if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err));
378 fprintf(stderr, "\n");
384 /*************************************************
385 * Setup up DH parameters *
386 *************************************************/
388 /* For the test suite, the parameters should always be available in the spool
397 uschar filename[200];
400 /* Initialize the data structures for holding the parameters */
402 ret = gnutls_dh_params_init(&dh_params);
403 if (ret < 0) gnutls_error(US"init dh_params", ret);
405 /* Open the cache file for reading and if successful, read it and set up the
408 fd = open("aux-fixed/gnutls-params", O_RDONLY, 0);
411 fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno));
415 if (fstat(fd, &statbuf) < 0)
418 return gnutls_error(US"TLS cache stat failed", 0);
421 m.size = statbuf.st_size;
422 m.data = malloc(m.size);
424 return gnutls_error(US"memory allocation failed", 0);
425 if (read(fd, m.data, m.size) != m.size)
426 return gnutls_error(US"TLS cache read failed", 0);
429 ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM);
430 if (ret < 0) return gnutls_error(US"DH params import", ret);
437 /*************************************************
438 * Initialize for GnuTLS *
439 *************************************************/
443 certificate certificate file
444 privatekey private key file
448 tls_init(uschar *certificate, uschar *privatekey)
452 rc = gnutls_global_init();
453 if (rc < 0) gnutls_error(US"gnutls_global_init", rc);
455 /* Read D-H parameters from the cache file. */
459 /* Create the credentials structure */
461 rc = gnutls_certificate_allocate_credentials(&x509_cred);
462 if (rc < 0) gnutls_error(US"certificate_allocate_credentials", rc);
464 /* Set the certificate and private keys */
466 if (certificate != NULL)
468 rc = gnutls_certificate_set_x509_key_file(x509_cred, CS certificate,
469 CS privatekey, GNUTLS_X509_FMT_PEM);
470 if (rc < 0) gnutls_error("gnutls_certificate", rc);
473 /* Associate the parameters with the x509 credentials structure. */
475 gnutls_certificate_set_dh_params(x509_cred, dh_params);
477 /* set the CA info for server-cert verify */
479 gnutls_certificate_set_x509_trust_file(x509_cred, ocsp_stapling,
480 GNUTLS_X509_FMT_PEM);
485 /*************************************************
486 * Initialize a single GNUTLS session *
487 *************************************************/
489 static gnutls_session_t
490 tls_session_init(void)
492 gnutls_session_t session;
494 gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS);
496 #if GNUTLS_VERSION_NUMBER < 0x030400
497 gnutls_cipher_set_priority(session, default_cipher_priority);
498 gnutls_compression_set_priority(session, comp_priority);
499 gnutls_kx_set_priority(session, kx_priority);
500 gnutls_protocol_set_priority(session, protocol_priority);
501 gnutls_mac_set_priority(session, mac_priority);
503 gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
505 gnutls_set_default_priority(session);
506 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
509 gnutls_dh_set_prime_bits(session, DH_BITS);
510 gnutls_db_set_cache_expiration(session, ssl_session_timeout);
517 /****************************************************************************/
518 /****************************************************************************/
523 /*************************************************
525 *************************************************/
527 const char * const HELP_MESSAGE = "\n\
535 [-tn] n seconds timeout\n\
538 [<outgoing interface>]\n\
543 int main(int argc, char **argv)
545 struct sockaddr *s_ptr;
546 struct sockaddr_in s_in4;
547 char *interface = NULL;
548 char *address = NULL;
549 char *certfile = NULL;
550 char *keyfile = NULL;
553 int host_af, port, s_len, rc, sock, save_errno;
556 int sent_starttls = 0;
557 int tls_on_connect = 0;
561 struct sockaddr_in6 s_in6;
569 unsigned char outbuffer[10240];
570 unsigned char inbuffer[10240];
571 unsigned char *inptr = inbuffer;
573 *inptr = 0; /* Buffer empty */
577 while (argc >= argi + 1 && argv[argi][0] == '-')
579 if (strcmp(argv[argi], "-help") == 0 ||
580 strcmp(argv[argi], "--help") == 0 ||
581 strcmp(argv[argi], "-h") == 0)
586 if (strcmp(argv[argi], "-tls-on-connect") == 0)
592 else if (strcmp(argv[argi], "-ocsp") == 0)
594 if (argc < ++argi + 1)
596 fprintf(stderr, "Missing required certificate file for ocsp option\n");
599 ocsp_stapling = argv[argi++];
603 else if (argv[argi][1] == 't' && isdigit(argv[argi][2]))
605 tmplong = strtol(argv[argi]+2, &end, 10);
606 if (end == argv[argi]+2 || *end)
608 fprintf(stderr, "Failed to parse seconds from option <%s>\n",
612 if (tmplong > 10000L)
614 fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n",
620 fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong);
623 timeout = (int) tmplong;
628 fprintf(stderr, "Unrecognized option %s\n", argv[argi]);
633 /* Mandatory 1st arg is IP address */
637 fprintf(stderr, "No IP address given\n");
641 address = argv[argi++];
642 host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET;
644 /* Mandatory 2nd arg is port */
648 fprintf(stderr, "No port number given\n");
652 port = atoi(argv[argi++]);
654 /* Optional next arg is interface */
657 (isdigit((unsigned char)argv[argi][0]) || argv[argi][0] == ':'))
658 interface = argv[argi++];
660 /* Any more arguments are the name of a certificate file and key file */
662 if (argc > argi) certfile = argv[argi++];
663 if (argc > argi) keyfile = argv[argi++];
667 /* For an IPv6 address, use an IPv6 sockaddr structure. */
669 if (host_af == AF_INET6)
671 s_ptr = (struct sockaddr *)&s_in6;
672 s_len = sizeof(s_in6);
677 /* For an IPv4 address, use an IPv4 sockaddr structure,
678 even on an IPv6 system. */
681 s_ptr = (struct sockaddr *)&s_in4;
682 s_len = sizeof(s_in4);
685 printf("Connecting to %s port %d ... ", address, port);
687 sock = socket(host_af, SOCK_STREAM, 0);
690 printf("socket creation failed: %s\n", strerror(errno));
694 /* Bind to a specific interface if requested. On an IPv6 system, this has
695 to be of the same family as the address we are calling. On an IPv4 system the
696 test is redundant, but it keeps the code tidier. */
698 if (interface != NULL)
700 int interface_af = (strchr(interface, ':') != NULL)? AF_INET6 : AF_INET;
702 if (interface_af == host_af)
706 /* Set up for IPv6 binding */
708 if (host_af == AF_INET6)
710 memset(&s_in6, 0, sizeof(s_in6));
711 s_in6.sin6_family = AF_INET6;
713 if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1)
715 printf("Unable to parse \"%s\"", interface);
722 /* Set up for IPv4 binding */
725 memset(&s_in4, 0, sizeof(s_in4));
726 s_in4.sin_family = AF_INET;
728 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(interface);
733 if (bind(sock, s_ptr, s_len) < 0)
735 printf("Unable to bind outgoing SMTP call to %s: %s",
736 interface, strerror(errno));
742 /* Set up a remote IPv6 address */
745 if (host_af == AF_INET6)
747 memset(&s_in6, 0, sizeof(s_in6));
748 s_in6.sin6_family = AF_INET6;
749 s_in6.sin6_port = htons(port);
750 if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1)
752 printf("Unable to parse \"%s\"", address);
759 /* Set up a remote IPv4 address */
762 memset(&s_in4, 0, sizeof(s_in4));
763 s_in4.sin_family = AF_INET;
764 s_in4.sin_port = htons(port);
765 s_in4.sin_addr.s_addr = (S_ADDR_TYPE)inet_addr(address);
768 /* SIGALRM handler crashes out */
770 signal(SIGALRM, sigalrm_handler_crash);
772 rc = connect(sock, s_ptr, s_len);
776 /* A failure whose error code is "Interrupted system call" is in fact
777 an externally applied timeout if the signal handler has been run. */
782 printf("connect failed: %s\n", strerror(save_errno));
786 printf("connected\n");
789 /* --------------- Set up for OpenSSL --------------- */
793 SSL_load_error_strings();
795 ctx = SSL_CTX_new(SSLv23_method());
798 printf ("SSL_CTX_new failed\n");
802 if (certfile != NULL)
804 if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
806 printf("SSL_CTX_use_certificate_file failed\n");
809 printf("Certificate file = %s\n", certfile);
814 if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM))
816 printf("SSL_CTX_use_PrivateKey_file failed\n");
819 printf("Key file = %s\n", keyfile);
822 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);
823 SSL_CTX_set_timeout(ctx, 200);
824 SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);
828 /* --------------- Set up for GnuTLS --------------- */
831 if (certfile != NULL) printf("Certificate file = %s\n", certfile);
832 if (keyfile != NULL) printf("Key file = %s\n", keyfile);
833 tls_init(certfile, keyfile);
834 tls_session = tls_session_init();
837 gnutls_ocsp_status_request_enable_client(tls_session, NULL, 0, NULL);
839 gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr_t)(intptr_t)sock);
841 /* When the server asks for a certificate and the client does not have one,
842 there is a SIGPIPE error in the gnutls_handshake() function for some reason
843 that is not understood. As luck would have it, this has never hit Exim itself
844 because it ignores SIGPIPE errors. Doing the same here allows it all to work as
847 signal(SIGPIPE, SIG_IGN);
850 /* ---------------------------------------------- */
853 /* Start TLS session if configured to do so without STARTTLS */
858 printf("Attempting to start TLS\n");
861 tls_active = tls_start(sock, &ssl, ctx);
867 sigalrm_seen = FALSE;
870 rc = gnutls_handshake(tls_session);
871 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
872 tls_active = rc >= 0;
875 if (!tls_active) printf("%s\n", gnutls_strerror(rc));
880 printf("Failed to start TLS\n");
881 #if defined(HAVE_GNUTLS) && defined(HAVE_OCSP)
882 else if ( ocsp_stapling
883 && gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
884 printf("Failed to verify certificate status\n");
887 printf("Succeeded in starting TLS\n");
891 while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL)
893 int n = (int)strlen(CS outbuffer);
895 /* Strip trailing newline */
896 if (outbuffer[n-1] == '\n') outbuffer[--n] = 0;
898 /* Expect incoming */
900 if (strncmp(CS outbuffer, "??? ", 4) == 0)
902 unsigned char *lineptr;
903 printf("%s\n", outbuffer);
905 if (*inptr == 0) /* Refill input buffer */
910 rc = SSL_read (ssl, inbuffer, sizeof(inbuffer) - 1);
913 rc = gnutls_record_recv(tls_session, CS inbuffer, sizeof(inbuffer) - 1);
919 rc = read(sock, inbuffer, sizeof(inbuffer));
925 printf("Read error %s\n", strerror(errno));
930 printf("Unexpected EOF read\n");
942 while (*inptr != 0 && *inptr != '\r' && *inptr != '\n') inptr++;
946 if (*inptr == '\n') inptr++;
949 printf("<<< %s\n", lineptr);
950 if (strncmp(CS lineptr, CS outbuffer + 4, (int)strlen(CS outbuffer) - 4) != 0)
952 printf("\n******** Input mismatch ********\n");
959 if (lineptr[0] == '2')
964 printf("Attempting to start TLS\n");
968 tls_active = tls_start(sock, &ssl, ctx);
974 sigalrm_seen = FALSE;
977 rc = gnutls_handshake(tls_session);
978 } while (rc < 0 && gnutls_error_is_fatal(rc) == 0);
979 tls_active = rc >= 0;
982 if (!tls_active) printf("%s\n", gnutls_strerror(rc));
988 printf("Failed to start TLS\n");
992 else if (ocsp_stapling)
994 if ((rc= gnutls_certificate_verify_peers2(tls_session, &verify)) < 0)
996 printf("Failed to verify certificate: %s\n", gnutls_strerror(rc));
999 else if (verify & (GNUTLS_CERT_INVALID|GNUTLS_CERT_REVOKED))
1001 printf("Bad certificate\n");
1005 else if (gnutls_ocsp_status_request_is_checked(tls_session, 0) == 0)
1007 printf("Failed to verify certificate status\n");
1009 gnutls_datum_t stapling;
1010 gnutls_ocsp_resp_t resp;
1011 gnutls_datum_t printed;
1012 if ( (rc= gnutls_ocsp_status_request_get(tls_session, &stapling)) == 0
1013 && (rc= gnutls_ocsp_resp_init(&resp)) == 0
1014 && (rc= gnutls_ocsp_resp_import(resp, &stapling)) == 0
1015 && (rc= gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &printed)) == 0
1018 fprintf(stderr, "%.4096s", printed.data);
1019 gnutls_free(printed.data);
1022 (void) fprintf(stderr,"ocsp decode: %s", gnutls_strerror(rc));
1030 printf("Succeeded in starting TLS\n");
1032 else printf("Abandoning TLS start attempt\n");
1038 /* Wait for a bit before proceeding */
1040 else if (strncmp(CS outbuffer, "+++ ", 4) == 0)
1042 printf("%s\n", outbuffer);
1043 sleep(atoi(CS outbuffer + 4));
1046 /* Send outgoing, but barf if unconsumed incoming */
1050 unsigned char *escape;
1054 printf("Unconsumed input: %s", inptr);
1055 printf(" About to send: %s\n", outbuffer);
1063 if (strcmp(CS outbuffer, "stoptls") == 0 ||
1064 strcmp(CS outbuffer, "STOPTLS") == 0)
1068 printf("STOPTLS read when TLS not active\n");
1071 printf("Shutting down TLS encryption\n");
1079 gnutls_bye(tls_session, GNUTLS_SHUT_WR);
1080 gnutls_deinit(tls_session);
1082 gnutls_global_deinit();
1089 /* Remember that we sent STARTTLS */
1091 sent_starttls = (strcmp(CS outbuffer, "starttls") == 0 ||
1092 strcmp(CS outbuffer, "STARTTLS") == 0);
1094 /* Fudge: if the command is "starttls_wait", we send the starttls bit,
1095 but we haven't set the flag, so that there is no negotiation. This is for
1096 testing the server's timeout. */
1098 if (strcmp(CS outbuffer, "starttls_wait") == 0)
1105 printf(">>> %s\n", outbuffer);
1106 strcpy(CS outbuffer + n, "\r\n");
1108 /* Turn "\n" and "\r" into the relevant characters. This is a hack. */
1110 while ((escape = US strstr(CS outbuffer, "\\r")) != NULL)
1113 memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2);
1117 while ((escape = US strstr(CS outbuffer, "\\n")) != NULL)
1120 memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2);
1130 rc = SSL_write (ssl, outbuffer, n + 2);
1133 rc = gnutls_record_send(tls_session, CS outbuffer, n + 2);
1136 printf("GnuTLS write error: %s\n", gnutls_strerror(rc));
1143 rc = write(sock, outbuffer, n + 2);
1149 printf("Write error: %s\n", strerror(errno));
1155 printf("End of script\n");
1156 shutdown(sock, SHUT_WR);
1157 while ((rc = read(sock, inbuffer, sizeof(inbuffer))) > 0) ;
1163 /* End of client.c */