VMS static libraries have the extension .OLB, not .LIB
[openssl.git] / test / ssltest.c
index d6b6618cbd73335d8735355de93b9f7a433f43c7..b5d44a0c0fe5db1b4aa9515d863fca9cd113123d 100644 (file)
@@ -1,4 +1,3 @@
-/* ssl/ssltest.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -733,6 +732,8 @@ static int debug = 0;
 static const char rnd_seed[] =
     "string to make the random number generator think it has entropy";
 
+int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family,
+                   long bytes, clock_t *s_time, clock_t *c_time);
 int doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time,
                  clock_t *c_time);
 int doit(SSL *s_ssl, SSL *c_ssl, long bytes);
@@ -776,14 +777,20 @@ static void sv_usage(void)
     fprintf(stderr, " -srpuser user  - SRP username to use\n");
     fprintf(stderr, " -srppass arg   - password for 'user'\n");
 #endif
-#ifndef OPENSSL_NO_SSL3_METHOD
+#ifndef OPENSSL_NO_SSL3
     fprintf(stderr, " -ssl3         - use SSLv3\n");
 #endif
+#ifndef OPENSSL_NO_TLS1
     fprintf(stderr, " -tls1         - use TLSv1\n");
+#endif
 #ifndef OPENSSL_NO_DTLS
     fprintf(stderr, " -dtls        - use DTLS\n");
+#ifndef OPENSSL_NO_DTLS1
     fprintf(stderr, " -dtls1        - use DTLSv1\n");
+#endif
+#ifndef OPENSSL_NO_DTLS1_2
     fprintf(stderr, " -dtls12       - use DTLSv1.2\n");
+#endif
 #endif
     fprintf(stderr, " -CApath arg   - PEM format directory of CA's\n");
     fprintf(stderr, " -CAfile arg   - PEM format file of CA's\n");
@@ -795,6 +802,8 @@ static void sv_usage(void)
             " -c_key arg    - Client key file (default: same as -c_cert)\n");
     fprintf(stderr, " -cipher arg   - The cipher list\n");
     fprintf(stderr, " -bio_pair     - Use BIO pairs\n");
+    fprintf(stderr, " -ipv4         - Use IPv4 connection on localhost\n");
+    fprintf(stderr, " -ipv6         - Use IPv6 connection on localhost\n");
     fprintf(stderr, " -f            - Test even cases that can't work\n");
     fprintf(stderr,
             " -time         - measure processor time used by client and server\n");
@@ -1002,7 +1011,7 @@ int main(int argc, char *argv[])
 {
     char *CApath = NULL, *CAfile = NULL;
     int badop = 0;
-    int bio_pair = 0;
+    enum { BIO_MEM, BIO_PAIR, BIO_IPV4, BIO_IPV6 } bio_type = BIO_MEM;
     int force = 0;
     int dtls1 = 0, dtls12 = 0, dtls = 0, tls1 = 0, ssl3 = 0, ret = 1;
     int client_auth = 0;
@@ -1046,7 +1055,7 @@ int main(int argc, char *argv[])
 #ifdef OPENSSL_FIPS
     int fips_mode = 0;
 #endif
-    int no_protocol = 0;
+    int no_protocol;
 
     SSL_CONF_CTX *s_cctx = NULL, *c_cctx = NULL;
     STACK_OF(OPENSSL_STRING) *conf_args = NULL;
@@ -1173,24 +1182,12 @@ int main(int argc, char *argv[])
         else if (strcmp(*argv, "-tls1") == 0) {
             tls1 = 1;
         } else if (strcmp(*argv, "-ssl3") == 0) {
-#ifdef OPENSSL_NO_SSL3_METHOD
-            no_protocol = 1;
-#endif
             ssl3 = 1;
         } else if (strcmp(*argv, "-dtls1") == 0) {
-#ifdef OPENSSL_NO_DTLS
-            no_protocol = 1;
-#endif
             dtls1 = 1;
         } else if (strcmp(*argv, "-dtls12") == 0) {
-#ifdef OPENSSL_NO_DTLS
-            no_protocol = 1;
-#endif
             dtls12 = 1;
         } else if (strcmp(*argv, "-dtls") == 0) {
-#ifdef OPENSSL_NO_DTLS
-            no_protocol = 1;
-#endif
             dtls = 1;
         } else if (strncmp(*argv, "-num", 4) == 0) {
             if (--argc < 1)
@@ -1222,7 +1219,11 @@ int main(int argc, char *argv[])
                 goto bad;
             CAfile = *(++argv);
         } else if (strcmp(*argv, "-bio_pair") == 0) {
-            bio_pair = 1;
+            bio_type = BIO_PAIR;
+        } else if (strcmp(*argv, "-ipv4") == 0) {
+            bio_type = BIO_IPV4;
+        } else if (strcmp(*argv, "-ipv6") == 0) {
+            bio_type = BIO_IPV6;
         } else if (strcmp(*argv, "-f") == 0) {
             force = 1;
         } else if (strcmp(*argv, "-time") == 0) {
@@ -1365,6 +1366,28 @@ int main(int argc, char *argv[])
         EXIT(1);
     }
 
+#ifdef OPENSSL_NO_SSL3
+    if (ssl3)
+        no_protocol = 1;
+    else
+#endif
+#ifdef OPENSSL_NO_TLS1
+    if (tls1)
+        no_protocol = 1;
+    else
+#endif
+#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1)
+    if (dtls1)
+        no_protocol = 1;
+    else
+#endif
+#if defined(OPENSSL_NO_DTLS) || defined(OPENSSL_NO_DTLS1_2)
+    if (dtls12)
+        no_protocol = 1;
+    else
+#endif
+        no_protocol = 0;
+
     /*
      * Testing was requested for a compiled-out protocol (e.g. SSLv3).
      * Ideally, we would error out, but the generic test wrapper can't know
@@ -1387,7 +1410,6 @@ int main(int argc, char *argv[])
 #ifdef OPENSSL_FIPS
     if (fips_mode) {
         if (!FIPS_mode_set(1)) {
-            ERR_load_crypto_strings();
             ERR_print_errors(bio_err);
             EXIT(1);
         } else
@@ -1396,9 +1418,9 @@ int main(int argc, char *argv[])
 #endif
 
     if (print_time) {
-        if (!bio_pair) {
+        if (bio_type != BIO_PAIR) {
             fprintf(stderr, "Using BIO pair (-bio_pair)\n");
-            bio_pair = 1;
+            bio_type = BIO_PAIR;
         }
         if (number < 50 && !force)
             fprintf(stderr,
@@ -1407,9 +1429,6 @@ int main(int argc, char *argv[])
 
 /*      if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */
 
