Changes with Apache 2.4.4
+ *) mod_ssl: Add support for TLS-SRP (Secure Remote Password key exchange
+ for TLS, RFC 5054). PR 51075. [Quinn Slack <sqs cs stanford edu>,
+ Christophe Renou, Peter Sylvester]
+
*) mod_rewrite: Stop mergeing RewriteBase down to subdirectories
unless new option 'RewriteOptions MergeBase' is configured.
PR 53963. [Eric Covener]
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- * mod_ssl: Add support for TLS-SRP (Secure Remote Password key exchange
- for TLS, RFC 5054).
- trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1347980 and
- http://svn.apache.org/viewvc?view=revision&revision=1348653
- 2.4.x patch: http://people.apache.org/~sf/ssl-TLS-SRP-2_4-v2.patch
- +1: sf, minfrin, rjung
- rjung: Please add docs compatibility note for 2.4.4.
- There is another docs block missing from the backport about
- how to create the verifier file using the openssl commandline tool.
-
* mod_proxy: Make balancers server-specific, as they should have
been. Inheritance causes too many behind-the-scene interactions
to be reliable in a dynamic environ.
#SSLVerifyClient require
#SSLVerifyDepth 10
+# TLS-SRP mutual authentication:
+# Enable TLS-SRP and set the path to the OpenSSL SRP verifier
+# file (containing login information for SRP user accounts).
+# Requires OpenSSL 1.0.1 or newer. See the mod_ssl FAQ for
+# detailed instructions on creating this file. Example:
+# "openssl srp -srpvfile @exp_sysconfdir@/passwd.srpv -add username"
+#SSLSRPVerifierFile "@exp_sysconfdir@/passwd.srpv"
+
# Access Control:
# With SSLRequire you can do per-directory access control based
# on arbitrary complex boolean expressions containing server
<tr><td><code>SSL_SERVER_A_SIG</code></td> <td>string</td> <td>Algorithm used for the signature of server's certificate</td></tr>
<tr><td><code>SSL_SERVER_A_KEY</code></td> <td>string</td> <td>Algorithm used for the public key of server's certificate</td></tr>
<tr><td><code>SSL_SERVER_CERT</code></td> <td>string</td> <td>PEM-encoded server certificate</td></tr>
+<tr><td><code>SSL_SRP_USER</code></td> <td>string</td> <td>SRP username</td></tr>
+<tr><td><code>SSL_SRP_USERINFO</code></td> <td>string</td> <td>SRP user info</td></tr>
</table>
<p><em>x509</em> specifies a component of an X.509 DN; one of
<tr><td><code>kDHr</code></td> <td>Diffie-Hellman key exchange with RSA key</td></tr>
<tr><td><code>kDHd</code></td> <td>Diffie-Hellman key exchange with DSA key</td></tr>
<tr><td><code>kEDH</code></td> <td>Ephemeral (temp.key) Diffie-Hellman key exchange (no cert)</td> </tr>
+<tr><td><code>kSRP</code></td> <td>Secure Remote Password (SRP) key exchange</td></tr>
<tr><td colspan="2"><em>Authentication Algorithm:</em></td></tr>
<tr><td><code>aNULL</code></td> <td>No authentication</td></tr>
<tr><td><code>aRSA</code></td> <td>RSA authentication</td></tr>
<tr><td><code>ECDH</code></td> <td>Elliptic Curve Diffie-Hellman key exchange</td> </tr>
<tr><td><code>ADH</code></td> <td>all ciphers using Anonymous Diffie-Hellman key exchange</td> </tr>
<tr><td><code>AECDH</code></td> <td>all ciphers using Anonymous Elliptic Curve Diffie-Hellman key exchange</td> </tr>
+<tr><td><code>SRP</code></td> <td>all ciphers using Secure Remote Password (SRP) key exchange</td> </tr>
<tr><td><code>DSS</code></td> <td>all ciphers using DSS authentication</td> </tr>
<tr><td><code>ECDSA</code></td> <td>all ciphers using ECDSA authentication</td> </tr>
<tr><td><code>aNULL</code></td> <td>all ciphers using no authentication</td> </tr>
</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>SSLSRPVerifierFile</name>
+<description>Path to SRP verifier file</description>
+<syntax>SSLSRPVerifierFile <em>file-path</em></syntax>
+<contextlist><context>server config</context>
+<context>virtual host</context></contextlist>
+<compatibility>Available in httpd 2.4.4 and later, if using OpenSSL 1.0.1 or
+later</compatibility>
+
+<usage>
+<p>
+This directive enables TLS-SRP and sets the path to the OpenSSL SRP (Secure
+Remote Password) verifier file containing TLS-SRP usernames, verifiers, salts,
+and group parameters.</p>
+<example><title>Example</title>
+SSLSRPVerifierFile "/path/to/file.srpv"
+</example>
+<p>
+The verifier file can be created with the <code>openssl</code> command line
+utility:</p>
+<example><title>Creating the SRP verifier file</title>
+openssl srp -srpvfile passwd.srpv -userinfo "some info" -add username
+</example>
+<p> The value given with the optional <code>-userinfo</code> parameter is
+avalable in the <code>SSL_SRP_USERINFO</code> request environment variable.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SSLSRPUnknownUserSeed</name>
+<description>SRP unknown user seed</description>
+<syntax>SSLSRPUnknownUserSeed <em>secret-string</em></syntax>
+<contextlist><context>server config</context>
+<context>virtual host</context></contextlist>
+<compatibility>Available in httpd 2.4.4 and later, if using OpenSSL 1.0.1 or
+later</compatibility>
+
+<usage>
+<p>
+This directive sets the seed used to fake SRP user parameters for unknown
+users, to avoid leaking whether a given user exists. Specify a secret
+string. If this directive is not used, then Apache will return the
+UNKNOWN_PSK_IDENTITY alert to clients who specify an unknown username.
+</p>
+<example><title>Example</title>
+SSLSRPUnknownUserSeed "secret"
+</example>
+</usage>
+</directivesynopsis>
+
<directivesynopsis>
<name>SSLOptions</name>
<description>Configure various SSL engine run-time options</description>
or otherwise.</p>
</section>
+<section id="srp"><title>How do I enable TLS-SRP?</title>
+ <p>TLS-SRP (Secure Remote Password key exchange for TLS, specified in RFC 5054)
+ can supplement or replace certificates in authenticating an SSL connection.
+ To use TLS-SRP, set the
+ <directive module="mod_ssl">SSLSRPVerifierFile</directive> directive to
+ point to an OpenSSL SRP verifier file. To create the verifier file, use the
+ <code>openssl</code> tool:</p>
+ <example>
+ openssl srp -srpvfile passwd.srpv -add username
+ </example>
+ <p>After creating this file, specify it in the SSL server configuration:</p>
+ <example>
+ SSLSRPVerifierFile /path/to/passwd.srpv
+ </example>
+ <p>To force clients to use non-certificate TLS-SRP cipher suites, use the
+ following directive:</p>
+ <example>
+ SSLCipherSuite "!DSS:!aRSA:SRP"
+ </example>
+</section>
+
</section>
<!-- /aboutssl -->
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
*/
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,
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,
#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;
modssl_init_stapling(s, p, ptemp, mctx);
}
#endif
+
+#ifndef OPENSSL_NO_SRP
+ /*
+ * TLS-SRP support
+ */
+ if (mctx->srp_vfile != NULL) {
+ int err;
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02308)
+ "Using SRP verifier file [%s]", mctx->srp_vfile);
+
+ if (!(mctx->srp_vbase = SRP_VBASE_new(mctx->srp_unknown_user_seed))) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02309)
+ "Unable to initialize SRP verifier structure "
+ "[%s seed]",
+ mctx->srp_unknown_user_seed ? "with" : "without");
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ ssl_die(s);
+ }
+
+ err = SRP_VBASE_init(mctx->srp_vbase, mctx->srp_vfile);
+ if (err != SRP_NO_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02310)
+ "Unable to load SRP verifier file [error %d]", err);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ ssl_die(s);
+ }
+
+ SSL_CTX_set_srp_username_callback(mctx->ssl_ctx,
+ ssl_callback_SRPServerParams);
+ SSL_CTX_set_srp_cb_arg(mctx->ssl_ctx, mctx);
+ }
+#endif
}
#endif
static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx)
{
MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx);
+
+#ifndef OPENSSL_NO_SRP
+ if (mctx->srp_vbase != NULL) {
+ SRP_VBASE_free(mctx->srp_vbase);
+ mctx->srp_vbase = NULL;
+ }
+#endif
}
static void ssl_init_ctx_cleanup_proxy(modssl_ctx_t *mctx)
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.
*
"SSL_SERVER_A_SIG",
"SSL_SESSION_ID",
"SSL_SESSION_RESUMED",
+#ifndef OPENSSL_NO_SRP
+ "SSL_SRP_USER",
+ "SSL_SRP_USERINFO",
+#endif
NULL
};
return 0;
}
-#endif
+#endif /* OPENSSL_NO_TLSEXT */
#ifdef HAVE_TLS_SESSION_TICKETS
/*
/* OpenSSL is not expected to call us with modes other than 1 or 0 */
return -1;
}
-#endif
+#endif /* HAVE_TLS_SESSION_TICKETS */
+
+#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 */
#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;
}
#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"
const char *stapling_force_url;
#endif
+#ifndef OPENSSL_NO_SRP
+ char *srp_vfile;
+ char *srp_unknown_user_seed;
+ SRP_VBASE *srp_vbase;
+#endif
+
modssl_auth_ctx_t auth;
BOOL ocsp_enabled; /* true if OCSP verification enabled */
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 */
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 *);