X-Git-Url: https://bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=tools%2Fserver.c;h=fbc778686eda58fb886138b5b9b1ea04b37c1a16;hp=a63198244002b0a07b0968b96b6f57e8982fae37;hb=3f00688b9d9f483a6ca97e659eea104995ea15b7;hpb=9dc3c9b61d0e8446ff8b8b7a873bbdc3f1c033fe;ds=sidebyside diff --git a/tools/server.c b/tools/server.c index a631982..fbc7786 100644 --- a/tools/server.c +++ b/tools/server.c @@ -27,7 +27,12 @@ #include #include #include +#include +#ifdef _WIN32 +#include +#include +#else #include #include #include @@ -36,14 +41,18 @@ #include #include +#define SOCKET int +#define INVALID_SOCKET (-1) +#define SOCKADDR_STORAGE struct sockaddr_storage +#endif + #include "brssl.h" -#include "bearssl.h" -static int +static SOCKET host_bind(const char *host, const char *port, int verbose) { struct addrinfo hints, *si, *p; - int fd; + SOCKET fd; int err; memset(&hints, 0, sizeof hints); @@ -53,16 +62,15 @@ host_bind(const char *host, const char *port, int verbose) if (err != 0) { fprintf(stderr, "ERROR: getaddrinfo(): %s\n", gai_strerror(err)); - return -1; + return INVALID_SOCKET; } - fd = -1; + fd = INVALID_SOCKET; for (p = si; p != NULL; p = p->ai_next) { struct sockaddr *sa; struct sockaddr_in sa4; struct sockaddr_in6 sa6; size_t sa_len; void *addr; - char tmp[INET6_ADDRSTRLEN + 50]; int opt; sa = (struct sockaddr *)p->ai_addr; @@ -86,31 +94,43 @@ host_bind(const char *host, const char *port, int verbose) addr = NULL; sa_len = p->ai_addrlen; } - if (addr != NULL) { - inet_ntop(p->ai_family, addr, tmp, sizeof tmp); - } else { - sprintf(tmp, "", - (int)sa->sa_family); - } if (verbose) { + char tmp[INET6_ADDRSTRLEN + 50]; + + if (addr != NULL) { + if (!inet_ntop(p->ai_family, addr, + tmp, sizeof tmp)) + { + strcpy(tmp, ""); + } + } else { + sprintf(tmp, "", + (int)sa->sa_family); + } fprintf(stderr, "binding to: %s\n", tmp); } fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (fd < 0) { + if (fd == INVALID_SOCKET) { if (verbose) { perror("socket()"); } continue; } opt = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (void *)&opt, sizeof opt); opt = 0; - setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt); + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&opt, sizeof opt); if (bind(fd, sa, sa_len) < 0) { if (verbose) { perror("bind()"); } +#ifdef _WIN32 + closesocket(fd); +#else close(fd); +#endif continue; } break; @@ -118,15 +138,19 @@ host_bind(const char *host, const char *port, int verbose) if (p == NULL) { freeaddrinfo(si); fprintf(stderr, "ERROR: failed to bind\n"); - return -1; + return INVALID_SOCKET; } freeaddrinfo(si); if (listen(fd, 5) < 0) { if (verbose) { perror("listen()"); } +#ifdef _WIN32 + closesocket(fd); +#else close(fd); - return -1; +#endif + return INVALID_SOCKET; } if (verbose) { fprintf(stderr, "bound.\n"); @@ -134,27 +158,27 @@ host_bind(const char *host, const char *port, int verbose) return fd; } -static int -accept_client(int server_fd, int verbose) +static SOCKET +accept_client(SOCKET server_fd, int verbose) { int fd; - struct sockaddr sa; + SOCKADDR_STORAGE sa; socklen_t sa_len; sa_len = sizeof sa; - fd = accept(server_fd, &sa, &sa_len); - if (fd < 0) { + fd = accept(server_fd, (struct sockaddr *)&sa, &sa_len); + if (fd == INVALID_SOCKET) { if (verbose) { perror("accept()"); } - return -1; + return INVALID_SOCKET; } if (verbose) { char tmp[INET6_ADDRSTRLEN + 50]; const char *name; name = NULL; - switch (sa.sa_family) { + switch (((struct sockaddr *)&sa)->sa_family) { case AF_INET: name = inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr, @@ -167,8 +191,8 @@ accept_client(int server_fd, int verbose) break; } if (name == NULL) { - sprintf(tmp, "", - (unsigned long)sa.sa_family); + sprintf(tmp, "", (unsigned long) + ((struct sockaddr *)&sa)->sa_family); name = tmp; } fprintf(stderr, "accepting connection from: %s\n", name); @@ -176,9 +200,18 @@ accept_client(int server_fd, int verbose) /* * We make the socket non-blocking, since we are going to use - * poll() to organise I/O. + * poll() or select() to organise I/O. */ +#ifdef _WIN32 + { + u_long arg; + + arg = 1; + ioctlsocket(fd, FIONBIO, &arg); + } +#else fcntl(fd, F_SETFL, O_NONBLOCK); +#endif return fd; } @@ -208,6 +241,10 @@ usage_server(void) fprintf(stderr, " -key fname read private key from file 'fname'\n"); fprintf(stderr, +" -CA file add trust anchors from 'file' (for client auth)\n"); + fprintf(stderr, +" -anon_ok request but do not require a client certificate\n"); + fprintf(stderr, " -list list supported names (protocols, algorithms...)\n"); fprintf(stderr, " -vmin name set minimum supported version (default: TLS-1.0)\n"); @@ -218,7 +255,15 @@ usage_server(void) fprintf(stderr, " -hf names add support for some hash functions (comma-separated)\n"); fprintf(stderr, +" -cbhash test hashing in policy callback\n"); + fprintf(stderr, " -serverpref enforce server's preferences for cipher suites\n"); + fprintf(stderr, +" -noreneg prohibit renegotiations\n"); + fprintf(stderr, +" -alpn name add protocol name to list of protocols (ALPN extension)\n"); + fprintf(stderr, +" -strictalpn fail on ALPN mismatch\n"); exit(EXIT_FAILURE); } @@ -229,22 +274,46 @@ typedef struct { size_t chain_len; int cert_signer_algo; private_key *sk; + int cbhash; } policy_context; -static int -get_cert_signer_algo(br_x509_certificate *xc) +static void +print_hashes(unsigned chashes) { - br_x509_decoder_context dc; - int err; + int i; - br_x509_decoder_init(&dc, 0, 0); - br_x509_decoder_push(&dc, xc->data, xc->data_len); - err = br_x509_decoder_last_error(&dc); - if (err != 0) { - return -err; - } else { - return br_x509_decoder_get_signer_key_type(&dc); + for (i = 2; i <= 6; i ++) { + if ((chashes >> i) & 1) { + int z; + + switch (i) { + case 3: z = 224; break; + case 4: z = 256; break; + case 5: z = 384; break; + case 6: z = 512; break; + default: + z = 1; + break; + } + fprintf(stderr, " sha%d", z); + } + } +} + +static unsigned +choose_hash(unsigned chashes) +{ + unsigned hash_id; + + for (hash_id = 6; hash_id >= 2; hash_id --) { + if (((chashes >> hash_id) & 1) != 0) { + return hash_id; + } } + /* + * Normally unreachable. + */ + return 0; } static int @@ -256,16 +325,10 @@ sp_choose(const br_ssl_server_policy_class **pctx, const br_suite_translated *st; size_t u, st_num; unsigned chashes; - int hash_id; pc = (policy_context *)pctx; st = br_ssl_server_get_client_suites(cc, &st_num); chashes = br_ssl_server_get_client_hashes(cc); - for (hash_id = 6; hash_id >= 2; hash_id --) { - if ((chashes >> hash_id) & 1) { - break; - } - } if (pc->verbose) { fprintf(stderr, "Client parameters:\n"); fprintf(stderr, " Maximum version: "); @@ -295,24 +358,17 @@ sp_choose(const br_ssl_server_policy_class **pctx, get_suite_name_ext(st[u][0], csn, sizeof csn); fprintf(stderr, " %s\n", csn); } - fprintf(stderr, " Common hash functions:"); - for (u = 2; u <= 6; u ++) { - if ((chashes >> u) & 1) { - int z; - - switch (u) { - case 3: z = 224; break; - case 4: z = 256; break; - case 5: z = 384; break; - case 6: z = 512; break; - default: - z = 1; - break; - } - fprintf(stderr, " sha%d", z); - } + fprintf(stderr, " Common sign+hash functions:\n"); + if ((chashes & 0xFF) != 0) { + fprintf(stderr, " with RSA:"); + print_hashes(chashes); + fprintf(stderr, "\n"); + } + if ((chashes >> 8) != 0) { + fprintf(stderr, " with ECDSA:"); + print_hashes(chashes >> 8); + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); } for (u = 0; u < st_num; u ++) { unsigned tt; @@ -328,14 +384,52 @@ sp_choose(const br_ssl_server_policy_class **pctx, case BR_SSLKEYX_ECDHE_RSA: if (pc->sk->key_type == BR_KEYTYPE_RSA) { choices->cipher_suite = st[u][0]; - choices->hash_id = hash_id; + if (br_ssl_engine_get_version(&cc->eng) + < BR_TLS12) + { + if (pc->cbhash) { + choices->algo_id = 0x0001; + } else { + choices->algo_id = 0xFF00; + } + } else { + unsigned id; + + id = choose_hash(chashes); + if (pc->cbhash) { + choices->algo_id = + (id << 8) + 0x01; + } else { + choices->algo_id = 0xFF00 + id; + } + } goto choose_ok; } break; case BR_SSLKEYX_ECDHE_ECDSA: if (pc->sk->key_type == BR_KEYTYPE_EC) { choices->cipher_suite = st[u][0]; - choices->hash_id = hash_id; + if (br_ssl_engine_get_version(&cc->eng) + < BR_TLS12) + { + if (pc->cbhash) { + choices->algo_id = 0x0203; + } else { + choices->algo_id = + 0xFF00 + br_sha1_ID; + } + } else { + unsigned id; + + id = choose_hash(chashes >> 8); + if (pc->cbhash) { + choices->algo_id = + (id << 8) + 0x03; + } else { + choices->algo_id = + 0xFF00 + id; + } + } goto choose_ok; } break; @@ -373,19 +467,25 @@ choose_ok: static uint32_t sp_do_keyx(const br_ssl_server_policy_class **pctx, - unsigned char *data, size_t len) + unsigned char *data, size_t *len) { policy_context *pc; + uint32_t r; + size_t xoff, xlen; pc = (policy_context *)pctx; switch (pc->sk->key_type) { case BR_KEYTYPE_RSA: return br_rsa_ssl_decrypt( &br_rsa_i31_private, &pc->sk->key.rsa, - data, len); + data, *len); case BR_KEYTYPE_EC: - return br_ec_prime_i31.mul(data, len, pc->sk->key.ec.x, + r = br_ec_all_m15.mul(data, *len, pc->sk->key.ec.x, pc->sk->key.ec.xlen, pc->sk->key.ec.curve); + xoff = br_ec_all_m15.xoff(pc->sk->key.ec.curve, &xlen); + memmove(data, data + xoff, xlen); + *len = xlen; + return r; default: fprintf(stderr, "ERROR: unknown private key type (%d)\n", (int)pc->sk->key_type); @@ -393,64 +493,42 @@ sp_do_keyx(const br_ssl_server_policy_class **pctx, } } -/* - * OID for hash functions in RSA signatures. - */ -static const unsigned char HASH_OID_SHA1[] = { - 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A -}; - -static const unsigned char HASH_OID_SHA224[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 -}; - -static const unsigned char HASH_OID_SHA256[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 -}; - -static const unsigned char HASH_OID_SHA384[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 -}; - -static const unsigned char HASH_OID_SHA512[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 -}; - -static const unsigned char *HASH_OID[] = { - HASH_OID_SHA1, - HASH_OID_SHA224, - HASH_OID_SHA256, - HASH_OID_SHA384, - HASH_OID_SHA512 -}; - -static const br_hash_class * -get_hash_impl(int hash_id) -{ - size_t u; - - for (u = 0; hash_functions[u].name; u ++) { - const br_hash_class *hc; - int id; - - hc = hash_functions[u].hclass; - id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK; - if (id == hash_id) { - return hc; - } - } - return NULL; -} - static size_t sp_do_sign(const br_ssl_server_policy_class **pctx, - int hash_id, size_t hv_len, unsigned char *data, size_t len) + unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) { policy_context *pc; unsigned char hv[64]; pc = (policy_context *)pctx; - memcpy(hv, data, hv_len); + if (algo_id >= 0xFF00) { + algo_id &= 0xFF; + memcpy(hv, data, hv_len); + } else { + const br_hash_class *hc; + br_hash_compat_context zc; + + if (pc->verbose) { + fprintf(stderr, "Callback hashing, algo = 0x%04X," + " data_len = %lu\n", + algo_id, (unsigned long)hv_len); + } + algo_id >>= 8; + hc = get_hash_impl(algo_id); + if (hc == NULL) { + if (pc->verbose) { + fprintf(stderr, + "ERROR: unsupported hash function %u\n", + algo_id); + } + return 0; + } + hc->init(&zc.vtable); + hc->update(&zc.vtable, data, hv_len); + hc->out(&zc.vtable, hv); + hv_len = (hc->desc >> BR_HASHDESC_OUT_OFF) + & BR_HASHDESC_OUT_MASK; + } switch (pc->sk->key_type) { size_t sig_len; uint32_t x; @@ -458,15 +536,12 @@ sp_do_sign(const br_ssl_server_policy_class **pctx, const br_hash_class *hc; case BR_KEYTYPE_RSA: - if (hash_id == 0) { - hash_oid = NULL; - } else if (hash_id >= 2 && hash_id <= 6) { - hash_oid = HASH_OID[hash_id - 2]; - } else { + hash_oid = get_hash_oid(algo_id); + if (hash_oid == NULL && algo_id != 0) { if (pc->verbose) { fprintf(stderr, "ERROR: cannot RSA-sign with" - " unknown hash function: %d\n", - hash_id); + " unknown hash function: %u\n", + algo_id); } return 0; } @@ -492,12 +567,12 @@ sp_do_sign(const br_ssl_server_policy_class **pctx, return sig_len; case BR_KEYTYPE_EC: - hc = get_hash_impl(hash_id); + hc = get_hash_impl(algo_id); if (hc == NULL) { if (pc->verbose) { - fprintf(stderr, "ERROR: cannot RSA-sign with" - " unknown hash function: %d\n", - hash_id); + fprintf(stderr, "ERROR: cannot ECDSA-sign with" + " unknown hash function: %u\n", + algo_id); } return 0; } @@ -509,7 +584,7 @@ sp_do_sign(const br_ssl_server_policy_class **pctx, } return 0; } - sig_len = br_ecdsa_i31_sign_asn1(&br_ec_prime_i31, + sig_len = br_ecdsa_i31_sign_asn1(&br_ec_all_m15, hc, hv, &pc->sk->key.ec, data); if (sig_len == 0) { if (pc->verbose) { @@ -531,6 +606,12 @@ static const br_ssl_server_policy_class policy_vtable = { sp_do_sign }; +void +free_alpn(void *alpn) +{ + xfree(*(char **)alpn); +} + /* see brssl.h */ int do_server(int argc, char *argv[]) @@ -546,10 +627,15 @@ do_server(int argc, char *argv[]) size_t num_suites; uint16_t *suite_ids; unsigned hfuns; + int cbhash; br_x509_certificate *chain; size_t chain_len; int cert_signer_algo; private_key *sk; + anchor_list anchors = VEC_INIT; + VECTOR(char *) alpn_names = VEC_INIT; + br_x509_minimal_context xc; + const br_hash_class *dnhash; size_t u; br_ssl_server_context cc; policy_context pc; @@ -557,7 +643,7 @@ do_server(int argc, char *argv[]) unsigned char *iobuf, *cache; size_t iobuf_len, cache_len; uint32_t flags; - int server_fd, fd; + SOCKET server_fd, fd; retcode = 0; verbose = 1; @@ -570,6 +656,7 @@ do_server(int argc, char *argv[]) suites = NULL; num_suites = 0; hfuns = 0; + cbhash = 0; suite_ids = NULL; chain = NULL; chain_len = 0; @@ -579,8 +666,8 @@ do_server(int argc, char *argv[]) cache = NULL; cache_len = (size_t)-1; flags = 0; - server_fd = -1; - fd = -1; + server_fd = INVALID_SOCKET; + fd = INVALID_SOCKET; for (i = 0; i < argc; i ++) { const char *arg; @@ -637,7 +724,11 @@ do_server(int argc, char *argv[]) usage_server(); goto server_exit_error; } - iobuf_len = strtoul(arg, 0, 10); + iobuf_len = parse_size(arg); + if (iobuf_len == (size_t)-1) { + usage_server(); + goto server_exit_error; + } } else if (eqstr(arg, "-cache")) { if (++ i >= argc) { fprintf(stderr, @@ -652,7 +743,11 @@ do_server(int argc, char *argv[]) usage_server(); goto server_exit_error; } - cache_len = strtoul(arg, 0, 10); + cache_len = parse_size(arg); + if (cache_len == (size_t)-1) { + usage_server(); + goto server_exit_error; + } } else if (eqstr(arg, "-cert")) { if (++ i >= argc) { fprintf(stderr, @@ -689,6 +784,20 @@ do_server(int argc, char *argv[]) if (sk == NULL) { goto server_exit_error; } + } else if (eqstr(arg, "-CA")) { + if (++ i >= argc) { + fprintf(stderr, + "ERROR: no argument for '-CA'\n"); + usage_server(); + goto server_exit_error; + } + arg = argv[i]; + if (read_trust_anchors(&anchors, arg) == 0) { + usage_server(); + goto server_exit_error; + } + } else if (eqstr(arg, "-anon_ok")) { + flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH; } else if (eqstr(arg, "-list")) { list_names(); goto server_exit; @@ -771,8 +880,22 @@ do_server(int argc, char *argv[]) goto server_exit_error; } hfuns |= x; + } else if (eqstr(arg, "-cbhash")) { + cbhash = 1; } else if (eqstr(arg, "-serverpref")) { flags |= BR_OPT_ENFORCE_SERVER_PREFERENCES; + } else if (eqstr(arg, "-noreneg")) { + flags |= BR_OPT_NO_RENEGOTIATION; + } else if (eqstr(arg, "-alpn")) { + if (++ i >= argc) { + fprintf(stderr, + "ERROR: no argument for '-alpn'\n"); + usage_server(); + goto server_exit_error; + } + VEC_ADD(alpn_names, xstrdup(argv[i])); + } else if (eqstr(arg, "-strictalpn")) { + flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH; } else { fprintf(stderr, "ERROR: unknown option: '%s'\n", arg); usage_server(); @@ -833,7 +956,7 @@ do_server(int argc, char *argv[]) break; case BR_KEYTYPE_EC: curve = sk->key.ec.curve; - supp = br_ec_prime_i31.supported_curves; + supp = br_ec_all_m15.supported_curves; if (curve > 31 || !((supp >> curve) & 1)) { fprintf(stderr, "ERROR: private key curve (%d)" " is not supported\n", curve); @@ -846,11 +969,10 @@ do_server(int argc, char *argv[]) break; } cert_signer_algo = get_cert_signer_algo(chain); - if (cert_signer_algo < 0) { - fprintf(stderr, "ERROR: server certificate cannot be" - " decoded (err=%d)\n", -cert_signer_algo); + if (cert_signer_algo == 0) { goto server_exit_error; - } else if (verbose) { + } + if (verbose) { const char *csas; switch (cert_signer_algo) { @@ -882,7 +1004,7 @@ do_server(int argc, char *argv[]) suite_ids = xmalloc(num_suites * sizeof *suite_ids); br_ssl_server_zero(&cc); br_ssl_engine_set_versions(&cc.eng, vmin, vmax); - br_ssl_server_set_all_flags(&cc, flags); + br_ssl_engine_set_all_flags(&cc.eng, flags); if (vmin <= BR_TLS11) { if (!(hfuns & (1 << br_md5_ID))) { fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n"); @@ -940,6 +1062,15 @@ do_server(int argc, char *argv[]) &br_sslrec_in_gcm_vtable, &br_sslrec_out_gcm_vtable); } + if ((req & REQ_CHAPOL) != 0) { + br_ssl_engine_set_chacha20(&cc.eng, + &br_chacha20_ct_run); + br_ssl_engine_set_poly1305(&cc.eng, + &br_poly1305_ctmul_run); + br_ssl_engine_set_chapol(&cc.eng, + &br_sslrec_in_chapol_vtable, + &br_sslrec_out_chapol_vtable); + } if ((req & REQ_3DESCBC) != 0) { br_ssl_engine_set_des_cbc(&cc.eng, &br_des_ct_cbcenc_vtable, @@ -949,11 +1080,12 @@ do_server(int argc, char *argv[]) &br_sslrec_out_cbc_vtable); } if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) { - br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31); + br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); } } br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites); + dnhash = NULL; for (u = 0; hash_functions[u].name; u ++) { const br_hash_class *hc; int id; @@ -961,6 +1093,7 @@ do_server(int argc, char *argv[]) hc = hash_functions[u].hclass; id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK; if ((hfuns & ((unsigned)1 << id)) != 0) { + dnhash = hc; br_ssl_engine_set_hash(&cc.eng, id, hc); } } @@ -981,21 +1114,70 @@ do_server(int argc, char *argv[]) br_ssl_session_cache_lru_init(&lru, cache, cache_len); br_ssl_server_set_cache(&cc, &lru.vtable); + if (VEC_LEN(alpn_names) != 0) { + br_ssl_engine_set_protocol_names(&cc.eng, + (const char **)&VEC_ELT(alpn_names, 0), + VEC_LEN(alpn_names)); + } + + /* + * Set the policy handler (that chooses the actual cipher suite, + * selects the certificate chain, and runs the private key + * operations). + */ pc.vtable = &policy_vtable; pc.verbose = verbose; pc.chain = chain; pc.chain_len = chain_len; pc.cert_signer_algo = cert_signer_algo; pc.sk = sk; + pc.cbhash = cbhash; br_ssl_server_set_policy(&cc, &pc.vtable); + /* + * If trust anchors have been configured, then set an X.509 + * validation engine and activate client certificate + * authentication. + */ + if (VEC_LEN(anchors) != 0) { + br_x509_minimal_init(&xc, dnhash, + &VEC_ELT(anchors, 0), VEC_LEN(anchors)); + for (u = 0; hash_functions[u].name; u ++) { + const br_hash_class *hc; + int id; + + hc = hash_functions[u].hclass; + id = (hc->desc >> BR_HASHDESC_ID_OFF) + & BR_HASHDESC_ID_MASK; + if ((hfuns & ((unsigned)1 << id)) != 0) { + br_x509_minimal_set_hash(&xc, id, hc); + } + } + br_ssl_engine_set_rsavrfy(&cc.eng, &br_rsa_i31_pkcs1_vrfy); + br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); + br_ssl_engine_set_ecdsa(&cc.eng, &br_ecdsa_i31_vrfy_asn1); + br_x509_minimal_set_rsa(&xc, &br_rsa_i31_pkcs1_vrfy); + br_x509_minimal_set_ecdsa(&xc, + &br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1); + br_ssl_engine_set_x509(&cc.eng, &xc.vtable); + br_ssl_server_set_trust_anchor_names_alt(&cc, + &VEC_ELT(anchors, 0), VEC_LEN(anchors)); + } + br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi); + /* + * On Unix systems, we need to ignore SIGPIPE. + */ +#ifndef _WIN32 + signal(SIGPIPE, SIG_IGN); +#endif + /* * Open the server socket. */ server_fd = host_bind(bind_name, port, verbose); - if (server_fd < 0) { + if (server_fd == INVALID_SOCKET) { goto server_exit_error; } @@ -1010,15 +1192,19 @@ do_server(int argc, char *argv[]) int x; fd = accept_client(server_fd, verbose); - if (fd < 0) { + if (fd == INVALID_SOCKET) { goto server_exit_error; } br_ssl_server_reset(&cc); x = run_ssl_engine(&cc.eng, fd, (verbose ? RUN_ENGINE_VERBOSE : 0) | (trace ? RUN_ENGINE_TRACE : 0)); +#ifdef _WIN32 + closesocket(fd); +#else close(fd); - fd = -1; +#endif + fd = INVALID_SOCKET; if (x < -1) { goto server_exit_error; } @@ -1030,17 +1216,18 @@ do_server(int argc, char *argv[]) server_exit: xfree(suites); xfree(suite_ids); - if (chain != NULL) { - for (u = 0; u < chain_len; u ++) { - xfree(chain[u].data); - } - xfree(chain); - } + free_certificates(chain, chain_len); free_private_key(sk); + VEC_CLEAREXT(anchors, &free_ta_contents); + VEC_CLEAREXT(alpn_names, &free_alpn); xfree(iobuf); xfree(cache); - if (fd >= 0) { + if (fd != INVALID_SOCKET) { +#ifdef _WIN32 + closesocket(fd); +#else close(fd); +#endif } return retcode;