X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=tools%2Fclient.c;h=72bdbd1377e7832489ebe12d3502f68e5dad1bef;hp=3b462a8495944eb3c496ac25d1d9362dadee2e84;hb=2e2b17186bf66b19831c0003cacc7afe2dd3dcdf;hpb=3210f38e0491b39aec1ef419cb4114e9483089fb diff --git a/tools/client.c b/tools/client.c index 3b462a8..72bdbd1 100644 --- a/tools/client.c +++ b/tools/client.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include #include -#include #include "brssl.h" #include "bearssl.h" @@ -58,25 +58,29 @@ host_connect(const char *host, const char *port, int verbose) } fd = -1; for (p = si; p != NULL; p = p->ai_next) { - struct sockaddr *sa; - void *addr; - char tmp[INET6_ADDRSTRLEN + 50]; - - sa = (struct sockaddr *)p->ai_addr; - if (sa->sa_family == AF_INET) { - addr = &((struct sockaddr_in *)sa)->sin_addr; - } else if (sa->sa_family == AF_INET6) { - addr = &((struct sockaddr_in6 *)sa)->sin6_addr; - } else { - addr = NULL; - } - if (addr != NULL) { - inet_ntop(p->ai_family, addr, tmp, sizeof tmp); - } else { - sprintf(tmp, "", - (int)sa->sa_family); - } if (verbose) { + struct sockaddr *sa; + void *addr; + char tmp[INET6_ADDRSTRLEN + 50]; + + sa = (struct sockaddr *)p->ai_addr; + if (sa->sa_family == AF_INET) { + addr = &((struct sockaddr_in *)sa)->sin_addr; + } else if (sa->sa_family == AF_INET6) { + addr = &((struct sockaddr_in6 *)sa)->sin6_addr; + } else { + addr = NULL; + } + if (addr != NULL) { + if (!inet_ntop(p->ai_family, addr, + tmp, sizeof tmp)) + { + strcpy(tmp, ""); + } + } else { + sprintf(tmp, "", + (int)sa->sa_family); + } fprintf(stderr, "connecting to: %s\n", tmp); } fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); @@ -121,29 +125,35 @@ usage_client(void) fprintf(stderr, "options:\n"); fprintf(stderr, -" -q suppress verbose messages\n"); +" -q suppress verbose messages\n"); + fprintf(stderr, +" -trace activate extra debug messages (dump of all packets)\n"); fprintf(stderr, -" -trace activate extra debug messages (dump of all packets)\n"); +" -sni name use this specific name for SNI\n"); fprintf(stderr, -" -sni name use this specific name for SNI\n"); +" -nosni do not send any SNI\n"); fprintf(stderr, -" -nosni do not send any SNI\n"); +" -mono use monodirectional buffering\n"); fprintf(stderr, -" -mono use monodirectional buffering\n"); +" -buf length set the I/O buffer length (in bytes)\n"); fprintf(stderr, -" -buf length set the I/O buffer length (in bytes)\n"); +" -CA file add certificates in 'file' to trust anchors\n"); fprintf(stderr, -" -CA file add certificates in 'file' to trust anchors\n"); +" -list list supported names (protocols, algorithms...)\n"); fprintf(stderr, -" -list list supported names (protocols, algorithms...)\n"); +" -vmin name set minimum supported version (default: TLS-1.0)\n"); fprintf(stderr, -" -vmin name set minimum supported version (default: TLS-1.0)\n"); +" -vmax name set maximum supported version (default: TLS-1.2)\n"); fprintf(stderr, -" -vmax name set maximum supported version (default: TLS-1.2)\n"); +" -cs names set list of supported cipher suites (comma-separated)\n"); fprintf(stderr, -" -cs names set list of supported cipher suites (comma-separated)\n"); +" -hf names add support for some hash functions (comma-separated)\n"); fprintf(stderr, -" -hf names add support for some hash functions (comma-separated)\n"); +" -minhello len set minimum ClientHello length (in bytes)\n"); + fprintf(stderr, +" -fallback send the TLS_FALLBACK_SCSV (i.e. claim a downgrade)\n"); + fprintf(stderr, +" -noreneg prohibit renegotiations\n"); } /* see brssl.h */ @@ -171,6 +181,9 @@ do_client(int argc, char *argv[]) const br_hash_class *dnhash; unsigned char *iobuf; size_t iobuf_len; + size_t minhello_len; + int fallback; + uint32_t flags; int fd; retcode = 0; @@ -189,6 +202,9 @@ do_client(int argc, char *argv[]) suite_ids = NULL; iobuf = NULL; iobuf_len = 0; + minhello_len = (size_t)-1; + fallback = 0; + flags = 0; fd = -1; for (i = 0; i < argc; i ++) { const char *arg; @@ -246,7 +262,11 @@ do_client(int argc, char *argv[]) usage_client(); goto client_exit_error; } - iobuf_len = strtoul(arg, 0, 10); + iobuf_len = parse_size(arg); + if (iobuf_len == (size_t)-1) { + usage_client(); + goto client_exit_error; + } } else if (eqstr(arg, "-CA")) { if (++ i >= argc) { fprintf(stderr, @@ -341,6 +361,34 @@ do_client(int argc, char *argv[]) goto client_exit_error; } hfuns |= x; + } else if (eqstr(arg, "-minhello")) { + if (++ i >= argc) { + fprintf(stderr, + "ERROR: no argument for '-minhello'\n"); + usage_client(); + goto client_exit_error; + } + arg = argv[i]; + if (minhello_len != (size_t)-1) { + fprintf(stderr, "ERROR: duplicate minium" + " ClientHello length\n"); + usage_client(); + goto client_exit_error; + } + minhello_len = parse_size(arg); + /* + * Minimum ClientHello length must fit on 16 bits. + */ + if (minhello_len == (size_t)-1 + || (((minhello_len >> 12) >> 4) != 0)) + { + usage_client(); + goto client_exit_error; + } + } else if (eqstr(arg, "-fallback")) { + fallback = 1; + } else if (eqstr(arg, "-noreneg")) { + flags |= BR_OPT_NO_RENEGOTIATION; } else { fprintf(stderr, "ERROR: unknown option: '%s'\n", arg); usage_client(); @@ -422,7 +470,7 @@ do_client(int argc, char *argv[]) /* * Compute implementation requirements and inject implementations. */ - suite_ids = xmalloc(num_suites * sizeof *suite_ids); + suite_ids = xmalloc((num_suites + 1) * sizeof *suite_ids); br_ssl_client_zero(&cc); br_ssl_engine_set_versions(&cc.eng, vmin, vmax); dnhash = NULL; @@ -522,6 +570,9 @@ do_client(int argc, char *argv[]) br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31); } } + if (fallback) { + suite_ids[num_suites ++] = 0x5600; + } br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites); for (u = 0; hash_functions[u].name; u ++) { @@ -568,9 +619,19 @@ do_client(int argc, char *argv[]) br_ssl_engine_set_x509(&cc.eng, &xc.vtable); } + if (minhello_len != (size_t)-1) { + br_ssl_client_set_min_clienthello_len(&cc, minhello_len); + } + br_ssl_engine_set_all_flags(&cc.eng, flags); + br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi); br_ssl_client_reset(&cc, sni, 0); + /* + * We need to avoid SIGPIPE. + */ + signal(SIGPIPE, SIG_IGN); + /* * Connect to the peer. */