#define SK_VALUE(x,y) sk_X509_value(x,y)
typedef STACK_OF(X509) X509_STACK_TYPE;
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(LIBRESSL_VERSION_NUMBER)
/* The following logic ensures we correctly glue FILE* within one CRT used
* by the OpenSSL library build to another CRT used by the ab.exe build.
* This became especially problematic with Visual Studio 2015.
SSL_CTX *ssl_ctx;
char *ssl_cipher = NULL;
char *ssl_info = NULL;
+char *ssl_cert = NULL;
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
char *ssl_tmp_key = NULL;
+#endif
BIO *bio_out,*bio_err;
#ifdef HAVE_TLSEXT
int tls_use_sni = 1; /* used by default, -I disables it */
SSL_CIPHER_get_name(ci),
pk_bits, sk_bits);
}
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (ssl_tmp_key == NULL) {
EVP_PKEY *key;
if (SSL_get_server_tmp_key(c->ssl, &key)) {
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
EC_KEY_free(ec);
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
cname = EC_curve_nid2nist(nid);
-#endif
if (!cname)
cname = OBJ_nid2sn(nid);
break;
}
#endif
+ default:
+ apr_snprintf(ssl_tmp_key, 128, "%s %d bits",
+ OBJ_nid2sn(EVP_PKEY_id(key)),
+ EVP_PKEY_bits(key));
+ break;
}
EVP_PKEY_free(key);
}
}
+#endif
write_request(c);
do_next = 0;
break;
return;
}
l = e;
- e = APR_SUCCESS;
}
else
#endif
{
e = apr_socket_send(c->aprsock, request + c->rwrote, &l);
- if (e != APR_SUCCESS) {
+ if (e != APR_SUCCESS && !l) {
if (!APR_STATUS_IS_EAGAIN(e)) {
epipe++;
printf("Send request failed!\n");
close_connection(c);
- return;
}
- if (!l) {
+ else {
set_polled_events(c, APR_POLLOUT);
- return;
}
+ return;
}
}
totalposted += l;
if (is_ssl && ssl_info) {
printf("SSL/TLS Protocol: %s\n", ssl_info);
}
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (is_ssl && ssl_tmp_key) {
printf("Server Temp Key: %s\n", ssl_tmp_key);
}
+#endif
#ifdef HAVE_TLSEXT
if (is_ssl && tls_sni) {
printf("TLS Server Name: %s\n", tls_sni);
fprintf(stderr, " -Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)\n");
fprintf(stderr, " -f protocol Specify SSL/TLS protocol\n");
fprintf(stderr, " (" SSL2_HELP_MSG SSL3_HELP_MSG "TLS1" TLS1_X_HELP_MSG " or ALL)\n");
+ fprintf(stderr, " -E certfile Specify optional client certificate chain and private key\n");
#endif
exit(EINVAL);
}
apr_getopt_init(&opt, cntxt, argc, argv);
while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwiIx:y:z:C:H:P:A:g:X:de:SqB:m:"
#ifdef USE_SSL
- "Z:f:"
+ "Z:f:E:"
#endif
,&c, &opt_arg)) == APR_SUCCESS) {
switch (c) {
case 'Z':
ssl_cipher = strdup(opt_arg);
break;
+ case 'E':
+ ssl_cert = strdup(opt_arg);
+ break;
case 'f':
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (strncasecmp(opt_arg, "ALL", 3) == 0) {
if (verbosity >= 3) {
SSL_CTX_set_info_callback(ssl_ctx, ssl_state_cb);
}
+ if (ssl_cert != NULL) {
+ if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
+ BIO_printf(bio_err, "unable to get certificate from '%s'\n",
+ ssl_cert);
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) <= 0) {
+ BIO_printf(bio_err, "unable to get private key from '%s'\n",
+ ssl_cert);
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
+ if (!SSL_CTX_check_private_key(ssl_ctx)) {
+ BIO_printf(bio_err,
+ "private key does not match the certificate public key in %s\n", ssl_cert);
+ exit(1);
+ }
+ }
+
#endif
#ifdef SIGPIPE
apr_signal(SIGPIPE, SIG_IGN); /* Ignore writes to connections that