X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/348051adc5ea922f4e82d971d44f03e87557b6ec..f64fbe039033d51be277431ce09fabd3ebbc7e74:/test/src/client.c diff --git a/test/src/client.c b/test/src/client.c index e7210f223..ee00912bc 100644 --- a/test/src/client.c +++ b/test/src/client.c @@ -58,7 +58,6 @@ static int sigalrm_seen = 0; /* TLS support can be optionally included, either for OpenSSL or GnuTLS. The latter needs a whole pile of tables. */ - #ifdef HAVE_OPENSSL # define HAVE_TLS # include @@ -67,7 +66,14 @@ latter needs a whole pile of tables. */ # include # include # include -# include + +# if OPENSSL_VERSION_NUMBER < 0x0090806fL && !defined(DISABLE_OCSP) && !defined(OPENSSL_NO_TLSEXT) +# warning "OpenSSL library version too old; define DISABLE_OCSP in Makefile" +# define DISABLE_OCSP +# endif +# ifndef DISABLE_OCSP +# include +# endif #endif @@ -79,6 +85,9 @@ latter needs a whole pile of tables. */ # define HAVE_OCSP # include # endif +# ifndef GNUTLS_NO_EXTENSIONS +# define GNUTLS_NO_EXTENSIONS 0 +# endif # define DH_BITS 768 @@ -188,6 +197,7 @@ setup_verify(BIO *bp, char *CAfile, char *CApath) } +#ifndef DISABLE_OCSP static int tls_client_stapling_cb(SSL *s, void *arg) { @@ -238,6 +248,7 @@ else X509_STORE_free(store); return ret; } +#endif /************************************************* @@ -248,21 +259,23 @@ int tls_start(int sock, SSL **ssl, SSL_CTX *ctx) { int rc; -static const char *sid_ctx = "exim"; +static const unsigned char *sid_ctx = US"exim"; RAND_load_file("client.c", -1); /* Not *very* random! */ *ssl = SSL_new (ctx); -SSL_set_session_id_context(*ssl, sid_ctx, strlen(sid_ctx)); +SSL_set_session_id_context(*ssl, sid_ctx, strlen(CS sid_ctx)); SSL_set_fd (*ssl, sock); SSL_set_connect_state(*ssl); +#ifndef DISABLE_OCSP if (ocsp_stapling) { SSL_CTX_set_tlsext_status_cb(ctx, tls_client_stapling_cb); SSL_CTX_set_tlsext_status_arg(ctx, BIO_new_fp(stdout, BIO_NOCLOSE)); SSL_set_tlsext_status_type(*ssl, TLSEXT_STATUSTYPE_ocsp); } +#endif signal(SIGALRM, sigalrm_handler_flag); sigalrm_seen = 0; @@ -326,7 +339,7 @@ gnutls_error(uschar *prefix, int err) fprintf(stderr, "GnuTLS connection error: %s:", prefix); if (err != 0) fprintf(stderr, " %s", gnutls_strerror(err)); fprintf(stderr, "\n"); -exit(1); +exit(98); } @@ -359,7 +372,7 @@ fd = open("aux-fixed/gnutls-params", O_RDONLY, 0); if (fd < 0) { fprintf(stderr, "Failed to open spool/gnutls-params: %s\n", strerror(errno)); - exit(1); + exit(97); } if (fstat(fd, &statbuf) < 0) @@ -441,7 +454,7 @@ tls_session_init(void) { gnutls_session session; -gnutls_init(&session, GNUTLS_CLIENT); +gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_NO_EXTENSIONS); gnutls_cipher_set_priority(session, default_cipher_priority); gnutls_compression_set_priority(session, comp_priority); @@ -470,7 +483,14 @@ return session; *************************************************/ const char * const HELP_MESSAGE = "\n\ -Usage: client\n\ +Usage: client\n" +#ifdef HAVE_TLS +"\ + [-tls-on-connect]\n\ + [-ocsp]\n" +#endif +"\ + [-tn] n seconds timeout\n\ \n\ \n\ []\n\ @@ -489,7 +509,7 @@ char *keyfile = NULL; char *end = NULL; int argi = 1; int host_af, port, s_len, rc, sock, save_errno; -int timeout = 1; +int timeout = 5; int tls_active = 0; int sent_starttls = 0; int tls_on_connect = 0; @@ -518,7 +538,7 @@ while (argc >= argi + 1 && argv[argi][0] == '-') strcmp(argv[argi], "--help") == 0 || strcmp(argv[argi], "-h") == 0) { - printf(HELP_MESSAGE); + puts(HELP_MESSAGE); exit(0); } if (strcmp(argv[argi], "-tls-on-connect") == 0) @@ -532,7 +552,7 @@ while (argc >= argi + 1 && argv[argi][0] == '-') if (argc < ++argi + 1) { fprintf(stderr, "Missing required certificate file for ocsp option\n"); - exit(1); + exit(96); } ocsp_stapling = argv[argi++]; } @@ -545,18 +565,18 @@ while (argc >= argi + 1 && argv[argi][0] == '-') { fprintf(stderr, "Failed to parse seconds from option <%s>\n", argv[argi]); - exit(1); + exit(95); } if (tmplong > 10000L) { - fprintf(stderr, "Unreasonably long wait of %d seconds requested\n", + fprintf(stderr, "Unreasonably long wait of %ld seconds requested\n", tmplong); - exit(1); + exit(94); } if (tmplong < 0L) { - fprintf(stderr, "Timeout must not be negative (%d)\n", tmplong); - exit(1); + fprintf(stderr, "Timeout must not be negative (%ld)\n", tmplong); + exit(93); } timeout = (int) tmplong; argi++; @@ -564,7 +584,7 @@ while (argc >= argi + 1 && argv[argi][0] == '-') else { fprintf(stderr, "Unrecognized option %s\n", argv[argi]); - exit(1); + exit(92); } } @@ -573,7 +593,7 @@ while (argc >= argi + 1 && argv[argi][0] == '-') if (argc < argi+1) { fprintf(stderr, "No IP address given\n"); - exit(1); + exit(91); } address = argv[argi++]; @@ -584,7 +604,7 @@ host_af = (strchr(address, ':') != NULL)? AF_INET6 : AF_INET; if (argc < argi+1) { fprintf(stderr, "No port number given\n"); - exit(1); + exit(90); } port = atoi(argv[argi++]); @@ -626,7 +646,7 @@ sock = socket(host_af, SOCK_STREAM, 0); if (sock < 0) { printf("socket creation failed: %s\n", strerror(errno)); - exit(1); + exit(89); } /* Bind to a specific interface if requested. On an IPv6 system, this has @@ -651,7 +671,7 @@ if (interface != NULL) if (inet_pton(AF_INET6, interface, &s_in6.sin6_addr) != 1) { printf("Unable to parse \"%s\"", interface); - exit(1); + exit(88); } } else @@ -672,7 +692,7 @@ if (interface != NULL) { printf("Unable to bind outgoing SMTP call to %s: %s", interface, strerror(errno)); - exit(1); + exit(87); } } } @@ -688,7 +708,7 @@ if (host_af == AF_INET6) if (inet_pton(host_af, address, &s_in6.sin6_addr) != 1) { printf("Unable to parse \"%s\"", address); - exit(1); + exit(86); } } else @@ -717,8 +737,8 @@ an externally applied timeout if the signal handler has been run. */ if (rc < 0) { close(sock); - printf("failed: %s\n", strerror(save_errno)); - exit(1); + printf("connect failed: %s\n", strerror(save_errno)); + exit(85); } printf("connected\n"); @@ -734,7 +754,7 @@ ctx = SSL_CTX_new(SSLv23_method()); if (ctx == NULL) { printf ("SSL_CTX_new failed\n"); - exit(1); + exit(84); } if (certfile != NULL) @@ -742,7 +762,7 @@ if (certfile != NULL) if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) { printf("SSL_CTX_use_certificate_file failed\n"); - exit(1); + exit(83); } printf("Certificate file = %s\n", certfile); } @@ -752,7 +772,7 @@ if (keyfile != NULL) if (!SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)) { printf("SSL_CTX_use_PrivateKey_file failed\n"); - exit(1); + exit(82); } printf("Key file = %s\n", keyfile); } @@ -818,15 +838,15 @@ if (tls_on_connect) } #endif -while (fgets(outbuffer, sizeof(outbuffer), stdin) != NULL) +while (fgets(CS outbuffer, sizeof(outbuffer), stdin) != NULL) { - int n = (int)strlen(outbuffer); + int n = (int)strlen(CS outbuffer); while (n > 0 && isspace(outbuffer[n-1])) n--; outbuffer[n] = 0; /* Expect incoming */ - if (strncmp(outbuffer, "??? ", 4) == 0) + if (strncmp(CS outbuffer, "??? ", 4) == 0) { unsigned char *lineptr; printf("%s\n", outbuffer); @@ -852,13 +872,13 @@ while (fgets(outbuffer, sizeof(outbuffer), stdin) != NULL) if (rc < 0) { printf("Read error %s\n", strerror(errno)); - exit(1) ; + exit(81) ; } else if (rc == 0) { printf("Unexpected EOF read\n"); close(sock); - exit(1); + exit(80); } else { @@ -876,10 +896,10 @@ while (fgets(outbuffer, sizeof(outbuffer), stdin) != NULL) } printf("<<< %s\n", lineptr); - if (strncmp(lineptr, outbuffer + 4, (int)strlen(outbuffer) - 4) != 0) + if (strncmp(CS lineptr, CS outbuffer + 4, (int)strlen(CS outbuffer) - 4) != 0) { printf("\n******** Input mismatch ********\n"); - exit(1); + exit(79); } #ifdef HAVE_TLS @@ -958,10 +978,10 @@ int rc; /* Wait for a bit before proceeding */ - else if (strncmp(outbuffer, "+++ ", 4) == 0) + else if (strncmp(CS outbuffer, "+++ ", 4) == 0) { printf("%s\n", outbuffer); - sleep(atoi(outbuffer + 4)); + sleep(atoi(CS outbuffer + 4)); } /* Send outgoing, but barf if unconsumed incoming */ @@ -974,20 +994,20 @@ int rc; { printf("Unconsumed input: %s", inptr); printf(" About to send: %s\n", outbuffer); - exit(1); + exit(78); } #ifdef HAVE_TLS /* Shutdown TLS */ - if (strcmp(outbuffer, "stoptls") == 0 || - strcmp(outbuffer, "STOPTLS") == 0) + if (strcmp(CS outbuffer, "stoptls") == 0 || + strcmp(CS outbuffer, "STOPTLS") == 0) { if (!tls_active) { printf("STOPTLS read when TLS not active\n"); - exit(1); + exit(77); } printf("Shutting down TLS encryption\n"); @@ -1009,14 +1029,14 @@ int rc; /* Remember that we sent STARTTLS */ - sent_starttls = (strcmp(outbuffer, "starttls") == 0 || - strcmp(outbuffer, "STARTTLS") == 0); + sent_starttls = (strcmp(CS outbuffer, "starttls") == 0 || + strcmp(CS outbuffer, "STARTTLS") == 0); /* Fudge: if the command is "starttls_wait", we send the starttls bit, but we haven't set the flag, so that there is no negotiation. This is for testing the server's timeout. */ - if (strcmp(outbuffer, "starttls_wait") == 0) + if (strcmp(CS outbuffer, "starttls_wait") == 0) { outbuffer[8] = 0; n = 8; @@ -1024,18 +1044,18 @@ int rc; #endif printf(">>> %s\n", outbuffer); - strcpy(outbuffer + n, "\r\n"); + strcpy(CS outbuffer + n, "\r\n"); /* Turn "\n" and "\r" into the relevant characters. This is a hack. */ - while ((escape = strstr(outbuffer, "\\r")) != NULL) + while ((escape = US strstr(CS outbuffer, "\\r")) != NULL) { *escape = '\r'; memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2); n--; } - while ((escape = strstr(outbuffer, "\\n")) != NULL) + while ((escape = US strstr(CS outbuffer, "\\n")) != NULL) { *escape = '\n'; memmove(escape + 1, escape + 2, (n + 2) - (escape - outbuffer) - 2); @@ -1055,7 +1075,7 @@ int rc; if (rc < 0) { printf("GnuTLS write error: %s\n", gnutls_strerror(rc)); - exit(1); + exit(76); } #endif } @@ -1068,7 +1088,7 @@ int rc; if (rc < 0) { printf("Write error: %s\n", strerror(errno)); - exit(1); + exit(75); } } }