|
28 | 28 | -- Unknown */ |
29 | 29 | #include "ssl_private.h" |
30 | 30 |
|
| 31 | +#include <apr_md5.h> |
| 32 | + |
31 | 33 | #include "mpm_common.h" |
32 | 34 | #include "mod_md.h" |
33 | 35 |
|
@@ -186,6 +188,110 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf, |
186 | 188 | modver, AP_SERVER_BASEVERSION, incver); |
187 | 189 | } |
188 | 190 |
|
| 191 | +#ifdef HAVE_TLSEXT |
| 192 | +/* Helper functions to create the SNI vhost policy hash. The policy |
| 193 | + * hash captures the configuration elements relevant to the mode |
| 194 | + * selected at runtime by SSLVHostSNIPolicy. */ |
| 195 | + |
| 196 | +#define md5_str_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); apr_md5_update(ctx_, str_, strlen(str_)); } while (0) |
| 197 | +#define md5_ifstr_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); if (str_) apr_md5_update(ctx_, str_, strlen(str_)); } while (0) |
| 198 | +#define md5_fmt_update(ctx_, fmt_, i_) do { char s_[128]; apr_snprintf(s_, sizeof s_, fmt_, i_); \ |
| 199 | + apr_md5_update(ctx_, s_, strlen(s_)); } while (0) |
| 200 | + |
| 201 | +static int md5_strarray_cmp(const void *p1, const void *p2) |
| 202 | +{ |
| 203 | + return strcmp(*(char **)p1, *(char **)p2); |
| 204 | +} |
| 205 | + |
| 206 | +/* Hashes an array of strings in sorted order. */ |
| 207 | +static void md5_strarray_hash(apr_pool_t *ptemp, apr_md5_ctx_t *hash, |
| 208 | + const char *pfx, apr_array_header_t *s) |
| 209 | +{ |
| 210 | + char **elts = apr_pmemdup(ptemp, s->elts, s->nelts * sizeof *elts); |
| 211 | + int i; |
| 212 | + |
| 213 | + qsort(elts, s->nelts, sizeof(char *), md5_strarray_cmp); |
| 214 | + |
| 215 | + apr_md5_update(hash, pfx, strlen(pfx)); |
| 216 | + for (i = 0; i < s->nelts; i++) { |
| 217 | + md5_str_update(hash, "elm:", elts[i]); |
| 218 | + } |
| 219 | +} |
| 220 | + |
| 221 | +static void hash_sni_policy_pk(apr_pool_t *ptemp, apr_md5_ctx_t *hash, modssl_ctx_t *ctx) |
| 222 | +{ |
| 223 | + md5_fmt_update(hash, "protocol:%d", ctx->protocol); |
| 224 | + |
| 225 | + md5_ifstr_update(hash, "ciphers:", ctx->auth.cipher_suite); |
| 226 | + md5_ifstr_update(hash, "tls13_ciphers:", ctx->auth.tls13_ciphers); |
| 227 | + |
| 228 | + md5_strarray_hash(ptemp, hash, "cert_files:", ctx->pks->cert_files); |
| 229 | + md5_strarray_hash(ptemp, hash, "key_files:", ctx->pks->key_files); |
| 230 | +} |
| 231 | + |
| 232 | +static void hash_sni_policy_auth(apr_md5_ctx_t *hash, modssl_ctx_t *ctx) |
| 233 | +{ |
| 234 | + modssl_pk_server_t *pks = ctx->pks; |
| 235 | + modssl_auth_ctx_t *a = &ctx->auth; |
| 236 | + |
| 237 | + md5_fmt_update(hash, "verify_depth:%d", a->verify_depth); |
| 238 | + md5_fmt_update(hash, "verify_mode:%d", a->verify_mode); |
| 239 | + |
| 240 | + md5_ifstr_update(hash, "ca_name_path:", pks->ca_name_path); |
| 241 | + md5_ifstr_update(hash, "ca_name_file:", pks->ca_name_file); |
| 242 | + md5_ifstr_update(hash, "ca_cert_path:", a->ca_cert_path); |
| 243 | + md5_ifstr_update(hash, "ca_cert_file:", a->ca_cert_file); |
| 244 | + md5_ifstr_update(hash, "crl_path:", ctx->crl_path); |
| 245 | + md5_ifstr_update(hash, "crl_file:", ctx->crl_file); |
| 246 | + md5_fmt_update(hash, "crl_check_mask:%d", ctx->crl_check_mask); |
| 247 | + md5_fmt_update(hash, "ocsp_mask:%d", ctx->ocsp_mask); |
| 248 | + md5_fmt_update(hash, "ocsp_force_default:%d", ctx->ocsp_force_default); |
| 249 | + md5_ifstr_update(hash, "ocsp_responder:", ctx->ocsp_responder); |
| 250 | + |
| 251 | +#ifdef HAVE_SRP |
| 252 | + md5_ifstr_update(hash, "srp_vfile:", ctx->srp_vfile); |
| 253 | +#endif |
| 254 | + |
| 255 | +#ifdef HAVE_SSL_CONF_CMD |
| 256 | + { |
| 257 | + apr_array_header_t *parms = ctx->ssl_ctx_param; |
| 258 | + int n; |
| 259 | + |
| 260 | + for (n = 0; n < parms->nelts; n++) { |
| 261 | + ssl_ctx_param_t *p = &APR_ARRAY_IDX(parms, n, ssl_ctx_param_t); |
| 262 | + |
| 263 | + md5_str_update(hash, "param:", p->name); |
| 264 | + md5_str_update(hash, "value:", p->value); |
| 265 | + } |
| 266 | + } |
| 267 | +#endif |
| 268 | +} |
| 269 | +#endif |
| 270 | + |
| 271 | +static char *create_sni_policy_hash(apr_pool_t *p, apr_pool_t *ptemp, |
| 272 | + modssl_snivhpolicy_t policy, |
| 273 | + SSLSrvConfigRec *sc) |
| 274 | +{ |
| 275 | + char *rv = NULL; |
| 276 | +#ifdef HAVE_TLSEXT |
| 277 | + if (policy != MODSSL_SNIVH_STRICT && policy != MODSSL_SNIVH_INSECURE) { |
| 278 | + apr_md5_ctx_t hash; |
| 279 | + unsigned char digest[APR_MD5_DIGESTSIZE]; |
| 280 | + |
| 281 | + /* Create the vhost policy hash for comparison later. */ |
| 282 | + apr_md5_init(&hash); |
| 283 | + hash_sni_policy_auth(&hash, sc->server); |
| 284 | + if (policy == MODSSL_SNIVH_SECURE) |
| 285 | + hash_sni_policy_pk(ptemp, &hash, sc->server); |
| 286 | + apr_md5_final(digest, &hash); |
| 287 | + |
| 288 | + rv = apr_palloc(p, 2 * APR_MD5_DIGESTSIZE + 1); |
| 289 | + ap_bin2hex(digest, APR_MD5_DIGESTSIZE, rv); /* sets final '\0' */ |
| 290 | + } |
| 291 | +#endif |
| 292 | + return rv; |
| 293 | +} |
| 294 | + |
189 | 295 | /* _________________________________________________________________ |
190 | 296 | ** |
191 | 297 | ** Let other answer special connection attempts. |
@@ -439,6 +545,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, |
439 | 545 | return rv; |
440 | 546 | } |
441 | 547 | } |
| 548 | + |
| 549 | + sc->sni_policy_hash = create_sni_policy_hash(p, ptemp, mc->snivh_policy, sc); |
442 | 550 | } |
443 | 551 |
|
444 | 552 | /* |
|
0 commit comments