1e71b7053SJung-uk Kim /* 2e71b7053SJung-uk Kim * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 3e71b7053SJung-uk Kim * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 41f13597dSJung-uk Kim * Copyright 2005 Nokia. All rights reserved. 51f13597dSJung-uk Kim * 6e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 7e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 8e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 9e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 101f13597dSJung-uk Kim */ 113b4e3dcbSSimon L. B. Nielsen 121f13597dSJung-uk Kim #include <ctype.h> 1374664626SKris Kennaway #include <stdio.h> 1474664626SKris Kennaway #include <stdlib.h> 1574664626SKris Kennaway #include <string.h> 16e71b7053SJung-uk Kim #if defined(_WIN32) 17e71b7053SJung-uk Kim /* Included before async.h to avoid some warnings */ 18e71b7053SJung-uk Kim # include <windows.h> 19e71b7053SJung-uk Kim #endif 203b4e3dcbSSimon L. B. Nielsen 215c87c606SMark Murray #include <openssl/e_os2.h> 22e71b7053SJung-uk Kim #include <openssl/async.h> 23e71b7053SJung-uk Kim #include <openssl/ssl.h> 2474664626SKris Kennaway 25e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SOCK 263b4e3dcbSSimon L. B. Nielsen 276f9291ceSJung-uk Kim /* 286f9291ceSJung-uk Kim * With IPv6, it looks like Digital has mixed up the proper order of 296f9291ceSJung-uk Kim * recursive header file inclusion, resulting in the compiler complaining 306f9291ceSJung-uk Kim * that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is 316f9291ceSJung-uk Kim * needed to have fileno() declared correctly... So let's define u_int 326f9291ceSJung-uk Kim */ 335c87c606SMark Murray #if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT) 3474664626SKris Kennaway # define __U_INT 3574664626SKris Kennaway typedef unsigned int u_int; 3674664626SKris Kennaway #endif 3774664626SKris Kennaway 3874664626SKris Kennaway #include <openssl/bn.h> 3974664626SKris Kennaway #include "apps.h" 40e71b7053SJung-uk Kim #include "progs.h" 4174664626SKris Kennaway #include <openssl/err.h> 4274664626SKris Kennaway #include <openssl/pem.h> 4374664626SKris Kennaway #include <openssl/x509.h> 4474664626SKris Kennaway #include <openssl/ssl.h> 455740a5e3SKris Kennaway #include <openssl/rand.h> 46db522d3aSSimon L. B. Nielsen #include <openssl/ocsp.h> 473b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DH 483b4e3dcbSSimon L. B. Nielsen # include <openssl/dh.h> 493b4e3dcbSSimon L. B. Nielsen #endif 503b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_RSA 513b4e3dcbSSimon L. B. Nielsen # include <openssl/rsa.h> 523b4e3dcbSSimon L. B. Nielsen #endif 531f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 541f13597dSJung-uk Kim # include <openssl/srp.h> 551f13597dSJung-uk Kim #endif 5674664626SKris Kennaway #include "s_apps.h" 573b4e3dcbSSimon L. B. Nielsen #include "timeouts.h" 58e71b7053SJung-uk Kim #ifdef CHARSET_EBCDIC 59e71b7053SJung-uk Kim #include <openssl/ebcdic.h> 6074664626SKris Kennaway #endif 61e71b7053SJung-uk Kim #include "internal/sockets.h" 6274664626SKris Kennaway 63e71b7053SJung-uk Kim static int not_resumable_sess_cb(SSL *s, int is_forward_secure); 64e71b7053SJung-uk Kim static int sv_body(int s, int stype, int prot, unsigned char *context); 65e71b7053SJung-uk Kim static int www_body(int s, int stype, int prot, unsigned char *context); 66e71b7053SJung-uk Kim static int rev_body(int s, int stype, int prot, unsigned char *context); 6774664626SKris Kennaway static void close_accept_socket(void); 6874664626SKris Kennaway static int init_ssl_connection(SSL *s); 6974664626SKris Kennaway static void print_stats(BIO *bp, SSL_CTX *ctx); 70e71b7053SJung-uk Kim static int generate_session_id(SSL *ssl, unsigned char *id, 715c87c606SMark Murray unsigned int *id_len); 727bded2dbSJung-uk Kim static void init_session_cache_ctx(SSL_CTX *sctx); 737bded2dbSJung-uk Kim static void free_sessions(void); 745c87c606SMark Murray #ifndef OPENSSL_NO_DH 753b4e3dcbSSimon L. B. Nielsen static DH *load_dh_param(const char *dhfile); 7674664626SKris Kennaway #endif 77e71b7053SJung-uk Kim static void print_connection_info(SSL *con); 783b4e3dcbSSimon L. B. Nielsen 79e71b7053SJung-uk Kim static const int bufsize = 16 * 1024; 8074664626SKris Kennaway static int accept_socket = -1; 8174664626SKris Kennaway 8274664626SKris Kennaway #define TEST_CERT "server.pem" 83db522d3aSSimon L. B. Nielsen #define TEST_CERT2 "server2.pem" 8474664626SKris Kennaway 8574664626SKris Kennaway static int s_nbio = 0; 8674664626SKris Kennaway static int s_nbio_test = 0; 87e71b7053SJung-uk Kim static int s_crlf = 0; 8874664626SKris Kennaway static SSL_CTX *ctx = NULL; 89db522d3aSSimon L. B. Nielsen static SSL_CTX *ctx2 = NULL; 9074664626SKris Kennaway static int www = 0; 9174664626SKris Kennaway 9274664626SKris Kennaway static BIO *bio_s_out = NULL; 937bded2dbSJung-uk Kim static BIO *bio_s_msg = NULL; 9474664626SKris Kennaway static int s_debug = 0; 95db522d3aSSimon L. B. Nielsen static int s_tlsextdebug = 0; 965c87c606SMark Murray static int s_msg = 0; 9774664626SKris Kennaway static int s_quiet = 0; 987bded2dbSJung-uk Kim static int s_ign_eof = 0; 997bded2dbSJung-uk Kim static int s_brief = 0; 10074664626SKris Kennaway 1011f13597dSJung-uk Kim static char *keymatexportlabel = NULL; 1021f13597dSJung-uk Kim static int keymatexportlen = 20; 1031f13597dSJung-uk Kim 104e71b7053SJung-uk Kim static int async = 0; 105e71b7053SJung-uk Kim 1065c87c606SMark Murray static const char *session_id_prefix = NULL; 107f579bf8eSKris Kennaway 108e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1093b4e3dcbSSimon L. B. Nielsen static int enable_timeouts = 0; 1106a599222SSimon L. B. Nielsen static long socket_mtu; 1116a599222SSimon L. B. Nielsen #endif 1123b4e3dcbSSimon L. B. Nielsen 113e71b7053SJung-uk Kim /* 114e71b7053SJung-uk Kim * We define this but make it always be 0 in no-dtls builds to simplify the 115e71b7053SJung-uk Kim * code. 116e71b7053SJung-uk Kim */ 117e71b7053SJung-uk Kim static int dtlslisten = 0; 118e71b7053SJung-uk Kim static int stateless = 0; 1197bded2dbSJung-uk Kim 120e71b7053SJung-uk Kim static int early_data = 0; 121e71b7053SJung-uk Kim static SSL_SESSION *psksess = NULL; 1227bded2dbSJung-uk Kim 1231f13597dSJung-uk Kim static char *psk_identity = "Client_identity"; 1241f13597dSJung-uk Kim char *psk_key = NULL; /* by default PSK is not used */ 1251f13597dSJung-uk Kim 126e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK 1271f13597dSJung-uk Kim static unsigned int psk_server_cb(SSL *ssl, const char *identity, 1286f9291ceSJung-uk Kim unsigned char *psk, 1296f9291ceSJung-uk Kim unsigned int max_psk_len) 1301f13597dSJung-uk Kim { 131aeb5019cSJung-uk Kim long key_len = 0; 132aeb5019cSJung-uk Kim unsigned char *key; 1331f13597dSJung-uk Kim 1341f13597dSJung-uk Kim if (s_debug) 1351f13597dSJung-uk Kim BIO_printf(bio_s_out, "psk_server_cb\n"); 136e71b7053SJung-uk Kim if (identity == NULL) { 1371f13597dSJung-uk Kim BIO_printf(bio_err, "Error: client did not send PSK identity\n"); 1381f13597dSJung-uk Kim goto out_err; 1391f13597dSJung-uk Kim } 1401f13597dSJung-uk Kim if (s_debug) 1411f13597dSJung-uk Kim BIO_printf(bio_s_out, "identity_len=%d identity=%s\n", 1426f9291ceSJung-uk Kim (int)strlen(identity), identity); 1431f13597dSJung-uk Kim 1441f13597dSJung-uk Kim /* here we could lookup the given identity e.g. from a database */ 1456f9291ceSJung-uk Kim if (strcmp(identity, psk_identity) != 0) { 146e71b7053SJung-uk Kim BIO_printf(bio_s_out, "PSK warning: client identity not what we expected" 1476f9291ceSJung-uk Kim " (got '%s' expected '%s')\n", identity, psk_identity); 148e71b7053SJung-uk Kim } else { 1491f13597dSJung-uk Kim if (s_debug) 1501f13597dSJung-uk Kim BIO_printf(bio_s_out, "PSK client identity found\n"); 151e71b7053SJung-uk Kim } 1521f13597dSJung-uk Kim 1531f13597dSJung-uk Kim /* convert the PSK key to binary */ 154e71b7053SJung-uk Kim key = OPENSSL_hexstr2buf(psk_key, &key_len); 155aeb5019cSJung-uk Kim if (key == NULL) { 156aeb5019cSJung-uk Kim BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", 1576f9291ceSJung-uk Kim psk_key); 1581f13597dSJung-uk Kim return 0; 1591f13597dSJung-uk Kim } 160aeb5019cSJung-uk Kim if (key_len > (int)max_psk_len) { 1616f9291ceSJung-uk Kim BIO_printf(bio_err, 162aeb5019cSJung-uk Kim "psk buffer of callback is too small (%d) for key (%ld)\n", 163aeb5019cSJung-uk Kim max_psk_len, key_len); 164aeb5019cSJung-uk Kim OPENSSL_free(key); 1651f13597dSJung-uk Kim return 0; 1661f13597dSJung-uk Kim } 1671f13597dSJung-uk Kim 168aeb5019cSJung-uk Kim memcpy(psk, key, key_len); 169aeb5019cSJung-uk Kim OPENSSL_free(key); 1701f13597dSJung-uk Kim 1711f13597dSJung-uk Kim if (s_debug) 172aeb5019cSJung-uk Kim BIO_printf(bio_s_out, "fetched PSK len=%ld\n", key_len); 173aeb5019cSJung-uk Kim return key_len; 1741f13597dSJung-uk Kim out_err: 1751f13597dSJung-uk Kim if (s_debug) 1761f13597dSJung-uk Kim BIO_printf(bio_err, "Error in PSK server callback\n"); 177e71b7053SJung-uk Kim (void)BIO_flush(bio_err); 178e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 1791f13597dSJung-uk Kim return 0; 1801f13597dSJung-uk Kim } 1811f13597dSJung-uk Kim #endif 1821f13597dSJung-uk Kim 183e71b7053SJung-uk Kim #define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") 184e71b7053SJung-uk Kim #define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") 185e71b7053SJung-uk Kim 186e71b7053SJung-uk Kim static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, 187e71b7053SJung-uk Kim size_t identity_len, SSL_SESSION **sess) 188e71b7053SJung-uk Kim { 189e71b7053SJung-uk Kim SSL_SESSION *tmpsess = NULL; 190e71b7053SJung-uk Kim unsigned char *key; 191e71b7053SJung-uk Kim long key_len; 192e71b7053SJung-uk Kim const SSL_CIPHER *cipher = NULL; 193e71b7053SJung-uk Kim 194e71b7053SJung-uk Kim if (strlen(psk_identity) != identity_len 195e71b7053SJung-uk Kim || memcmp(psk_identity, identity, identity_len) != 0) { 196*c9cf7b5cSJung-uk Kim *sess = NULL; 197*c9cf7b5cSJung-uk Kim return 1; 198e71b7053SJung-uk Kim } 199e71b7053SJung-uk Kim 200e71b7053SJung-uk Kim if (psksess != NULL) { 201e71b7053SJung-uk Kim SSL_SESSION_up_ref(psksess); 202e71b7053SJung-uk Kim *sess = psksess; 203e71b7053SJung-uk Kim return 1; 204e71b7053SJung-uk Kim } 205e71b7053SJung-uk Kim 206e71b7053SJung-uk Kim key = OPENSSL_hexstr2buf(psk_key, &key_len); 207e71b7053SJung-uk Kim if (key == NULL) { 208e71b7053SJung-uk Kim BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n", 209e71b7053SJung-uk Kim psk_key); 210e71b7053SJung-uk Kim return 0; 211e71b7053SJung-uk Kim } 212e71b7053SJung-uk Kim 213e71b7053SJung-uk Kim /* We default to SHA256 */ 214e71b7053SJung-uk Kim cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); 215e71b7053SJung-uk Kim if (cipher == NULL) { 216e71b7053SJung-uk Kim BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); 217e71b7053SJung-uk Kim OPENSSL_free(key); 218e71b7053SJung-uk Kim return 0; 219e71b7053SJung-uk Kim } 220e71b7053SJung-uk Kim 221e71b7053SJung-uk Kim tmpsess = SSL_SESSION_new(); 222e71b7053SJung-uk Kim if (tmpsess == NULL 223e71b7053SJung-uk Kim || !SSL_SESSION_set1_master_key(tmpsess, key, key_len) 224e71b7053SJung-uk Kim || !SSL_SESSION_set_cipher(tmpsess, cipher) 225e71b7053SJung-uk Kim || !SSL_SESSION_set_protocol_version(tmpsess, SSL_version(ssl))) { 226e71b7053SJung-uk Kim OPENSSL_free(key); 227e71b7053SJung-uk Kim return 0; 228e71b7053SJung-uk Kim } 229e71b7053SJung-uk Kim OPENSSL_free(key); 230e71b7053SJung-uk Kim *sess = tmpsess; 231e71b7053SJung-uk Kim 232e71b7053SJung-uk Kim return 1; 233e71b7053SJung-uk Kim } 234e71b7053SJung-uk Kim 2351f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 2361f13597dSJung-uk Kim /* This is a context that we pass to callbacks */ 2376f9291ceSJung-uk Kim typedef struct srpsrvparm_st { 2381f13597dSJung-uk Kim char *login; 2391f13597dSJung-uk Kim SRP_VBASE *vb; 2401f13597dSJung-uk Kim SRP_user_pwd *user; 2411f13597dSJung-uk Kim } srpsrvparm; 242e71b7053SJung-uk Kim static srpsrvparm srp_callback_parm; 2431f13597dSJung-uk Kim 2446f9291ceSJung-uk Kim /* 2456f9291ceSJung-uk Kim * This callback pretends to require some asynchronous logic in order to 2466f9291ceSJung-uk Kim * obtain a verifier. When the callback is called for a new connection we 2476f9291ceSJung-uk Kim * return with a negative value. This will provoke the accept etc to return 2486f9291ceSJung-uk Kim * with an LOOKUP_X509. The main logic of the reinvokes the suspended call 2496f9291ceSJung-uk Kim * (which would normally occur after a worker has finished) and we set the 2506f9291ceSJung-uk Kim * user parameters. 2511f13597dSJung-uk Kim */ 252e71b7053SJung-uk Kim static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) 2531f13597dSJung-uk Kim { 2541f13597dSJung-uk Kim srpsrvparm *p = (srpsrvparm *) arg; 2554c6a0400SJung-uk Kim int ret = SSL3_AL_FATAL; 2564c6a0400SJung-uk Kim 2576f9291ceSJung-uk Kim if (p->login == NULL && p->user == NULL) { 2581f13597dSJung-uk Kim p->login = SSL_get_srp_username(s); 2591f13597dSJung-uk Kim BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login); 260e71b7053SJung-uk Kim return -1; 2611f13597dSJung-uk Kim } 2621f13597dSJung-uk Kim 2636f9291ceSJung-uk Kim if (p->user == NULL) { 2641f13597dSJung-uk Kim BIO_printf(bio_err, "User %s doesn't exist\n", p->login); 2654c6a0400SJung-uk Kim goto err; 2661f13597dSJung-uk Kim } 2674c6a0400SJung-uk Kim 2686f9291ceSJung-uk Kim if (SSL_set_srp_server_param 2696f9291ceSJung-uk Kim (s, p->user->N, p->user->g, p->user->s, p->user->v, 2706f9291ceSJung-uk Kim p->user->info) < 0) { 2711f13597dSJung-uk Kim *ad = SSL_AD_INTERNAL_ERROR; 2724c6a0400SJung-uk Kim goto err; 2731f13597dSJung-uk Kim } 2746f9291ceSJung-uk Kim BIO_printf(bio_err, 2756f9291ceSJung-uk Kim "SRP parameters set: username = \"%s\" info=\"%s\" \n", 2766f9291ceSJung-uk Kim p->login, p->user->info); 2774c6a0400SJung-uk Kim ret = SSL_ERROR_NONE; 2784c6a0400SJung-uk Kim 2794c6a0400SJung-uk Kim err: 2804c6a0400SJung-uk Kim SRP_user_pwd_free(p->user); 2811f13597dSJung-uk Kim p->user = NULL; 2821f13597dSJung-uk Kim p->login = NULL; 2834c6a0400SJung-uk Kim return ret; 2841f13597dSJung-uk Kim } 2851f13597dSJung-uk Kim 2861f13597dSJung-uk Kim #endif 2871f13597dSJung-uk Kim 28874664626SKris Kennaway static int local_argc = 0; 28974664626SKris Kennaway static char **local_argv; 29074664626SKris Kennaway 29174664626SKris Kennaway #ifdef CHARSET_EBCDIC 29274664626SKris Kennaway static int ebcdic_new(BIO *bi); 29374664626SKris Kennaway static int ebcdic_free(BIO *a); 29474664626SKris Kennaway static int ebcdic_read(BIO *b, char *out, int outl); 2955c87c606SMark Murray static int ebcdic_write(BIO *b, const char *in, int inl); 2965c87c606SMark Murray static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr); 29774664626SKris Kennaway static int ebcdic_gets(BIO *bp, char *buf, int size); 2985c87c606SMark Murray static int ebcdic_puts(BIO *bp, const char *str); 29974664626SKris Kennaway 30074664626SKris Kennaway # define BIO_TYPE_EBCDIC_FILTER (18|0x0200) 301e71b7053SJung-uk Kim static BIO_METHOD *methods_ebcdic = NULL; 30274664626SKris Kennaway 303e71b7053SJung-uk Kim /* This struct is "unwarranted chumminess with the compiler." */ 3046f9291ceSJung-uk Kim typedef struct { 30574664626SKris Kennaway size_t alloced; 30674664626SKris Kennaway char buff[1]; 30774664626SKris Kennaway } EBCDIC_OUTBUFF; 30874664626SKris Kennaway 309e71b7053SJung-uk Kim static const BIO_METHOD *BIO_f_ebcdic_filter() 31074664626SKris Kennaway { 311e71b7053SJung-uk Kim if (methods_ebcdic == NULL) { 312e71b7053SJung-uk Kim methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER, 313e71b7053SJung-uk Kim "EBCDIC/ASCII filter"); 314e71b7053SJung-uk Kim if (methods_ebcdic == NULL 315e71b7053SJung-uk Kim || !BIO_meth_set_write(methods_ebcdic, ebcdic_write) 316e71b7053SJung-uk Kim || !BIO_meth_set_read(methods_ebcdic, ebcdic_read) 317e71b7053SJung-uk Kim || !BIO_meth_set_puts(methods_ebcdic, ebcdic_puts) 318e71b7053SJung-uk Kim || !BIO_meth_set_gets(methods_ebcdic, ebcdic_gets) 319e71b7053SJung-uk Kim || !BIO_meth_set_ctrl(methods_ebcdic, ebcdic_ctrl) 320e71b7053SJung-uk Kim || !BIO_meth_set_create(methods_ebcdic, ebcdic_new) 321e71b7053SJung-uk Kim || !BIO_meth_set_destroy(methods_ebcdic, ebcdic_free)) 322e71b7053SJung-uk Kim return NULL; 323e71b7053SJung-uk Kim } 324e71b7053SJung-uk Kim return methods_ebcdic; 32574664626SKris Kennaway } 32674664626SKris Kennaway 32774664626SKris Kennaway static int ebcdic_new(BIO *bi) 32874664626SKris Kennaway { 32974664626SKris Kennaway EBCDIC_OUTBUFF *wbuf; 33074664626SKris Kennaway 331e71b7053SJung-uk Kim wbuf = app_malloc(sizeof(*wbuf) + 1024, "ebcdic wbuf"); 33274664626SKris Kennaway wbuf->alloced = 1024; 33374664626SKris Kennaway wbuf->buff[0] = '\0'; 33474664626SKris Kennaway 335e71b7053SJung-uk Kim BIO_set_data(bi, wbuf); 336e71b7053SJung-uk Kim BIO_set_init(bi, 1); 337e71b7053SJung-uk Kim return 1; 33874664626SKris Kennaway } 33974664626SKris Kennaway 34074664626SKris Kennaway static int ebcdic_free(BIO *a) 34174664626SKris Kennaway { 342e71b7053SJung-uk Kim EBCDIC_OUTBUFF *wbuf; 343e71b7053SJung-uk Kim 3446f9291ceSJung-uk Kim if (a == NULL) 345e71b7053SJung-uk Kim return 0; 346e71b7053SJung-uk Kim wbuf = BIO_get_data(a); 347e71b7053SJung-uk Kim OPENSSL_free(wbuf); 348e71b7053SJung-uk Kim BIO_set_data(a, NULL); 349e71b7053SJung-uk Kim BIO_set_init(a, 0); 350e71b7053SJung-uk Kim 351e71b7053SJung-uk Kim return 1; 35274664626SKris Kennaway } 35374664626SKris Kennaway 35474664626SKris Kennaway static int ebcdic_read(BIO *b, char *out, int outl) 35574664626SKris Kennaway { 35674664626SKris Kennaway int ret = 0; 357e71b7053SJung-uk Kim BIO *next = BIO_next(b); 35874664626SKris Kennaway 3596f9291ceSJung-uk Kim if (out == NULL || outl == 0) 360e71b7053SJung-uk Kim return 0; 361e71b7053SJung-uk Kim if (next == NULL) 362e71b7053SJung-uk Kim return 0; 36374664626SKris Kennaway 364e71b7053SJung-uk Kim ret = BIO_read(next, out, outl); 36574664626SKris Kennaway if (ret > 0) 36674664626SKris Kennaway ascii2ebcdic(out, out, ret); 367e71b7053SJung-uk Kim return ret; 36874664626SKris Kennaway } 36974664626SKris Kennaway 3705c87c606SMark Murray static int ebcdic_write(BIO *b, const char *in, int inl) 37174664626SKris Kennaway { 37274664626SKris Kennaway EBCDIC_OUTBUFF *wbuf; 373e71b7053SJung-uk Kim BIO *next = BIO_next(b); 37474664626SKris Kennaway int ret = 0; 37574664626SKris Kennaway int num; 37674664626SKris Kennaway 3776f9291ceSJung-uk Kim if ((in == NULL) || (inl <= 0)) 378e71b7053SJung-uk Kim return 0; 379e71b7053SJung-uk Kim if (next == NULL) 380e71b7053SJung-uk Kim return 0; 38174664626SKris Kennaway 382e71b7053SJung-uk Kim wbuf = (EBCDIC_OUTBUFF *) BIO_get_data(b); 38374664626SKris Kennaway 3846f9291ceSJung-uk Kim if (inl > (num = wbuf->alloced)) { 38574664626SKris Kennaway num = num + num; /* double the size */ 38674664626SKris Kennaway if (num < inl) 38774664626SKris Kennaway num = inl; 388e71b7053SJung-uk Kim OPENSSL_free(wbuf); 389e71b7053SJung-uk Kim wbuf = app_malloc(sizeof(*wbuf) + num, "grow ebcdic wbuf"); 39074664626SKris Kennaway 39174664626SKris Kennaway wbuf->alloced = num; 39274664626SKris Kennaway wbuf->buff[0] = '\0'; 39374664626SKris Kennaway 394e71b7053SJung-uk Kim BIO_set_data(b, wbuf); 39574664626SKris Kennaway } 39674664626SKris Kennaway 39774664626SKris Kennaway ebcdic2ascii(wbuf->buff, in, inl); 39874664626SKris Kennaway 399e71b7053SJung-uk Kim ret = BIO_write(next, wbuf->buff, inl); 40074664626SKris Kennaway 401e71b7053SJung-uk Kim return ret; 40274664626SKris Kennaway } 40374664626SKris Kennaway 4045c87c606SMark Murray static long ebcdic_ctrl(BIO *b, int cmd, long num, void *ptr) 40574664626SKris Kennaway { 40674664626SKris Kennaway long ret; 407e71b7053SJung-uk Kim BIO *next = BIO_next(b); 40874664626SKris Kennaway 409e71b7053SJung-uk Kim if (next == NULL) 410e71b7053SJung-uk Kim return 0; 4116f9291ceSJung-uk Kim switch (cmd) { 41274664626SKris Kennaway case BIO_CTRL_DUP: 41374664626SKris Kennaway ret = 0L; 41474664626SKris Kennaway break; 41574664626SKris Kennaway default: 416e71b7053SJung-uk Kim ret = BIO_ctrl(next, cmd, num, ptr); 41774664626SKris Kennaway break; 41874664626SKris Kennaway } 419e71b7053SJung-uk Kim return ret; 42074664626SKris Kennaway } 42174664626SKris Kennaway 42274664626SKris Kennaway static int ebcdic_gets(BIO *bp, char *buf, int size) 42374664626SKris Kennaway { 4245c87c606SMark Murray int i, ret = 0; 425e71b7053SJung-uk Kim BIO *next = BIO_next(bp); 426e71b7053SJung-uk Kim 427e71b7053SJung-uk Kim if (next == NULL) 428e71b7053SJung-uk Kim return 0; 42974664626SKris Kennaway /* return(BIO_gets(bp->next_bio,buf,size));*/ 4306f9291ceSJung-uk Kim for (i = 0; i < size - 1; ++i) { 43174664626SKris Kennaway ret = ebcdic_read(bp, &buf[i], 1); 43274664626SKris Kennaway if (ret <= 0) 43374664626SKris Kennaway break; 4346f9291ceSJung-uk Kim else if (buf[i] == '\n') { 43574664626SKris Kennaway ++i; 43674664626SKris Kennaway break; 43774664626SKris Kennaway } 43874664626SKris Kennaway } 43974664626SKris Kennaway if (i < size) 44074664626SKris Kennaway buf[i] = '\0'; 44174664626SKris Kennaway return (ret < 0 && i == 0) ? ret : i; 44274664626SKris Kennaway } 44374664626SKris Kennaway 4445c87c606SMark Murray static int ebcdic_puts(BIO *bp, const char *str) 44574664626SKris Kennaway { 446e71b7053SJung-uk Kim if (BIO_next(bp) == NULL) 447e71b7053SJung-uk Kim return 0; 44874664626SKris Kennaway return ebcdic_write(bp, str, strlen(str)); 44974664626SKris Kennaway } 45074664626SKris Kennaway #endif 45174664626SKris Kennaway 452db522d3aSSimon L. B. Nielsen /* This is a context that we pass to callbacks */ 453db522d3aSSimon L. B. Nielsen typedef struct tlsextctx_st { 454db522d3aSSimon L. B. Nielsen char *servername; 455db522d3aSSimon L. B. Nielsen BIO *biodebug; 456db522d3aSSimon L. B. Nielsen int extension_error; 457db522d3aSSimon L. B. Nielsen } tlsextctx; 458db522d3aSSimon L. B. Nielsen 459e71b7053SJung-uk Kim static int ssl_servername_cb(SSL *s, int *ad, void *arg) 460db522d3aSSimon L. B. Nielsen { 461db522d3aSSimon L. B. Nielsen tlsextctx *p = (tlsextctx *) arg; 462db522d3aSSimon L. B. Nielsen const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); 463db522d3aSSimon L. B. Nielsen 464e71b7053SJung-uk Kim if (servername != NULL && p->biodebug != NULL) { 465e71b7053SJung-uk Kim const char *cp = servername; 466e71b7053SJung-uk Kim unsigned char uc; 467e71b7053SJung-uk Kim 468e71b7053SJung-uk Kim BIO_printf(p->biodebug, "Hostname in TLS extension: \""); 469e71b7053SJung-uk Kim while ((uc = *cp++) != 0) 470e71b7053SJung-uk Kim BIO_printf(p->biodebug, 471e71b7053SJung-uk Kim isascii(uc) && isprint(uc) ? "%c" : "\\x%02x", uc); 472e71b7053SJung-uk Kim BIO_printf(p->biodebug, "\"\n"); 473e71b7053SJung-uk Kim } 474e71b7053SJung-uk Kim 475e71b7053SJung-uk Kim if (p->servername == NULL) 476db522d3aSSimon L. B. Nielsen return SSL_TLSEXT_ERR_NOACK; 477db522d3aSSimon L. B. Nielsen 478e71b7053SJung-uk Kim if (servername != NULL) { 479a93cbc2bSJung-uk Kim if (strcasecmp(servername, p->servername)) 480db522d3aSSimon L. B. Nielsen return p->extension_error; 481e71b7053SJung-uk Kim if (ctx2 != NULL) { 4821f13597dSJung-uk Kim BIO_printf(p->biodebug, "Switching server context.\n"); 483db522d3aSSimon L. B. Nielsen SSL_set_SSL_CTX(s, ctx2); 484db522d3aSSimon L. B. Nielsen } 485db522d3aSSimon L. B. Nielsen } 486db522d3aSSimon L. B. Nielsen return SSL_TLSEXT_ERR_OK; 487db522d3aSSimon L. B. Nielsen } 488db522d3aSSimon L. B. Nielsen 489db522d3aSSimon L. B. Nielsen /* Structure passed to cert status callback */ 490db522d3aSSimon L. B. Nielsen typedef struct tlsextstatusctx_st { 491e71b7053SJung-uk Kim int timeout; 492e71b7053SJung-uk Kim /* File to load OCSP Response from (or NULL if no file) */ 493e71b7053SJung-uk Kim char *respin; 494db522d3aSSimon L. B. Nielsen /* Default responder to use */ 495db522d3aSSimon L. B. Nielsen char *host, *path, *port; 496db522d3aSSimon L. B. Nielsen int use_ssl; 497db522d3aSSimon L. B. Nielsen int verbose; 498db522d3aSSimon L. B. Nielsen } tlsextstatusctx; 499db522d3aSSimon L. B. Nielsen 500e71b7053SJung-uk Kim static tlsextstatusctx tlscstatp = { -1 }; 501e71b7053SJung-uk Kim 502e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 503db522d3aSSimon L. B. Nielsen 5046f9291ceSJung-uk Kim /* 505e71b7053SJung-uk Kim * Helper function to get an OCSP_RESPONSE from a responder. This is a 506e71b7053SJung-uk Kim * simplified version. It examines certificates each time and makes one OCSP 507e71b7053SJung-uk Kim * responder query for each request. A full version would store details such as 508e71b7053SJung-uk Kim * the OCSP certificate IDs and minimise the number of OCSP responses by caching 509e71b7053SJung-uk Kim * them until they were considered "expired". 510db522d3aSSimon L. B. Nielsen */ 511e71b7053SJung-uk Kim static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, 512e71b7053SJung-uk Kim OCSP_RESPONSE **resp) 513db522d3aSSimon L. B. Nielsen { 514e71b7053SJung-uk Kim char *host = NULL, *port = NULL, *path = NULL; 515db522d3aSSimon L. B. Nielsen int use_ssl; 5161f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *aia = NULL; 517db522d3aSSimon L. B. Nielsen X509 *x = NULL; 518e71b7053SJung-uk Kim X509_STORE_CTX *inctx = NULL; 519e71b7053SJung-uk Kim X509_OBJECT *obj; 520db522d3aSSimon L. B. Nielsen OCSP_REQUEST *req = NULL; 521db522d3aSSimon L. B. Nielsen OCSP_CERTID *id = NULL; 522db522d3aSSimon L. B. Nielsen STACK_OF(X509_EXTENSION) *exts; 523db522d3aSSimon L. B. Nielsen int ret = SSL_TLSEXT_ERR_NOACK; 524db522d3aSSimon L. B. Nielsen int i; 525e71b7053SJung-uk Kim 526db522d3aSSimon L. B. Nielsen /* Build up OCSP query from server certificate */ 527db522d3aSSimon L. B. Nielsen x = SSL_get_certificate(s); 528db522d3aSSimon L. B. Nielsen aia = X509_get1_ocsp(x); 529e71b7053SJung-uk Kim if (aia != NULL) { 5301f13597dSJung-uk Kim if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0), 5316f9291ceSJung-uk Kim &host, &port, &path, &use_ssl)) { 532e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: can't parse AIA URL\n"); 533db522d3aSSimon L. B. Nielsen goto err; 534db522d3aSSimon L. B. Nielsen } 535db522d3aSSimon L. B. Nielsen if (srctx->verbose) 536e71b7053SJung-uk Kim BIO_printf(bio_err, "cert_status: AIA URL: %s\n", 5371f13597dSJung-uk Kim sk_OPENSSL_STRING_value(aia, 0)); 5386f9291ceSJung-uk Kim } else { 539e71b7053SJung-uk Kim if (srctx->host == NULL) { 540e71b7053SJung-uk Kim BIO_puts(bio_err, 5416f9291ceSJung-uk Kim "cert_status: no AIA and no default responder URL\n"); 542db522d3aSSimon L. B. Nielsen goto done; 543db522d3aSSimon L. B. Nielsen } 544db522d3aSSimon L. B. Nielsen host = srctx->host; 545db522d3aSSimon L. B. Nielsen path = srctx->path; 546db522d3aSSimon L. B. Nielsen port = srctx->port; 547db522d3aSSimon L. B. Nielsen use_ssl = srctx->use_ssl; 548db522d3aSSimon L. B. Nielsen } 549db522d3aSSimon L. B. Nielsen 550e71b7053SJung-uk Kim inctx = X509_STORE_CTX_new(); 551e71b7053SJung-uk Kim if (inctx == NULL) 552e71b7053SJung-uk Kim goto err; 553e71b7053SJung-uk Kim if (!X509_STORE_CTX_init(inctx, 554db522d3aSSimon L. B. Nielsen SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)), 555db522d3aSSimon L. B. Nielsen NULL, NULL)) 556db522d3aSSimon L. B. Nielsen goto err; 557e71b7053SJung-uk Kim obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509, 558e71b7053SJung-uk Kim X509_get_issuer_name(x)); 559e71b7053SJung-uk Kim if (obj == NULL) { 560e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n"); 561db522d3aSSimon L. B. Nielsen goto done; 562db522d3aSSimon L. B. Nielsen } 563e71b7053SJung-uk Kim id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj)); 564e71b7053SJung-uk Kim X509_OBJECT_free(obj); 565e71b7053SJung-uk Kim if (id == NULL) 566db522d3aSSimon L. B. Nielsen goto err; 567e71b7053SJung-uk Kim req = OCSP_REQUEST_new(); 568e71b7053SJung-uk Kim if (req == NULL) 569db522d3aSSimon L. B. Nielsen goto err; 570db522d3aSSimon L. B. Nielsen if (!OCSP_request_add0_id(req, id)) 571db522d3aSSimon L. B. Nielsen goto err; 572db522d3aSSimon L. B. Nielsen id = NULL; 573db522d3aSSimon L. B. Nielsen /* Add any extensions to the request */ 574db522d3aSSimon L. B. Nielsen SSL_get_tlsext_status_exts(s, &exts); 5756f9291ceSJung-uk Kim for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 576db522d3aSSimon L. B. Nielsen X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); 577db522d3aSSimon L. B. Nielsen if (!OCSP_REQUEST_add_ext(req, ext, -1)) 578db522d3aSSimon L. B. Nielsen goto err; 579db522d3aSSimon L. B. Nielsen } 580e71b7053SJung-uk Kim *resp = process_responder(req, host, path, port, use_ssl, NULL, 581db522d3aSSimon L. B. Nielsen srctx->timeout); 582e71b7053SJung-uk Kim if (*resp == NULL) { 583e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: error querying responder\n"); 584db522d3aSSimon L. B. Nielsen goto done; 585db522d3aSSimon L. B. Nielsen } 586e71b7053SJung-uk Kim 587db522d3aSSimon L. B. Nielsen ret = SSL_TLSEXT_ERR_OK; 588e71b7053SJung-uk Kim goto done; 589e71b7053SJung-uk Kim 590e71b7053SJung-uk Kim err: 591e71b7053SJung-uk Kim ret = SSL_TLSEXT_ERR_ALERT_FATAL; 592db522d3aSSimon L. B. Nielsen done: 593e71b7053SJung-uk Kim /* 594e71b7053SJung-uk Kim * If we parsed aia we need to free; otherwise they were copied and we 595e71b7053SJung-uk Kim * don't 596e71b7053SJung-uk Kim */ 597e71b7053SJung-uk Kim if (aia != NULL) { 598db522d3aSSimon L. B. Nielsen OPENSSL_free(host); 599db522d3aSSimon L. B. Nielsen OPENSSL_free(path); 600db522d3aSSimon L. B. Nielsen OPENSSL_free(port); 601db522d3aSSimon L. B. Nielsen X509_email_free(aia); 602db522d3aSSimon L. B. Nielsen } 603db522d3aSSimon L. B. Nielsen OCSP_CERTID_free(id); 604db522d3aSSimon L. B. Nielsen OCSP_REQUEST_free(req); 605e71b7053SJung-uk Kim X509_STORE_CTX_free(inctx); 606db522d3aSSimon L. B. Nielsen return ret; 607db522d3aSSimon L. B. Nielsen } 6081f13597dSJung-uk Kim 609e71b7053SJung-uk Kim /* 610e71b7053SJung-uk Kim * Certificate Status callback. This is called when a client includes a 611e71b7053SJung-uk Kim * certificate status request extension. The response is either obtained from a 612e71b7053SJung-uk Kim * file, or from an OCSP responder. 613e71b7053SJung-uk Kim */ 614e71b7053SJung-uk Kim static int cert_status_cb(SSL *s, void *arg) 615e71b7053SJung-uk Kim { 616e71b7053SJung-uk Kim tlsextstatusctx *srctx = arg; 617e71b7053SJung-uk Kim OCSP_RESPONSE *resp = NULL; 618e71b7053SJung-uk Kim unsigned char *rspder = NULL; 619e71b7053SJung-uk Kim int rspderlen; 620e71b7053SJung-uk Kim int ret = SSL_TLSEXT_ERR_ALERT_FATAL; 621e71b7053SJung-uk Kim 622e71b7053SJung-uk Kim if (srctx->verbose) 623e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: callback called\n"); 624e71b7053SJung-uk Kim 625e71b7053SJung-uk Kim if (srctx->respin != NULL) { 626e71b7053SJung-uk Kim BIO *derbio = bio_open_default(srctx->respin, 'r', FORMAT_ASN1); 627e71b7053SJung-uk Kim if (derbio == NULL) { 628e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: Cannot open OCSP response file\n"); 629e71b7053SJung-uk Kim goto err; 630e71b7053SJung-uk Kim } 631e71b7053SJung-uk Kim resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); 632e71b7053SJung-uk Kim BIO_free(derbio); 633e71b7053SJung-uk Kim if (resp == NULL) { 634e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: Error reading OCSP response\n"); 635e71b7053SJung-uk Kim goto err; 636e71b7053SJung-uk Kim } 637e71b7053SJung-uk Kim } else { 638e71b7053SJung-uk Kim ret = get_ocsp_resp_from_responder(s, srctx, &resp); 639e71b7053SJung-uk Kim if (ret != SSL_TLSEXT_ERR_OK) 640e71b7053SJung-uk Kim goto err; 641e71b7053SJung-uk Kim } 642e71b7053SJung-uk Kim 643e71b7053SJung-uk Kim rspderlen = i2d_OCSP_RESPONSE(resp, &rspder); 644e71b7053SJung-uk Kim if (rspderlen <= 0) 645e71b7053SJung-uk Kim goto err; 646e71b7053SJung-uk Kim 647e71b7053SJung-uk Kim SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen); 648e71b7053SJung-uk Kim if (srctx->verbose) { 649e71b7053SJung-uk Kim BIO_puts(bio_err, "cert_status: ocsp response sent:\n"); 650e71b7053SJung-uk Kim OCSP_RESPONSE_print(bio_err, resp, 2); 651e71b7053SJung-uk Kim } 652e71b7053SJung-uk Kim 653e71b7053SJung-uk Kim ret = SSL_TLSEXT_ERR_OK; 654e71b7053SJung-uk Kim 655e71b7053SJung-uk Kim err: 656e71b7053SJung-uk Kim if (ret != SSL_TLSEXT_ERR_OK) 657e71b7053SJung-uk Kim ERR_print_errors(bio_err); 658e71b7053SJung-uk Kim 659e71b7053SJung-uk Kim OCSP_RESPONSE_free(resp); 660e71b7053SJung-uk Kim 661e71b7053SJung-uk Kim return ret; 662e71b7053SJung-uk Kim } 663e71b7053SJung-uk Kim #endif 664e71b7053SJung-uk Kim 6651f13597dSJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 6661f13597dSJung-uk Kim /* This is the context that we pass to next_proto_cb */ 6671f13597dSJung-uk Kim typedef struct tlsextnextprotoctx_st { 6681f13597dSJung-uk Kim unsigned char *data; 669e71b7053SJung-uk Kim size_t len; 6701f13597dSJung-uk Kim } tlsextnextprotoctx; 6711f13597dSJung-uk Kim 6726f9291ceSJung-uk Kim static int next_proto_cb(SSL *s, const unsigned char **data, 6736f9291ceSJung-uk Kim unsigned int *len, void *arg) 6741f13597dSJung-uk Kim { 6751f13597dSJung-uk Kim tlsextnextprotoctx *next_proto = arg; 6761f13597dSJung-uk Kim 6771f13597dSJung-uk Kim *data = next_proto->data; 6781f13597dSJung-uk Kim *len = next_proto->len; 6791f13597dSJung-uk Kim 6801f13597dSJung-uk Kim return SSL_TLSEXT_ERR_OK; 6811f13597dSJung-uk Kim } 6821f13597dSJung-uk Kim #endif /* ndef OPENSSL_NO_NEXTPROTONEG */ 6831f13597dSJung-uk Kim 6847bded2dbSJung-uk Kim /* This the context that we pass to alpn_cb */ 6857bded2dbSJung-uk Kim typedef struct tlsextalpnctx_st { 6867bded2dbSJung-uk Kim unsigned char *data; 687e71b7053SJung-uk Kim size_t len; 6887bded2dbSJung-uk Kim } tlsextalpnctx; 6897bded2dbSJung-uk Kim 6907bded2dbSJung-uk Kim static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, 6917bded2dbSJung-uk Kim const unsigned char *in, unsigned int inlen, void *arg) 6927bded2dbSJung-uk Kim { 6937bded2dbSJung-uk Kim tlsextalpnctx *alpn_ctx = arg; 6947bded2dbSJung-uk Kim 6957bded2dbSJung-uk Kim if (!s_quiet) { 6967bded2dbSJung-uk Kim /* We can assume that |in| is syntactically valid. */ 697e71b7053SJung-uk Kim unsigned int i; 6987bded2dbSJung-uk Kim BIO_printf(bio_s_out, "ALPN protocols advertised by the client: "); 6997bded2dbSJung-uk Kim for (i = 0; i < inlen;) { 7007bded2dbSJung-uk Kim if (i) 7017bded2dbSJung-uk Kim BIO_write(bio_s_out, ", ", 2); 7027bded2dbSJung-uk Kim BIO_write(bio_s_out, &in[i + 1], in[i]); 7037bded2dbSJung-uk Kim i += in[i] + 1; 7047bded2dbSJung-uk Kim } 7057bded2dbSJung-uk Kim BIO_write(bio_s_out, "\n", 1); 7067bded2dbSJung-uk Kim } 7077bded2dbSJung-uk Kim 7087bded2dbSJung-uk Kim if (SSL_select_next_proto 7097bded2dbSJung-uk Kim ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in, 7107bded2dbSJung-uk Kim inlen) != OPENSSL_NPN_NEGOTIATED) { 7117bded2dbSJung-uk Kim return SSL_TLSEXT_ERR_NOACK; 7127bded2dbSJung-uk Kim } 7137bded2dbSJung-uk Kim 7147bded2dbSJung-uk Kim if (!s_quiet) { 7157bded2dbSJung-uk Kim BIO_printf(bio_s_out, "ALPN protocols selected: "); 7167bded2dbSJung-uk Kim BIO_write(bio_s_out, *out, *outlen); 7177bded2dbSJung-uk Kim BIO_write(bio_s_out, "\n", 1); 7187bded2dbSJung-uk Kim } 7197bded2dbSJung-uk Kim 7207bded2dbSJung-uk Kim return SSL_TLSEXT_ERR_OK; 7217bded2dbSJung-uk Kim } 7221f13597dSJung-uk Kim 723e71b7053SJung-uk Kim static int not_resumable_sess_cb(SSL *s, int is_forward_secure) 724e71b7053SJung-uk Kim { 725e71b7053SJung-uk Kim /* disable resumption for sessions with forward secure ciphers */ 726e71b7053SJung-uk Kim return is_forward_secure; 727e71b7053SJung-uk Kim } 728f579bf8eSKris Kennaway 729e71b7053SJung-uk Kim typedef enum OPTION_choice { 730e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, 731e71b7053SJung-uk Kim OPT_4, OPT_6, OPT_ACCEPT, OPT_PORT, OPT_UNIX, OPT_UNLINK, OPT_NACCEPT, 732e71b7053SJung-uk Kim OPT_VERIFY, OPT_NAMEOPT, OPT_UPPER_V_VERIFY, OPT_CONTEXT, OPT_CERT, OPT_CRL, 733e71b7053SJung-uk Kim OPT_CRL_DOWNLOAD, OPT_SERVERINFO, OPT_CERTFORM, OPT_KEY, OPT_KEYFORM, 734e71b7053SJung-uk Kim OPT_PASS, OPT_CERT_CHAIN, OPT_DHPARAM, OPT_DCERTFORM, OPT_DCERT, 735e71b7053SJung-uk Kim OPT_DKEYFORM, OPT_DPASS, OPT_DKEY, OPT_DCERT_CHAIN, OPT_NOCERT, 736e71b7053SJung-uk Kim OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_NO_CACHE, 737e71b7053SJung-uk Kim OPT_EXT_CACHE, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, 738e71b7053SJung-uk Kim OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, 739e71b7053SJung-uk Kim OPT_VERIFYCAFILE, OPT_NBIO, OPT_NBIO_TEST, OPT_IGN_EOF, OPT_NO_IGN_EOF, 740e71b7053SJung-uk Kim OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_STATUS_VERBOSE, 741e71b7053SJung-uk Kim OPT_STATUS_TIMEOUT, OPT_STATUS_URL, OPT_STATUS_FILE, OPT_MSG, OPT_MSGFILE, 742e71b7053SJung-uk Kim OPT_TRACE, OPT_SECURITY_DEBUG, OPT_SECURITY_DEBUG_VERBOSE, OPT_STATE, 743e71b7053SJung-uk Kim OPT_CRLF, OPT_QUIET, OPT_BRIEF, OPT_NO_DHE, 744e71b7053SJung-uk Kim OPT_NO_RESUME_EPHEMERAL, OPT_PSK_IDENTITY, OPT_PSK_HINT, OPT_PSK, 745e71b7053SJung-uk Kim OPT_PSK_SESS, OPT_SRPVFILE, OPT_SRPUSERSEED, OPT_REV, OPT_WWW, 746e71b7053SJung-uk Kim OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC, OPT_SSL_CONFIG, 747e71b7053SJung-uk Kim OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, 748e71b7053SJung-uk Kim OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, 749e71b7053SJung-uk Kim OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS, 750e71b7053SJung-uk Kim OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL, 751e71b7053SJung-uk Kim OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN, 752e71b7053SJung-uk Kim OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, 753e71b7053SJung-uk Kim OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, 754e71b7053SJung-uk Kim OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, 755e71b7053SJung-uk Kim OPT_R_ENUM, 756e71b7053SJung-uk Kim OPT_S_ENUM, 757e71b7053SJung-uk Kim OPT_V_ENUM, 758e71b7053SJung-uk Kim OPT_X_ENUM 759e71b7053SJung-uk Kim } OPTION_CHOICE; 760e71b7053SJung-uk Kim 761e71b7053SJung-uk Kim const OPTIONS s_server_options[] = { 762e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 763e71b7053SJung-uk Kim {"port", OPT_PORT, 'p', 764e71b7053SJung-uk Kim "TCP/IP port to listen on for connections (default is " PORT ")"}, 765e71b7053SJung-uk Kim {"accept", OPT_ACCEPT, 's', 766e71b7053SJung-uk Kim "TCP/IP optional host and port to listen on for connections (default is *:" PORT ")"}, 767e71b7053SJung-uk Kim #ifdef AF_UNIX 768e71b7053SJung-uk Kim {"unix", OPT_UNIX, 's', "Unix domain socket to accept on"}, 769db522d3aSSimon L. B. Nielsen #endif 770e71b7053SJung-uk Kim {"4", OPT_4, '-', "Use IPv4 only"}, 771e71b7053SJung-uk Kim {"6", OPT_6, '-', "Use IPv6 only"}, 772e71b7053SJung-uk Kim #ifdef AF_UNIX 773e71b7053SJung-uk Kim {"unlink", OPT_UNLINK, '-', "For -unix, unlink existing socket first"}, 774e71b7053SJung-uk Kim #endif 775e71b7053SJung-uk Kim {"context", OPT_CONTEXT, 's', "Set session ID context"}, 776e71b7053SJung-uk Kim {"verify", OPT_VERIFY, 'n', "Turn on peer certificate verification"}, 777e71b7053SJung-uk Kim {"Verify", OPT_UPPER_V_VERIFY, 'n', 778e71b7053SJung-uk Kim "Turn on peer certificate verification, must have a cert"}, 779e71b7053SJung-uk Kim {"cert", OPT_CERT, '<', "Certificate file to use; default is " TEST_CERT}, 780e71b7053SJung-uk Kim {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 781e71b7053SJung-uk Kim {"naccept", OPT_NACCEPT, 'p', "Terminate after #num connections"}, 782e71b7053SJung-uk Kim {"serverinfo", OPT_SERVERINFO, 's', 783e71b7053SJung-uk Kim "PEM serverinfo file for certificate"}, 784e71b7053SJung-uk Kim {"certform", OPT_CERTFORM, 'F', 785e71b7053SJung-uk Kim "Certificate format (PEM or DER) PEM default"}, 786e71b7053SJung-uk Kim {"key", OPT_KEY, 's', 787e71b7053SJung-uk Kim "Private Key if not in -cert; default is " TEST_CERT}, 788e71b7053SJung-uk Kim {"keyform", OPT_KEYFORM, 'f', 789e71b7053SJung-uk Kim "Key format (PEM, DER or ENGINE) PEM default"}, 790e71b7053SJung-uk Kim {"pass", OPT_PASS, 's', "Private key file pass phrase source"}, 791e71b7053SJung-uk Kim {"dcert", OPT_DCERT, '<', 792e71b7053SJung-uk Kim "Second certificate file to use (usually for DSA)"}, 793e71b7053SJung-uk Kim {"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"}, 794e71b7053SJung-uk Kim {"dcertform", OPT_DCERTFORM, 'F', 795e71b7053SJung-uk Kim "Second certificate format (PEM or DER) PEM default"}, 796e71b7053SJung-uk Kim {"dkey", OPT_DKEY, '<', 797e71b7053SJung-uk Kim "Second private key file to use (usually for DSA)"}, 798e71b7053SJung-uk Kim {"dkeyform", OPT_DKEYFORM, 'F', 799e71b7053SJung-uk Kim "Second key format (PEM, DER or ENGINE) PEM default"}, 800e71b7053SJung-uk Kim {"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"}, 801e71b7053SJung-uk Kim {"nbio_test", OPT_NBIO_TEST, '-', "Test with the non-blocking test bio"}, 802e71b7053SJung-uk Kim {"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"}, 803e71b7053SJung-uk Kim {"debug", OPT_DEBUG, '-', "Print more output"}, 804e71b7053SJung-uk Kim {"msg", OPT_MSG, '-', "Show protocol messages"}, 805e71b7053SJung-uk Kim {"msgfile", OPT_MSGFILE, '>', 806e71b7053SJung-uk Kim "File to send output of -msg or -trace, instead of stdout"}, 807e71b7053SJung-uk Kim {"state", OPT_STATE, '-', "Print the SSL states"}, 808e71b7053SJung-uk Kim {"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"}, 809e71b7053SJung-uk Kim {"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"}, 810e71b7053SJung-uk Kim {"no-CAfile", OPT_NOCAFILE, '-', 811e71b7053SJung-uk Kim "Do not load the default certificates file"}, 812e71b7053SJung-uk Kim {"no-CApath", OPT_NOCAPATH, '-', 813e71b7053SJung-uk Kim "Do not load certificates from the default certificates directory"}, 814e71b7053SJung-uk Kim {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"}, 815e71b7053SJung-uk Kim {"quiet", OPT_QUIET, '-', "No server output"}, 816e71b7053SJung-uk Kim {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-', 817e71b7053SJung-uk Kim "Disable caching and tickets if ephemeral (EC)DH is used"}, 818e71b7053SJung-uk Kim {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"}, 819e71b7053SJung-uk Kim {"WWW", OPT_UPPER_WWW, '-', "Respond to a 'GET with the file ./path"}, 820e71b7053SJung-uk Kim {"servername", OPT_SERVERNAME, 's', 821e71b7053SJung-uk Kim "Servername for HostName TLS extension"}, 822e71b7053SJung-uk Kim {"servername_fatal", OPT_SERVERNAME_FATAL, '-', 823e71b7053SJung-uk Kim "mismatch send fatal alert (default warning alert)"}, 824e71b7053SJung-uk Kim {"cert2", OPT_CERT2, '<', 825e71b7053SJung-uk Kim "Certificate file to use for servername; default is" TEST_CERT2}, 826e71b7053SJung-uk Kim {"key2", OPT_KEY2, '<', 827e71b7053SJung-uk Kim "-Private Key file to use for servername if not in -cert2"}, 828e71b7053SJung-uk Kim {"tlsextdebug", OPT_TLSEXTDEBUG, '-', 829e71b7053SJung-uk Kim "Hex dump of all TLS extensions received"}, 830e71b7053SJung-uk Kim {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"}, 831e71b7053SJung-uk Kim {"id_prefix", OPT_ID_PREFIX, 's', 832e71b7053SJung-uk Kim "Generate SSL/TLS session IDs prefixed by arg"}, 833e71b7053SJung-uk Kim OPT_R_OPTIONS, 834e71b7053SJung-uk Kim {"keymatexport", OPT_KEYMATEXPORT, 's', 835e71b7053SJung-uk Kim "Export keying material using label"}, 836e71b7053SJung-uk Kim {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', 837e71b7053SJung-uk Kim "Export len bytes of keying material (default 20)"}, 838e71b7053SJung-uk Kim {"CRL", OPT_CRL, '<', "CRL file to use"}, 839e71b7053SJung-uk Kim {"crl_download", OPT_CRL_DOWNLOAD, '-', 840e71b7053SJung-uk Kim "Download CRL from distribution points"}, 841e71b7053SJung-uk Kim {"cert_chain", OPT_CERT_CHAIN, '<', 842e71b7053SJung-uk Kim "certificate chain file in PEM format"}, 843e71b7053SJung-uk Kim {"dcert_chain", OPT_DCERT_CHAIN, '<', 844e71b7053SJung-uk Kim "second certificate chain file in PEM format"}, 845e71b7053SJung-uk Kim {"chainCApath", OPT_CHAINCAPATH, '/', 846e71b7053SJung-uk Kim "use dir as certificate store path to build CA certificate chain"}, 847e71b7053SJung-uk Kim {"verifyCApath", OPT_VERIFYCAPATH, '/', 848e71b7053SJung-uk Kim "use dir as certificate store path to verify CA certificate"}, 849e71b7053SJung-uk Kim {"no_cache", OPT_NO_CACHE, '-', "Disable session cache"}, 850e71b7053SJung-uk Kim {"ext_cache", OPT_EXT_CACHE, '-', 851e71b7053SJung-uk Kim "Disable internal cache, setup and use external cache"}, 852e71b7053SJung-uk Kim {"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"}, 853e71b7053SJung-uk Kim {"verify_return_error", OPT_VERIFY_RET_ERROR, '-', 854e71b7053SJung-uk Kim "Close connection on verification error"}, 855e71b7053SJung-uk Kim {"verify_quiet", OPT_VERIFY_QUIET, '-', 856e71b7053SJung-uk Kim "No verify output except verify errors"}, 857e71b7053SJung-uk Kim {"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"}, 858e71b7053SJung-uk Kim {"chainCAfile", OPT_CHAINCAFILE, '<', 859e71b7053SJung-uk Kim "CA file for certificate chain (PEM format)"}, 860e71b7053SJung-uk Kim {"verifyCAfile", OPT_VERIFYCAFILE, '<', 861e71b7053SJung-uk Kim "CA file for certificate verification (PEM format)"}, 862e71b7053SJung-uk Kim {"ign_eof", OPT_IGN_EOF, '-', "ignore input eof (default when -quiet)"}, 863e71b7053SJung-uk Kim {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Do not ignore input eof"}, 864e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 865e71b7053SJung-uk Kim {"status", OPT_STATUS, '-', "Request certificate status from server"}, 866e71b7053SJung-uk Kim {"status_verbose", OPT_STATUS_VERBOSE, '-', 867e71b7053SJung-uk Kim "Print more output in certificate status callback"}, 868e71b7053SJung-uk Kim {"status_timeout", OPT_STATUS_TIMEOUT, 'n', 869e71b7053SJung-uk Kim "Status request responder timeout"}, 870e71b7053SJung-uk Kim {"status_url", OPT_STATUS_URL, 's', "Status request fallback URL"}, 871e71b7053SJung-uk Kim {"status_file", OPT_STATUS_FILE, '<', 872e71b7053SJung-uk Kim "File containing DER encoded OCSP Response"}, 873e71b7053SJung-uk Kim #endif 874e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SSL_TRACE 875e71b7053SJung-uk Kim {"trace", OPT_TRACE, '-', "trace protocol messages"}, 876e71b7053SJung-uk Kim #endif 877e71b7053SJung-uk Kim {"security_debug", OPT_SECURITY_DEBUG, '-', 878e71b7053SJung-uk Kim "Print output from SSL/TLS security framework"}, 879e71b7053SJung-uk Kim {"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-', 880e71b7053SJung-uk Kim "Print more output from SSL/TLS security framework"}, 881e71b7053SJung-uk Kim {"brief", OPT_BRIEF, '-', 882e71b7053SJung-uk Kim "Restrict output to brief summary of connection parameters"}, 883e71b7053SJung-uk Kim {"rev", OPT_REV, '-', 884e71b7053SJung-uk Kim "act as a simple test server which just sends back with the received text reversed"}, 885e71b7053SJung-uk Kim {"async", OPT_ASYNC, '-', "Operate in asynchronous mode"}, 886e71b7053SJung-uk Kim {"ssl_config", OPT_SSL_CONFIG, 's', 887e71b7053SJung-uk Kim "Configure SSL_CTX using the configuration 'val'"}, 888e71b7053SJung-uk Kim {"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "}, 889e71b7053SJung-uk Kim {"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p', 890e71b7053SJung-uk Kim "Size used to split data for encrypt pipelines"}, 891e71b7053SJung-uk Kim {"max_pipelines", OPT_MAX_PIPELINES, 'p', 892e71b7053SJung-uk Kim "Maximum number of encrypt/decrypt pipelines to be used"}, 893e71b7053SJung-uk Kim {"read_buf", OPT_READ_BUF, 'p', 894e71b7053SJung-uk Kim "Default read buffer size to be used for connections"}, 895e71b7053SJung-uk Kim OPT_S_OPTIONS, 896e71b7053SJung-uk Kim OPT_V_OPTIONS, 897e71b7053SJung-uk Kim OPT_X_OPTIONS, 898e71b7053SJung-uk Kim {"nbio", OPT_NBIO, '-', "Use non-blocking IO"}, 899e71b7053SJung-uk Kim {"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity to expect"}, 900e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK 901e71b7053SJung-uk Kim {"psk_hint", OPT_PSK_HINT, 's', "PSK identity hint to use"}, 902e71b7053SJung-uk Kim #endif 903e71b7053SJung-uk Kim {"psk", OPT_PSK, 's', "PSK in hex (without 0x)"}, 904e71b7053SJung-uk Kim {"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"}, 9051f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 906e71b7053SJung-uk Kim {"srpvfile", OPT_SRPVFILE, '<', "The verifier file for SRP"}, 907e71b7053SJung-uk Kim {"srpuserseed", OPT_SRPUSERSEED, 's', 908e71b7053SJung-uk Kim "A seed string for a default user salt"}, 909e71b7053SJung-uk Kim #endif 910e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SSL3 911e71b7053SJung-uk Kim {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"}, 912e71b7053SJung-uk Kim #endif 913e71b7053SJung-uk Kim #ifndef OPENSSL_NO_TLS1 914e71b7053SJung-uk Kim {"tls1", OPT_TLS1, '-', "Just talk TLSv1"}, 915e71b7053SJung-uk Kim #endif 916e71b7053SJung-uk Kim #ifndef OPENSSL_NO_TLS1_1 917e71b7053SJung-uk Kim {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"}, 918e71b7053SJung-uk Kim #endif 919e71b7053SJung-uk Kim #ifndef OPENSSL_NO_TLS1_2 920e71b7053SJung-uk Kim {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"}, 921e71b7053SJung-uk Kim #endif 922e71b7053SJung-uk Kim #ifndef OPENSSL_NO_TLS1_3 923e71b7053SJung-uk Kim {"tls1_3", OPT_TLS1_3, '-', "just talk TLSv1.3"}, 924e71b7053SJung-uk Kim #endif 925e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 926e71b7053SJung-uk Kim {"dtls", OPT_DTLS, '-', "Use any DTLS version"}, 927e71b7053SJung-uk Kim {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"}, 928e71b7053SJung-uk Kim {"mtu", OPT_MTU, 'p', "Set link layer MTU"}, 929e71b7053SJung-uk Kim {"listen", OPT_LISTEN, '-', 930e71b7053SJung-uk Kim "Listen for a DTLS ClientHello with a cookie and then connect"}, 931e71b7053SJung-uk Kim #endif 932e71b7053SJung-uk Kim {"stateless", OPT_STATELESS, '-', "Require TLSv1.3 cookies"}, 933e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS1 934e71b7053SJung-uk Kim {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"}, 935e71b7053SJung-uk Kim #endif 936e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS1_2 937e71b7053SJung-uk Kim {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"}, 938e71b7053SJung-uk Kim #endif 939e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SCTP 940e71b7053SJung-uk Kim {"sctp", OPT_SCTP, '-', "Use SCTP"}, 941e71b7053SJung-uk Kim #endif 942e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DH 943e71b7053SJung-uk Kim {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"}, 944e71b7053SJung-uk Kim #endif 945e71b7053SJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 946e71b7053SJung-uk Kim {"nextprotoneg", OPT_NEXTPROTONEG, 's', 947e71b7053SJung-uk Kim "Set the advertised protocols for the NPN extension (comma-separated list)"}, 9481f13597dSJung-uk Kim #endif 94909286989SJung-uk Kim #ifndef OPENSSL_NO_SRTP 950e71b7053SJung-uk Kim {"use_srtp", OPT_SRTP_PROFILES, 's', 951e71b7053SJung-uk Kim "Offer SRTP key management with a colon-separated profile list"}, 95209286989SJung-uk Kim #endif 953e71b7053SJung-uk Kim {"alpn", OPT_ALPN, 's', 954e71b7053SJung-uk Kim "Set the advertised protocols for the ALPN extension (comma-separated list)"}, 955e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE 956e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 957e71b7053SJung-uk Kim #endif 958e71b7053SJung-uk Kim {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, 959e71b7053SJung-uk Kim {"max_early_data", OPT_MAX_EARLY, 'n', 960e71b7053SJung-uk Kim "The maximum number of bytes of early data as advertised in tickets"}, 961e71b7053SJung-uk Kim {"recv_max_early_data", OPT_RECV_MAX_EARLY, 'n', 962e71b7053SJung-uk Kim "The maximum number of bytes of early data (hard limit)"}, 963e71b7053SJung-uk Kim {"early_data", OPT_EARLY_DATA, '-', "Attempt to read early data"}, 964e71b7053SJung-uk Kim {"num_tickets", OPT_S_NUM_TICKETS, 'n', 965e71b7053SJung-uk Kim "The number of TLSv1.3 session tickets that a server will automatically issue" }, 966e71b7053SJung-uk Kim {"anti_replay", OPT_ANTI_REPLAY, '-', "Switch on anti-replay protection (default)"}, 967e71b7053SJung-uk Kim {"no_anti_replay", OPT_NO_ANTI_REPLAY, '-', "Switch off anti-replay protection"}, 968e71b7053SJung-uk Kim {NULL, OPT_EOF, 0, NULL} 969e71b7053SJung-uk Kim }; 970db522d3aSSimon L. B. Nielsen 971e71b7053SJung-uk Kim #define IS_PROT_FLAG(o) \ 972e71b7053SJung-uk Kim (o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \ 973e71b7053SJung-uk Kim || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2) 974e71b7053SJung-uk Kim 975e71b7053SJung-uk Kim int s_server_main(int argc, char *argv[]) 97674664626SKris Kennaway { 977e71b7053SJung-uk Kim ENGINE *engine = NULL; 978e71b7053SJung-uk Kim EVP_PKEY *s_key = NULL, *s_dkey = NULL; 979e71b7053SJung-uk Kim SSL_CONF_CTX *cctx = NULL; 980e71b7053SJung-uk Kim const SSL_METHOD *meth = TLS_server_method(); 981e71b7053SJung-uk Kim SSL_EXCERT *exc = NULL; 982e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *ssl_args = NULL; 983e71b7053SJung-uk Kim STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; 984e71b7053SJung-uk Kim STACK_OF(X509_CRL) *crls = NULL; 985e71b7053SJung-uk Kim X509 *s_cert = NULL, *s_dcert = NULL; 9861f13597dSJung-uk Kim X509_VERIFY_PARAM *vpm = NULL; 987e71b7053SJung-uk Kim const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL; 988e71b7053SJung-uk Kim char *dpassarg = NULL, *dpass = NULL; 989e71b7053SJung-uk Kim char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL; 990e71b7053SJung-uk Kim char *crl_file = NULL, *prog; 991e71b7053SJung-uk Kim #ifdef AF_UNIX 992e71b7053SJung-uk Kim int unlink_unix_path = 0; 993e71b7053SJung-uk Kim #endif 994e71b7053SJung-uk Kim do_server_cb server_cb; 995e71b7053SJung-uk Kim int vpmtouched = 0, build_chain = 0, no_cache = 0, ext_cache = 0; 996dea77ea6SJung-uk Kim #ifndef OPENSSL_NO_DH 997f579bf8eSKris Kennaway char *dhfile = NULL; 998dea77ea6SJung-uk Kim int no_dhe = 0; 999dea77ea6SJung-uk Kim #endif 1000e71b7053SJung-uk Kim int nocert = 0, ret = 1; 1001e71b7053SJung-uk Kim int noCApath = 0, noCAfile = 0; 10023b4e3dcbSSimon L. B. Nielsen int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM; 10033b4e3dcbSSimon L. B. Nielsen int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM; 1004e71b7053SJung-uk Kim int rev = 0, naccept = -1, sdebug = 0; 1005e71b7053SJung-uk Kim int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; 1006e71b7053SJung-uk Kim int state = 0, crl_format = FORMAT_PEM, crl_download = 0; 1007e71b7053SJung-uk Kim char *host = NULL; 1008e71b7053SJung-uk Kim char *port = BUF_strdup(PORT); 1009e71b7053SJung-uk Kim unsigned char *context = NULL; 1010e71b7053SJung-uk Kim OPTION_CHOICE o; 1011db522d3aSSimon L. B. Nielsen EVP_PKEY *s_key2 = NULL; 1012db522d3aSSimon L. B. Nielsen X509 *s_cert2 = NULL; 1013db522d3aSSimon L. B. Nielsen tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING }; 1014e71b7053SJung-uk Kim const char *ssl_config = NULL; 1015e71b7053SJung-uk Kim int read_buf_len = 0; 10161f13597dSJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 10171f13597dSJung-uk Kim const char *next_proto_neg_in = NULL; 10187bded2dbSJung-uk Kim tlsextnextprotoctx next_proto = { NULL, 0 }; 1019db522d3aSSimon L. B. Nielsen #endif 10207bded2dbSJung-uk Kim const char *alpn_in = NULL; 10217bded2dbSJung-uk Kim tlsextalpnctx alpn_ctx = { NULL, 0 }; 10221f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK 10231f13597dSJung-uk Kim /* by default do not send a PSK identity hint */ 1024e71b7053SJung-uk Kim char *psk_identity_hint = NULL; 10251f13597dSJung-uk Kim #endif 1026e71b7053SJung-uk Kim char *p; 10271f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 10281f13597dSJung-uk Kim char *srpuserseed = NULL; 10291f13597dSJung-uk Kim char *srp_verifier_file = NULL; 10301f13597dSJung-uk Kim #endif 1031e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRTP 1032e71b7053SJung-uk Kim char *srtp_profiles = NULL; 1033e71b7053SJung-uk Kim #endif 1034e71b7053SJung-uk Kim int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0; 1035e71b7053SJung-uk Kim int s_server_verify = SSL_VERIFY_NONE; 1036e71b7053SJung-uk Kim int s_server_session_id_context = 1; /* anything will do */ 1037e71b7053SJung-uk Kim const char *s_cert_file = TEST_CERT, *s_key_file = NULL, *s_chain_file = NULL; 1038e71b7053SJung-uk Kim const char *s_cert_file2 = TEST_CERT2, *s_key_file2 = NULL; 1039e71b7053SJung-uk Kim char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL; 1040e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1041e71b7053SJung-uk Kim int s_tlsextstatus = 0; 1042e71b7053SJung-uk Kim #endif 1043e71b7053SJung-uk Kim int no_resume_ephemeral = 0; 1044e71b7053SJung-uk Kim unsigned int max_send_fragment = 0; 1045e71b7053SJung-uk Kim unsigned int split_send_fragment = 0, max_pipelines = 0; 1046e71b7053SJung-uk Kim const char *s_serverinfo_file = NULL; 1047e71b7053SJung-uk Kim const char *keylog_file = NULL; 1048e71b7053SJung-uk Kim int max_early_data = -1, recv_max_early_data = -1; 1049e71b7053SJung-uk Kim char *psksessf = NULL; 10507bded2dbSJung-uk Kim 1051e71b7053SJung-uk Kim /* Init of few remaining global variables */ 105274664626SKris Kennaway local_argc = argc; 105374664626SKris Kennaway local_argv = argv; 105474664626SKris Kennaway 1055e71b7053SJung-uk Kim ctx = ctx2 = NULL; 1056e71b7053SJung-uk Kim s_nbio = s_nbio_test = 0; 1057e71b7053SJung-uk Kim www = 0; 1058e71b7053SJung-uk Kim bio_s_out = NULL; 1059e71b7053SJung-uk Kim s_debug = 0; 1060e71b7053SJung-uk Kim s_msg = 0; 1061e71b7053SJung-uk Kim s_quiet = 0; 1062e71b7053SJung-uk Kim s_brief = 0; 1063e71b7053SJung-uk Kim async = 0; 10645c87c606SMark Murray 10657bded2dbSJung-uk Kim cctx = SSL_CONF_CTX_new(); 1066e71b7053SJung-uk Kim vpm = X509_VERIFY_PARAM_new(); 1067e71b7053SJung-uk Kim if (cctx == NULL || vpm == NULL) 10687bded2dbSJung-uk Kim goto end; 1069e71b7053SJung-uk Kim SSL_CONF_CTX_set_flags(cctx, 1070e71b7053SJung-uk Kim SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CMDLINE); 10717bded2dbSJung-uk Kim 1072e71b7053SJung-uk Kim prog = opt_init(argc, argv, s_server_options); 1073e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 1074e71b7053SJung-uk Kim if (IS_PROT_FLAG(o) && ++prot_opt > 1) { 1075e71b7053SJung-uk Kim BIO_printf(bio_err, "Cannot supply multiple protocol flags\n"); 1076e71b7053SJung-uk Kim goto end; 10777bded2dbSJung-uk Kim } 1078e71b7053SJung-uk Kim if (IS_NO_PROT_FLAG(o)) 1079e71b7053SJung-uk Kim no_prot_opt++; 1080e71b7053SJung-uk Kim if (prot_opt == 1 && no_prot_opt) { 1081e71b7053SJung-uk Kim BIO_printf(bio_err, 1082e71b7053SJung-uk Kim "Cannot supply both a protocol flag and '-no_<prot>'\n"); 1083e71b7053SJung-uk Kim goto end; 1084e71b7053SJung-uk Kim } 1085e71b7053SJung-uk Kim switch (o) { 1086e71b7053SJung-uk Kim case OPT_EOF: 1087e71b7053SJung-uk Kim case OPT_ERR: 1088e71b7053SJung-uk Kim opthelp: 1089e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 1090e71b7053SJung-uk Kim goto end; 1091e71b7053SJung-uk Kim case OPT_HELP: 1092e71b7053SJung-uk Kim opt_help(s_server_options); 1093e71b7053SJung-uk Kim ret = 0; 1094e71b7053SJung-uk Kim goto end; 1095e71b7053SJung-uk Kim 1096e71b7053SJung-uk Kim case OPT_4: 1097e71b7053SJung-uk Kim #ifdef AF_UNIX 1098e71b7053SJung-uk Kim if (socket_family == AF_UNIX) { 1099e71b7053SJung-uk Kim OPENSSL_free(host); host = NULL; 1100e71b7053SJung-uk Kim OPENSSL_free(port); port = NULL; 1101e71b7053SJung-uk Kim } 1102e71b7053SJung-uk Kim #endif 1103e71b7053SJung-uk Kim socket_family = AF_INET; 1104e71b7053SJung-uk Kim break; 1105e71b7053SJung-uk Kim case OPT_6: 1106e71b7053SJung-uk Kim if (1) { 1107e71b7053SJung-uk Kim #ifdef AF_INET6 1108e71b7053SJung-uk Kim #ifdef AF_UNIX 1109e71b7053SJung-uk Kim if (socket_family == AF_UNIX) { 1110e71b7053SJung-uk Kim OPENSSL_free(host); host = NULL; 1111e71b7053SJung-uk Kim OPENSSL_free(port); port = NULL; 1112e71b7053SJung-uk Kim } 1113e71b7053SJung-uk Kim #endif 1114e71b7053SJung-uk Kim socket_family = AF_INET6; 1115e71b7053SJung-uk Kim } else { 1116e71b7053SJung-uk Kim #endif 1117e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: IPv6 domain sockets unsupported\n", prog); 1118e71b7053SJung-uk Kim goto end; 1119e71b7053SJung-uk Kim } 1120e71b7053SJung-uk Kim break; 1121e71b7053SJung-uk Kim case OPT_PORT: 1122e71b7053SJung-uk Kim #ifdef AF_UNIX 1123e71b7053SJung-uk Kim if (socket_family == AF_UNIX) { 1124e71b7053SJung-uk Kim socket_family = AF_UNSPEC; 1125e71b7053SJung-uk Kim } 1126e71b7053SJung-uk Kim #endif 1127e71b7053SJung-uk Kim OPENSSL_free(port); port = NULL; 1128e71b7053SJung-uk Kim OPENSSL_free(host); host = NULL; 1129e71b7053SJung-uk Kim if (BIO_parse_hostserv(opt_arg(), NULL, &port, BIO_PARSE_PRIO_SERV) < 1) { 1130e71b7053SJung-uk Kim BIO_printf(bio_err, 1131e71b7053SJung-uk Kim "%s: -port argument malformed or ambiguous\n", 1132e71b7053SJung-uk Kim port); 1133e71b7053SJung-uk Kim goto end; 1134e71b7053SJung-uk Kim } 1135e71b7053SJung-uk Kim break; 1136e71b7053SJung-uk Kim case OPT_ACCEPT: 1137e71b7053SJung-uk Kim #ifdef AF_UNIX 1138e71b7053SJung-uk Kim if (socket_family == AF_UNIX) { 1139e71b7053SJung-uk Kim socket_family = AF_UNSPEC; 1140e71b7053SJung-uk Kim } 1141e71b7053SJung-uk Kim #endif 1142e71b7053SJung-uk Kim OPENSSL_free(port); port = NULL; 1143e71b7053SJung-uk Kim OPENSSL_free(host); host = NULL; 1144e71b7053SJung-uk Kim if (BIO_parse_hostserv(opt_arg(), &host, &port, BIO_PARSE_PRIO_SERV) < 1) { 1145e71b7053SJung-uk Kim BIO_printf(bio_err, 1146e71b7053SJung-uk Kim "%s: -accept argument malformed or ambiguous\n", 1147e71b7053SJung-uk Kim port); 1148e71b7053SJung-uk Kim goto end; 1149e71b7053SJung-uk Kim } 1150e71b7053SJung-uk Kim break; 1151e71b7053SJung-uk Kim #ifdef AF_UNIX 1152e71b7053SJung-uk Kim case OPT_UNIX: 1153e71b7053SJung-uk Kim socket_family = AF_UNIX; 1154e71b7053SJung-uk Kim OPENSSL_free(host); host = BUF_strdup(opt_arg()); 1155e71b7053SJung-uk Kim OPENSSL_free(port); port = NULL; 1156e71b7053SJung-uk Kim break; 1157e71b7053SJung-uk Kim case OPT_UNLINK: 1158e71b7053SJung-uk Kim unlink_unix_path = 1; 1159e71b7053SJung-uk Kim break; 1160e71b7053SJung-uk Kim #endif 1161e71b7053SJung-uk Kim case OPT_NACCEPT: 1162e71b7053SJung-uk Kim naccept = atol(opt_arg()); 1163e71b7053SJung-uk Kim break; 1164e71b7053SJung-uk Kim case OPT_VERIFY: 116574664626SKris Kennaway s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; 1166e71b7053SJung-uk Kim verify_args.depth = atoi(opt_arg()); 11677bded2dbSJung-uk Kim if (!s_quiet) 1168e71b7053SJung-uk Kim BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth); 1169e71b7053SJung-uk Kim break; 1170e71b7053SJung-uk Kim case OPT_UPPER_V_VERIFY: 11716f9291ceSJung-uk Kim s_server_verify = 11726f9291ceSJung-uk Kim SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | 117374664626SKris Kennaway SSL_VERIFY_CLIENT_ONCE; 1174e71b7053SJung-uk Kim verify_args.depth = atoi(opt_arg()); 11757bded2dbSJung-uk Kim if (!s_quiet) 11766f9291ceSJung-uk Kim BIO_printf(bio_err, 11776f9291ceSJung-uk Kim "verify depth is %d, must return a certificate\n", 1178e71b7053SJung-uk Kim verify_args.depth); 1179e71b7053SJung-uk Kim break; 1180e71b7053SJung-uk Kim case OPT_CONTEXT: 1181e71b7053SJung-uk Kim context = (unsigned char *)opt_arg(); 1182e71b7053SJung-uk Kim break; 1183e71b7053SJung-uk Kim case OPT_CERT: 1184e71b7053SJung-uk Kim s_cert_file = opt_arg(); 1185e71b7053SJung-uk Kim break; 1186e71b7053SJung-uk Kim case OPT_NAMEOPT: 1187e71b7053SJung-uk Kim if (!set_nameopt(opt_arg())) 1188e71b7053SJung-uk Kim goto end; 1189e71b7053SJung-uk Kim break; 1190e71b7053SJung-uk Kim case OPT_CRL: 1191e71b7053SJung-uk Kim crl_file = opt_arg(); 1192e71b7053SJung-uk Kim break; 1193e71b7053SJung-uk Kim case OPT_CRL_DOWNLOAD: 11947bded2dbSJung-uk Kim crl_download = 1; 1195e71b7053SJung-uk Kim break; 1196e71b7053SJung-uk Kim case OPT_SERVERINFO: 1197e71b7053SJung-uk Kim s_serverinfo_file = opt_arg(); 1198e71b7053SJung-uk Kim break; 1199e71b7053SJung-uk Kim case OPT_CERTFORM: 1200e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format)) 1201e71b7053SJung-uk Kim goto opthelp; 1202e71b7053SJung-uk Kim break; 1203e71b7053SJung-uk Kim case OPT_KEY: 1204e71b7053SJung-uk Kim s_key_file = opt_arg(); 1205e71b7053SJung-uk Kim break; 1206e71b7053SJung-uk Kim case OPT_KEYFORM: 1207e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format)) 1208e71b7053SJung-uk Kim goto opthelp; 1209e71b7053SJung-uk Kim break; 1210e71b7053SJung-uk Kim case OPT_PASS: 1211e71b7053SJung-uk Kim passarg = opt_arg(); 1212e71b7053SJung-uk Kim break; 1213e71b7053SJung-uk Kim case OPT_CERT_CHAIN: 1214e71b7053SJung-uk Kim s_chain_file = opt_arg(); 1215e71b7053SJung-uk Kim break; 1216e71b7053SJung-uk Kim case OPT_DHPARAM: 1217dea77ea6SJung-uk Kim #ifndef OPENSSL_NO_DH 1218e71b7053SJung-uk Kim dhfile = opt_arg(); 1219dea77ea6SJung-uk Kim #endif 1220e71b7053SJung-uk Kim break; 1221e71b7053SJung-uk Kim case OPT_DCERTFORM: 1222e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format)) 1223e71b7053SJung-uk Kim goto opthelp; 1224e71b7053SJung-uk Kim break; 1225e71b7053SJung-uk Kim case OPT_DCERT: 1226e71b7053SJung-uk Kim s_dcert_file = opt_arg(); 1227e71b7053SJung-uk Kim break; 1228e71b7053SJung-uk Kim case OPT_DKEYFORM: 1229e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dkey_format)) 1230e71b7053SJung-uk Kim goto opthelp; 1231e71b7053SJung-uk Kim break; 1232e71b7053SJung-uk Kim case OPT_DPASS: 1233e71b7053SJung-uk Kim dpassarg = opt_arg(); 1234e71b7053SJung-uk Kim break; 1235e71b7053SJung-uk Kim case OPT_DKEY: 1236e71b7053SJung-uk Kim s_dkey_file = opt_arg(); 1237e71b7053SJung-uk Kim break; 1238e71b7053SJung-uk Kim case OPT_DCERT_CHAIN: 1239e71b7053SJung-uk Kim s_dchain_file = opt_arg(); 1240e71b7053SJung-uk Kim break; 1241e71b7053SJung-uk Kim case OPT_NOCERT: 124274664626SKris Kennaway nocert = 1; 1243e71b7053SJung-uk Kim break; 1244e71b7053SJung-uk Kim case OPT_CAPATH: 1245e71b7053SJung-uk Kim CApath = opt_arg(); 1246e71b7053SJung-uk Kim break; 1247e71b7053SJung-uk Kim case OPT_NOCAPATH: 1248e71b7053SJung-uk Kim noCApath = 1; 1249e71b7053SJung-uk Kim break; 1250e71b7053SJung-uk Kim case OPT_CHAINCAPATH: 1251e71b7053SJung-uk Kim chCApath = opt_arg(); 1252e71b7053SJung-uk Kim break; 1253e71b7053SJung-uk Kim case OPT_VERIFYCAPATH: 1254e71b7053SJung-uk Kim vfyCApath = opt_arg(); 1255e71b7053SJung-uk Kim break; 1256e71b7053SJung-uk Kim case OPT_NO_CACHE: 12576a599222SSimon L. B. Nielsen no_cache = 1; 1258e71b7053SJung-uk Kim break; 1259e71b7053SJung-uk Kim case OPT_EXT_CACHE: 12607bded2dbSJung-uk Kim ext_cache = 1; 1261e71b7053SJung-uk Kim break; 1262e71b7053SJung-uk Kim case OPT_CRLFORM: 1263e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format)) 1264e71b7053SJung-uk Kim goto opthelp; 1265e71b7053SJung-uk Kim break; 1266e71b7053SJung-uk Kim case OPT_S_CASES: 1267e71b7053SJung-uk Kim case OPT_S_NUM_TICKETS: 1268e71b7053SJung-uk Kim case OPT_ANTI_REPLAY: 1269e71b7053SJung-uk Kim case OPT_NO_ANTI_REPLAY: 1270e71b7053SJung-uk Kim if (ssl_args == NULL) 1271e71b7053SJung-uk Kim ssl_args = sk_OPENSSL_STRING_new_null(); 1272e71b7053SJung-uk Kim if (ssl_args == NULL 1273e71b7053SJung-uk Kim || !sk_OPENSSL_STRING_push(ssl_args, opt_flag()) 1274e71b7053SJung-uk Kim || !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) { 1275e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Memory allocation failure\n", prog); 1276e71b7053SJung-uk Kim goto end; 1277e71b7053SJung-uk Kim } 1278e71b7053SJung-uk Kim break; 1279e71b7053SJung-uk Kim case OPT_V_CASES: 1280e71b7053SJung-uk Kim if (!opt_verify(o, vpm)) 1281e71b7053SJung-uk Kim goto end; 1282e71b7053SJung-uk Kim vpmtouched++; 1283e71b7053SJung-uk Kim break; 1284e71b7053SJung-uk Kim case OPT_X_CASES: 1285e71b7053SJung-uk Kim if (!args_excert(o, &exc)) 1286e71b7053SJung-uk Kim goto end; 1287e71b7053SJung-uk Kim break; 1288e71b7053SJung-uk Kim case OPT_VERIFY_RET_ERROR: 1289e71b7053SJung-uk Kim verify_args.return_error = 1; 1290e71b7053SJung-uk Kim break; 1291e71b7053SJung-uk Kim case OPT_VERIFY_QUIET: 1292e71b7053SJung-uk Kim verify_args.quiet = 1; 1293e71b7053SJung-uk Kim break; 1294e71b7053SJung-uk Kim case OPT_BUILD_CHAIN: 12957bded2dbSJung-uk Kim build_chain = 1; 1296e71b7053SJung-uk Kim break; 1297e71b7053SJung-uk Kim case OPT_CAFILE: 1298e71b7053SJung-uk Kim CAfile = opt_arg(); 1299e71b7053SJung-uk Kim break; 1300e71b7053SJung-uk Kim case OPT_NOCAFILE: 1301e71b7053SJung-uk Kim noCAfile = 1; 1302e71b7053SJung-uk Kim break; 1303e71b7053SJung-uk Kim case OPT_CHAINCAFILE: 1304e71b7053SJung-uk Kim chCAfile = opt_arg(); 1305e71b7053SJung-uk Kim break; 1306e71b7053SJung-uk Kim case OPT_VERIFYCAFILE: 1307e71b7053SJung-uk Kim vfyCAfile = opt_arg(); 1308e71b7053SJung-uk Kim break; 1309e71b7053SJung-uk Kim case OPT_NBIO: 13106f9291ceSJung-uk Kim s_nbio = 1; 1311e71b7053SJung-uk Kim break; 1312e71b7053SJung-uk Kim case OPT_NBIO_TEST: 1313e71b7053SJung-uk Kim s_nbio = s_nbio_test = 1; 1314e71b7053SJung-uk Kim break; 1315e71b7053SJung-uk Kim case OPT_IGN_EOF: 13167bded2dbSJung-uk Kim s_ign_eof = 1; 1317e71b7053SJung-uk Kim break; 1318e71b7053SJung-uk Kim case OPT_NO_IGN_EOF: 13197bded2dbSJung-uk Kim s_ign_eof = 0; 1320e71b7053SJung-uk Kim break; 1321e71b7053SJung-uk Kim case OPT_DEBUG: 13226f9291ceSJung-uk Kim s_debug = 1; 1323e71b7053SJung-uk Kim break; 1324e71b7053SJung-uk Kim case OPT_TLSEXTDEBUG: 1325db522d3aSSimon L. B. Nielsen s_tlsextdebug = 1; 1326e71b7053SJung-uk Kim break; 1327e71b7053SJung-uk Kim case OPT_STATUS: 1328e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1329db522d3aSSimon L. B. Nielsen s_tlsextstatus = 1; 1330e71b7053SJung-uk Kim #endif 1331e71b7053SJung-uk Kim break; 1332e71b7053SJung-uk Kim case OPT_STATUS_VERBOSE: 1333e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1334e71b7053SJung-uk Kim s_tlsextstatus = tlscstatp.verbose = 1; 1335e71b7053SJung-uk Kim #endif 1336e71b7053SJung-uk Kim break; 1337e71b7053SJung-uk Kim case OPT_STATUS_TIMEOUT: 1338e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1339db522d3aSSimon L. B. Nielsen s_tlsextstatus = 1; 1340e71b7053SJung-uk Kim tlscstatp.timeout = atoi(opt_arg()); 1341e71b7053SJung-uk Kim #endif 1342e71b7053SJung-uk Kim break; 1343e71b7053SJung-uk Kim case OPT_STATUS_URL: 1344e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1345db522d3aSSimon L. B. Nielsen s_tlsextstatus = 1; 1346e71b7053SJung-uk Kim if (!OCSP_parse_url(opt_arg(), 1347db522d3aSSimon L. B. Nielsen &tlscstatp.host, 1348db522d3aSSimon L. B. Nielsen &tlscstatp.port, 13496f9291ceSJung-uk Kim &tlscstatp.path, &tlscstatp.use_ssl)) { 1350db522d3aSSimon L. B. Nielsen BIO_printf(bio_err, "Error parsing URL\n"); 135174664626SKris Kennaway goto end; 135274664626SKris Kennaway } 1353e71b7053SJung-uk Kim #endif 1354e71b7053SJung-uk Kim break; 1355e71b7053SJung-uk Kim case OPT_STATUS_FILE: 1356e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 1357e71b7053SJung-uk Kim s_tlsextstatus = 1; 1358e71b7053SJung-uk Kim tlscstatp.respin = opt_arg(); 1359e71b7053SJung-uk Kim #endif 1360e71b7053SJung-uk Kim break; 1361e71b7053SJung-uk Kim case OPT_MSG: 1362e71b7053SJung-uk Kim s_msg = 1; 1363e71b7053SJung-uk Kim break; 1364e71b7053SJung-uk Kim case OPT_MSGFILE: 1365e71b7053SJung-uk Kim bio_s_msg = BIO_new_file(opt_arg(), "w"); 1366e71b7053SJung-uk Kim break; 1367e71b7053SJung-uk Kim case OPT_TRACE: 1368e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SSL_TRACE 1369e71b7053SJung-uk Kim s_msg = 2; 1370e71b7053SJung-uk Kim #endif 1371e71b7053SJung-uk Kim break; 1372e71b7053SJung-uk Kim case OPT_SECURITY_DEBUG: 1373e71b7053SJung-uk Kim sdebug = 1; 1374e71b7053SJung-uk Kim break; 1375e71b7053SJung-uk Kim case OPT_SECURITY_DEBUG_VERBOSE: 1376e71b7053SJung-uk Kim sdebug = 2; 1377e71b7053SJung-uk Kim break; 1378e71b7053SJung-uk Kim case OPT_STATE: 1379e71b7053SJung-uk Kim state = 1; 1380e71b7053SJung-uk Kim break; 1381e71b7053SJung-uk Kim case OPT_CRLF: 1382e71b7053SJung-uk Kim s_crlf = 1; 1383e71b7053SJung-uk Kim break; 1384e71b7053SJung-uk Kim case OPT_QUIET: 1385e71b7053SJung-uk Kim s_quiet = 1; 1386e71b7053SJung-uk Kim break; 1387e71b7053SJung-uk Kim case OPT_BRIEF: 1388e71b7053SJung-uk Kim s_quiet = s_brief = verify_args.quiet = 1; 1389e71b7053SJung-uk Kim break; 1390e71b7053SJung-uk Kim case OPT_NO_DHE: 1391e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DH 1392e71b7053SJung-uk Kim no_dhe = 1; 1393e71b7053SJung-uk Kim #endif 1394e71b7053SJung-uk Kim break; 1395e71b7053SJung-uk Kim case OPT_NO_RESUME_EPHEMERAL: 1396e71b7053SJung-uk Kim no_resume_ephemeral = 1; 1397e71b7053SJung-uk Kim break; 1398e71b7053SJung-uk Kim case OPT_PSK_IDENTITY: 1399e71b7053SJung-uk Kim psk_identity = opt_arg(); 1400e71b7053SJung-uk Kim break; 1401e71b7053SJung-uk Kim case OPT_PSK_HINT: 1402e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK 1403e71b7053SJung-uk Kim psk_identity_hint = opt_arg(); 1404e71b7053SJung-uk Kim #endif 1405e71b7053SJung-uk Kim break; 1406e71b7053SJung-uk Kim case OPT_PSK: 1407e71b7053SJung-uk Kim for (p = psk_key = opt_arg(); *p; p++) { 1408e71b7053SJung-uk Kim if (isxdigit(_UC(*p))) 1409e71b7053SJung-uk Kim continue; 1410e71b7053SJung-uk Kim BIO_printf(bio_err, "Not a hex number '%s'\n", *argv); 1411e71b7053SJung-uk Kim goto end; 1412e71b7053SJung-uk Kim } 1413e71b7053SJung-uk Kim break; 1414e71b7053SJung-uk Kim case OPT_PSK_SESS: 1415e71b7053SJung-uk Kim psksessf = opt_arg(); 1416e71b7053SJung-uk Kim break; 1417e71b7053SJung-uk Kim case OPT_SRPVFILE: 1418e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRP 1419e71b7053SJung-uk Kim srp_verifier_file = opt_arg(); 1420e71b7053SJung-uk Kim if (min_version < TLS1_VERSION) 1421e71b7053SJung-uk Kim min_version = TLS1_VERSION; 1422e71b7053SJung-uk Kim #endif 1423e71b7053SJung-uk Kim break; 1424e71b7053SJung-uk Kim case OPT_SRPUSERSEED: 1425e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRP 1426e71b7053SJung-uk Kim srpuserseed = opt_arg(); 1427e71b7053SJung-uk Kim if (min_version < TLS1_VERSION) 1428e71b7053SJung-uk Kim min_version = TLS1_VERSION; 1429e71b7053SJung-uk Kim #endif 1430e71b7053SJung-uk Kim break; 1431e71b7053SJung-uk Kim case OPT_REV: 1432e71b7053SJung-uk Kim rev = 1; 1433e71b7053SJung-uk Kim break; 1434e71b7053SJung-uk Kim case OPT_WWW: 1435e71b7053SJung-uk Kim www = 1; 1436e71b7053SJung-uk Kim break; 1437e71b7053SJung-uk Kim case OPT_UPPER_WWW: 1438e71b7053SJung-uk Kim www = 2; 1439e71b7053SJung-uk Kim break; 1440e71b7053SJung-uk Kim case OPT_HTTP: 1441e71b7053SJung-uk Kim www = 3; 1442e71b7053SJung-uk Kim break; 1443e71b7053SJung-uk Kim case OPT_SSL_CONFIG: 1444e71b7053SJung-uk Kim ssl_config = opt_arg(); 1445e71b7053SJung-uk Kim break; 1446e71b7053SJung-uk Kim case OPT_SSL3: 1447e71b7053SJung-uk Kim min_version = SSL3_VERSION; 1448e71b7053SJung-uk Kim max_version = SSL3_VERSION; 1449e71b7053SJung-uk Kim break; 1450e71b7053SJung-uk Kim case OPT_TLS1_3: 1451e71b7053SJung-uk Kim min_version = TLS1_3_VERSION; 1452e71b7053SJung-uk Kim max_version = TLS1_3_VERSION; 1453e71b7053SJung-uk Kim break; 1454e71b7053SJung-uk Kim case OPT_TLS1_2: 1455e71b7053SJung-uk Kim min_version = TLS1_2_VERSION; 1456e71b7053SJung-uk Kim max_version = TLS1_2_VERSION; 1457e71b7053SJung-uk Kim break; 1458e71b7053SJung-uk Kim case OPT_TLS1_1: 1459e71b7053SJung-uk Kim min_version = TLS1_1_VERSION; 1460e71b7053SJung-uk Kim max_version = TLS1_1_VERSION; 1461e71b7053SJung-uk Kim break; 1462e71b7053SJung-uk Kim case OPT_TLS1: 1463e71b7053SJung-uk Kim min_version = TLS1_VERSION; 1464e71b7053SJung-uk Kim max_version = TLS1_VERSION; 1465e71b7053SJung-uk Kim break; 1466e71b7053SJung-uk Kim case OPT_DTLS: 1467e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1468e71b7053SJung-uk Kim meth = DTLS_server_method(); 1469e71b7053SJung-uk Kim socket_type = SOCK_DGRAM; 1470e71b7053SJung-uk Kim #endif 1471e71b7053SJung-uk Kim break; 1472e71b7053SJung-uk Kim case OPT_DTLS1: 1473e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1474e71b7053SJung-uk Kim meth = DTLS_server_method(); 1475e71b7053SJung-uk Kim min_version = DTLS1_VERSION; 1476e71b7053SJung-uk Kim max_version = DTLS1_VERSION; 1477e71b7053SJung-uk Kim socket_type = SOCK_DGRAM; 1478e71b7053SJung-uk Kim #endif 1479e71b7053SJung-uk Kim break; 1480e71b7053SJung-uk Kim case OPT_DTLS1_2: 1481e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1482e71b7053SJung-uk Kim meth = DTLS_server_method(); 1483e71b7053SJung-uk Kim min_version = DTLS1_2_VERSION; 1484e71b7053SJung-uk Kim max_version = DTLS1_2_VERSION; 1485e71b7053SJung-uk Kim socket_type = SOCK_DGRAM; 1486e71b7053SJung-uk Kim #endif 1487e71b7053SJung-uk Kim break; 1488e71b7053SJung-uk Kim case OPT_SCTP: 1489e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SCTP 1490e71b7053SJung-uk Kim protocol = IPPROTO_SCTP; 1491e71b7053SJung-uk Kim #endif 1492e71b7053SJung-uk Kim break; 1493e71b7053SJung-uk Kim case OPT_TIMEOUT: 1494e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1495e71b7053SJung-uk Kim enable_timeouts = 1; 1496e71b7053SJung-uk Kim #endif 1497e71b7053SJung-uk Kim break; 1498e71b7053SJung-uk Kim case OPT_MTU: 1499e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1500e71b7053SJung-uk Kim socket_mtu = atol(opt_arg()); 1501e71b7053SJung-uk Kim #endif 1502e71b7053SJung-uk Kim break; 1503e71b7053SJung-uk Kim case OPT_LISTEN: 1504e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 1505e71b7053SJung-uk Kim dtlslisten = 1; 1506e71b7053SJung-uk Kim #endif 1507e71b7053SJung-uk Kim break; 1508e71b7053SJung-uk Kim case OPT_STATELESS: 1509e71b7053SJung-uk Kim stateless = 1; 1510e71b7053SJung-uk Kim break; 1511e71b7053SJung-uk Kim case OPT_ID_PREFIX: 1512e71b7053SJung-uk Kim session_id_prefix = opt_arg(); 1513e71b7053SJung-uk Kim break; 1514e71b7053SJung-uk Kim case OPT_ENGINE: 1515e71b7053SJung-uk Kim engine = setup_engine(opt_arg(), 1); 1516e71b7053SJung-uk Kim break; 1517e71b7053SJung-uk Kim case OPT_R_CASES: 1518e71b7053SJung-uk Kim if (!opt_rand(o)) 1519e71b7053SJung-uk Kim goto end; 1520e71b7053SJung-uk Kim break; 1521e71b7053SJung-uk Kim case OPT_SERVERNAME: 1522e71b7053SJung-uk Kim tlsextcbp.servername = opt_arg(); 1523e71b7053SJung-uk Kim break; 1524e71b7053SJung-uk Kim case OPT_SERVERNAME_FATAL: 1525e71b7053SJung-uk Kim tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL; 1526e71b7053SJung-uk Kim break; 1527e71b7053SJung-uk Kim case OPT_CERT2: 1528e71b7053SJung-uk Kim s_cert_file2 = opt_arg(); 1529e71b7053SJung-uk Kim break; 1530e71b7053SJung-uk Kim case OPT_KEY2: 1531e71b7053SJung-uk Kim s_key_file2 = opt_arg(); 1532e71b7053SJung-uk Kim break; 1533e71b7053SJung-uk Kim case OPT_NEXTPROTONEG: 1534e71b7053SJung-uk Kim # ifndef OPENSSL_NO_NEXTPROTONEG 1535e71b7053SJung-uk Kim next_proto_neg_in = opt_arg(); 1536e71b7053SJung-uk Kim #endif 1537e71b7053SJung-uk Kim break; 1538e71b7053SJung-uk Kim case OPT_ALPN: 1539e71b7053SJung-uk Kim alpn_in = opt_arg(); 1540e71b7053SJung-uk Kim break; 1541e71b7053SJung-uk Kim case OPT_SRTP_PROFILES: 1542e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRTP 1543e71b7053SJung-uk Kim srtp_profiles = opt_arg(); 1544e71b7053SJung-uk Kim #endif 1545e71b7053SJung-uk Kim break; 1546e71b7053SJung-uk Kim case OPT_KEYMATEXPORT: 1547e71b7053SJung-uk Kim keymatexportlabel = opt_arg(); 1548e71b7053SJung-uk Kim break; 1549e71b7053SJung-uk Kim case OPT_KEYMATEXPORTLEN: 1550e71b7053SJung-uk Kim keymatexportlen = atoi(opt_arg()); 1551e71b7053SJung-uk Kim break; 1552e71b7053SJung-uk Kim case OPT_ASYNC: 1553e71b7053SJung-uk Kim async = 1; 1554e71b7053SJung-uk Kim break; 1555e71b7053SJung-uk Kim case OPT_MAX_SEND_FRAG: 1556e71b7053SJung-uk Kim max_send_fragment = atoi(opt_arg()); 1557e71b7053SJung-uk Kim break; 1558e71b7053SJung-uk Kim case OPT_SPLIT_SEND_FRAG: 1559e71b7053SJung-uk Kim split_send_fragment = atoi(opt_arg()); 1560e71b7053SJung-uk Kim break; 1561e71b7053SJung-uk Kim case OPT_MAX_PIPELINES: 1562e71b7053SJung-uk Kim max_pipelines = atoi(opt_arg()); 1563e71b7053SJung-uk Kim break; 1564e71b7053SJung-uk Kim case OPT_READ_BUF: 1565e71b7053SJung-uk Kim read_buf_len = atoi(opt_arg()); 1566e71b7053SJung-uk Kim break; 1567e71b7053SJung-uk Kim case OPT_KEYLOG_FILE: 1568e71b7053SJung-uk Kim keylog_file = opt_arg(); 1569e71b7053SJung-uk Kim break; 1570e71b7053SJung-uk Kim case OPT_MAX_EARLY: 1571e71b7053SJung-uk Kim max_early_data = atoi(opt_arg()); 1572e71b7053SJung-uk Kim if (max_early_data < 0) { 1573e71b7053SJung-uk Kim BIO_printf(bio_err, "Invalid value for max_early_data\n"); 1574e71b7053SJung-uk Kim goto end; 1575e71b7053SJung-uk Kim } 1576e71b7053SJung-uk Kim break; 1577e71b7053SJung-uk Kim case OPT_RECV_MAX_EARLY: 1578e71b7053SJung-uk Kim recv_max_early_data = atoi(opt_arg()); 1579e71b7053SJung-uk Kim if (recv_max_early_data < 0) { 1580e71b7053SJung-uk Kim BIO_printf(bio_err, "Invalid value for recv_max_early_data\n"); 1581e71b7053SJung-uk Kim goto end; 1582e71b7053SJung-uk Kim } 1583e71b7053SJung-uk Kim break; 1584e71b7053SJung-uk Kim case OPT_EARLY_DATA: 1585e71b7053SJung-uk Kim early_data = 1; 1586e71b7053SJung-uk Kim if (max_early_data == -1) 1587e71b7053SJung-uk Kim max_early_data = SSL3_RT_MAX_PLAIN_LENGTH; 1588e71b7053SJung-uk Kim break; 1589e71b7053SJung-uk Kim } 1590e71b7053SJung-uk Kim } 1591e71b7053SJung-uk Kim argc = opt_num_rest(); 1592e71b7053SJung-uk Kim argv = opt_rest(); 1593e71b7053SJung-uk Kim 1594e71b7053SJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 1595e71b7053SJung-uk Kim if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) { 1596e71b7053SJung-uk Kim BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n"); 1597e71b7053SJung-uk Kim goto opthelp; 1598e71b7053SJung-uk Kim } 1599e71b7053SJung-uk Kim #endif 1600e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 16016f9291ceSJung-uk Kim if (www && socket_type == SOCK_DGRAM) { 16026f9291ceSJung-uk Kim BIO_printf(bio_err, "Can't use -HTTP, -www or -WWW with DTLS\n"); 1603a93cbc2bSJung-uk Kim goto end; 1604a93cbc2bSJung-uk Kim } 160574664626SKris Kennaway 1606e71b7053SJung-uk Kim if (dtlslisten && socket_type != SOCK_DGRAM) { 1607e71b7053SJung-uk Kim BIO_printf(bio_err, "Can only use -listen with DTLS\n"); 16081f13597dSJung-uk Kim goto end; 16091f13597dSJung-uk Kim } 16101f13597dSJung-uk Kim #endif 16111f13597dSJung-uk Kim 1612e71b7053SJung-uk Kim if (stateless && socket_type != SOCK_STREAM) { 1613e71b7053SJung-uk Kim BIO_printf(bio_err, "Can only use --stateless with TLS\n"); 1614aeb5019cSJung-uk Kim goto end; 1615aeb5019cSJung-uk Kim } 1616aeb5019cSJung-uk Kim 1617e71b7053SJung-uk Kim #ifdef AF_UNIX 1618e71b7053SJung-uk Kim if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) { 1619e71b7053SJung-uk Kim BIO_printf(bio_err, 1620e71b7053SJung-uk Kim "Can't use unix sockets and datagrams together\n"); 1621aeb5019cSJung-uk Kim goto end; 1622aeb5019cSJung-uk Kim } 1623e71b7053SJung-uk Kim #endif 1624*c9cf7b5cSJung-uk Kim if (early_data && (www > 0 || rev)) { 1625*c9cf7b5cSJung-uk Kim BIO_printf(bio_err, 1626*c9cf7b5cSJung-uk Kim "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n"); 1627*c9cf7b5cSJung-uk Kim goto end; 1628*c9cf7b5cSJung-uk Kim } 1629aeb5019cSJung-uk Kim 1630e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SCTP 1631e71b7053SJung-uk Kim if (protocol == IPPROTO_SCTP) { 1632e71b7053SJung-uk Kim if (socket_type != SOCK_DGRAM) { 1633e71b7053SJung-uk Kim BIO_printf(bio_err, "Can't use -sctp without DTLS\n"); 1634e71b7053SJung-uk Kim goto end; 1635e71b7053SJung-uk Kim } 1636e71b7053SJung-uk Kim /* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */ 1637e71b7053SJung-uk Kim socket_type = SOCK_STREAM; 1638e71b7053SJung-uk Kim } 1639e71b7053SJung-uk Kim #endif 16405c87c606SMark Murray 1641e71b7053SJung-uk Kim if (!app_passwd(passarg, dpassarg, &pass, &dpass)) { 16423b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "Error getting password\n"); 16433b4e3dcbSSimon L. B. Nielsen goto end; 16443b4e3dcbSSimon L. B. Nielsen } 16453b4e3dcbSSimon L. B. Nielsen 16463b4e3dcbSSimon L. B. Nielsen if (s_key_file == NULL) 16473b4e3dcbSSimon L. B. Nielsen s_key_file = s_cert_file; 1648e71b7053SJung-uk Kim 1649db522d3aSSimon L. B. Nielsen if (s_key_file2 == NULL) 1650db522d3aSSimon L. B. Nielsen s_key_file2 = s_cert_file2; 16513b4e3dcbSSimon L. B. Nielsen 1652e71b7053SJung-uk Kim if (!load_excert(&exc)) 16537bded2dbSJung-uk Kim goto end; 16547bded2dbSJung-uk Kim 16556f9291ceSJung-uk Kim if (nocert == 0) { 1656e71b7053SJung-uk Kim s_key = load_key(s_key_file, s_key_format, 0, pass, engine, 16573b4e3dcbSSimon L. B. Nielsen "server certificate private key file"); 1658e71b7053SJung-uk Kim if (s_key == NULL) { 16593b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 16603b4e3dcbSSimon L. B. Nielsen goto end; 16613b4e3dcbSSimon L. B. Nielsen } 16623b4e3dcbSSimon L. B. Nielsen 1663e71b7053SJung-uk Kim s_cert = load_cert(s_cert_file, s_cert_format, 1664e71b7053SJung-uk Kim "server certificate file"); 16653b4e3dcbSSimon L. B. Nielsen 1666e71b7053SJung-uk Kim if (s_cert == NULL) { 16673b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 16683b4e3dcbSSimon L. B. Nielsen goto end; 16693b4e3dcbSSimon L. B. Nielsen } 1670e71b7053SJung-uk Kim if (s_chain_file != NULL) { 1671e71b7053SJung-uk Kim if (!load_certs(s_chain_file, &s_chain, FORMAT_PEM, NULL, 1672e71b7053SJung-uk Kim "server certificate chain")) 16737bded2dbSJung-uk Kim goto end; 16747bded2dbSJung-uk Kim } 1675e71b7053SJung-uk Kim 1676e71b7053SJung-uk Kim if (tlsextcbp.servername != NULL) { 1677e71b7053SJung-uk Kim s_key2 = load_key(s_key_file2, s_key_format, 0, pass, engine, 1678db522d3aSSimon L. B. Nielsen "second server certificate private key file"); 1679e71b7053SJung-uk Kim if (s_key2 == NULL) { 1680db522d3aSSimon L. B. Nielsen ERR_print_errors(bio_err); 1681db522d3aSSimon L. B. Nielsen goto end; 16823b4e3dcbSSimon L. B. Nielsen } 16833b4e3dcbSSimon L. B. Nielsen 1684e71b7053SJung-uk Kim s_cert2 = load_cert(s_cert_file2, s_cert_format, 1685e71b7053SJung-uk Kim "second server certificate file"); 1686db522d3aSSimon L. B. Nielsen 1687e71b7053SJung-uk Kim if (s_cert2 == NULL) { 1688db522d3aSSimon L. B. Nielsen ERR_print_errors(bio_err); 1689db522d3aSSimon L. B. Nielsen goto end; 1690db522d3aSSimon L. B. Nielsen } 1691db522d3aSSimon L. B. Nielsen } 169209286989SJung-uk Kim } 16937bded2dbSJung-uk Kim #if !defined(OPENSSL_NO_NEXTPROTONEG) 16946f9291ceSJung-uk Kim if (next_proto_neg_in) { 1695e71b7053SJung-uk Kim next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); 16961f13597dSJung-uk Kim if (next_proto.data == NULL) 16971f13597dSJung-uk Kim goto end; 16981f13597dSJung-uk Kim } 16991f13597dSJung-uk Kim #endif 17007bded2dbSJung-uk Kim alpn_ctx.data = NULL; 17017bded2dbSJung-uk Kim if (alpn_in) { 1702e71b7053SJung-uk Kim alpn_ctx.data = next_protos_parse(&alpn_ctx.len, alpn_in); 17037bded2dbSJung-uk Kim if (alpn_ctx.data == NULL) 17047bded2dbSJung-uk Kim goto end; 17057bded2dbSJung-uk Kim } 17067bded2dbSJung-uk Kim 1707e71b7053SJung-uk Kim if (crl_file != NULL) { 17087bded2dbSJung-uk Kim X509_CRL *crl; 17097bded2dbSJung-uk Kim crl = load_crl(crl_file, crl_format); 1710e71b7053SJung-uk Kim if (crl == NULL) { 17117bded2dbSJung-uk Kim BIO_puts(bio_err, "Error loading CRL\n"); 17127bded2dbSJung-uk Kim ERR_print_errors(bio_err); 17137bded2dbSJung-uk Kim goto end; 17147bded2dbSJung-uk Kim } 17157bded2dbSJung-uk Kim crls = sk_X509_CRL_new_null(); 1716e71b7053SJung-uk Kim if (crls == NULL || !sk_X509_CRL_push(crls, crl)) { 17177bded2dbSJung-uk Kim BIO_puts(bio_err, "Error adding CRL\n"); 17187bded2dbSJung-uk Kim ERR_print_errors(bio_err); 17197bded2dbSJung-uk Kim X509_CRL_free(crl); 17207bded2dbSJung-uk Kim goto end; 17217bded2dbSJung-uk Kim } 17227bded2dbSJung-uk Kim } 17231f13597dSJung-uk Kim 1724e71b7053SJung-uk Kim if (s_dcert_file != NULL) { 17253b4e3dcbSSimon L. B. Nielsen 17263b4e3dcbSSimon L. B. Nielsen if (s_dkey_file == NULL) 17273b4e3dcbSSimon L. B. Nielsen s_dkey_file = s_dcert_file; 17283b4e3dcbSSimon L. B. Nielsen 1729e71b7053SJung-uk Kim s_dkey = load_key(s_dkey_file, s_dkey_format, 1730e71b7053SJung-uk Kim 0, dpass, engine, "second certificate private key file"); 1731e71b7053SJung-uk Kim if (s_dkey == NULL) { 17323b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 17333b4e3dcbSSimon L. B. Nielsen goto end; 17343b4e3dcbSSimon L. B. Nielsen } 17353b4e3dcbSSimon L. B. Nielsen 1736e71b7053SJung-uk Kim s_dcert = load_cert(s_dcert_file, s_dcert_format, 1737e71b7053SJung-uk Kim "second server certificate file"); 17383b4e3dcbSSimon L. B. Nielsen 1739e71b7053SJung-uk Kim if (s_dcert == NULL) { 17403b4e3dcbSSimon L. B. Nielsen ERR_print_errors(bio_err); 17413b4e3dcbSSimon L. B. Nielsen goto end; 17423b4e3dcbSSimon L. B. Nielsen } 1743e71b7053SJung-uk Kim if (s_dchain_file != NULL) { 1744e71b7053SJung-uk Kim if (!load_certs(s_dchain_file, &s_dchain, FORMAT_PEM, NULL, 1745e71b7053SJung-uk Kim "second server certificate chain")) 17467bded2dbSJung-uk Kim goto end; 17477bded2dbSJung-uk Kim } 17483b4e3dcbSSimon L. B. Nielsen 17493b4e3dcbSSimon L. B. Nielsen } 17503b4e3dcbSSimon L. B. Nielsen 17516f9291ceSJung-uk Kim if (bio_s_out == NULL) { 17527bded2dbSJung-uk Kim if (s_quiet && !s_debug) { 175374664626SKris Kennaway bio_s_out = BIO_new(BIO_s_null()); 1754e71b7053SJung-uk Kim if (s_msg && bio_s_msg == NULL) 1755e71b7053SJung-uk Kim bio_s_msg = dup_bio_out(FORMAT_TEXT); 17566f9291ceSJung-uk Kim } else { 175774664626SKris Kennaway if (bio_s_out == NULL) 1758e71b7053SJung-uk Kim bio_s_out = dup_bio_out(FORMAT_TEXT); 175974664626SKris Kennaway } 176074664626SKris Kennaway } 1761e71b7053SJung-uk Kim #if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) 176274664626SKris Kennaway if (nocert) 176374664626SKris Kennaway #endif 176474664626SKris Kennaway { 176574664626SKris Kennaway s_cert_file = NULL; 176674664626SKris Kennaway s_key_file = NULL; 176774664626SKris Kennaway s_dcert_file = NULL; 176874664626SKris Kennaway s_dkey_file = NULL; 1769db522d3aSSimon L. B. Nielsen s_cert_file2 = NULL; 1770db522d3aSSimon L. B. Nielsen s_key_file2 = NULL; 177174664626SKris Kennaway } 177274664626SKris Kennaway 177374664626SKris Kennaway ctx = SSL_CTX_new(meth); 17746f9291ceSJung-uk Kim if (ctx == NULL) { 177574664626SKris Kennaway ERR_print_errors(bio_err); 177674664626SKris Kennaway goto end; 177774664626SKris Kennaway } 1778e71b7053SJung-uk Kim 1779e71b7053SJung-uk Kim SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); 1780e71b7053SJung-uk Kim 1781e71b7053SJung-uk Kim if (sdebug) 1782e71b7053SJung-uk Kim ssl_ctx_security_debug(ctx, sdebug); 1783e71b7053SJung-uk Kim 1784e71b7053SJung-uk Kim if (!config_ctx(cctx, ssl_args, ctx)) 1785e71b7053SJung-uk Kim goto end; 1786e71b7053SJung-uk Kim 1787e71b7053SJung-uk Kim if (ssl_config) { 1788e71b7053SJung-uk Kim if (SSL_CTX_config(ctx, ssl_config) == 0) { 1789e71b7053SJung-uk Kim BIO_printf(bio_err, "Error using configuration \"%s\"\n", 1790e71b7053SJung-uk Kim ssl_config); 1791e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1792e71b7053SJung-uk Kim goto end; 1793e71b7053SJung-uk Kim } 1794e71b7053SJung-uk Kim } 1795e71b7053SJung-uk Kim if (min_version != 0 1796e71b7053SJung-uk Kim && SSL_CTX_set_min_proto_version(ctx, min_version) == 0) 1797e71b7053SJung-uk Kim goto end; 1798e71b7053SJung-uk Kim if (max_version != 0 1799e71b7053SJung-uk Kim && SSL_CTX_set_max_proto_version(ctx, max_version) == 0) 1800e71b7053SJung-uk Kim goto end; 1801e71b7053SJung-uk Kim 18026f9291ceSJung-uk Kim if (session_id_prefix) { 18035c87c606SMark Murray if (strlen(session_id_prefix) >= 32) 18045c87c606SMark Murray BIO_printf(bio_err, 18055c87c606SMark Murray "warning: id_prefix is too long, only one new session will be possible\n"); 18066f9291ceSJung-uk Kim if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { 18075c87c606SMark Murray BIO_printf(bio_err, "error setting 'id_prefix'\n"); 18085c87c606SMark Murray ERR_print_errors(bio_err); 18095c87c606SMark Murray goto end; 18105c87c606SMark Murray } 18115c87c606SMark Murray BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); 18125c87c606SMark Murray } 181374664626SKris Kennaway SSL_CTX_set_quiet_shutdown(ctx, 1); 1814e71b7053SJung-uk Kim if (exc != NULL) 18157bded2dbSJung-uk Kim ssl_ctx_set_excert(ctx, exc); 181674664626SKris Kennaway 18176f9291ceSJung-uk Kim if (state) 18186f9291ceSJung-uk Kim SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); 18196a599222SSimon L. B. Nielsen if (no_cache) 18206a599222SSimon L. B. Nielsen SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 18217bded2dbSJung-uk Kim else if (ext_cache) 18227bded2dbSJung-uk Kim init_session_cache_ctx(ctx); 18236a599222SSimon L. B. Nielsen else 182474664626SKris Kennaway SSL_CTX_sess_set_cache_size(ctx, 128); 182574664626SKris Kennaway 1826e71b7053SJung-uk Kim if (async) { 1827e71b7053SJung-uk Kim SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); 1828e71b7053SJung-uk Kim } 18291f13597dSJung-uk Kim 1830e71b7053SJung-uk Kim if (max_send_fragment > 0 1831e71b7053SJung-uk Kim && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { 1832e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n", 1833e71b7053SJung-uk Kim prog, max_send_fragment); 183474664626SKris Kennaway goto end; 183574664626SKris Kennaway } 1836e71b7053SJung-uk Kim 1837e71b7053SJung-uk Kim if (split_send_fragment > 0 1838e71b7053SJung-uk Kim && !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) { 1839e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n", 1840e71b7053SJung-uk Kim prog, split_send_fragment); 1841e71b7053SJung-uk Kim goto end; 1842e71b7053SJung-uk Kim } 1843e71b7053SJung-uk Kim if (max_pipelines > 0 1844e71b7053SJung-uk Kim && !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) { 1845e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n", 1846e71b7053SJung-uk Kim prog, max_pipelines); 1847e71b7053SJung-uk Kim goto end; 1848e71b7053SJung-uk Kim } 1849e71b7053SJung-uk Kim 1850e71b7053SJung-uk Kim if (read_buf_len > 0) { 1851e71b7053SJung-uk Kim SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); 1852e71b7053SJung-uk Kim } 1853e71b7053SJung-uk Kim #ifndef OPENSSL_NO_SRTP 1854e71b7053SJung-uk Kim if (srtp_profiles != NULL) { 1855e71b7053SJung-uk Kim /* Returns 0 on success! */ 1856e71b7053SJung-uk Kim if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) { 1857e71b7053SJung-uk Kim BIO_printf(bio_err, "Error setting SRTP profile\n"); 1858e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1859e71b7053SJung-uk Kim goto end; 1860e71b7053SJung-uk Kim } 1861e71b7053SJung-uk Kim } 186274664626SKris Kennaway #endif 186374664626SKris Kennaway 1864e71b7053SJung-uk Kim if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { 186574664626SKris Kennaway ERR_print_errors(bio_err); 1866e71b7053SJung-uk Kim goto end; 186774664626SKris Kennaway } 1868e71b7053SJung-uk Kim if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { 1869e71b7053SJung-uk Kim BIO_printf(bio_err, "Error setting verify params\n"); 1870e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1871e71b7053SJung-uk Kim goto end; 1872e71b7053SJung-uk Kim } 18731f13597dSJung-uk Kim 18747bded2dbSJung-uk Kim ssl_ctx_add_crls(ctx, crls, 0); 18757bded2dbSJung-uk Kim 18767bded2dbSJung-uk Kim if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile, 18777bded2dbSJung-uk Kim crls, crl_download)) { 18787bded2dbSJung-uk Kim BIO_printf(bio_err, "Error loading store locations\n"); 18797bded2dbSJung-uk Kim ERR_print_errors(bio_err); 18807bded2dbSJung-uk Kim goto end; 18817bded2dbSJung-uk Kim } 1882e71b7053SJung-uk Kim 18836f9291ceSJung-uk Kim if (s_cert2) { 1884db522d3aSSimon L. B. Nielsen ctx2 = SSL_CTX_new(meth); 18856f9291ceSJung-uk Kim if (ctx2 == NULL) { 1886db522d3aSSimon L. B. Nielsen ERR_print_errors(bio_err); 1887db522d3aSSimon L. B. Nielsen goto end; 1888db522d3aSSimon L. B. Nielsen } 1889db522d3aSSimon L. B. Nielsen } 1890db522d3aSSimon L. B. Nielsen 1891e71b7053SJung-uk Kim if (ctx2 != NULL) { 1892db522d3aSSimon L. B. Nielsen BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); 1893db522d3aSSimon L. B. Nielsen 1894e71b7053SJung-uk Kim if (sdebug) 1895e71b7053SJung-uk Kim ssl_ctx_security_debug(ctx, sdebug); 1896e71b7053SJung-uk Kim 18976f9291ceSJung-uk Kim if (session_id_prefix) { 1898db522d3aSSimon L. B. Nielsen if (strlen(session_id_prefix) >= 32) 1899db522d3aSSimon L. B. Nielsen BIO_printf(bio_err, 1900db522d3aSSimon L. B. Nielsen "warning: id_prefix is too long, only one new session will be possible\n"); 19016f9291ceSJung-uk Kim if (!SSL_CTX_set_generate_session_id(ctx2, generate_session_id)) { 1902db522d3aSSimon L. B. Nielsen BIO_printf(bio_err, "error setting 'id_prefix'\n"); 1903db522d3aSSimon L. B. Nielsen ERR_print_errors(bio_err); 1904db522d3aSSimon L. B. Nielsen goto end; 1905db522d3aSSimon L. B. Nielsen } 1906db522d3aSSimon L. B. Nielsen BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix); 1907db522d3aSSimon L. B. Nielsen } 1908db522d3aSSimon L. B. Nielsen SSL_CTX_set_quiet_shutdown(ctx2, 1); 1909e71b7053SJung-uk Kim if (exc != NULL) 19107bded2dbSJung-uk Kim ssl_ctx_set_excert(ctx2, exc); 1911db522d3aSSimon L. B. Nielsen 19126f9291ceSJung-uk Kim if (state) 19136f9291ceSJung-uk Kim SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback); 1914db522d3aSSimon L. B. Nielsen 19156a599222SSimon L. B. Nielsen if (no_cache) 19166a599222SSimon L. B. Nielsen SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF); 19177bded2dbSJung-uk Kim else if (ext_cache) 19187bded2dbSJung-uk Kim init_session_cache_ctx(ctx2); 19196a599222SSimon L. B. Nielsen else 1920db522d3aSSimon L. B. Nielsen SSL_CTX_sess_set_cache_size(ctx2, 128); 1921db522d3aSSimon L. B. Nielsen 1922e71b7053SJung-uk Kim if (async) 1923e71b7053SJung-uk Kim SSL_CTX_set_mode(ctx2, SSL_MODE_ASYNC); 1924e71b7053SJung-uk Kim 1925e71b7053SJung-uk Kim if (!ctx_set_verify_locations(ctx2, CAfile, CApath, noCAfile, 1926e71b7053SJung-uk Kim noCApath)) { 1927db522d3aSSimon L. B. Nielsen ERR_print_errors(bio_err); 1928e71b7053SJung-uk Kim goto end; 1929db522d3aSSimon L. B. Nielsen } 1930e71b7053SJung-uk Kim if (vpmtouched && !SSL_CTX_set1_param(ctx2, vpm)) { 1931e71b7053SJung-uk Kim BIO_printf(bio_err, "Error setting verify params\n"); 1932e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1933e71b7053SJung-uk Kim goto end; 1934e71b7053SJung-uk Kim } 19357bded2dbSJung-uk Kim 19367bded2dbSJung-uk Kim ssl_ctx_add_crls(ctx2, crls, 0); 1937e71b7053SJung-uk Kim if (!config_ctx(cctx, ssl_args, ctx2)) 19387bded2dbSJung-uk Kim goto end; 1939db522d3aSSimon L. B. Nielsen } 19401f13597dSJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 19411f13597dSJung-uk Kim if (next_proto.data) 19426f9291ceSJung-uk Kim SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, 19436f9291ceSJung-uk Kim &next_proto); 19441f13597dSJung-uk Kim #endif 19457bded2dbSJung-uk Kim if (alpn_ctx.data) 19467bded2dbSJung-uk Kim SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); 194774664626SKris Kennaway 19485c87c606SMark Murray #ifndef OPENSSL_NO_DH 19496f9291ceSJung-uk Kim if (!no_dhe) { 19505c87c606SMark Murray DH *dh = NULL; 19515c87c606SMark Murray 1952e71b7053SJung-uk Kim if (dhfile != NULL) 19535c87c606SMark Murray dh = load_dh_param(dhfile); 1954e71b7053SJung-uk Kim else if (s_cert_file != NULL) 19555c87c606SMark Murray dh = load_dh_param(s_cert_file); 19565c87c606SMark Murray 19576f9291ceSJung-uk Kim if (dh != NULL) { 195874664626SKris Kennaway BIO_printf(bio_s_out, "Setting temp DH parameters\n"); 19596f9291ceSJung-uk Kim } else { 196074664626SKris Kennaway BIO_printf(bio_s_out, "Using default temp DH parameters\n"); 196174664626SKris Kennaway } 196274664626SKris Kennaway (void)BIO_flush(bio_s_out); 196374664626SKris Kennaway 1964e71b7053SJung-uk Kim if (dh == NULL) { 1965e71b7053SJung-uk Kim SSL_CTX_set_dh_auto(ctx, 1); 1966e71b7053SJung-uk Kim } else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { 1967e71b7053SJung-uk Kim BIO_puts(bio_err, "Error setting temp DH parameters\n"); 1968e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1969e71b7053SJung-uk Kim DH_free(dh); 1970e71b7053SJung-uk Kim goto end; 1971e71b7053SJung-uk Kim } 1972e71b7053SJung-uk Kim 1973e71b7053SJung-uk Kim if (ctx2 != NULL) { 19746f9291ceSJung-uk Kim if (!dhfile) { 1975db522d3aSSimon L. B. Nielsen DH *dh2 = load_dh_param(s_cert_file2); 19766f9291ceSJung-uk Kim if (dh2 != NULL) { 1977db522d3aSSimon L. B. Nielsen BIO_printf(bio_s_out, "Setting temp DH parameters\n"); 1978db522d3aSSimon L. B. Nielsen (void)BIO_flush(bio_s_out); 1979db522d3aSSimon L. B. Nielsen 1980db522d3aSSimon L. B. Nielsen DH_free(dh); 1981db522d3aSSimon L. B. Nielsen dh = dh2; 1982db522d3aSSimon L. B. Nielsen } 1983db522d3aSSimon L. B. Nielsen } 1984e71b7053SJung-uk Kim if (dh == NULL) { 1985e71b7053SJung-uk Kim SSL_CTX_set_dh_auto(ctx2, 1); 1986e71b7053SJung-uk Kim } else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { 1987e71b7053SJung-uk Kim BIO_puts(bio_err, "Error setting temp DH parameters\n"); 1988e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1989e71b7053SJung-uk Kim DH_free(dh); 1990e71b7053SJung-uk Kim goto end; 1991db522d3aSSimon L. B. Nielsen } 1992e71b7053SJung-uk Kim } 199374664626SKris Kennaway DH_free(dh); 199474664626SKris Kennaway } 199574664626SKris Kennaway #endif 199674664626SKris Kennaway 19977bded2dbSJung-uk Kim if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain)) 19983b4e3dcbSSimon L. B. Nielsen goto end; 1999e71b7053SJung-uk Kim 20007bded2dbSJung-uk Kim if (s_serverinfo_file != NULL 20017bded2dbSJung-uk Kim && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) { 20027bded2dbSJung-uk Kim ERR_print_errors(bio_err); 20037bded2dbSJung-uk Kim goto end; 20047bded2dbSJung-uk Kim } 2005e71b7053SJung-uk Kim 2006e71b7053SJung-uk Kim if (ctx2 != NULL 2007e71b7053SJung-uk Kim && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain)) 2008db522d3aSSimon L. B. Nielsen goto end; 2009e71b7053SJung-uk Kim 20106f9291ceSJung-uk Kim if (s_dcert != NULL) { 20117bded2dbSJung-uk Kim if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain)) 201274664626SKris Kennaway goto end; 201374664626SKris Kennaway } 201474664626SKris Kennaway 2015e71b7053SJung-uk Kim if (no_resume_ephemeral) { 2016e71b7053SJung-uk Kim SSL_CTX_set_not_resumable_session_callback(ctx, 2017e71b7053SJung-uk Kim not_resumable_sess_cb); 201874664626SKris Kennaway 2019e71b7053SJung-uk Kim if (ctx2 != NULL) 2020e71b7053SJung-uk Kim SSL_CTX_set_not_resumable_session_callback(ctx2, 2021e71b7053SJung-uk Kim not_resumable_sess_cb); 202274664626SKris Kennaway } 20231f13597dSJung-uk Kim #ifndef OPENSSL_NO_PSK 2024e71b7053SJung-uk Kim if (psk_key != NULL) { 20251f13597dSJung-uk Kim if (s_debug) 2026e71b7053SJung-uk Kim BIO_printf(bio_s_out, "PSK key given, setting server callback\n"); 20271f13597dSJung-uk Kim SSL_CTX_set_psk_server_callback(ctx, psk_server_cb); 20281f13597dSJung-uk Kim } 20291f13597dSJung-uk Kim 20306f9291ceSJung-uk Kim if (!SSL_CTX_use_psk_identity_hint(ctx, psk_identity_hint)) { 20311f13597dSJung-uk Kim BIO_printf(bio_err, "error setting PSK identity hint to context\n"); 20321f13597dSJung-uk Kim ERR_print_errors(bio_err); 20331f13597dSJung-uk Kim goto end; 20341f13597dSJung-uk Kim } 20351f13597dSJung-uk Kim #endif 2036e71b7053SJung-uk Kim if (psksessf != NULL) { 2037e71b7053SJung-uk Kim BIO *stmp = BIO_new_file(psksessf, "r"); 2038e71b7053SJung-uk Kim 2039e71b7053SJung-uk Kim if (stmp == NULL) { 2040e71b7053SJung-uk Kim BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf); 2041e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2042e71b7053SJung-uk Kim goto end; 2043e71b7053SJung-uk Kim } 2044e71b7053SJung-uk Kim psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); 2045e71b7053SJung-uk Kim BIO_free(stmp); 2046e71b7053SJung-uk Kim if (psksess == NULL) { 2047e71b7053SJung-uk Kim BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf); 2048e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2049e71b7053SJung-uk Kim goto end; 2050e71b7053SJung-uk Kim } 2051e71b7053SJung-uk Kim 2052e71b7053SJung-uk Kim } 2053e71b7053SJung-uk Kim 2054e71b7053SJung-uk Kim if (psk_key != NULL || psksess != NULL) 2055e71b7053SJung-uk Kim SSL_CTX_set_psk_find_session_callback(ctx, psk_find_session_cb); 20561f13597dSJung-uk Kim 205774664626SKris Kennaway SSL_CTX_set_verify(ctx, s_server_verify, verify_callback); 2058e71b7053SJung-uk Kim if (!SSL_CTX_set_session_id_context(ctx, 2059e71b7053SJung-uk Kim (void *)&s_server_session_id_context, 2060e71b7053SJung-uk Kim sizeof(s_server_session_id_context))) { 2061e71b7053SJung-uk Kim BIO_printf(bio_err, "error setting session id context\n"); 2062e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2063e71b7053SJung-uk Kim goto end; 2064e71b7053SJung-uk Kim } 206574664626SKris Kennaway 20666a599222SSimon L. B. Nielsen /* Set DTLS cookie generation and verification callbacks */ 20676a599222SSimon L. B. Nielsen SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); 20686a599222SSimon L. B. Nielsen SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); 20696a599222SSimon L. B. Nielsen 2070e71b7053SJung-uk Kim /* Set TLS1.3 cookie generation and verification callbacks */ 2071e71b7053SJung-uk Kim SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback); 2072e71b7053SJung-uk Kim SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback); 207374664626SKris Kennaway 2074e71b7053SJung-uk Kim if (ctx2 != NULL) { 2075e71b7053SJung-uk Kim SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback); 2076e71b7053SJung-uk Kim if (!SSL_CTX_set_session_id_context(ctx2, 2077e71b7053SJung-uk Kim (void *)&s_server_session_id_context, 2078e71b7053SJung-uk Kim sizeof(s_server_session_id_context))) { 2079e71b7053SJung-uk Kim BIO_printf(bio_err, "error setting session id context\n"); 2080e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2081e71b7053SJung-uk Kim goto end; 2082e71b7053SJung-uk Kim } 2083db522d3aSSimon L. B. Nielsen tlsextcbp.biodebug = bio_s_out; 2084db522d3aSSimon L. B. Nielsen SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); 2085db522d3aSSimon L. B. Nielsen SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp); 2086db522d3aSSimon L. B. Nielsen SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); 2087db522d3aSSimon L. B. Nielsen SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); 2088db522d3aSSimon L. B. Nielsen } 20891f13597dSJung-uk Kim 20901f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 20916f9291ceSJung-uk Kim if (srp_verifier_file != NULL) { 20921f13597dSJung-uk Kim srp_callback_parm.vb = SRP_VBASE_new(srpuserseed); 20931f13597dSJung-uk Kim srp_callback_parm.user = NULL; 20941f13597dSJung-uk Kim srp_callback_parm.login = NULL; 20956f9291ceSJung-uk Kim if ((ret = 20966f9291ceSJung-uk Kim SRP_VBASE_init(srp_callback_parm.vb, 20976f9291ceSJung-uk Kim srp_verifier_file)) != SRP_NO_ERROR) { 20981f13597dSJung-uk Kim BIO_printf(bio_err, 20991f13597dSJung-uk Kim "Cannot initialize SRP verifier file \"%s\":ret=%d\n", 21001f13597dSJung-uk Kim srp_verifier_file, ret); 21011f13597dSJung-uk Kim goto end; 21021f13597dSJung-uk Kim } 21031f13597dSJung-uk Kim SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); 21041f13597dSJung-uk Kim SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm); 21051f13597dSJung-uk Kim SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb); 21066f9291ceSJung-uk Kim } else 21071f13597dSJung-uk Kim #endif 21086f9291ceSJung-uk Kim if (CAfile != NULL) { 2109db522d3aSSimon L. B. Nielsen SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile)); 2110e71b7053SJung-uk Kim 2111db522d3aSSimon L. B. Nielsen if (ctx2) 2112db522d3aSSimon L. B. Nielsen SSL_CTX_set_client_CA_list(ctx2, SSL_load_client_CA_file(CAfile)); 2113db522d3aSSimon L. B. Nielsen } 2114e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCSP 2115e71b7053SJung-uk Kim if (s_tlsextstatus) { 2116e71b7053SJung-uk Kim SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); 2117e71b7053SJung-uk Kim SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp); 2118e71b7053SJung-uk Kim if (ctx2) { 2119e71b7053SJung-uk Kim SSL_CTX_set_tlsext_status_cb(ctx2, cert_status_cb); 2120e71b7053SJung-uk Kim SSL_CTX_set_tlsext_status_arg(ctx2, &tlscstatp); 2121e71b7053SJung-uk Kim } 2122e71b7053SJung-uk Kim } 2123e71b7053SJung-uk Kim #endif 2124e71b7053SJung-uk Kim if (set_keylog_file(ctx, keylog_file)) 2125e71b7053SJung-uk Kim goto end; 21261f13597dSJung-uk Kim 2127e71b7053SJung-uk Kim if (max_early_data >= 0) 2128e71b7053SJung-uk Kim SSL_CTX_set_max_early_data(ctx, max_early_data); 2129e71b7053SJung-uk Kim if (recv_max_early_data >= 0) 2130e71b7053SJung-uk Kim SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data); 2131e71b7053SJung-uk Kim 21327bded2dbSJung-uk Kim if (rev) 2133e71b7053SJung-uk Kim server_cb = rev_body; 21347bded2dbSJung-uk Kim else if (www) 2135e71b7053SJung-uk Kim server_cb = www_body; 213674664626SKris Kennaway else 2137e71b7053SJung-uk Kim server_cb = sv_body; 2138e71b7053SJung-uk Kim #ifdef AF_UNIX 2139e71b7053SJung-uk Kim if (socket_family == AF_UNIX 2140e71b7053SJung-uk Kim && unlink_unix_path) 2141e71b7053SJung-uk Kim unlink(host); 2142e71b7053SJung-uk Kim #endif 2143e71b7053SJung-uk Kim do_server(&accept_socket, host, port, socket_family, socket_type, protocol, 2144e71b7053SJung-uk Kim server_cb, context, naccept, bio_s_out); 214574664626SKris Kennaway print_stats(bio_s_out, ctx); 214674664626SKris Kennaway ret = 0; 214774664626SKris Kennaway end: 21486f9291ceSJung-uk Kim SSL_CTX_free(ctx); 2149e71b7053SJung-uk Kim SSL_SESSION_free(psksess); 2150e71b7053SJung-uk Kim set_keylog_file(NULL, NULL); 21513b4e3dcbSSimon L. B. Nielsen X509_free(s_cert); 21527bded2dbSJung-uk Kim sk_X509_CRL_pop_free(crls, X509_CRL_free); 21533b4e3dcbSSimon L. B. Nielsen X509_free(s_dcert); 21543b4e3dcbSSimon L. B. Nielsen EVP_PKEY_free(s_key); 21553b4e3dcbSSimon L. B. Nielsen EVP_PKEY_free(s_dkey); 21567bded2dbSJung-uk Kim sk_X509_pop_free(s_chain, X509_free); 21577bded2dbSJung-uk Kim sk_X509_pop_free(s_dchain, X509_free); 21583b4e3dcbSSimon L. B. Nielsen OPENSSL_free(pass); 21593b4e3dcbSSimon L. B. Nielsen OPENSSL_free(dpass); 2160e71b7053SJung-uk Kim OPENSSL_free(host); 2161e71b7053SJung-uk Kim OPENSSL_free(port); 216209286989SJung-uk Kim X509_VERIFY_PARAM_free(vpm); 21637bded2dbSJung-uk Kim free_sessions(); 216409286989SJung-uk Kim OPENSSL_free(tlscstatp.host); 216509286989SJung-uk Kim OPENSSL_free(tlscstatp.port); 216609286989SJung-uk Kim OPENSSL_free(tlscstatp.path); 21676f9291ceSJung-uk Kim SSL_CTX_free(ctx2); 2168db522d3aSSimon L. B. Nielsen X509_free(s_cert2); 2169db522d3aSSimon L. B. Nielsen EVP_PKEY_free(s_key2); 21707bded2dbSJung-uk Kim #ifndef OPENSSL_NO_NEXTPROTONEG 21717bded2dbSJung-uk Kim OPENSSL_free(next_proto.data); 21727bded2dbSJung-uk Kim #endif 21737bded2dbSJung-uk Kim OPENSSL_free(alpn_ctx.data); 21747bded2dbSJung-uk Kim ssl_excert_free(exc); 21757bded2dbSJung-uk Kim sk_OPENSSL_STRING_free(ssl_args); 21767bded2dbSJung-uk Kim SSL_CONF_CTX_free(cctx); 2177e71b7053SJung-uk Kim release_engine(engine); 217874664626SKris Kennaway BIO_free(bio_s_out); 217974664626SKris Kennaway bio_s_out = NULL; 21807bded2dbSJung-uk Kim BIO_free(bio_s_msg); 21817bded2dbSJung-uk Kim bio_s_msg = NULL; 2182e71b7053SJung-uk Kim #ifdef CHARSET_EBCDIC 2183e71b7053SJung-uk Kim BIO_meth_free(methods_ebcdic); 2184e71b7053SJung-uk Kim #endif 2185e71b7053SJung-uk Kim return ret; 218674664626SKris Kennaway } 218774664626SKris Kennaway 218874664626SKris Kennaway static void print_stats(BIO *bio, SSL_CTX *ssl_ctx) 218974664626SKris Kennaway { 219074664626SKris Kennaway BIO_printf(bio, "%4ld items in the session cache\n", 219174664626SKris Kennaway SSL_CTX_sess_number(ssl_ctx)); 21923b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld client connects (SSL_connect())\n", 219374664626SKris Kennaway SSL_CTX_sess_connect(ssl_ctx)); 21943b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n", 219574664626SKris Kennaway SSL_CTX_sess_connect_renegotiate(ssl_ctx)); 21963b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld client connects that finished\n", 219774664626SKris Kennaway SSL_CTX_sess_connect_good(ssl_ctx)); 21983b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld server accepts (SSL_accept())\n", 219974664626SKris Kennaway SSL_CTX_sess_accept(ssl_ctx)); 22003b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n", 220174664626SKris Kennaway SSL_CTX_sess_accept_renegotiate(ssl_ctx)); 22023b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld server accepts that finished\n", 220374664626SKris Kennaway SSL_CTX_sess_accept_good(ssl_ctx)); 22043b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld session cache hits\n", SSL_CTX_sess_hits(ssl_ctx)); 22056f9291ceSJung-uk Kim BIO_printf(bio, "%4ld session cache misses\n", 22066f9291ceSJung-uk Kim SSL_CTX_sess_misses(ssl_ctx)); 22076f9291ceSJung-uk Kim BIO_printf(bio, "%4ld session cache timeouts\n", 22086f9291ceSJung-uk Kim SSL_CTX_sess_timeouts(ssl_ctx)); 22096f9291ceSJung-uk Kim BIO_printf(bio, "%4ld callback cache hits\n", 22106f9291ceSJung-uk Kim SSL_CTX_sess_cb_hits(ssl_ctx)); 22113b4e3dcbSSimon L. B. Nielsen BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n", 221274664626SKris Kennaway SSL_CTX_sess_cache_full(ssl_ctx), 221374664626SKris Kennaway SSL_CTX_sess_get_cache_size(ssl_ctx)); 221474664626SKris Kennaway } 221574664626SKris Kennaway 2216e71b7053SJung-uk Kim static int sv_body(int s, int stype, int prot, unsigned char *context) 221774664626SKris Kennaway { 221874664626SKris Kennaway char *buf = NULL; 221974664626SKris Kennaway fd_set readfds; 222074664626SKris Kennaway int ret = 1, width; 222174664626SKris Kennaway int k, i; 222274664626SKris Kennaway unsigned long l; 222374664626SKris Kennaway SSL *con = NULL; 222474664626SKris Kennaway BIO *sbio; 22256a599222SSimon L. B. Nielsen struct timeval timeout; 2226e71b7053SJung-uk Kim #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)) 22276a599222SSimon L. B. Nielsen struct timeval *timeoutp; 2228f579bf8eSKris Kennaway #endif 2229e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 2230e71b7053SJung-uk Kim # ifndef OPENSSL_NO_SCTP 2231e71b7053SJung-uk Kim int isdtls = (stype == SOCK_DGRAM || prot == IPPROTO_SCTP); 2232e71b7053SJung-uk Kim # else 2233e71b7053SJung-uk Kim int isdtls = (stype == SOCK_DGRAM); 2234e71b7053SJung-uk Kim # endif 223574664626SKris Kennaway #endif 223674664626SKris Kennaway 2237e71b7053SJung-uk Kim buf = app_malloc(bufsize, "server buffer"); 2238e71b7053SJung-uk Kim if (s_nbio) { 2239e71b7053SJung-uk Kim if (!BIO_socket_nbio(s, 1)) 2240e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2241e71b7053SJung-uk Kim else if (!s_quiet) 2242e71b7053SJung-uk Kim BIO_printf(bio_err, "Turned on non blocking io\n"); 2243e71b7053SJung-uk Kim } 2244e71b7053SJung-uk Kim 2245f579bf8eSKris Kennaway con = SSL_new(ctx); 2246e71b7053SJung-uk Kim if (con == NULL) { 2247e71b7053SJung-uk Kim ret = -1; 2248e71b7053SJung-uk Kim goto err; 2249e71b7053SJung-uk Kim } 2250e71b7053SJung-uk Kim 22516f9291ceSJung-uk Kim if (s_tlsextdebug) { 2252db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_callback(con, tlsext_cb); 2253db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_arg(con, bio_s_out); 2254db522d3aSSimon L. B. Nielsen } 225574664626SKris Kennaway 2256e71b7053SJung-uk Kim if (context != NULL 2257e71b7053SJung-uk Kim && !SSL_set_session_id_context(con, context, 2258e71b7053SJung-uk Kim strlen((char *)context))) { 2259e71b7053SJung-uk Kim BIO_printf(bio_err, "Error setting session id context\n"); 2260e71b7053SJung-uk Kim ret = -1; 2261e71b7053SJung-uk Kim goto err; 2262e71b7053SJung-uk Kim } 22633b4e3dcbSSimon L. B. Nielsen 2264e71b7053SJung-uk Kim if (!SSL_clear(con)) { 2265e71b7053SJung-uk Kim BIO_printf(bio_err, "Error clearing SSL connection\n"); 2266e71b7053SJung-uk Kim ret = -1; 2267e71b7053SJung-uk Kim goto err; 2268e71b7053SJung-uk Kim } 2269e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DTLS 2270e71b7053SJung-uk Kim if (isdtls) { 2271e71b7053SJung-uk Kim # ifndef OPENSSL_NO_SCTP 2272e71b7053SJung-uk Kim if (prot == IPPROTO_SCTP) 2273e71b7053SJung-uk Kim sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE); 2274e71b7053SJung-uk Kim else 2275e71b7053SJung-uk Kim # endif 22763b4e3dcbSSimon L. B. Nielsen sbio = BIO_new_dgram(s, BIO_NOCLOSE); 22773b4e3dcbSSimon L. B. Nielsen 22786f9291ceSJung-uk Kim if (enable_timeouts) { 22793b4e3dcbSSimon L. B. Nielsen timeout.tv_sec = 0; 22803b4e3dcbSSimon L. B. Nielsen timeout.tv_usec = DGRAM_RCV_TIMEOUT; 22813b4e3dcbSSimon L. B. Nielsen BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); 22823b4e3dcbSSimon L. B. Nielsen 22833b4e3dcbSSimon L. B. Nielsen timeout.tv_sec = 0; 22843b4e3dcbSSimon L. B. Nielsen timeout.tv_usec = DGRAM_SND_TIMEOUT; 22853b4e3dcbSSimon L. B. Nielsen BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); 22863b4e3dcbSSimon L. B. Nielsen } 22873b4e3dcbSSimon L. B. Nielsen 22886f9291ceSJung-uk Kim if (socket_mtu) { 22896f9291ceSJung-uk Kim if (socket_mtu < DTLS_get_link_min_mtu(con)) { 2290751d2991SJung-uk Kim BIO_printf(bio_err, "MTU too small. Must be at least %ld\n", 2291751d2991SJung-uk Kim DTLS_get_link_min_mtu(con)); 2292751d2991SJung-uk Kim ret = -1; 2293751d2991SJung-uk Kim BIO_free(sbio); 2294751d2991SJung-uk Kim goto err; 2295751d2991SJung-uk Kim } 22963b4e3dcbSSimon L. B. Nielsen SSL_set_options(con, SSL_OP_NO_QUERY_MTU); 22976f9291ceSJung-uk Kim if (!DTLS_set_link_mtu(con, socket_mtu)) { 2298751d2991SJung-uk Kim BIO_printf(bio_err, "Failed to set MTU\n"); 2299751d2991SJung-uk Kim ret = -1; 2300751d2991SJung-uk Kim BIO_free(sbio); 2301751d2991SJung-uk Kim goto err; 2302751d2991SJung-uk Kim } 23036f9291ceSJung-uk Kim } else 23043b4e3dcbSSimon L. B. Nielsen /* want to do MTU discovery */ 23053b4e3dcbSSimon L. B. Nielsen BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); 23063b4e3dcbSSimon L. B. Nielsen 2307e71b7053SJung-uk Kim # ifndef OPENSSL_NO_SCTP 2308e71b7053SJung-uk Kim if (prot != IPPROTO_SCTP) 2309e71b7053SJung-uk Kim # endif 2310e71b7053SJung-uk Kim /* Turn on cookie exchange. Not necessary for SCTP */ 23113b4e3dcbSSimon L. B. Nielsen SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); 23126f9291ceSJung-uk Kim } else 2313e71b7053SJung-uk Kim #endif 231474664626SKris Kennaway sbio = BIO_new_socket(s, BIO_NOCLOSE); 23153b4e3dcbSSimon L. B. Nielsen 2316e71b7053SJung-uk Kim if (sbio == NULL) { 2317e71b7053SJung-uk Kim BIO_printf(bio_err, "Unable to create BIO\n"); 2318e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2319e71b7053SJung-uk Kim goto err; 2320e71b7053SJung-uk Kim } 2321e71b7053SJung-uk Kim 23226f9291ceSJung-uk Kim if (s_nbio_test) { 232374664626SKris Kennaway BIO *test; 232474664626SKris Kennaway 232574664626SKris Kennaway test = BIO_new(BIO_f_nbio_test()); 232674664626SKris Kennaway sbio = BIO_push(test, sbio); 232774664626SKris Kennaway } 2328db522d3aSSimon L. B. Nielsen 232974664626SKris Kennaway SSL_set_bio(con, sbio, sbio); 233074664626SKris Kennaway SSL_set_accept_state(con); 233174664626SKris Kennaway /* SSL_set_fd(con,s); */ 233274664626SKris Kennaway 23336f9291ceSJung-uk Kim if (s_debug) { 23343b4e3dcbSSimon L. B. Nielsen BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); 23355471f83eSSimon L. B. Nielsen BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); 233674664626SKris Kennaway } 23376f9291ceSJung-uk Kim if (s_msg) { 23387bded2dbSJung-uk Kim #ifndef OPENSSL_NO_SSL_TRACE 23397bded2dbSJung-uk Kim if (s_msg == 2) 23407bded2dbSJung-uk Kim SSL_set_msg_callback(con, SSL_trace); 23417bded2dbSJung-uk Kim else 23427bded2dbSJung-uk Kim #endif 23435c87c606SMark Murray SSL_set_msg_callback(con, msg_cb); 23447bded2dbSJung-uk Kim SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); 23455c87c606SMark Murray } 2346e71b7053SJung-uk Kim 23476f9291ceSJung-uk Kim if (s_tlsextdebug) { 2348db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_callback(con, tlsext_cb); 2349db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_arg(con, bio_s_out); 2350db522d3aSSimon L. B. Nielsen } 2351e71b7053SJung-uk Kim 2352e71b7053SJung-uk Kim if (early_data) { 2353e71b7053SJung-uk Kim int write_header = 1, edret = SSL_READ_EARLY_DATA_ERROR; 2354e71b7053SJung-uk Kim size_t readbytes; 2355e71b7053SJung-uk Kim 2356e71b7053SJung-uk Kim while (edret != SSL_READ_EARLY_DATA_FINISH) { 2357e71b7053SJung-uk Kim for (;;) { 2358e71b7053SJung-uk Kim edret = SSL_read_early_data(con, buf, bufsize, &readbytes); 2359e71b7053SJung-uk Kim if (edret != SSL_READ_EARLY_DATA_ERROR) 2360e71b7053SJung-uk Kim break; 2361e71b7053SJung-uk Kim 2362e71b7053SJung-uk Kim switch (SSL_get_error(con, 0)) { 2363e71b7053SJung-uk Kim case SSL_ERROR_WANT_WRITE: 2364e71b7053SJung-uk Kim case SSL_ERROR_WANT_ASYNC: 2365e71b7053SJung-uk Kim case SSL_ERROR_WANT_READ: 2366e71b7053SJung-uk Kim /* Just keep trying - busy waiting */ 2367e71b7053SJung-uk Kim continue; 2368e71b7053SJung-uk Kim default: 2369e71b7053SJung-uk Kim BIO_printf(bio_err, "Error reading early data\n"); 2370e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2371e71b7053SJung-uk Kim goto err; 2372e71b7053SJung-uk Kim } 2373e71b7053SJung-uk Kim } 2374e71b7053SJung-uk Kim if (readbytes > 0) { 2375e71b7053SJung-uk Kim if (write_header) { 2376e71b7053SJung-uk Kim BIO_printf(bio_s_out, "Early data received:\n"); 2377e71b7053SJung-uk Kim write_header = 0; 2378e71b7053SJung-uk Kim } 2379e71b7053SJung-uk Kim raw_write_stdout(buf, (unsigned int)readbytes); 2380e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 2381e71b7053SJung-uk Kim } 2382e71b7053SJung-uk Kim } 2383e71b7053SJung-uk Kim if (write_header) { 2384e71b7053SJung-uk Kim if (SSL_get_early_data_status(con) == SSL_EARLY_DATA_NOT_SENT) 2385e71b7053SJung-uk Kim BIO_printf(bio_s_out, "No early data received\n"); 2386e71b7053SJung-uk Kim else 2387e71b7053SJung-uk Kim BIO_printf(bio_s_out, "Early data was rejected\n"); 2388e71b7053SJung-uk Kim } else { 2389e71b7053SJung-uk Kim BIO_printf(bio_s_out, "\nEnd of early data\n"); 2390e71b7053SJung-uk Kim } 2391e71b7053SJung-uk Kim if (SSL_is_init_finished(con)) 2392e71b7053SJung-uk Kim print_connection_info(con); 2393e71b7053SJung-uk Kim } 239474664626SKris Kennaway 2395aeb5019cSJung-uk Kim if (fileno_stdin() > s) 2396aeb5019cSJung-uk Kim width = fileno_stdin() + 1; 2397aeb5019cSJung-uk Kim else 239874664626SKris Kennaway width = s + 1; 23996f9291ceSJung-uk Kim for (;;) { 2400f579bf8eSKris Kennaway int read_from_terminal; 2401f579bf8eSKris Kennaway int read_from_sslcon; 2402f579bf8eSKris Kennaway 2403f579bf8eSKris Kennaway read_from_terminal = 0; 2404e71b7053SJung-uk Kim read_from_sslcon = SSL_has_pending(con) 2405e71b7053SJung-uk Kim || (async && SSL_waiting_for_async(con)); 2406f579bf8eSKris Kennaway 24076f9291ceSJung-uk Kim if (!read_from_sslcon) { 240874664626SKris Kennaway FD_ZERO(&readfds); 2409e71b7053SJung-uk Kim #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) 2410aeb5019cSJung-uk Kim openssl_fdset(fileno_stdin(), &readfds); 241174664626SKris Kennaway #endif 24121f13597dSJung-uk Kim openssl_fdset(s, &readfds); 24136f9291ceSJung-uk Kim /* 24146f9291ceSJung-uk Kim * Note: under VMS with SOCKETSHR the second parameter is 24156f9291ceSJung-uk Kim * currently of type (int *) whereas under other systems it is 24166f9291ceSJung-uk Kim * (void *) if you don't have a cast it will choke the compiler: 24176f9291ceSJung-uk Kim * if you do have a cast then you can either go for (int *) or 24186f9291ceSJung-uk Kim * (void *). 241974664626SKris Kennaway */ 2420e71b7053SJung-uk Kim #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) 24216f9291ceSJung-uk Kim /* 24226f9291ceSJung-uk Kim * Under DOS (non-djgpp) and Windows we can't select on stdin: 24236f9291ceSJung-uk Kim * only on sockets. As a workaround we timeout the select every 2424f579bf8eSKris Kennaway * second and check for any keypress. In a proper Windows 2425f579bf8eSKris Kennaway * application we wouldn't do this because it is inefficient. 2426f579bf8eSKris Kennaway */ 2427e71b7053SJung-uk Kim timeout.tv_sec = 1; 2428e71b7053SJung-uk Kim timeout.tv_usec = 0; 2429e71b7053SJung-uk Kim i = select(width, (void *)&readfds, NULL, NULL, &timeout); 2430e71b7053SJung-uk Kim if (has_stdin_waiting()) 2431f579bf8eSKris Kennaway read_from_terminal = 1; 2432e71b7053SJung-uk Kim if ((i < 0) || (!i && !read_from_terminal)) 24331f13597dSJung-uk Kim continue; 2434f579bf8eSKris Kennaway #else 2435e71b7053SJung-uk Kim if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) 24366a599222SSimon L. B. Nielsen timeoutp = &timeout; 24376a599222SSimon L. B. Nielsen else 24386a599222SSimon L. B. Nielsen timeoutp = NULL; 24396a599222SSimon L. B. Nielsen 24406a599222SSimon L. B. Nielsen i = select(width, (void *)&readfds, NULL, NULL, timeoutp); 24416a599222SSimon L. B. Nielsen 2442e71b7053SJung-uk Kim if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0) 2443e71b7053SJung-uk Kim BIO_printf(bio_err, "TIMEOUT occurred\n"); 24446a599222SSimon L. B. Nielsen 24456f9291ceSJung-uk Kim if (i <= 0) 24466f9291ceSJung-uk Kim continue; 2447aeb5019cSJung-uk Kim if (FD_ISSET(fileno_stdin(), &readfds)) 2448f579bf8eSKris Kennaway read_from_terminal = 1; 2449f579bf8eSKris Kennaway #endif 2450f579bf8eSKris Kennaway if (FD_ISSET(s, &readfds)) 2451f579bf8eSKris Kennaway read_from_sslcon = 1; 2452f579bf8eSKris Kennaway } 24536f9291ceSJung-uk Kim if (read_from_terminal) { 24546f9291ceSJung-uk Kim if (s_crlf) { 245574664626SKris Kennaway int j, lf_num; 245674664626SKris Kennaway 24571f13597dSJung-uk Kim i = raw_read_stdin(buf, bufsize / 2); 245874664626SKris Kennaway lf_num = 0; 245974664626SKris Kennaway /* both loops are skipped when i <= 0 */ 246074664626SKris Kennaway for (j = 0; j < i; j++) 246174664626SKris Kennaway if (buf[j] == '\n') 246274664626SKris Kennaway lf_num++; 24636f9291ceSJung-uk Kim for (j = i - 1; j >= 0; j--) { 246474664626SKris Kennaway buf[j + lf_num] = buf[j]; 24656f9291ceSJung-uk Kim if (buf[j] == '\n') { 246674664626SKris Kennaway lf_num--; 246774664626SKris Kennaway i++; 246874664626SKris Kennaway buf[j + lf_num] = '\r'; 246974664626SKris Kennaway } 247074664626SKris Kennaway } 247174664626SKris Kennaway assert(lf_num == 0); 2472e71b7053SJung-uk Kim } else { 24731f13597dSJung-uk Kim i = raw_read_stdin(buf, bufsize); 2474e71b7053SJung-uk Kim } 2475aeb5019cSJung-uk Kim 24767bded2dbSJung-uk Kim if (!s_quiet && !s_brief) { 24776f9291ceSJung-uk Kim if ((i <= 0) || (buf[0] == 'Q')) { 247874664626SKris Kennaway BIO_printf(bio_s_out, "DONE\n"); 2479e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 2480e71b7053SJung-uk Kim BIO_closesocket(s); 248174664626SKris Kennaway close_accept_socket(); 248274664626SKris Kennaway ret = -11; 248374664626SKris Kennaway goto err; 248474664626SKris Kennaway } 24856f9291ceSJung-uk Kim if ((i <= 0) || (buf[0] == 'q')) { 248674664626SKris Kennaway BIO_printf(bio_s_out, "DONE\n"); 2487e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 24883b4e3dcbSSimon L. B. Nielsen if (SSL_version(con) != DTLS1_VERSION) 2489e71b7053SJung-uk Kim BIO_closesocket(s); 24906f9291ceSJung-uk Kim /* 24916f9291ceSJung-uk Kim * close_accept_socket(); ret= -11; 24926f9291ceSJung-uk Kim */ 249374664626SKris Kennaway goto err; 249474664626SKris Kennaway } 24951f13597dSJung-uk Kim #ifndef OPENSSL_NO_HEARTBEATS 24966f9291ceSJung-uk Kim if ((buf[0] == 'B') && ((buf[1] == '\n') || (buf[1] == '\r'))) { 24971f13597dSJung-uk Kim BIO_printf(bio_err, "HEARTBEATING\n"); 24981f13597dSJung-uk Kim SSL_heartbeat(con); 24991f13597dSJung-uk Kim i = 0; 25001f13597dSJung-uk Kim continue; 25011f13597dSJung-uk Kim } 25021f13597dSJung-uk Kim #endif 25036f9291ceSJung-uk Kim if ((buf[0] == 'r') && ((buf[1] == '\n') || (buf[1] == '\r'))) { 250474664626SKris Kennaway SSL_renegotiate(con); 250574664626SKris Kennaway i = SSL_do_handshake(con); 250674664626SKris Kennaway printf("SSL_do_handshake -> %d\n", i); 250774664626SKris Kennaway i = 0; /* 13; */ 250874664626SKris Kennaway continue; 250974664626SKris Kennaway } 25106f9291ceSJung-uk Kim if ((buf[0] == 'R') && ((buf[1] == '\n') || (buf[1] == '\r'))) { 251174664626SKris Kennaway SSL_set_verify(con, 25126f9291ceSJung-uk Kim SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, 25136f9291ceSJung-uk Kim NULL); 251474664626SKris Kennaway SSL_renegotiate(con); 251574664626SKris Kennaway i = SSL_do_handshake(con); 251674664626SKris Kennaway printf("SSL_do_handshake -> %d\n", i); 251774664626SKris Kennaway i = 0; /* 13; */ 251874664626SKris Kennaway continue; 2519e71b7053SJung-uk Kim } 2520e71b7053SJung-uk Kim if ((buf[0] == 'K' || buf[0] == 'k') 2521e71b7053SJung-uk Kim && ((buf[1] == '\n') || (buf[1] == '\r'))) { 2522e71b7053SJung-uk Kim SSL_key_update(con, buf[0] == 'K' ? 2523e71b7053SJung-uk Kim SSL_KEY_UPDATE_REQUESTED 2524e71b7053SJung-uk Kim : SSL_KEY_UPDATE_NOT_REQUESTED); 2525e71b7053SJung-uk Kim i = SSL_do_handshake(con); 2526e71b7053SJung-uk Kim printf("SSL_do_handshake -> %d\n", i); 2527e71b7053SJung-uk Kim i = 0; 2528e71b7053SJung-uk Kim continue; 2529e71b7053SJung-uk Kim } 2530e71b7053SJung-uk Kim if (buf[0] == 'c' && ((buf[1] == '\n') || (buf[1] == '\r'))) { 2531e71b7053SJung-uk Kim SSL_set_verify(con, SSL_VERIFY_PEER, NULL); 2532e71b7053SJung-uk Kim i = SSL_verify_client_post_handshake(con); 2533e71b7053SJung-uk Kim if (i == 0) { 2534e71b7053SJung-uk Kim printf("Failed to initiate request\n"); 2535e71b7053SJung-uk Kim ERR_print_errors(bio_err); 2536e71b7053SJung-uk Kim } else { 2537e71b7053SJung-uk Kim i = SSL_do_handshake(con); 2538e71b7053SJung-uk Kim printf("SSL_do_handshake -> %d\n", i); 2539e71b7053SJung-uk Kim i = 0; 2540e71b7053SJung-uk Kim } 2541e71b7053SJung-uk Kim continue; 254274664626SKris Kennaway } 25436f9291ceSJung-uk Kim if (buf[0] == 'P') { 25443b4e3dcbSSimon L. B. Nielsen static const char *str = "Lets print some clear text\n"; 254574664626SKris Kennaway BIO_write(SSL_get_wbio(con), str, strlen(str)); 254674664626SKris Kennaway } 25476f9291ceSJung-uk Kim if (buf[0] == 'S') { 254874664626SKris Kennaway print_stats(bio_s_out, SSL_get_SSL_CTX(con)); 254974664626SKris Kennaway } 255074664626SKris Kennaway } 255174664626SKris Kennaway #ifdef CHARSET_EBCDIC 255274664626SKris Kennaway ebcdic2ascii(buf, buf, i); 255374664626SKris Kennaway #endif 255474664626SKris Kennaway l = k = 0; 25556f9291ceSJung-uk Kim for (;;) { 255674664626SKris Kennaway /* should do a select for the write */ 255774664626SKris Kennaway #ifdef RENEG 25586f9291ceSJung-uk Kim static count = 0; 25596f9291ceSJung-uk Kim if (++count == 100) { 25606f9291ceSJung-uk Kim count = 0; 25616f9291ceSJung-uk Kim SSL_renegotiate(con); 25626f9291ceSJung-uk Kim } 256374664626SKris Kennaway #endif 256474664626SKris Kennaway k = SSL_write(con, &(buf[l]), (unsigned int)i); 25651f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 25666f9291ceSJung-uk Kim while (SSL_get_error(con, k) == SSL_ERROR_WANT_X509_LOOKUP) { 25671f13597dSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP renego during write\n"); 25684c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 25696f9291ceSJung-uk Kim srp_callback_parm.user = 25704c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 25716f9291ceSJung-uk Kim srp_callback_parm.login); 25721f13597dSJung-uk Kim if (srp_callback_parm.user) 25736f9291ceSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 25746f9291ceSJung-uk Kim srp_callback_parm.user->info); 25751f13597dSJung-uk Kim else 25761f13597dSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 25771f13597dSJung-uk Kim k = SSL_write(con, &(buf[l]), (unsigned int)i); 25781f13597dSJung-uk Kim } 25791f13597dSJung-uk Kim #endif 25806f9291ceSJung-uk Kim switch (SSL_get_error(con, k)) { 258174664626SKris Kennaway case SSL_ERROR_NONE: 258274664626SKris Kennaway break; 2583e71b7053SJung-uk Kim case SSL_ERROR_WANT_ASYNC: 2584e71b7053SJung-uk Kim BIO_printf(bio_s_out, "Write BLOCK (Async)\n"); 2585e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 2586e71b7053SJung-uk Kim wait_for_async(con); 2587e71b7053SJung-uk Kim break; 258874664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 258974664626SKris Kennaway case SSL_ERROR_WANT_READ: 259074664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 259174664626SKris Kennaway BIO_printf(bio_s_out, "Write BLOCK\n"); 2592e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 259374664626SKris Kennaway break; 2594e71b7053SJung-uk Kim case SSL_ERROR_WANT_ASYNC_JOB: 2595e71b7053SJung-uk Kim /* 2596e71b7053SJung-uk Kim * This shouldn't ever happen in s_server. Treat as an error 2597e71b7053SJung-uk Kim */ 259874664626SKris Kennaway case SSL_ERROR_SYSCALL: 259974664626SKris Kennaway case SSL_ERROR_SSL: 260074664626SKris Kennaway BIO_printf(bio_s_out, "ERROR\n"); 2601e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 260274664626SKris Kennaway ERR_print_errors(bio_err); 260374664626SKris Kennaway ret = 1; 260474664626SKris Kennaway goto err; 260574664626SKris Kennaway /* break; */ 260674664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 260774664626SKris Kennaway BIO_printf(bio_s_out, "DONE\n"); 2608e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 260974664626SKris Kennaway ret = 1; 261074664626SKris Kennaway goto err; 261174664626SKris Kennaway } 2612ed6b93beSJung-uk Kim if (k > 0) { 261374664626SKris Kennaway l += k; 261474664626SKris Kennaway i -= k; 2615ed6b93beSJung-uk Kim } 26166f9291ceSJung-uk Kim if (i <= 0) 26176f9291ceSJung-uk Kim break; 261874664626SKris Kennaway } 261974664626SKris Kennaway } 26206f9291ceSJung-uk Kim if (read_from_sslcon) { 2621e71b7053SJung-uk Kim /* 2622e71b7053SJung-uk Kim * init_ssl_connection handles all async events itself so if we're 2623e71b7053SJung-uk Kim * waiting for async then we shouldn't go back into 2624e71b7053SJung-uk Kim * init_ssl_connection 2625e71b7053SJung-uk Kim */ 2626e71b7053SJung-uk Kim if ((!async || !SSL_waiting_for_async(con)) 2627e71b7053SJung-uk Kim && !SSL_is_init_finished(con)) { 262874664626SKris Kennaway i = init_ssl_connection(con); 262974664626SKris Kennaway 26306f9291ceSJung-uk Kim if (i < 0) { 263174664626SKris Kennaway ret = 0; 263274664626SKris Kennaway goto err; 26336f9291ceSJung-uk Kim } else if (i == 0) { 263474664626SKris Kennaway ret = 1; 263574664626SKris Kennaway goto err; 263674664626SKris Kennaway } 26376f9291ceSJung-uk Kim } else { 263874664626SKris Kennaway again: 263974664626SKris Kennaway i = SSL_read(con, (char *)buf, bufsize); 26401f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 26416f9291ceSJung-uk Kim while (SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { 26421f13597dSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP renego during read\n"); 26434c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 26446f9291ceSJung-uk Kim srp_callback_parm.user = 26454c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 26466f9291ceSJung-uk Kim srp_callback_parm.login); 26471f13597dSJung-uk Kim if (srp_callback_parm.user) 26486f9291ceSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 26496f9291ceSJung-uk Kim srp_callback_parm.user->info); 26501f13597dSJung-uk Kim else 26511f13597dSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 26521f13597dSJung-uk Kim i = SSL_read(con, (char *)buf, bufsize); 26531f13597dSJung-uk Kim } 26541f13597dSJung-uk Kim #endif 26556f9291ceSJung-uk Kim switch (SSL_get_error(con, i)) { 265674664626SKris Kennaway case SSL_ERROR_NONE: 265774664626SKris Kennaway #ifdef CHARSET_EBCDIC 265874664626SKris Kennaway ascii2ebcdic(buf, buf, i); 265974664626SKris Kennaway #endif 26606f9291ceSJung-uk Kim raw_write_stdout(buf, (unsigned int)i); 2661e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 2662e71b7053SJung-uk Kim if (SSL_has_pending(con)) 26636f9291ceSJung-uk Kim goto again; 266474664626SKris Kennaway break; 2665e71b7053SJung-uk Kim case SSL_ERROR_WANT_ASYNC: 2666e71b7053SJung-uk Kim BIO_printf(bio_s_out, "Read BLOCK (Async)\n"); 2667e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 2668e71b7053SJung-uk Kim wait_for_async(con); 2669e71b7053SJung-uk Kim break; 267074664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 267174664626SKris Kennaway case SSL_ERROR_WANT_READ: 267274664626SKris Kennaway BIO_printf(bio_s_out, "Read BLOCK\n"); 2673e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 267474664626SKris Kennaway break; 2675e71b7053SJung-uk Kim case SSL_ERROR_WANT_ASYNC_JOB: 2676e71b7053SJung-uk Kim /* 2677e71b7053SJung-uk Kim * This shouldn't ever happen in s_server. Treat as an error 2678e71b7053SJung-uk Kim */ 267974664626SKris Kennaway case SSL_ERROR_SYSCALL: 268074664626SKris Kennaway case SSL_ERROR_SSL: 268174664626SKris Kennaway BIO_printf(bio_s_out, "ERROR\n"); 2682e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 268374664626SKris Kennaway ERR_print_errors(bio_err); 268474664626SKris Kennaway ret = 1; 268574664626SKris Kennaway goto err; 268674664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 268774664626SKris Kennaway BIO_printf(bio_s_out, "DONE\n"); 2688e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 268974664626SKris Kennaway ret = 1; 269074664626SKris Kennaway goto err; 269174664626SKris Kennaway } 269274664626SKris Kennaway } 269374664626SKris Kennaway } 269474664626SKris Kennaway } 269574664626SKris Kennaway err: 26966f9291ceSJung-uk Kim if (con != NULL) { 269774664626SKris Kennaway BIO_printf(bio_s_out, "shutting down SSL\n"); 269874664626SKris Kennaway SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 26991f13597dSJung-uk Kim SSL_free(con); 27001f13597dSJung-uk Kim } 270174664626SKris Kennaway BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); 2702e71b7053SJung-uk Kim OPENSSL_clear_free(buf, bufsize); 2703e71b7053SJung-uk Kim return ret; 270474664626SKris Kennaway } 270574664626SKris Kennaway 270674664626SKris Kennaway static void close_accept_socket(void) 270774664626SKris Kennaway { 270874664626SKris Kennaway BIO_printf(bio_err, "shutdown accept socket\n"); 27096f9291ceSJung-uk Kim if (accept_socket >= 0) { 2710e71b7053SJung-uk Kim BIO_closesocket(accept_socket); 271174664626SKris Kennaway } 271274664626SKris Kennaway } 271374664626SKris Kennaway 2714e71b7053SJung-uk Kim static int is_retryable(SSL *con, int i) 2715e71b7053SJung-uk Kim { 2716e71b7053SJung-uk Kim int err = SSL_get_error(con, i); 2717e71b7053SJung-uk Kim 2718e71b7053SJung-uk Kim /* If it's not a fatal error, it must be retryable */ 2719e71b7053SJung-uk Kim return (err != SSL_ERROR_SSL) 2720e71b7053SJung-uk Kim && (err != SSL_ERROR_SYSCALL) 2721e71b7053SJung-uk Kim && (err != SSL_ERROR_ZERO_RETURN); 2722e71b7053SJung-uk Kim } 2723e71b7053SJung-uk Kim 272474664626SKris Kennaway static int init_ssl_connection(SSL *con) 272574664626SKris Kennaway { 272674664626SKris Kennaway int i; 2727e71b7053SJung-uk Kim long verify_err; 2728e71b7053SJung-uk Kim int retry = 0; 272974664626SKris Kennaway 2730e71b7053SJung-uk Kim if (dtlslisten || stateless) { 2731e71b7053SJung-uk Kim BIO_ADDR *client = NULL; 2732e71b7053SJung-uk Kim 2733e71b7053SJung-uk Kim if (dtlslisten) { 2734e71b7053SJung-uk Kim if ((client = BIO_ADDR_new()) == NULL) { 2735e71b7053SJung-uk Kim BIO_printf(bio_err, "ERROR - memory\n"); 2736e71b7053SJung-uk Kim return 0; 2737e71b7053SJung-uk Kim } 2738e71b7053SJung-uk Kim i = DTLSv1_listen(con, client); 2739e71b7053SJung-uk Kim } else { 2740e71b7053SJung-uk Kim i = SSL_stateless(con); 2741e71b7053SJung-uk Kim } 2742e71b7053SJung-uk Kim if (i > 0) { 2743e71b7053SJung-uk Kim BIO *wbio; 2744e71b7053SJung-uk Kim int fd = -1; 2745e71b7053SJung-uk Kim 2746e71b7053SJung-uk Kim if (dtlslisten) { 2747e71b7053SJung-uk Kim wbio = SSL_get_wbio(con); 2748e71b7053SJung-uk Kim if (wbio) { 2749e71b7053SJung-uk Kim BIO_get_fd(wbio, &fd); 2750e71b7053SJung-uk Kim } 2751e71b7053SJung-uk Kim 2752e71b7053SJung-uk Kim if (!wbio || BIO_connect(fd, client, 0) == 0) { 2753e71b7053SJung-uk Kim BIO_printf(bio_err, "ERROR - unable to connect\n"); 2754e71b7053SJung-uk Kim BIO_ADDR_free(client); 2755e71b7053SJung-uk Kim return 0; 2756e71b7053SJung-uk Kim } 2757e71b7053SJung-uk Kim BIO_ADDR_free(client); 2758e71b7053SJung-uk Kim dtlslisten = 0; 2759e71b7053SJung-uk Kim } else { 2760e71b7053SJung-uk Kim stateless = 0; 2761e71b7053SJung-uk Kim } 27621f13597dSJung-uk Kim i = SSL_accept(con); 2763e71b7053SJung-uk Kim } else { 2764e71b7053SJung-uk Kim BIO_ADDR_free(client); 2765e71b7053SJung-uk Kim } 2766e71b7053SJung-uk Kim } else { 2767e71b7053SJung-uk Kim do { 2768e71b7053SJung-uk Kim i = SSL_accept(con); 2769e71b7053SJung-uk Kim 2770e71b7053SJung-uk Kim if (i <= 0) 2771e71b7053SJung-uk Kim retry = is_retryable(con, i); 27727bded2dbSJung-uk Kim #ifdef CERT_CB_TEST_RETRY 27737bded2dbSJung-uk Kim { 2774e71b7053SJung-uk Kim while (i <= 0 2775e71b7053SJung-uk Kim && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP 2776e71b7053SJung-uk Kim && SSL_get_state(con) == TLS_ST_SR_CLNT_HELLO) { 2777e71b7053SJung-uk Kim BIO_printf(bio_err, 27787bded2dbSJung-uk Kim "LOOKUP from certificate callback during accept\n"); 27797bded2dbSJung-uk Kim i = SSL_accept(con); 2780e71b7053SJung-uk Kim if (i <= 0) 2781e71b7053SJung-uk Kim retry = is_retryable(con, i); 27827bded2dbSJung-uk Kim } 27837bded2dbSJung-uk Kim } 27847bded2dbSJung-uk Kim #endif 2785e71b7053SJung-uk Kim 27861f13597dSJung-uk Kim #ifndef OPENSSL_NO_SRP 2787e71b7053SJung-uk Kim while (i <= 0 2788e71b7053SJung-uk Kim && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) { 27896f9291ceSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP during accept %s\n", 27906f9291ceSJung-uk Kim srp_callback_parm.login); 27914c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 27926f9291ceSJung-uk Kim srp_callback_parm.user = 27934c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 27946f9291ceSJung-uk Kim srp_callback_parm.login); 27951f13597dSJung-uk Kim if (srp_callback_parm.user) 27966f9291ceSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 27976f9291ceSJung-uk Kim srp_callback_parm.user->info); 27981f13597dSJung-uk Kim else 27991f13597dSJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 28001f13597dSJung-uk Kim i = SSL_accept(con); 2801e71b7053SJung-uk Kim if (i <= 0) 2802e71b7053SJung-uk Kim retry = is_retryable(con, i); 28031f13597dSJung-uk Kim } 28041f13597dSJung-uk Kim #endif 2805e71b7053SJung-uk Kim } while (i < 0 && SSL_waiting_for_async(con)); 2806e71b7053SJung-uk Kim } 28077bded2dbSJung-uk Kim 28086f9291ceSJung-uk Kim if (i <= 0) { 2809e71b7053SJung-uk Kim if (((dtlslisten || stateless) && i == 0) 2810e71b7053SJung-uk Kim || (!dtlslisten && !stateless && retry)) { 281174664626SKris Kennaway BIO_printf(bio_s_out, "DELAY\n"); 2812e71b7053SJung-uk Kim return 1; 281374664626SKris Kennaway } 281474664626SKris Kennaway 281574664626SKris Kennaway BIO_printf(bio_err, "ERROR\n"); 2816e71b7053SJung-uk Kim 2817e71b7053SJung-uk Kim verify_err = SSL_get_verify_result(con); 2818e71b7053SJung-uk Kim if (verify_err != X509_V_OK) { 281974664626SKris Kennaway BIO_printf(bio_err, "verify error:%s\n", 2820e71b7053SJung-uk Kim X509_verify_cert_error_string(verify_err)); 28217bded2dbSJung-uk Kim } 28227bded2dbSJung-uk Kim /* Always print any error messages */ 282374664626SKris Kennaway ERR_print_errors(bio_err); 2824e71b7053SJung-uk Kim return 0; 282574664626SKris Kennaway } 282674664626SKris Kennaway 2827e71b7053SJung-uk Kim print_connection_info(con); 2828e71b7053SJung-uk Kim return 1; 2829e71b7053SJung-uk Kim } 2830e71b7053SJung-uk Kim 2831e71b7053SJung-uk Kim static void print_connection_info(SSL *con) 2832e71b7053SJung-uk Kim { 2833e71b7053SJung-uk Kim const char *str; 2834e71b7053SJung-uk Kim X509 *peer; 2835e71b7053SJung-uk Kim char buf[BUFSIZ]; 2836e71b7053SJung-uk Kim #if !defined(OPENSSL_NO_NEXTPROTONEG) 2837e71b7053SJung-uk Kim const unsigned char *next_proto_neg; 2838e71b7053SJung-uk Kim unsigned next_proto_neg_len; 2839e71b7053SJung-uk Kim #endif 2840e71b7053SJung-uk Kim unsigned char *exportedkeymat; 2841e71b7053SJung-uk Kim int i; 2842e71b7053SJung-uk Kim 28437bded2dbSJung-uk Kim if (s_brief) 2844e71b7053SJung-uk Kim print_ssl_summary(con); 28457bded2dbSJung-uk Kim 284674664626SKris Kennaway PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); 284774664626SKris Kennaway 284874664626SKris Kennaway peer = SSL_get_peer_certificate(con); 28496f9291ceSJung-uk Kim if (peer != NULL) { 285074664626SKris Kennaway BIO_printf(bio_s_out, "Client certificate\n"); 285174664626SKris Kennaway PEM_write_bio_X509(bio_s_out, peer); 2852e71b7053SJung-uk Kim dump_cert_text(bio_s_out, peer); 285374664626SKris Kennaway X509_free(peer); 2854e71b7053SJung-uk Kim peer = NULL; 285574664626SKris Kennaway } 285674664626SKris Kennaway 2857dee36b4fSJung-uk Kim if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL) 285874664626SKris Kennaway BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); 285974664626SKris Kennaway str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); 28607bded2dbSJung-uk Kim ssl_print_sigalgs(bio_s_out, con); 28617bded2dbSJung-uk Kim #ifndef OPENSSL_NO_EC 28627bded2dbSJung-uk Kim ssl_print_point_formats(bio_s_out, con); 2863e71b7053SJung-uk Kim ssl_print_groups(bio_s_out, con, 0); 28647bded2dbSJung-uk Kim #endif 2865e71b7053SJung-uk Kim print_ca_names(bio_s_out, con); 286674664626SKris Kennaway BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); 286709286989SJung-uk Kim 2868e71b7053SJung-uk Kim #if !defined(OPENSSL_NO_NEXTPROTONEG) 28691f13597dSJung-uk Kim SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); 28706f9291ceSJung-uk Kim if (next_proto_neg) { 28711f13597dSJung-uk Kim BIO_printf(bio_s_out, "NEXTPROTO is "); 28721f13597dSJung-uk Kim BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len); 28731f13597dSJung-uk Kim BIO_printf(bio_s_out, "\n"); 28741f13597dSJung-uk Kim } 28751f13597dSJung-uk Kim #endif 287609286989SJung-uk Kim #ifndef OPENSSL_NO_SRTP 28771f13597dSJung-uk Kim { 28781f13597dSJung-uk Kim SRTP_PROTECTION_PROFILE *srtp_profile 28791f13597dSJung-uk Kim = SSL_get_selected_srtp_profile(con); 28801f13597dSJung-uk Kim 28811f13597dSJung-uk Kim if (srtp_profile) 28821f13597dSJung-uk Kim BIO_printf(bio_s_out, "SRTP Extension negotiated, profile=%s\n", 28831f13597dSJung-uk Kim srtp_profile->name); 28841f13597dSJung-uk Kim } 288509286989SJung-uk Kim #endif 2886e71b7053SJung-uk Kim if (SSL_session_reused(con)) 28876f9291ceSJung-uk Kim BIO_printf(bio_s_out, "Reused session-id\n"); 28886a599222SSimon L. B. Nielsen BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", 28896a599222SSimon L. B. Nielsen SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); 2890e71b7053SJung-uk Kim if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION)) 2891e71b7053SJung-uk Kim BIO_printf(bio_s_out, "Renegotiation is DISABLED\n"); 2892e71b7053SJung-uk Kim 28936f9291ceSJung-uk Kim if (keymatexportlabel != NULL) { 28941f13597dSJung-uk Kim BIO_printf(bio_s_out, "Keying material exporter:\n"); 28951f13597dSJung-uk Kim BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel); 28966f9291ceSJung-uk Kim BIO_printf(bio_s_out, " Length: %i bytes\n", keymatexportlen); 2897e71b7053SJung-uk Kim exportedkeymat = app_malloc(keymatexportlen, "export key"); 28981f13597dSJung-uk Kim if (!SSL_export_keying_material(con, exportedkeymat, 28991f13597dSJung-uk Kim keymatexportlen, 29001f13597dSJung-uk Kim keymatexportlabel, 29011f13597dSJung-uk Kim strlen(keymatexportlabel), 29026f9291ceSJung-uk Kim NULL, 0, 0)) { 29031f13597dSJung-uk Kim BIO_printf(bio_s_out, " Error\n"); 29046f9291ceSJung-uk Kim } else { 29051f13597dSJung-uk Kim BIO_printf(bio_s_out, " Keying material: "); 29061f13597dSJung-uk Kim for (i = 0; i < keymatexportlen; i++) 29076f9291ceSJung-uk Kim BIO_printf(bio_s_out, "%02X", exportedkeymat[i]); 29081f13597dSJung-uk Kim BIO_printf(bio_s_out, "\n"); 29091f13597dSJung-uk Kim } 29101f13597dSJung-uk Kim OPENSSL_free(exportedkeymat); 29111f13597dSJung-uk Kim } 29121f13597dSJung-uk Kim 2913e71b7053SJung-uk Kim (void)BIO_flush(bio_s_out); 291474664626SKris Kennaway } 291574664626SKris Kennaway 29165c87c606SMark Murray #ifndef OPENSSL_NO_DH 29173b4e3dcbSSimon L. B. Nielsen static DH *load_dh_param(const char *dhfile) 291874664626SKris Kennaway { 291974664626SKris Kennaway DH *ret = NULL; 292074664626SKris Kennaway BIO *bio; 292174664626SKris Kennaway 2922f579bf8eSKris Kennaway if ((bio = BIO_new_file(dhfile, "r")) == NULL) 292374664626SKris Kennaway goto err; 292474664626SKris Kennaway ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); 292574664626SKris Kennaway err: 29266f9291ceSJung-uk Kim BIO_free(bio); 2927e71b7053SJung-uk Kim return ret; 292874664626SKris Kennaway } 292974664626SKris Kennaway #endif 293074664626SKris Kennaway 2931e71b7053SJung-uk Kim static int www_body(int s, int stype, int prot, unsigned char *context) 293274664626SKris Kennaway { 293374664626SKris Kennaway char *buf = NULL; 293474664626SKris Kennaway int ret = 1; 2935a3ddd25aSSimon L. B. Nielsen int i, j, k, dot; 293674664626SKris Kennaway SSL *con; 29371f13597dSJung-uk Kim const SSL_CIPHER *c; 293874664626SKris Kennaway BIO *io, *ssl_bio, *sbio; 2939e71b7053SJung-uk Kim #ifdef RENEG 2940e71b7053SJung-uk Kim int total_bytes = 0; 2941a3ddd25aSSimon L. B. Nielsen #endif 2942e71b7053SJung-uk Kim int width; 2943e71b7053SJung-uk Kim fd_set readfds; 294474664626SKris Kennaway 2945e71b7053SJung-uk Kim /* Set width for a select call if needed */ 2946e71b7053SJung-uk Kim width = s + 1; 2947e71b7053SJung-uk Kim 2948e71b7053SJung-uk Kim buf = app_malloc(bufsize, "server www buffer"); 294974664626SKris Kennaway io = BIO_new(BIO_f_buffer()); 295074664626SKris Kennaway ssl_bio = BIO_new(BIO_f_ssl()); 29516f9291ceSJung-uk Kim if ((io == NULL) || (ssl_bio == NULL)) 29526f9291ceSJung-uk Kim goto err; 295374664626SKris Kennaway 29546f9291ceSJung-uk Kim if (s_nbio) { 2955e71b7053SJung-uk Kim if (!BIO_socket_nbio(s, 1)) 295674664626SKris Kennaway ERR_print_errors(bio_err); 2957e71b7053SJung-uk Kim else if (!s_quiet) 2958e71b7053SJung-uk Kim BIO_printf(bio_err, "Turned on non blocking io\n"); 295974664626SKris Kennaway } 296074664626SKris Kennaway 296174664626SKris Kennaway /* lets make the output buffer a reasonable size */ 29626f9291ceSJung-uk Kim if (!BIO_set_write_buffer_size(io, bufsize)) 29636f9291ceSJung-uk Kim goto err; 296474664626SKris Kennaway 29656f9291ceSJung-uk Kim if ((con = SSL_new(ctx)) == NULL) 29666f9291ceSJung-uk Kim goto err; 2967e71b7053SJung-uk Kim 29686f9291ceSJung-uk Kim if (s_tlsextdebug) { 2969db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_callback(con, tlsext_cb); 2970db522d3aSSimon L. B. Nielsen SSL_set_tlsext_debug_arg(con, bio_s_out); 2971db522d3aSSimon L. B. Nielsen } 2972e71b7053SJung-uk Kim 2973e71b7053SJung-uk Kim if (context != NULL 2974e71b7053SJung-uk Kim && !SSL_set_session_id_context(con, context, 2975e71b7053SJung-uk Kim strlen((char *)context))) { 2976e71b7053SJung-uk Kim SSL_free(con); 2977e71b7053SJung-uk Kim goto err; 29785c87c606SMark Murray } 297974664626SKris Kennaway 298074664626SKris Kennaway sbio = BIO_new_socket(s, BIO_NOCLOSE); 29816f9291ceSJung-uk Kim if (s_nbio_test) { 298274664626SKris Kennaway BIO *test; 298374664626SKris Kennaway 298474664626SKris Kennaway test = BIO_new(BIO_f_nbio_test()); 298574664626SKris Kennaway sbio = BIO_push(test, sbio); 298674664626SKris Kennaway } 298774664626SKris Kennaway SSL_set_bio(con, sbio, sbio); 298874664626SKris Kennaway SSL_set_accept_state(con); 298974664626SKris Kennaway 2990e71b7053SJung-uk Kim /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ 299174664626SKris Kennaway BIO_set_ssl(ssl_bio, con, BIO_CLOSE); 299274664626SKris Kennaway BIO_push(io, ssl_bio); 299374664626SKris Kennaway #ifdef CHARSET_EBCDIC 299474664626SKris Kennaway io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); 299574664626SKris Kennaway #endif 299674664626SKris Kennaway 29976f9291ceSJung-uk Kim if (s_debug) { 29983b4e3dcbSSimon L. B. Nielsen BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); 29995471f83eSSimon L. B. Nielsen BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); 300074664626SKris Kennaway } 30016f9291ceSJung-uk Kim if (s_msg) { 30027bded2dbSJung-uk Kim #ifndef OPENSSL_NO_SSL_TRACE 30037bded2dbSJung-uk Kim if (s_msg == 2) 30047bded2dbSJung-uk Kim SSL_set_msg_callback(con, SSL_trace); 30057bded2dbSJung-uk Kim else 30067bded2dbSJung-uk Kim #endif 30075c87c606SMark Murray SSL_set_msg_callback(con, msg_cb); 30087bded2dbSJung-uk Kim SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); 30095c87c606SMark Murray } 301074664626SKris Kennaway 30116f9291ceSJung-uk Kim for (;;) { 301274664626SKris Kennaway i = BIO_gets(io, buf, bufsize - 1); 30136f9291ceSJung-uk Kim if (i < 0) { /* error */ 3014e71b7053SJung-uk Kim if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) { 301574664626SKris Kennaway if (!s_quiet) 301674664626SKris Kennaway ERR_print_errors(bio_err); 301774664626SKris Kennaway goto err; 30186f9291ceSJung-uk Kim } else { 301974664626SKris Kennaway BIO_printf(bio_s_out, "read R BLOCK\n"); 302080815a77SJung-uk Kim #ifndef OPENSSL_NO_SRP 302180815a77SJung-uk Kim if (BIO_should_io_special(io) 302280815a77SJung-uk Kim && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { 302380815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP renego during read\n"); 30244c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 302580815a77SJung-uk Kim srp_callback_parm.user = 30264c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 302780815a77SJung-uk Kim srp_callback_parm.login); 302880815a77SJung-uk Kim if (srp_callback_parm.user) 302980815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 303080815a77SJung-uk Kim srp_callback_parm.user->info); 303180815a77SJung-uk Kim else 303280815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 303380815a77SJung-uk Kim continue; 303480815a77SJung-uk Kim } 303580815a77SJung-uk Kim #endif 3036e71b7053SJung-uk Kim #if !defined(OPENSSL_SYS_MSDOS) 303774664626SKris Kennaway sleep(1); 303874664626SKris Kennaway #endif 303974664626SKris Kennaway continue; 304074664626SKris Kennaway } 30416f9291ceSJung-uk Kim } else if (i == 0) { /* end of input */ 304274664626SKris Kennaway ret = 1; 304374664626SKris Kennaway goto end; 304474664626SKris Kennaway } 304574664626SKris Kennaway 304674664626SKris Kennaway /* else we have data */ 304774664626SKris Kennaway if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) || 30486f9291ceSJung-uk Kim ((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) { 304974664626SKris Kennaway char *p; 3050e71b7053SJung-uk Kim X509 *peer = NULL; 305174664626SKris Kennaway STACK_OF(SSL_CIPHER) *sk; 30523b4e3dcbSSimon L. B. Nielsen static const char *space = " "; 305374664626SKris Kennaway 3054e71b7053SJung-uk Kim if (www == 1 && strncmp("GET /reneg", buf, 10) == 0) { 3055e71b7053SJung-uk Kim if (strncmp("GET /renegcert", buf, 14) == 0) 3056e71b7053SJung-uk Kim SSL_set_verify(con, 3057e71b7053SJung-uk Kim SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, 3058e71b7053SJung-uk Kim NULL); 3059e71b7053SJung-uk Kim i = SSL_renegotiate(con); 3060e71b7053SJung-uk Kim BIO_printf(bio_s_out, "SSL_renegotiate -> %d\n", i); 3061e71b7053SJung-uk Kim /* Send the HelloRequest */ 3062e71b7053SJung-uk Kim i = SSL_do_handshake(con); 3063e71b7053SJung-uk Kim if (i <= 0) { 3064e71b7053SJung-uk Kim BIO_printf(bio_s_out, "SSL_do_handshake() Retval %d\n", 3065e71b7053SJung-uk Kim SSL_get_error(con, i)); 3066e71b7053SJung-uk Kim ERR_print_errors(bio_err); 3067e71b7053SJung-uk Kim goto err; 3068e71b7053SJung-uk Kim } 3069e71b7053SJung-uk Kim /* Wait for a ClientHello to come back */ 3070e71b7053SJung-uk Kim FD_ZERO(&readfds); 3071e71b7053SJung-uk Kim openssl_fdset(s, &readfds); 3072e71b7053SJung-uk Kim i = select(width, (void *)&readfds, NULL, NULL, NULL); 3073e71b7053SJung-uk Kim if (i <= 0 || !FD_ISSET(s, &readfds)) { 3074e71b7053SJung-uk Kim BIO_printf(bio_s_out, 3075e71b7053SJung-uk Kim "Error waiting for client response\n"); 3076e71b7053SJung-uk Kim ERR_print_errors(bio_err); 3077e71b7053SJung-uk Kim goto err; 3078e71b7053SJung-uk Kim } 3079e71b7053SJung-uk Kim /* 3080e71b7053SJung-uk Kim * We're not actually expecting any data here and we ignore 3081e71b7053SJung-uk Kim * any that is sent. This is just to force the handshake that 3082e71b7053SJung-uk Kim * we're expecting to come from the client. If they haven't 3083e71b7053SJung-uk Kim * sent one there's not much we can do. 3084e71b7053SJung-uk Kim */ 3085e71b7053SJung-uk Kim BIO_gets(io, buf, bufsize - 1); 3086e71b7053SJung-uk Kim } 3087e71b7053SJung-uk Kim 30886f9291ceSJung-uk Kim BIO_puts(io, 30896f9291ceSJung-uk Kim "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); 309074664626SKris Kennaway BIO_puts(io, "<HTML><BODY BGCOLOR=\"#ffffff\">\n"); 309174664626SKris Kennaway BIO_puts(io, "<pre>\n"); 3092e71b7053SJung-uk Kim /* BIO_puts(io, OpenSSL_version(OPENSSL_VERSION)); */ 309374664626SKris Kennaway BIO_puts(io, "\n"); 30946f9291ceSJung-uk Kim for (i = 0; i < local_argc; i++) { 3095e71b7053SJung-uk Kim const char *myp; 3096e71b7053SJung-uk Kim for (myp = local_argv[i]; *myp; myp++) 3097e71b7053SJung-uk Kim switch (*myp) { 3098e71b7053SJung-uk Kim case '<': 3099e71b7053SJung-uk Kim BIO_puts(io, "<"); 3100e71b7053SJung-uk Kim break; 3101e71b7053SJung-uk Kim case '>': 3102e71b7053SJung-uk Kim BIO_puts(io, ">"); 3103e71b7053SJung-uk Kim break; 3104e71b7053SJung-uk Kim case '&': 3105e71b7053SJung-uk Kim BIO_puts(io, "&"); 3106e71b7053SJung-uk Kim break; 3107e71b7053SJung-uk Kim default: 3108e71b7053SJung-uk Kim BIO_write(io, myp, 1); 3109e71b7053SJung-uk Kim break; 3110e71b7053SJung-uk Kim } 311174664626SKris Kennaway BIO_write(io, " ", 1); 311274664626SKris Kennaway } 311374664626SKris Kennaway BIO_puts(io, "\n"); 311474664626SKris Kennaway 311509286989SJung-uk Kim BIO_printf(io, 311609286989SJung-uk Kim "Secure Renegotiation IS%s supported\n", 311709286989SJung-uk Kim SSL_get_secure_renegotiation_support(con) ? 311809286989SJung-uk Kim "" : " NOT"); 311909286989SJung-uk Kim 31206f9291ceSJung-uk Kim /* 31216f9291ceSJung-uk Kim * The following is evil and should not really be done 31226f9291ceSJung-uk Kim */ 312374664626SKris Kennaway BIO_printf(io, "Ciphers supported in s_server binary\n"); 312474664626SKris Kennaway sk = SSL_get_ciphers(con); 312574664626SKris Kennaway j = sk_SSL_CIPHER_num(sk); 31266f9291ceSJung-uk Kim for (i = 0; i < j; i++) { 312774664626SKris Kennaway c = sk_SSL_CIPHER_value(sk, i); 312874664626SKris Kennaway BIO_printf(io, "%-11s:%-25s ", 31296f9291ceSJung-uk Kim SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); 313074664626SKris Kennaway if ((((i + 1) % 2) == 0) && (i + 1 != j)) 313174664626SKris Kennaway BIO_puts(io, "\n"); 313274664626SKris Kennaway } 313374664626SKris Kennaway BIO_puts(io, "\n"); 313474664626SKris Kennaway p = SSL_get_shared_ciphers(con, buf, bufsize); 31356f9291ceSJung-uk Kim if (p != NULL) { 31366f9291ceSJung-uk Kim BIO_printf(io, 31376f9291ceSJung-uk Kim "---\nCiphers common between both SSL end points:\n"); 313874664626SKris Kennaway j = i = 0; 31396f9291ceSJung-uk Kim while (*p) { 31406f9291ceSJung-uk Kim if (*p == ':') { 314174664626SKris Kennaway BIO_write(io, space, 26 - j); 314274664626SKris Kennaway i++; 314374664626SKris Kennaway j = 0; 314474664626SKris Kennaway BIO_write(io, ((i % 3) ? " " : "\n"), 1); 31456f9291ceSJung-uk Kim } else { 314674664626SKris Kennaway BIO_write(io, p, 1); 314774664626SKris Kennaway j++; 314874664626SKris Kennaway } 314974664626SKris Kennaway p++; 315074664626SKris Kennaway } 315174664626SKris Kennaway BIO_puts(io, "\n"); 315274664626SKris Kennaway } 31537bded2dbSJung-uk Kim ssl_print_sigalgs(io, con); 31547bded2dbSJung-uk Kim #ifndef OPENSSL_NO_EC 3155e71b7053SJung-uk Kim ssl_print_groups(io, con, 0); 31567bded2dbSJung-uk Kim #endif 3157e71b7053SJung-uk Kim print_ca_names(io, con); 3158e71b7053SJung-uk Kim BIO_printf(io, (SSL_session_reused(con) 31596f9291ceSJung-uk Kim ? "---\nReused, " : "---\nNew, ")); 316074664626SKris Kennaway c = SSL_get_current_cipher(con); 316174664626SKris Kennaway BIO_printf(io, "%s, Cipher is %s\n", 31626f9291ceSJung-uk Kim SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); 316374664626SKris Kennaway SSL_SESSION_print(io, SSL_get_session(con)); 316474664626SKris Kennaway BIO_printf(io, "---\n"); 316574664626SKris Kennaway print_stats(io, SSL_get_SSL_CTX(con)); 316674664626SKris Kennaway BIO_printf(io, "---\n"); 316774664626SKris Kennaway peer = SSL_get_peer_certificate(con); 31686f9291ceSJung-uk Kim if (peer != NULL) { 316974664626SKris Kennaway BIO_printf(io, "Client certificate\n"); 317074664626SKris Kennaway X509_print(io, peer); 317174664626SKris Kennaway PEM_write_bio_X509(io, peer); 3172e71b7053SJung-uk Kim X509_free(peer); 3173e71b7053SJung-uk Kim peer = NULL; 3174e71b7053SJung-uk Kim } else { 317574664626SKris Kennaway BIO_puts(io, "no client certificate available\n"); 3176e71b7053SJung-uk Kim } 317747902a71SJung-uk Kim BIO_puts(io, "</pre></BODY></HTML>\r\n\r\n"); 317874664626SKris Kennaway break; 31796f9291ceSJung-uk Kim } else if ((www == 2 || www == 3) 31806f9291ceSJung-uk Kim && (strncmp("GET /", buf, 5) == 0)) { 318174664626SKris Kennaway BIO *file; 318274664626SKris Kennaway char *p, *e; 31836f9291ceSJung-uk Kim static const char *text = 31846f9291ceSJung-uk Kim "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"; 318574664626SKris Kennaway 318674664626SKris Kennaway /* skip the '/' */ 318774664626SKris Kennaway p = &(buf[5]); 31885740a5e3SKris Kennaway 31895740a5e3SKris Kennaway dot = 1; 31906f9291ceSJung-uk Kim for (e = p; *e != '\0'; e++) { 31915740a5e3SKris Kennaway if (e[0] == ' ') 31925740a5e3SKris Kennaway break; 319374664626SKris Kennaway 31946f9291ceSJung-uk Kim switch (dot) { 31955740a5e3SKris Kennaway case 1: 31965740a5e3SKris Kennaway dot = (e[0] == '.') ? 2 : 0; 31975740a5e3SKris Kennaway break; 31985740a5e3SKris Kennaway case 2: 31995740a5e3SKris Kennaway dot = (e[0] == '.') ? 3 : 0; 32005740a5e3SKris Kennaway break; 32015740a5e3SKris Kennaway case 3: 32025740a5e3SKris Kennaway dot = (e[0] == '/') ? -1 : 0; 32035740a5e3SKris Kennaway break; 32045740a5e3SKris Kennaway } 32055740a5e3SKris Kennaway if (dot == 0) 32065740a5e3SKris Kennaway dot = (e[0] == '/') ? 1 : 0; 32075740a5e3SKris Kennaway } 32086f9291ceSJung-uk Kim dot = (dot == 3) || (dot == -1); /* filename contains ".." 32096f9291ceSJung-uk Kim * component */ 321074664626SKris Kennaway 32116f9291ceSJung-uk Kim if (*e == '\0') { 321274664626SKris Kennaway BIO_puts(io, text); 321374664626SKris Kennaway BIO_printf(io, "'%s' is an invalid file name\r\n", p); 321474664626SKris Kennaway break; 321574664626SKris Kennaway } 321674664626SKris Kennaway *e = '\0'; 321774664626SKris Kennaway 32186f9291ceSJung-uk Kim if (dot) { 321974664626SKris Kennaway BIO_puts(io, text); 322074664626SKris Kennaway BIO_printf(io, "'%s' contains '..' reference\r\n", p); 322174664626SKris Kennaway break; 322274664626SKris Kennaway } 322374664626SKris Kennaway 32246f9291ceSJung-uk Kim if (*p == '/') { 322574664626SKris Kennaway BIO_puts(io, text); 322674664626SKris Kennaway BIO_printf(io, "'%s' is an invalid path\r\n", p); 322774664626SKris Kennaway break; 322874664626SKris Kennaway } 322974664626SKris Kennaway 323074664626SKris Kennaway /* if a directory, do the index thang */ 32316f9291ceSJung-uk Kim if (app_isdir(p) > 0) { 32325740a5e3SKris Kennaway BIO_puts(io, text); 32335740a5e3SKris Kennaway BIO_printf(io, "'%s' is a directory\r\n", p); 32345740a5e3SKris Kennaway break; 323574664626SKris Kennaway } 323674664626SKris Kennaway 32376f9291ceSJung-uk Kim if ((file = BIO_new_file(p, "r")) == NULL) { 323874664626SKris Kennaway BIO_puts(io, text); 323974664626SKris Kennaway BIO_printf(io, "Error opening '%s'\r\n", p); 324074664626SKris Kennaway ERR_print_errors(io); 324174664626SKris Kennaway break; 324274664626SKris Kennaway } 324374664626SKris Kennaway 324474664626SKris Kennaway if (!s_quiet) 324574664626SKris Kennaway BIO_printf(bio_err, "FILE:%s\n", p); 324674664626SKris Kennaway 32476f9291ceSJung-uk Kim if (www == 2) { 324874664626SKris Kennaway i = strlen(p); 324974664626SKris Kennaway if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) || 325074664626SKris Kennaway ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) || 325174664626SKris Kennaway ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0))) 32526f9291ceSJung-uk Kim BIO_puts(io, 32536f9291ceSJung-uk Kim "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); 325474664626SKris Kennaway else 32556f9291ceSJung-uk Kim BIO_puts(io, 32566f9291ceSJung-uk Kim "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n"); 32575c87c606SMark Murray } 325874664626SKris Kennaway /* send the file */ 32596f9291ceSJung-uk Kim for (;;) { 326074664626SKris Kennaway i = BIO_read(file, buf, bufsize); 32616f9291ceSJung-uk Kim if (i <= 0) 32626f9291ceSJung-uk Kim break; 326374664626SKris Kennaway 326474664626SKris Kennaway #ifdef RENEG 326574664626SKris Kennaway total_bytes += i; 3266e71b7053SJung-uk Kim BIO_printf(bio_err, "%d\n", i); 32676f9291ceSJung-uk Kim if (total_bytes > 3 * 1024) { 326874664626SKris Kennaway total_bytes = 0; 3269e71b7053SJung-uk Kim BIO_printf(bio_err, "RENEGOTIATE\n"); 327074664626SKris Kennaway SSL_renegotiate(con); 327174664626SKris Kennaway } 327274664626SKris Kennaway #endif 327374664626SKris Kennaway 32746f9291ceSJung-uk Kim for (j = 0; j < i;) { 327574664626SKris Kennaway #ifdef RENEG 32766f9291ceSJung-uk Kim static count = 0; 32776f9291ceSJung-uk Kim if (++count == 13) { 32786f9291ceSJung-uk Kim SSL_renegotiate(con); 32796f9291ceSJung-uk Kim } 328074664626SKris Kennaway #endif 328174664626SKris Kennaway k = BIO_write(io, &(buf[j]), i - j); 32826f9291ceSJung-uk Kim if (k <= 0) { 3283e71b7053SJung-uk Kim if (!BIO_should_retry(io) 3284e71b7053SJung-uk Kim && !SSL_waiting_for_async(con)) 328574664626SKris Kennaway goto write_error; 32866f9291ceSJung-uk Kim else { 328774664626SKris Kennaway BIO_printf(bio_s_out, "rwrite W BLOCK\n"); 328874664626SKris Kennaway } 32896f9291ceSJung-uk Kim } else { 329074664626SKris Kennaway j += k; 329174664626SKris Kennaway } 329274664626SKris Kennaway } 329374664626SKris Kennaway } 329474664626SKris Kennaway write_error: 329574664626SKris Kennaway BIO_free(file); 329674664626SKris Kennaway break; 329774664626SKris Kennaway } 329874664626SKris Kennaway } 329974664626SKris Kennaway 33006f9291ceSJung-uk Kim for (;;) { 330174664626SKris Kennaway i = (int)BIO_flush(io); 33026f9291ceSJung-uk Kim if (i <= 0) { 330374664626SKris Kennaway if (!BIO_should_retry(io)) 330474664626SKris Kennaway break; 33056f9291ceSJung-uk Kim } else 330674664626SKris Kennaway break; 330774664626SKris Kennaway } 330874664626SKris Kennaway end: 330974664626SKris Kennaway /* make sure we re-use sessions */ 331074664626SKris Kennaway SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 331174664626SKris Kennaway 331274664626SKris Kennaway err: 33136f9291ceSJung-uk Kim OPENSSL_free(buf); 33146f9291ceSJung-uk Kim BIO_free_all(io); 3315e71b7053SJung-uk Kim return ret; 331674664626SKris Kennaway } 331774664626SKris Kennaway 3318e71b7053SJung-uk Kim static int rev_body(int s, int stype, int prot, unsigned char *context) 33197bded2dbSJung-uk Kim { 33207bded2dbSJung-uk Kim char *buf = NULL; 33217bded2dbSJung-uk Kim int i; 33227bded2dbSJung-uk Kim int ret = 1; 33237bded2dbSJung-uk Kim SSL *con; 33247bded2dbSJung-uk Kim BIO *io, *ssl_bio, *sbio; 33257bded2dbSJung-uk Kim 3326e71b7053SJung-uk Kim buf = app_malloc(bufsize, "server rev buffer"); 33277bded2dbSJung-uk Kim io = BIO_new(BIO_f_buffer()); 33287bded2dbSJung-uk Kim ssl_bio = BIO_new(BIO_f_ssl()); 33297bded2dbSJung-uk Kim if ((io == NULL) || (ssl_bio == NULL)) 33307bded2dbSJung-uk Kim goto err; 33317bded2dbSJung-uk Kim 33327bded2dbSJung-uk Kim /* lets make the output buffer a reasonable size */ 33337bded2dbSJung-uk Kim if (!BIO_set_write_buffer_size(io, bufsize)) 33347bded2dbSJung-uk Kim goto err; 33357bded2dbSJung-uk Kim 33367bded2dbSJung-uk Kim if ((con = SSL_new(ctx)) == NULL) 33377bded2dbSJung-uk Kim goto err; 3338e71b7053SJung-uk Kim 33397bded2dbSJung-uk Kim if (s_tlsextdebug) { 33407bded2dbSJung-uk Kim SSL_set_tlsext_debug_callback(con, tlsext_cb); 33417bded2dbSJung-uk Kim SSL_set_tlsext_debug_arg(con, bio_s_out); 33427bded2dbSJung-uk Kim } 3343e71b7053SJung-uk Kim if (context != NULL 3344e71b7053SJung-uk Kim && !SSL_set_session_id_context(con, context, 3345e71b7053SJung-uk Kim strlen((char *)context))) { 3346e71b7053SJung-uk Kim SSL_free(con); 3347e71b7053SJung-uk Kim ERR_print_errors(bio_err); 3348e71b7053SJung-uk Kim goto err; 33497bded2dbSJung-uk Kim } 33507bded2dbSJung-uk Kim 33517bded2dbSJung-uk Kim sbio = BIO_new_socket(s, BIO_NOCLOSE); 33527bded2dbSJung-uk Kim SSL_set_bio(con, sbio, sbio); 33537bded2dbSJung-uk Kim SSL_set_accept_state(con); 33547bded2dbSJung-uk Kim 3355e71b7053SJung-uk Kim /* No need to free |con| after this. Done by BIO_free(ssl_bio) */ 33567bded2dbSJung-uk Kim BIO_set_ssl(ssl_bio, con, BIO_CLOSE); 33577bded2dbSJung-uk Kim BIO_push(io, ssl_bio); 33587bded2dbSJung-uk Kim #ifdef CHARSET_EBCDIC 33597bded2dbSJung-uk Kim io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io); 33607bded2dbSJung-uk Kim #endif 33617bded2dbSJung-uk Kim 33627bded2dbSJung-uk Kim if (s_debug) { 33637bded2dbSJung-uk Kim BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); 33647bded2dbSJung-uk Kim BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out); 33657bded2dbSJung-uk Kim } 33667bded2dbSJung-uk Kim if (s_msg) { 33677bded2dbSJung-uk Kim #ifndef OPENSSL_NO_SSL_TRACE 33687bded2dbSJung-uk Kim if (s_msg == 2) 33697bded2dbSJung-uk Kim SSL_set_msg_callback(con, SSL_trace); 33707bded2dbSJung-uk Kim else 33717bded2dbSJung-uk Kim #endif 33727bded2dbSJung-uk Kim SSL_set_msg_callback(con, msg_cb); 33737bded2dbSJung-uk Kim SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); 33747bded2dbSJung-uk Kim } 33757bded2dbSJung-uk Kim 33767bded2dbSJung-uk Kim for (;;) { 33777bded2dbSJung-uk Kim i = BIO_do_handshake(io); 33787bded2dbSJung-uk Kim if (i > 0) 33797bded2dbSJung-uk Kim break; 33807bded2dbSJung-uk Kim if (!BIO_should_retry(io)) { 33817bded2dbSJung-uk Kim BIO_puts(bio_err, "CONNECTION FAILURE\n"); 33827bded2dbSJung-uk Kim ERR_print_errors(bio_err); 33837bded2dbSJung-uk Kim goto end; 33847bded2dbSJung-uk Kim } 338580815a77SJung-uk Kim #ifndef OPENSSL_NO_SRP 338680815a77SJung-uk Kim if (BIO_should_io_special(io) 338780815a77SJung-uk Kim && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { 338880815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP renego during accept\n"); 33894c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 339080815a77SJung-uk Kim srp_callback_parm.user = 33914c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 339280815a77SJung-uk Kim srp_callback_parm.login); 339380815a77SJung-uk Kim if (srp_callback_parm.user) 339480815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 339580815a77SJung-uk Kim srp_callback_parm.user->info); 339680815a77SJung-uk Kim else 339780815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 339880815a77SJung-uk Kim continue; 339980815a77SJung-uk Kim } 340080815a77SJung-uk Kim #endif 34017bded2dbSJung-uk Kim } 34027bded2dbSJung-uk Kim BIO_printf(bio_err, "CONNECTION ESTABLISHED\n"); 3403e71b7053SJung-uk Kim print_ssl_summary(con); 34047bded2dbSJung-uk Kim 34057bded2dbSJung-uk Kim for (;;) { 34067bded2dbSJung-uk Kim i = BIO_gets(io, buf, bufsize - 1); 34077bded2dbSJung-uk Kim if (i < 0) { /* error */ 34087bded2dbSJung-uk Kim if (!BIO_should_retry(io)) { 34097bded2dbSJung-uk Kim if (!s_quiet) 34107bded2dbSJung-uk Kim ERR_print_errors(bio_err); 34117bded2dbSJung-uk Kim goto err; 34127bded2dbSJung-uk Kim } else { 34137bded2dbSJung-uk Kim BIO_printf(bio_s_out, "read R BLOCK\n"); 341480815a77SJung-uk Kim #ifndef OPENSSL_NO_SRP 341580815a77SJung-uk Kim if (BIO_should_io_special(io) 341680815a77SJung-uk Kim && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) { 341780815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP renego during read\n"); 34184c6a0400SJung-uk Kim SRP_user_pwd_free(srp_callback_parm.user); 341980815a77SJung-uk Kim srp_callback_parm.user = 34204c6a0400SJung-uk Kim SRP_VBASE_get1_by_user(srp_callback_parm.vb, 342180815a77SJung-uk Kim srp_callback_parm.login); 342280815a77SJung-uk Kim if (srp_callback_parm.user) 342380815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP done %s\n", 342480815a77SJung-uk Kim srp_callback_parm.user->info); 342580815a77SJung-uk Kim else 342680815a77SJung-uk Kim BIO_printf(bio_s_out, "LOOKUP not successful\n"); 342780815a77SJung-uk Kim continue; 342880815a77SJung-uk Kim } 342980815a77SJung-uk Kim #endif 3430e71b7053SJung-uk Kim #if !defined(OPENSSL_SYS_MSDOS) 34317bded2dbSJung-uk Kim sleep(1); 34327bded2dbSJung-uk Kim #endif 34337bded2dbSJung-uk Kim continue; 34347bded2dbSJung-uk Kim } 34357bded2dbSJung-uk Kim } else if (i == 0) { /* end of input */ 34367bded2dbSJung-uk Kim ret = 1; 34377bded2dbSJung-uk Kim BIO_printf(bio_err, "CONNECTION CLOSED\n"); 34387bded2dbSJung-uk Kim goto end; 34397bded2dbSJung-uk Kim } else { 34407bded2dbSJung-uk Kim char *p = buf + i - 1; 34417bded2dbSJung-uk Kim while (i && (*p == '\n' || *p == '\r')) { 34427bded2dbSJung-uk Kim p--; 34437bded2dbSJung-uk Kim i--; 34447bded2dbSJung-uk Kim } 3445e71b7053SJung-uk Kim if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) { 34467bded2dbSJung-uk Kim ret = 1; 34477bded2dbSJung-uk Kim BIO_printf(bio_err, "CONNECTION CLOSED\n"); 34487bded2dbSJung-uk Kim goto end; 34497bded2dbSJung-uk Kim } 34507bded2dbSJung-uk Kim BUF_reverse((unsigned char *)buf, NULL, i); 34517bded2dbSJung-uk Kim buf[i] = '\n'; 34527bded2dbSJung-uk Kim BIO_write(io, buf, i + 1); 34537bded2dbSJung-uk Kim for (;;) { 34547bded2dbSJung-uk Kim i = BIO_flush(io); 34557bded2dbSJung-uk Kim if (i > 0) 34567bded2dbSJung-uk Kim break; 34577bded2dbSJung-uk Kim if (!BIO_should_retry(io)) 34587bded2dbSJung-uk Kim goto end; 34597bded2dbSJung-uk Kim } 34607bded2dbSJung-uk Kim } 34617bded2dbSJung-uk Kim } 34627bded2dbSJung-uk Kim end: 34637bded2dbSJung-uk Kim /* make sure we re-use sessions */ 34647bded2dbSJung-uk Kim SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); 34657bded2dbSJung-uk Kim 34667bded2dbSJung-uk Kim err: 34677bded2dbSJung-uk Kim 34687bded2dbSJung-uk Kim OPENSSL_free(buf); 34697bded2dbSJung-uk Kim BIO_free_all(io); 3470e71b7053SJung-uk Kim return ret; 34717bded2dbSJung-uk Kim } 34727bded2dbSJung-uk Kim 34735c87c606SMark Murray #define MAX_SESSION_ID_ATTEMPTS 10 3474e71b7053SJung-uk Kim static int generate_session_id(SSL *ssl, unsigned char *id, 34755c87c606SMark Murray unsigned int *id_len) 34765c87c606SMark Murray { 34775c87c606SMark Murray unsigned int count = 0; 34785c87c606SMark Murray do { 3479aeb5019cSJung-uk Kim if (RAND_bytes(id, *id_len) <= 0) 3480ed6b93beSJung-uk Kim return 0; 34816f9291ceSJung-uk Kim /* 34826f9291ceSJung-uk Kim * Prefix the session_id with the required prefix. NB: If our prefix 34836f9291ceSJung-uk Kim * is too long, clip it - but there will be worse effects anyway, eg. 34846f9291ceSJung-uk Kim * the server could only possibly create 1 session ID (ie. the 34856f9291ceSJung-uk Kim * prefix!) so all future session negotiations will fail due to 34866f9291ceSJung-uk Kim * conflicts. 34876f9291ceSJung-uk Kim */ 34885c87c606SMark Murray memcpy(id, session_id_prefix, 34895c87c606SMark Murray (strlen(session_id_prefix) < *id_len) ? 34905c87c606SMark Murray strlen(session_id_prefix) : *id_len); 34915c87c606SMark Murray } 34925c87c606SMark Murray while (SSL_has_matching_session_id(ssl, id, *id_len) && 34935c87c606SMark Murray (++count < MAX_SESSION_ID_ATTEMPTS)); 34945c87c606SMark Murray if (count >= MAX_SESSION_ID_ATTEMPTS) 34955c87c606SMark Murray return 0; 34965c87c606SMark Murray return 1; 34975c87c606SMark Murray } 34987bded2dbSJung-uk Kim 34997bded2dbSJung-uk Kim /* 35007bded2dbSJung-uk Kim * By default s_server uses an in-memory cache which caches SSL_SESSION 35017bded2dbSJung-uk Kim * structures without any serialisation. This hides some bugs which only 35027bded2dbSJung-uk Kim * become apparent in deployed servers. By implementing a basic external 35037bded2dbSJung-uk Kim * session cache some issues can be debugged using s_server. 35047bded2dbSJung-uk Kim */ 35057bded2dbSJung-uk Kim 35067bded2dbSJung-uk Kim typedef struct simple_ssl_session_st { 35077bded2dbSJung-uk Kim unsigned char *id; 35087bded2dbSJung-uk Kim unsigned int idlen; 35097bded2dbSJung-uk Kim unsigned char *der; 35107bded2dbSJung-uk Kim int derlen; 35117bded2dbSJung-uk Kim struct simple_ssl_session_st *next; 35127bded2dbSJung-uk Kim } simple_ssl_session; 35137bded2dbSJung-uk Kim 35147bded2dbSJung-uk Kim static simple_ssl_session *first = NULL; 35157bded2dbSJung-uk Kim 35167bded2dbSJung-uk Kim static int add_session(SSL *ssl, SSL_SESSION *session) 35177bded2dbSJung-uk Kim { 3518e71b7053SJung-uk Kim simple_ssl_session *sess = app_malloc(sizeof(*sess), "get session"); 35197bded2dbSJung-uk Kim unsigned char *p; 35207bded2dbSJung-uk Kim 35217bded2dbSJung-uk Kim SSL_SESSION_get_id(session, &sess->idlen); 35227bded2dbSJung-uk Kim sess->derlen = i2d_SSL_SESSION(session, NULL); 3523e71b7053SJung-uk Kim if (sess->derlen < 0) { 3524e71b7053SJung-uk Kim BIO_printf(bio_err, "Error encoding session\n"); 3525e71b7053SJung-uk Kim OPENSSL_free(sess); 3526e71b7053SJung-uk Kim return 0; 3527e71b7053SJung-uk Kim } 35287bded2dbSJung-uk Kim 3529e71b7053SJung-uk Kim sess->id = OPENSSL_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen); 3530e71b7053SJung-uk Kim sess->der = app_malloc(sess->derlen, "get session buffer"); 3531e71b7053SJung-uk Kim if (!sess->id) { 3532e71b7053SJung-uk Kim BIO_printf(bio_err, "Out of memory adding to external cache\n"); 35337bded2dbSJung-uk Kim OPENSSL_free(sess->id); 35347bded2dbSJung-uk Kim OPENSSL_free(sess->der); 35357bded2dbSJung-uk Kim OPENSSL_free(sess); 35367bded2dbSJung-uk Kim return 0; 35377bded2dbSJung-uk Kim } 35387bded2dbSJung-uk Kim p = sess->der; 3539e71b7053SJung-uk Kim 3540e71b7053SJung-uk Kim /* Assume it still works. */ 3541e71b7053SJung-uk Kim if (i2d_SSL_SESSION(session, &p) != sess->derlen) { 3542e71b7053SJung-uk Kim BIO_printf(bio_err, "Unexpected session encoding length\n"); 3543e71b7053SJung-uk Kim OPENSSL_free(sess->id); 3544e71b7053SJung-uk Kim OPENSSL_free(sess->der); 3545e71b7053SJung-uk Kim OPENSSL_free(sess); 3546e71b7053SJung-uk Kim return 0; 3547e71b7053SJung-uk Kim } 35487bded2dbSJung-uk Kim 35497bded2dbSJung-uk Kim sess->next = first; 35507bded2dbSJung-uk Kim first = sess; 35517bded2dbSJung-uk Kim BIO_printf(bio_err, "New session added to external cache\n"); 35527bded2dbSJung-uk Kim return 0; 35537bded2dbSJung-uk Kim } 35547bded2dbSJung-uk Kim 3555e71b7053SJung-uk Kim static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, 35567bded2dbSJung-uk Kim int *do_copy) 35577bded2dbSJung-uk Kim { 35587bded2dbSJung-uk Kim simple_ssl_session *sess; 35597bded2dbSJung-uk Kim *do_copy = 0; 35607bded2dbSJung-uk Kim for (sess = first; sess; sess = sess->next) { 35617bded2dbSJung-uk Kim if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) { 35627bded2dbSJung-uk Kim const unsigned char *p = sess->der; 35637bded2dbSJung-uk Kim BIO_printf(bio_err, "Lookup session: cache hit\n"); 35647bded2dbSJung-uk Kim return d2i_SSL_SESSION(NULL, &p, sess->derlen); 35657bded2dbSJung-uk Kim } 35667bded2dbSJung-uk Kim } 35677bded2dbSJung-uk Kim BIO_printf(bio_err, "Lookup session: cache miss\n"); 35687bded2dbSJung-uk Kim return NULL; 35697bded2dbSJung-uk Kim } 35707bded2dbSJung-uk Kim 35717bded2dbSJung-uk Kim static void del_session(SSL_CTX *sctx, SSL_SESSION *session) 35727bded2dbSJung-uk Kim { 35737bded2dbSJung-uk Kim simple_ssl_session *sess, *prev = NULL; 35747bded2dbSJung-uk Kim const unsigned char *id; 35757bded2dbSJung-uk Kim unsigned int idlen; 35767bded2dbSJung-uk Kim id = SSL_SESSION_get_id(session, &idlen); 35777bded2dbSJung-uk Kim for (sess = first; sess; sess = sess->next) { 35787bded2dbSJung-uk Kim if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) { 35797bded2dbSJung-uk Kim if (prev) 35807bded2dbSJung-uk Kim prev->next = sess->next; 35817bded2dbSJung-uk Kim else 35827bded2dbSJung-uk Kim first = sess->next; 35837bded2dbSJung-uk Kim OPENSSL_free(sess->id); 35847bded2dbSJung-uk Kim OPENSSL_free(sess->der); 35857bded2dbSJung-uk Kim OPENSSL_free(sess); 35867bded2dbSJung-uk Kim return; 35877bded2dbSJung-uk Kim } 35887bded2dbSJung-uk Kim prev = sess; 35897bded2dbSJung-uk Kim } 35907bded2dbSJung-uk Kim } 35917bded2dbSJung-uk Kim 35927bded2dbSJung-uk Kim static void init_session_cache_ctx(SSL_CTX *sctx) 35937bded2dbSJung-uk Kim { 35947bded2dbSJung-uk Kim SSL_CTX_set_session_cache_mode(sctx, 35957bded2dbSJung-uk Kim SSL_SESS_CACHE_NO_INTERNAL | 35967bded2dbSJung-uk Kim SSL_SESS_CACHE_SERVER); 35977bded2dbSJung-uk Kim SSL_CTX_sess_set_new_cb(sctx, add_session); 35987bded2dbSJung-uk Kim SSL_CTX_sess_set_get_cb(sctx, get_session); 35997bded2dbSJung-uk Kim SSL_CTX_sess_set_remove_cb(sctx, del_session); 36007bded2dbSJung-uk Kim } 36017bded2dbSJung-uk Kim 36027bded2dbSJung-uk Kim static void free_sessions(void) 36037bded2dbSJung-uk Kim { 36047bded2dbSJung-uk Kim simple_ssl_session *sess, *tsess; 36057bded2dbSJung-uk Kim for (sess = first; sess;) { 36067bded2dbSJung-uk Kim OPENSSL_free(sess->id); 36077bded2dbSJung-uk Kim OPENSSL_free(sess->der); 36087bded2dbSJung-uk Kim tsess = sess; 36097bded2dbSJung-uk Kim sess = sess->next; 36107bded2dbSJung-uk Kim OPENSSL_free(tsess); 36117bded2dbSJung-uk Kim } 36127bded2dbSJung-uk Kim first = NULL; 36137bded2dbSJung-uk Kim } 3614e71b7053SJung-uk Kim 3615e71b7053SJung-uk Kim #endif /* OPENSSL_NO_SOCK */ 3616