-    SSL_library_init();
-    SSL_load_error_strings();
-
 #ifndef OPENSSL_NO_COMP
     if (comp == COMP_ZLIB)
         cm = COMP_zlib();
@@ -1444,23 +1463,31 @@ int main(int argc, char *argv[])
      * (Otherwise we exit early.) However the compiler doesn't know this, so
      * we ifdef.
      */
-#ifndef OPENSSL_NO_SSL3
-    if (ssl3)
-        meth = SSLv3_method();
-    else
-#endif
 #ifndef OPENSSL_NO_DTLS
+#ifndef OPENSSL_NO_DTLS1
     if (dtls1)
         meth = DTLSv1_method();
-    else if (dtls12)
+    else
+#endif
+#ifndef OPENSSL_NO_DTLS1_2
+    if (dtls12)
         meth = DTLSv1_2_method();
-    else if (dtls)
+    else
+#endif
+    if (dtls)
         meth = DTLS_method();
     else
 #endif
+#ifndef OPENSSL_NO_SSL3
+    if (ssl3)
+        meth = SSLv3_method();
+    else
+#endif
+#ifndef OPENSSL_NO_TLS1
     if (tls1)
         meth = TLSv1_method();
     else
+#endif
         meth = TLS_method();
 
     c_ctx = SSL_CTX_new(meth);
@@ -1754,11 +1781,23 @@ int main(int argc, char *argv[])
                 goto end;
             }
         }
-        if (bio_pair)
-            ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time);
-        else
+        switch (bio_type) {
+        case BIO_MEM:
             ret = doit(s_ssl, c_ssl, bytes);
-       if (ret)  break;
+            break;
+        case BIO_PAIR:
+            ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, &c_time);
+            break;
+        case BIO_IPV4:
+            ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV4,
+                                 bytes, &s_time, &c_time);
+            break;
+        case BIO_IPV6:
+            ret = doit_localhost(s_ssl, c_ssl, BIO_FAMILY_IPV6,
+                                 bytes, &s_time, &c_time);
+            break;
+        }
+        if (ret)  break;
     }
 
     if (should_negotiate && ret == 0 &&
@@ -1813,21 +1852,295 @@ int main(int argc, char *argv[])
 
     BIO_free(bio_stdout);
 
-#ifndef OPENSSL_NO_ENGINE
-    ENGINE_cleanup();
-#endif
-    CONF_modules_unload(1);
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    ERR_remove_thread_state(NULL);
-    EVP_cleanup();
 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    CRYPTO_mem_leaks(bio_err);
+    if (CRYPTO_mem_leaks(bio_err) <= 0)
+        ret = 1;
 #endif
     BIO_free(bio_err);
     EXIT(ret);
 }
 
