You need to sign in or sign up before continuing.
提交 75d5bd4e 编写于 作者: R Richard Levitte

Refactoring BIO: add a test, using test/ssltest

This adds a couple of simple tests to see that SSL traffic using the
reimplemented BIO_s_accept() and BIO_s_connect() works as expected,
both on IPv4 and on IPv6.
Reviewed-by: NKurt Roeckx <kurt@openssl.org>
上级 52f5926c
......@@ -329,7 +329,7 @@ sub testssl {
subtest 'standard SSL tests' => sub {
######################################################################
plan tests => 27;
plan tests => 29;
SKIP: {
skip "SSLv3 is not supported by this OpenSSL build", 4
......@@ -410,7 +410,7 @@ sub testssl {
}
SKIP: {
skip "Neither SSLv3 nor any TLS version are supported by this OpenSSL build", 6
skip "Neither SSLv3 nor any TLS version are supported by this OpenSSL build", 8
if $no_anytls;
SKIP: {
......@@ -430,6 +430,12 @@ sub testssl {
'test sslv2/sslv3 with both client and server authentication via BIO pair');
ok(run(test([@ssltest, "-bio_pair", "-server_auth", "-client_auth", "-app_verify", @CA, @extra])),
'test sslv2/sslv3 with both client and server authentication via BIO pair and app verify');
ok(run(test([@ssltest, "-ipv4", @extra])),
'test TLS via IPv4');
ok(run(test([@ssltest, "-ipv6", @extra])),
'test TLS via IPv6');
}
};
......
......@@ -732,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);
......@@ -800,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");
......@@ -1007,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;
......@@ -1215,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) {
......@@ -1411,9 +1419,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,
......@@ -1777,11 +1785,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 &&
......@@ -1851,6 +1871,287 @@ int main(int argc, char *argv[])
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;
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)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册