apache2/apache2-mod_ssl_npn.patch

553 lines
18 KiB
Diff
Raw Normal View History

--- httpd-2.4.3.orig/modules/ssl/mod_ssl.c
+++ httpd-2.4.3/modules/ssl/mod_ssl.c
@@ -94,6 +94,15 @@ static const command_rec ssl_config_cmds
SSL_CMD_SRV(PKCS7CertificateFile, TAKE1,
"PKCS#7 file containing server certificate and chain"
" certificates ('/path/to/file' - PEM encoded)")
+ SSL_CMD_ALL(RSAAuthzFile, TAKE1,
+ "RFC 5878 Authz Extension file for RSA certificate "
+ "(`/path/to/file')")
+ SSL_CMD_ALL(DSAAuthzFile, TAKE1,
+ "RFC 5878 Authz Extension file for DSA certificate "
+ "(`/path/to/file')")
+ SSL_CMD_ALL(ECAuthzFile, TAKE1,
+ "RFC 5878 Authz Extension file for EC certificate "
+ "(`/path/to/file')")
#ifdef HAVE_TLS_SESSION_TICKETS
SSL_CMD_SRV(SessionTicketKeyFile, TAKE1,
"TLS session ticket encryption/decryption key file (RFC 5077) "
@@ -148,6 +157,15 @@ static const command_rec ssl_config_cmds
SSL_CMD_SRV(StrictSNIVHostCheck, FLAG,
"Strict SNI virtual host checking")
+#ifndef OPENSSL_NO_SRP
+ SSL_CMD_SRV(SRPVerifierFile, TAKE1,
+ "SRP verifier file "
+ "('/path/to/file' - created by srptool)")
+ SSL_CMD_SRV(SRPUnknownUserSeed, TAKE1,
+ "SRP seed for unknown users (to avoid leaking a user's existence) "
+ "('some secret text')")
+#endif
+
/*
* Proxy configuration for remote SSL connections
*/
@@ -263,6 +281,18 @@ static const command_rec ssl_config_cmds
AP_END_CMD
};
+/* Implement 'modssl_run_npn_advertise_protos_hook'. */
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(
+ modssl, AP, int, npn_advertise_protos_hook,
+ (conn_rec *connection, apr_array_header_t *protos),
+ (connection, protos), OK, DECLINED);
+
+/* Implement 'modssl_run_npn_proto_negotiated_hook'. */
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(
+ modssl, AP, int, npn_proto_negotiated_hook,
+ (conn_rec *connection, const char *proto_name, apr_size_t proto_name_len),
+ (connection, proto_name, proto_name_len), OK, DECLINED);
+
/*
* the various processing hooks
*/
--- httpd-2.4.3.orig/modules/ssl/mod_ssl.h
+++ httpd-2.4.3/modules/ssl/mod_ssl.h
@@ -63,5 +63,26 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_e
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
+/** The npn_advertise_protos optional hook allows other modules to add entries
+ * to the list of protocol names advertised by the server during the Next
+ * Protocol Negotiation (NPN) portion of the SSL handshake. The hook callee is
+ * given the connection and an APR array; it should push one or more char*'s
+ * pointing to null-terminated strings (such as "http/1.1" or "spdy/2") onto
+ * the array and return OK, or do nothing and return DECLINED. */
+APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_advertise_protos_hook,
+ (conn_rec *connection, apr_array_header_t *protos));
+
+/** The npn_proto_negotiated optional hook allows other modules to discover the
+ * name of the protocol that was chosen during the Next Protocol Negotiation
+ * (NPN) portion of the SSL handshake. Note that this may be the empty string
+ * (in which case modules should probably assume HTTP), or it may be a protocol
+ * that was never even advertised by the server. The hook callee is given the
+ * connection, a non-null-terminated string containing the protocol name, and
+ * the length of the string; it should do something appropriate (i.e. insert or
+ * remove filters) and return OK, or do nothing and return DECLINED. */
+APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_proto_negotiated_hook,
+ (conn_rec *connection, const char *proto_name,
+ apr_size_t proto_name_len));
+
#endif /* __MOD_SSL_H__ */
/** @} */
--- httpd-2.4.3.orig/modules/ssl/ssl_engine_config.c
+++ httpd-2.4.3/modules/ssl/ssl_engine_config.c
@@ -125,6 +125,10 @@ static void modssl_ctx_init(modssl_ctx_t
mctx->crl_file = NULL;
mctx->crl_check_mode = SSL_CRLCHECK_UNSET;
+ mctx->rsa_authz_file = NULL;
+ mctx->dsa_authz_file = NULL;
+ mctx->ec_authz_file = NULL;
+
mctx->auth.ca_cert_path = NULL;
mctx->auth.ca_cert_file = NULL;
mctx->auth.cipher_suite = NULL;
@@ -149,6 +153,12 @@ static void modssl_ctx_init(modssl_ctx_t
mctx->stapling_responder_timeout = UNSET;
mctx->stapling_force_url = NULL;
#endif
+
+#ifndef OPENSSL_NO_SRP
+ mctx->srp_vfile = NULL;
+ mctx->srp_unknown_user_seed = NULL;
+ mctx->srp_vbase = NULL;
+#endif
}
static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
@@ -251,6 +264,10 @@ static void modssl_ctx_cfg_merge(modssl_
cfgMerge(crl_file, NULL);
cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET);
+ cfgMergeString(rsa_authz_file);
+ cfgMergeString(dsa_authz_file);
+ cfgMergeString(ec_authz_file);
+
cfgMergeString(auth.ca_cert_path);
cfgMergeString(auth.ca_cert_file);
cfgMergeString(auth.cipher_suite);
@@ -274,6 +291,11 @@ static void modssl_ctx_cfg_merge(modssl_
cfgMergeInt(stapling_responder_timeout);
cfgMerge(stapling_force_url, NULL);
#endif
+
+#ifndef OPENSSL_NO_SRP
+ cfgMergeString(srp_vfile);
+ cfgMergeString(srp_unknown_user_seed);
+#endif
}
static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base,
@@ -829,6 +871,54 @@ const char *ssl_cmd_SSLPKCS7CertificateF
return NULL;
}
+const char *ssl_cmd_SSLRSAAuthzFile(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+ if ((err = ssl_cmd_check_file(cmd, &arg))) {
+ return err;
+ }
+
+ sc->server->rsa_authz_file = arg;
+
+ return NULL;
+}
+
+const char *ssl_cmd_SSLDSAAuthzFile(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+ if ((err = ssl_cmd_check_file(cmd, &arg))) {
+ return err;
+ }
+
+ sc->server->dsa_authz_file = arg;
+
+ return NULL;
+}
+
+const char *ssl_cmd_SSLECAuthzFile(cmd_parms *cmd,
+ void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+ if ((err = ssl_cmd_check_file(cmd, &arg))) {
+ return err;
+ }
+
+ sc->server->ec_authz_file = arg;
+
+ return NULL;
+}
+
#ifdef HAVE_TLS_SESSION_TICKETS
const char *ssl_cmd_SSLSessionTicketKeyFile(cmd_parms *cmd,
void *dcfg,
@@ -1782,6 +1872,32 @@ const char *ssl_cmd_SSLStaplingForceURL(
#endif /* HAVE_OCSP_STAPLING */
+#ifndef OPENSSL_NO_SRP
+
+const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ const char *err;
+
+ if ((err = ssl_cmd_check_file(cmd, &arg)))
+ return err;
+ /* SRP_VBASE_init takes char*, not const char* */
+ sc->server->srp_vfile = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+
+const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg,
+ const char *arg)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ /* SRP_VBASE_new takes char*, not const char* */
+ sc->server->srp_unknown_user_seed = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+
+#endif /* OPENSSL_NO_SRP */
+
void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s)
{
apr_file_t *out = NULL;
--- httpd-2.4.3.orig/modules/ssl/ssl_engine_io.c
+++ httpd-2.4.3/modules/ssl/ssl_engine_io.c
@@ -28,6 +28,7 @@
core keeps dumping.''
-- Unknown */
#include "ssl_private.h"
+#include "mod_ssl.h"
#include "apr_date.h"
/* _________________________________________________________________
@@ -297,6 +298,7 @@ typedef struct {
apr_pool_t *pool;
char buffer[AP_IOBUFSIZE];
ssl_filter_ctx_t *filter_ctx;
+ int npn_finished; /* 1 if NPN has finished, 0 otherwise */
} bio_filter_in_ctx_t;
/*
@@ -1374,6 +1376,26 @@ static apr_status_t ssl_io_filter_input(
APR_BRIGADE_INSERT_TAIL(bb, bucket);
}
+#ifdef HAVE_TLS_NPN
+ /* By this point, Next Protocol Negotiation (NPN) should be completed (if
+ * our version of OpenSSL supports it). If we haven't already, find out
+ * which protocol was decided upon and inform other modules by calling
+ * npn_proto_negotiated_hook. */
+ if (!inctx->npn_finished) {
+ const unsigned char *next_proto = NULL;
+ unsigned next_proto_len = 0;
+
+ SSL_get0_next_proto_negotiated(
+ inctx->ssl, &next_proto, &next_proto_len);
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
+ APLOGNO(02306) "SSL NPN negotiated protocol: '%*s'",
+ next_proto_len, (const char*)next_proto);
+ modssl_run_npn_proto_negotiated_hook(
+ f->c, (const char*)next_proto, next_proto_len);
+ inctx->npn_finished = 1;
+ }
+#endif
+
return APR_SUCCESS;
}
@@ -1855,6 +1877,7 @@ static void ssl_io_input_add_filter(ssl_
inctx->block = APR_BLOCK_READ;
inctx->pool = c->pool;
inctx->filter_ctx = filter_ctx;
+ inctx->npn_finished = 0;
}
/* The request_rec pointer is passed in here only to ensure that the
--- httpd-2.4.3.orig/modules/ssl/ssl_engine_kernel.c
+++ httpd-2.4.3/modules/ssl/ssl_engine_kernel.c
@@ -29,6 +29,7 @@
time I was too famous.''
-- Unknown */
#include "ssl_private.h"
+#include "mod_ssl.h"
#include "util_md5.h"
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
@@ -329,6 +330,19 @@ int ssl_hook_Access(request_rec *r)
return DECLINED;
}
+#ifndef OPENSSL_NO_SRP
+ /*
+ * Support for per-directory reconfigured SSL connection parameters
+ *
+ * We do not force any renegotiation if the user is already authenticated
+ * via SRP.
+ *
+ */
+ if (SSL_get_srp_username(ssl)) {
+ return DECLINED;
+ }
+#endif
+
/*
* Support for per-directory reconfigured SSL connection parameters.
*
@@ -1088,6 +1102,10 @@ static const char *ssl_hook_Fixup_vars[]
"SSL_SERVER_A_SIG",
"SSL_SESSION_ID",
"SSL_SESSION_RESUMED",
+#ifndef OPENSSL_NO_SRP
+ "SSL_SRP_USER",
+ "SSL_SRP_USERINFO",
+#endif
NULL
};
@@ -2072,7 +2090,7 @@ static int ssl_find_vhost(void *serverna
return 0;
}
-#endif
+#endif /* OPENSSL_NO_TLSEXT */
#ifdef HAVE_TLS_SESSION_TICKETS
/*
@@ -2142,4 +2160,114 @@ int ssl_callback_SessionTicket(SSL *ssl,
/* OpenSSL is not expected to call us with modes other than 1 or 0 */
return -1;
}
-#endif
+#endif /* HAVE_TLS_SESSION_TICKETS */
+
+#ifdef HAVE_TLS_NPN
+/*
+ * This callback function is executed when SSL needs to decide what protocols
+ * to advertise during Next Protocol Negotiation (NPN). It must produce a
+ * string in wire format -- a sequence of length-prefixed strings -- indicating
+ * the advertised protocols. Refer to SSL_CTX_set_next_protos_advertised_cb
+ * in OpenSSL for reference.
+ */
+int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out,
+ unsigned int *size_out, void *arg)
+{
+ conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
+ apr_array_header_t *protos;
+ int num_protos;
+ unsigned int size;
+ int i;
+ unsigned char *data;
+ unsigned char *start;
+
+ *data_out = NULL;
+ *size_out = 0;
+
+ /* If the connection object is not available, then there's nothing for us
+ * to do. */
+ if (c == NULL) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ /* Invoke our npn_advertise_protos hook, giving other modules a chance to
+ * add alternate protocol names to advertise. */
+ protos = apr_array_make(c->pool, 0, sizeof(char*));
+ modssl_run_npn_advertise_protos_hook(c, protos);
+ num_protos = protos->nelts;
+
+ /* We now have a list of null-terminated strings; we need to concatenate
+ * them together into a single string, where each protocol name is prefixed
+ * by its length. First, calculate how long that string will be. */
+ size = 0;
+ for (i = 0; i < num_protos; ++i) {
+ const char *string = APR_ARRAY_IDX(protos, i, const char*);
+ unsigned int length = strlen(string);
+ /* If the protocol name is too long (the length must fit in one byte),
+ * then log an error and skip it. */
+ if (length > 255) {
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02307)
+ "SSL NPN protocol name too long (length=%u): %s",
+ length, string);
+ continue;
+ }
+ /* Leave room for the length prefix (one byte) plus the protocol name
+ * itself. */
+ size += 1 + length;
+ }
+
+ /* If there is nothing to advertise (either because no modules added
+ * anything to the protos array, or because all strings added to the array
+ * were skipped), then we're done. */
+ if (size == 0) {
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ /* Now we can build the string. Copy each protocol name string into the
+ * larger string, prefixed by its length. */
+ data = apr_palloc(c->pool, size * sizeof(unsigned char));
+ start = data;
+ for (i = 0; i < num_protos; ++i) {
+ const char *string = APR_ARRAY_IDX(protos, i, const char*);
+ apr_size_t length = strlen(string);
+ if (length > 255)
+ continue;
+ *start = (unsigned char)length;
+ ++start;
+ memcpy(start, string, length * sizeof(unsigned char));
+ start += length;
+ }
+
+ /* Success. */
+ *data_out = data;
+ *size_out = size;
+ return SSL_TLSEXT_ERR_OK;
+}
+
+#endif /* HAVE_TLS_NPN */
+
+#ifndef OPENSSL_NO_SRP
+
+int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
+{
+ modssl_ctx_t *mctx = (modssl_ctx_t *)arg;
+ char *username = SSL_get_srp_username(ssl);
+ SRP_user_pwd *u;
+
+ if (username == NULL
+ || (u = SRP_VBASE_get_by_user(mctx->srp_vbase, username)) == NULL) {
+ *ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ return SSL3_AL_FATAL;
+ }
+
+ if (SSL_set_srp_server_param(ssl, u->N, u->g, u->s, u->v, u->info) < 0) {
+ *ad = SSL_AD_INTERNAL_ERROR;
+ return SSL3_AL_FATAL;
+ }
+
+ /* reset all other options */
+ SSL_set_verify(ssl, SSL_VERIFY_NONE, ssl_callback_SSLVerify);
+ return SSL_ERROR_NONE;
+}
+
+#endif /* OPENSSL_NO_SRP */
--- httpd-2.4.3.orig/modules/ssl/ssl_engine_vars.c
+++ httpd-2.4.3/modules/ssl/ssl_engine_vars.c
@@ -395,6 +395,18 @@ static char *ssl_var_lookup_ssl(apr_pool
#endif
result = apr_pstrdup(p, flag ? "true" : "false");
}
+#ifndef OPENSSL_NO_SRP
+ else if (ssl != NULL && strcEQ(var, "SRP_USER")) {
+ if ((result = SSL_get_srp_username(ssl)) != NULL) {
+ result = apr_pstrdup(p, result);
+ }
+ }
+ else if (ssl != NULL && strcEQ(var, "SRP_USERINFO")) {
+ if ((result = SSL_get_srp_userinfo(ssl)) != NULL) {
+ result = apr_pstrdup(p, result);
+ }
+ }
+#endif
return result;
}
--- httpd-2.4.3.orig/modules/ssl/ssl_private.h
+++ httpd-2.4.3/modules/ssl/ssl_private.h
@@ -139,6 +139,11 @@
#define HAVE_FIPS
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) \
+ && !defined(OPENSSL_NO_TLSEXT)
+#define HAVE_TLS_NPN
+#endif
+
#if (OPENSSL_VERSION_NUMBER >= 0x10000000)
#define MODSSL_SSL_CIPHER_CONST const
#define MODSSL_SSL_METHOD_CONST const
@@ -185,6 +190,20 @@
#define OPENSSL_NO_COMP
#endif
+#if !defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION) \
+ && OPENSSL_VERSION_NUMBER < 0x00908000L
+#define OPENSSL_NO_COMP
+#endif
+
+/* SRP support came in OpenSSL 1.0.1 */
+#ifndef OPENSSL_NO_SRP
+#ifdef SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB
+#include <openssl/srp.h>
+#else
+#define OPENSSL_NO_SRP
+#endif
+#endif
+
/* mod_ssl headers */
#include "ssl_util_ssl.h"
@@ -647,6 +666,17 @@ typedef struct {
const char *stapling_force_url;
#endif
+#ifndef OPENSSL_NO_SRP
+ char *srp_vfile;
+ char *srp_unknown_user_seed;
+ SRP_VBASE *srp_vbase;
+#endif
+
+ /** RFC 5878 */
+ const char *rsa_authz_file;
+ const char *dsa_authz_file;
+ const char *ec_authz_file;
+
modssl_auth_ctx_t auth;
BOOL ocsp_enabled; /* true if OCSP verification enabled */
@@ -723,6 +756,9 @@ const char *ssl_cmd_SSLCryptoDevice(cmd
const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
+const char *ssl_cmd_SSLRSAAuthzFile(cmd_parms *, void *, const char *);
+const char *ssl_cmd_SSLDSAAuthzFile(cmd_parms *, void *, const char *);
+const char *ssl_cmd_SSLECAuthzFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *);
@@ -775,6 +811,11 @@ const char *ssl_cmd_SSLOCSPResponseMaxAg
const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg);
const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag);
+#ifndef OPENSSL_NO_SRP
+const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
+const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
+#endif
+
const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag);
/** module initialization */
@@ -820,6 +861,7 @@ int ssl_callback_ServerNameIndi
int ssl_callback_SessionTicket(SSL *, unsigned char *, unsigned char *,
EVP_CIPHER_CTX *, HMAC_CTX *, int);
#endif
+int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg);
/** Session Cache Support */
void ssl_scache_init(server_rec *, apr_pool_t *);
@@ -851,6 +893,9 @@ void modssl_init_stapling(server
void ssl_stapling_ex_init(void);
int ssl_stapling_init_cert(server_rec *s, modssl_ctx_t *mctx, X509 *x);
#endif
+#ifndef OPENSSL_NO_SRP
+int ssl_callback_SRPServerParams(SSL *, int *, void *);
+#endif
/** I/O */
void ssl_io_filter_init(conn_rec *, request_rec *r, SSL *);