+int doit_localhost(SSL *s_ssl, SSL *c_ssl, int family, long count,
+                   clock_t *s_time, clock_t *c_time)
+{
+    long cw_num = count, cr_num = count, sw_num = count, sr_num = count;
+    BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;
+    BIO *acpt = NULL, *server = NULL, *client = NULL;
+    char addr_str[40];
+    int ret = 1;
+    int err_in_client = 0;
+    int err_in_server = 0;
+
+    acpt = BIO_new_accept("0");
+    if (acpt == NULL)
+        goto err;
+    BIO_set_accept_ip_family(acpt, family);
+    BIO_set_bind_mode(acpt, BIO_SOCK_NONBLOCK | BIO_SOCK_REUSEADDR);
+    if (BIO_do_accept(acpt) <= 0)
+        goto err;
+
+    BIO_snprintf(addr_str, sizeof(addr_str), ":%s", BIO_get_accept_port(acpt));
+
+    client = BIO_new_connect(addr_str);
+    BIO_set_conn_ip_family(client, family);
+    if (!client)
+        goto err;
+
+    if (BIO_set_nbio(client, 1) <= 0)
+        goto err;
+    if (BIO_set_nbio(acpt, 1) <= 0)
+        goto err;
+
+    {
+        int st_connect = 0, st_accept = 0;
+
+        while(!st_connect || !st_accept) {
+            if (!st_connect) {
+                if (BIO_do_connect(client) <= 0) {
+                    if (!BIO_should_retry(client))
+                        goto err;
+                } else {
+                    st_connect = 1;
+                }
+            }
+            if (!st_accept) {
+                if (BIO_do_accept(acpt) <= 0) {
+                    if (!BIO_should_retry(acpt))
+                        goto err;
+                } else {
+                    st_accept = 1;
+                }
+            }
+        }
+    }
+    /* We're not interested in accepting further connects */
+    server = BIO_pop(acpt);
+    BIO_free_all(acpt);
+    acpt = NULL;
+
+    s_ssl_bio = BIO_new(BIO_f_ssl());
+    if (!s_ssl_bio)
+        goto err;
+
+    c_ssl_bio = BIO_new(BIO_f_ssl());
+    if (!c_ssl_bio)
+        goto err;
+
+    SSL_set_connect_state(c_ssl);
+    SSL_set_bio(c_ssl, client, client);
+    (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);
+
+    SSL_set_accept_state(s_ssl);
+    SSL_set_bio(s_ssl, server, server);
+    (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);
+
+    do {
+        /*-
+         * c_ssl_bio:          SSL filter BIO
+         *
+         * client:             I/O for SSL library
+         *
+         *
+         * server:             I/O for SSL library
+         *
+         * s_ssl_bio:          SSL filter BIO
+         */
+
+        /*
+         * We have non-blocking behaviour throughout this test program, but
+         * can be sure that there is *some* progress in each iteration; so we
+         * don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE --
+         * we just try everything in each iteration
+         */
+
+        {
+            /* CLIENT */
+
+            char cbuf[1024 * 8];
+            int i, r;
+            clock_t c_clock = clock();
+
+            memset(cbuf, 0, sizeof(cbuf));
+
+            if (debug)
+                if (SSL_in_init(c_ssl))
+                    printf("client waiting in SSL_connect - %s\n",
+                           SSL_state_string_long(c_ssl));
+
+            if (cw_num > 0) {
+                /* Write to server. */
+
+                if (cw_num > (long)sizeof cbuf)
+                    i = sizeof cbuf;
+                else
+                    i = (int)cw_num;
+                r = BIO_write(c_ssl_bio, cbuf, i);
+                if (r < 0) {
+                    if (!BIO_should_retry(c_ssl_bio)) {
+                        fprintf(stderr, "ERROR in CLIENT\n");
+                        err_in_client = 1;
+                        goto err;
+                    }
+                    /*
+                     * BIO_should_retry(...) can just be ignored here. The
+                     * library expects us to call BIO_write with the same
+                     * arguments again, and that's what we will do in the
+                     * next iteration.
+                     */
+                } else if (r == 0) {
+                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
+                    goto err;
+                } else {
+                    if (debug)
+                        printf("client wrote %d\n", r);
+                    cw_num -= r;
+                }
+            }
+
+            if (cr_num > 0) {
+                /* Read from server. */
+
+                r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));
+                if (r < 0) {
+                    if (!BIO_should_retry(c_ssl_bio)) {
+                        fprintf(stderr, "ERROR in CLIENT\n");
+                        err_in_client = 1;
+                        goto err;
+                    }
+                    /*
+                     * Again, "BIO_should_retry" can be ignored.
+                     */
+                } else if (r == 0) {
+                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
+                    goto err;
+                } else {
+                    if (debug)
+                        printf("client read %d\n", r);
+                    cr_num -= r;
+                }
+            }
+
+            /*
+             * c_time and s_time increments will typically be very small
+             * (depending on machine speed and clock tick intervals), but
+             * sampling over a large number of connections should result in
+             * fairly accurate figures.  We cannot guarantee a lot, however
+             * -- if each connection lasts for exactly one clock tick, it
+             * will be counted only for the client or only for the server or
+             * even not at all.
+             */
+            *c_time += (clock() - c_clock);
+        }
+
+        {
+            /* SERVER */
+
+            char sbuf[1024 * 8];
+            int i, r;
+            clock_t s_clock = clock();
+
+            memset(sbuf, 0, sizeof(sbuf));
+
+            if (debug)
+                if (SSL_in_init(s_ssl))
+                    printf("server waiting in SSL_accept - %s\n",
+                           SSL_state_string_long(s_ssl));
+
+            if (sw_num > 0) {
+                /* Write to client. */
+
+                if (sw_num > (long)sizeof sbuf)
+                    i = sizeof sbuf;
+                else
+                    i = (int)sw_num;
+                r = BIO_write(s_ssl_bio, sbuf, i);
+                if (r < 0) {
+                    if (!BIO_should_retry(s_ssl_bio)) {
+                        fprintf(stderr, "ERROR in SERVER\n");
+                        err_in_server = 1;
+                        goto err;
+                    }
+                    /* Ignore "BIO_should_retry". */
+                } else if (r == 0) {
+                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
+                    goto err;
+                } else {
+                    if (debug)
+                        printf("server wrote %d\n", r);
+                    sw_num -= r;
+                }
+            }
+
+            if (sr_num > 0) {
+                /* Read from client. */
+
+                r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));
+                if (r < 0) {
+                    if (!BIO_should_retry(s_ssl_bio)) {
+                        fprintf(stderr, "ERROR in SERVER\n");
+                        err_in_server = 1;
+                        goto err;
+                    }
+                    /* blah, blah */
+                } else if (r == 0) {
+                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
+                    goto err;
+                } else {
+                    if (debug)
+                        printf("server read %d\n", r);
+                    sr_num -= r;
+                }
+            }
+
+            *s_time += (clock() - s_clock);
+        }
+    }
+    while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);
+
+    if (verbose)
+        print_details(c_ssl, "DONE via TCP connect: ");
+#ifndef OPENSSL_NO_NEXTPROTONEG
+    if (verify_npn(c_ssl, s_ssl) < 0) {
+        ret = 1;
+        goto end;
+    }
+#endif
+    if (verify_serverinfo() < 0) {
+        fprintf(stderr, "Server info verify error\n");
+        ret = 1;
+        goto err;
+    }
+    if (verify_alpn(c_ssl, s_ssl) < 0) {
+        ret = 1;
+        goto err;
+    }
+
+    if (custom_ext_error) {
+        fprintf(stderr, "Custom extension error\n");
+        ret = 1;
+        goto err;
+    }
+
+ end:
+    ret = 0;
+
+ err:
+    ERR_print_errors(bio_err);
+
+    BIO_free_all(acpt);
+    BIO_free(server);
+    BIO_free(client);
+    BIO_free(s_ssl_bio);
+    BIO_free(c_ssl_bio);
+
+    if (should_negotiate != NULL && strcmp(should_negotiate, "fail-client") == 0)
+        ret = (err_in_client != 0) ? 0 : 1;
+    else if (should_negotiate != NULL && strcmp(should_negotiate, "fail-server") == 0)
+        ret = (err_in_server != 0) ? 0 : 1;
+
+    return ret;
+}
+
 int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
                  clock_t *s_time, clock_t *c_time)
 {
@@ -3163,9 +3476,11 @@ static unsigned int psk_server_callback(SSL *ssl, const char *identity,
 
 static int do_test_cipherlist(void)
 {
+#if !defined(OPENSSL_NO_SSL3) || !defined(OPENSSL_NO_TLS1)
     int i = 0;
     const SSL_METHOD *meth;
     const SSL_CIPHER *ci, *tci = NULL;
+#endif
 
 #ifndef OPENSSL_NO_SSL3
     meth = SSLv3_method();
@@ -3180,6 +3495,7 @@ static int do_test_cipherlist(void)
         tci = ci;
     }
 #endif
+#ifndef OPENSSL_NO_TLS1
     meth = TLSv1_method();
     tci = NULL;
     while ((ci = meth->get_cipher(i++)) != NULL) {
@@ -3191,6 +3507,7 @@ static int do_test_cipherlist(void)
             }
         tci = ci;
     }
+#endif
 
     return 1;
 }