View | Details | Raw Unified | Return to bug 52210
Collapse All | Expand All

(-)gen/httpd-2.4.x/modules/ssl/mod_ssl.c (+38 lines)
Lines 273-278 Link Here
273
		"OpenSSL configuration command")
270
		"OpenSSL configuration command")
274
#endif
271
#endif
275
272
273
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
274
    SSL_CMD_SRV(AlpnPreference, ITERATE,
275
                "Preference in Application-Layer Protocol Negotiation (ALPN), "
276
                "protocols are chosed in the specified order")
277
#endif
278
    
276
    /* Deprecated directives. */
279
    /* Deprecated directives. */
277
    AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
280
    AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
278
      "SSLLog directive is no longer supported - use ErrorLog."),
281
      "SSLLog directive is no longer supported - use ErrorLog."),
Lines 423-428 Link Here
423
    return 1;
423
    return 1;
424
}
424
}
425
425
426
static int modssl_register_alpn(conn_rec *c,
427
                               ssl_alpn_propose_protos advertisefn,
428
                               ssl_alpn_proto_negotiated negotiatedfn)
429
{
430
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
431
	SSLConnRec *sslconn = myConnConfig(c);
432
	
433
	if (!sslconn) {
434
		return DECLINED;
435
	}
436
	
437
	if (!sslconn->alpn_proposefns) {
438
		sslconn->alpn_proposefns =
439
		apr_array_make(c->pool, 5, sizeof(ssl_alpn_propose_protos));
440
		sslconn->alpn_negofns =
441
		apr_array_make(c->pool, 5, sizeof(ssl_alpn_proto_negotiated));
442
	}
443
	
444
	if (advertisefn)
445
		APR_ARRAY_PUSH(sslconn->alpn_proposefns, ssl_alpn_propose_protos) =
446
			advertisefn;
447
	if (negotiatedfn)
448
		APR_ARRAY_PUSH(sslconn->alpn_negofns, ssl_alpn_proto_negotiated) =
449
			negotiatedfn;
450
	
451
	return OK;
452
#else
453
    return DECLINED;
454
#endif
455
}
456
426
int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
457
int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
427
{
458
{
428
    SSLSrvConfigRec *sc;
459
    SSLSrvConfigRec *sc;
Lines 585-590 Link Here
585
616
586
    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
617
    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
587
    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
618
    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
619
    APR_REGISTER_OPTIONAL_FN(modssl_register_alpn);
588
620
589
    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
621
    ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
590
                              AUTHZ_PROVIDER_VERSION,
622
                              AUTHZ_PROVIDER_VERSION,
(-)gen/httpd-2.4.x/modules/ssl/mod_ssl.h (+41 lines)
Lines 63-67 Link Here
63
63
64
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
64
APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
65
65
66
/** The alpn_propose_proto callback allows other modules to propose
67
 * the name of the protocol that will be chosen during the
68
 * Application-Layer Protocol Negotiation (ALPN) portion of the SSL handshake.
69
 * The callback is given the connection and a list of NULL-terminated
70
 * protocol strings as supported by the client.  If this client_protos is 
71
 * non-empty, it must pick its preferred protocol from that list. Otherwise
72
 * it should add its supported protocols in order of precedence.
73
 * The callback should not yet modify the connection or install any filters
74
 * as its proposal(s) may be overridden by another callback or server 
75
 * configuration. 
76
 * It should return OK or, to prevent further processing of (other modules') 
77
 * callbacks, return DONE.
78
 */
79
typedef int (*ssl_alpn_propose_protos)(conn_rec *connection,
80
									apr_array_header_t *client_protos,
81
									apr_array_header_t *proposed_protos);
82
83
/** The alpn_proto_negotiated callback allows other modules to discover
84
 * the name of the protocol that was chosen during the Application-Layer
85
 * Protocol Negotiation (ALPN) portion of the SSL handshake.  
86
 * The callback is given the connection, a
87
 * non-NUL-terminated string containing the protocol name, and the
88
 * length of the string; it should do something appropriate
89
 * (i.e. insert or remove filters) and return OK. To prevent further
90
 * processing of (other modules') callbacks, return DONE. */
91
typedef int (*ssl_alpn_proto_negotiated)(conn_rec *connection,
92
                                        const char *proto_name,
93
                                        apr_size_t proto_name_len);
94
95
/* An optional function which can be used to register a pair of callbacks 
96
 * for ALPN handling.
97
 * This optional function should be invoked from a pre_connection hook 
98
 * which runs *after* mod_ssl.c's pre_connection hook.  The function returns 
99
 * OK if the callbacks are registered, or DECLINED otherwise (for example if 
100
 * mod_ssl does not support ALPN).
101
 */
102
APR_DECLARE_OPTIONAL_FN(int, modssl_register_alpn,
103
						(conn_rec *conn,
104
						 ssl_alpn_propose_protos proposefn,
105
						 ssl_alpn_proto_negotiated negotiatedfn));
106
66
#endif /* __MOD_SSL_H__ */
107
#endif /* __MOD_SSL_H__ */
67
/** @} */
108
/** @} */
(-)gen/httpd-2.4.x/modules/ssl/ssl_engine_config.c (+16 lines)
Lines 159-164 Link Here
159
    SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
159
    SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
160
    mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
160
    mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
161
#endif
161
#endif
162
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
163
    mctx->ssl_alpn_pref = apr_array_make(p, 5, sizeof(const char *));
164
#endif
162
}
165
}
163
166
164
static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
167
static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
Lines 298-303 Link Here
298
#ifdef HAVE_SSL_CONF_CMD
300
#ifdef HAVE_SSL_CONF_CMD
299
    cfgMergeArray(ssl_ctx_param);
301
    cfgMergeArray(ssl_ctx_param);
300
#endif
302
#endif
303
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
304
    cfgMergeArray(ssl_alpn_pref);
305
#endif
301
}
306
}
302
307
303
static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
308
static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
Lines 1868-1873 Link Here
1868
    return NULL;
1861
    return NULL;
1869
}
1862
}
1870
#endif
1863
#endif
1864
1865
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
1866
const char *ssl_cmd_SSLAlpnPreference(cmd_parms *cmd, void *dcfg,
1867
                                      const char *protocol)
1868
{
1869
    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
1870
    APR_ARRAY_PUSH(sc->server->ssl_alpn_pref, const char *) = protocol;
1871
    return NULL;
1872
}
1873
#endif
1871
1874
1872
#ifdef HAVE_SRP
1875
#ifdef HAVE_SRP
1873
1876
(-)gen/httpd-2.4.x/modules/ssl/ssl_engine_init.c (+8 lines)
Lines 623-628 Link Here
623
    SSL_CTX_set_tmp_dh_callback(ctx,  ssl_callback_TmpDH);
613
    SSL_CTX_set_tmp_dh_callback(ctx,  ssl_callback_TmpDH);
624
614
625
    SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
615
    SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
616
617
#if defined(HAVE_TLS_ALPN)
618
	SSL_CTX_set_alpn_select_cb(
619
	   ctx, ssl_callback_alpn_select, NULL);
620
#elif defined(HAVE_TLS_NPN)
621
    SSL_CTX_set_next_protos_advertised_cb(
622
        ctx, ssl_callback_AdvertiseNextProtos, NULL);
623
#endif
626
}
624
}
627
625
628
static apr_status_t ssl_init_ctx_verify(server_rec *s,
626
static apr_status_t ssl_init_ctx_verify(server_rec *s,
(-)gen/httpd-2.4.x/modules/ssl/ssl_engine_io.c (+40 lines)
Lines 28-33 Link Here
28
                                  core keeps dumping.''
28
                                  core keeps dumping.''
29
                                            -- Unknown    */
29
                                            -- Unknown    */
30
#include "ssl_private.h"
30
#include "ssl_private.h"
31
#include "mod_ssl.h"
31
#include "apr_date.h"
32
#include "apr_date.h"
32
33
33
/*  _________________________________________________________________
34
/*  _________________________________________________________________
Lines 297-302 Link Here
297
    apr_pool_t *pool;
298
    apr_pool_t *pool;
298
    char buffer[AP_IOBUFSIZE];
299
    char buffer[AP_IOBUFSIZE];
299
    ssl_filter_ctx_t *filter_ctx;
300
    ssl_filter_ctx_t *filter_ctx;
301
    int alpn_finished;  /* 1 if ALPN has finished, 0 otherwise */
300
} bio_filter_in_ctx_t;
302
} bio_filter_in_ctx_t;
301
303
302
/*
304
/*
Lines 1412-1417 Link Here
1412
        APR_BRIGADE_INSERT_TAIL(bb, bucket);
1414
        APR_BRIGADE_INSERT_TAIL(bb, bucket);
1413
    }
1415
    }
1414
1416
1417
#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
1418
	/* By this point, Application-Layer Protocol Negotiation (ALPN) should be 
1419
	 * completed (if our version of OpenSSL supports it). If we haven't already, 
1420
	 * find out which protocol was decided upon and inform other modules 
1421
	 * by calling alpn_proto_negotiated_hook. 
1422
	 */
1423
	if (!inctx->alpn_finished) {
1424
		SSLConnRec *sslconn = myConnConfig(f->c);
1425
		const unsigned char *next_proto = NULL;
1426
		unsigned next_proto_len = 0;
1427
		int n;
1428
		
1429
		if (sslconn->alpn_negofns) {
1430
	#ifdef HAVE_TLS_ALPN
1431
			SSL_get0_alpn_selected(inctx->ssl, &next_proto, &next_proto_len);
1432
			ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
1433
						  APLOGNO(02306) "SSL ALPN negotiated protocol: '%*s'",
1434
						  next_proto_len, (const char*)next_proto);
1435
	#else
1436
			SSL_get0_next_proto_negotiated(
1437
										   inctx->ssl, &next_proto, &next_proto_len);
1438
			ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
1439
						  APLOGNO(02306) "SSL NPN negotiated protocol: '%*s'",
1440
						  next_proto_len, (const char*)next_proto);
1441
	#endif
1442
			for (n = 0; n < sslconn->alpn_negofns->nelts; n++) {
1443
				ssl_alpn_proto_negotiated fn =
1444
				APR_ARRAY_IDX(sslconn->alpn_negofns, n, ssl_alpn_proto_negotiated);
1445
				
1446
				if (fn(f->c, (const char *)next_proto, next_proto_len) == DONE)
1447
				break;
1448
			}
1449
		}
1450
		inctx->alpn_finished = 1;
1451
	}
1452
#endif
1453
1415
    return APR_SUCCESS;
1454
    return APR_SUCCESS;
1416
}
1455
}
1417
1456
Lines 1893-1898 Link Here
1893
    inctx->block = APR_BLOCK_READ;
1932
    inctx->block = APR_BLOCK_READ;
1894
    inctx->pool = c->pool;
1933
    inctx->pool = c->pool;
1895
    inctx->filter_ctx = filter_ctx;
1934
    inctx->filter_ctx = filter_ctx;
1935
    inctx->alpn_finished = 0;
1896
}
1936
}
1897
1937
1898
/* The request_rec pointer is passed in here only to ensure that the
1938
/* The request_rec pointer is passed in here only to ensure that the
(-)gen/httpd-2.4.x/modules/ssl/ssl_engine_kernel.c (+265 lines)
Lines 29-34 Link Here
29
                                  time I was too famous.''
29
                                  time I was too famous.''
30
                                            -- Unknown                */
30
                                            -- Unknown                */
31
#include "ssl_private.h"
31
#include "ssl_private.h"
32
#include "mod_ssl.h"
32
#include "util_md5.h"
33
#include "util_md5.h"
33
34
34
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
35
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
Lines 2136-2141 Link Here
2136
}
2131
}
2137
#endif /* HAVE_TLS_SESSION_TICKETS */
2132
#endif /* HAVE_TLS_SESSION_TICKETS */
2138
2133
2134
static int ssl_array_index(apr_array_header_t *array,
2135
                           const unsigned char *s)
2136
{
2137
    int i;
2138
    for (i = 0; i < array->nelts; i++) {
2139
        const unsigned char *p = APR_ARRAY_IDX(array, i, const unsigned char*);
2140
        if (!strcmp((const char *)p, (const char *)s)) {
2141
            return i;
2142
        }
2143
    }
2144
    return -1;
2145
}
2146
2147
#ifdef HAVE_TLS_ALPN
2148
/*
2149
 * Compare to ALPN protocol proposal. Result is similar to strcmp():
2150
 * 0 gives same precedence, >0 means proto1 is prefered.
2151
 */
2152
static int ssl_cmp_alpn_protos(modssl_ctx_t *ctx,
2153
							   const unsigned char *proto1,
2154
							   const unsigned char *proto2)
2155
{
2156
	/* TODO: we should have a mod_ssl configuration parameter. */
2157
    if (ctx && ctx->ssl_alpn_pref) {
2158
        int index1 = ssl_array_index(ctx->ssl_alpn_pref, proto1);
2159
        int index2 = ssl_array_index(ctx->ssl_alpn_pref, proto2);
2160
        if (index2 > index1) {
2161
            return (index1 >= 0)? 1 : -1;
2162
        }
2163
        else if (index1 > index2) {
2164
            return (index2 >= 0)? -1 : 1;
2165
        }
2166
    }
2167
    /* both have the same index (mabye -1 or no pref configured) and we compare
2168
     * the names so that spdy3 gets precedence over spdy2. That makes
2169
     * the outcome at least deterministic. */
2170
	return strcmp((const char *)proto1, (const char *)proto2);
2171
}
2172
2173
/*
2174
 * This callback function is executed when the TLS Application Layer
2175
 * Protocol Negotiate Extension (ALPN, RFC 7301) is triggered by the client 
2176
 * hello, giving a list of desired protocol names (in descending preference) 
2177
 * to the server.
2178
 * The callback has to select a protocol name or return an error if none of
2179
 * the clients preferences is supported. 
2180
 * The selected protocol does not have to be on the client list, according
2181
 * to RFC 7301, so no checks are performed.
2182
 * The client protocol list is serialized as length byte followed by ascii
2183
 * characters (not null-terminated), followed by the next protocol name.
2184
 */
2185
int ssl_callback_alpn_select(SSL *ssl,
2186
							 const unsigned char **out, unsigned char *outlen,
2187
							 const unsigned char *in, unsigned int inlen, void *arg)
2188
{
2189
	conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
2190
	SSLConnRec *sslconn = myConnConfig(c);
2191
    server_rec *s       = mySrvFromConn(c);
2192
    SSLSrvConfigRec *sc = mySrvConfig(s);
2193
    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
2194
	const unsigned char *alpn_http1 = (const unsigned char*)"http/1.1";
2195
	apr_array_header_t *client_protos;
2196
	apr_array_header_t *proposed_protos;
2197
	int i;
2198
2199
	/* If the connection object is not available,
2200
	 * then there's nothing for us to do. */
2201
	if (c == NULL) {
2202
		return SSL_TLSEXT_ERR_OK;
2203
	}
2204
	
2205
	if (inlen == 0) {
2206
		// someone tries to trick us?
2207
		ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02306)
2208
					  "alpn client protocol list empty");
2209
		return SSL_TLSEXT_ERR_ALERT_FATAL;
2210
	}
2211
	
2212
	client_protos = apr_array_make(c->pool, 0, sizeof(char *));
2213
	for (i = 0; i < inlen; /**/) {
2214
		unsigned int plen = in[i++];
2215
		if (plen + i > inlen) {
2216
			// someone tries to trick us?
2217
			ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02306)
2218
						  "alpn protocol identier too long");
2219
			return SSL_TLSEXT_ERR_ALERT_FATAL;
2220
		}
2221
		APR_ARRAY_PUSH(client_protos, char*) =
2222
			apr_pstrndup(c->pool, (const char *)in+i, plen);
2223
		i += plen;
2224
	}
2225
	
2226
	/* Regardless of installed hooks, the http/1.1 protocol is always
2227
	 * supported by us. Add it to the proposals if the client also
2228
	 * offers it. */
2229
	proposed_protos = apr_array_make(c->pool, client_protos->nelts+1,
2230
									 sizeof(char *));
2231
	if (ssl_array_index(client_protos, alpn_http1) >= 0) {
2232
		APR_ARRAY_PUSH(proposed_protos, const unsigned char*) = alpn_http1;
2233
	}
2234
	
2235
	if (sslconn->alpn_proposefns != NULL) {
2236
		/* Invoke our alpn_propos_proto hooks, giving other modules a chance to
2237
		 * propose protocol names for selection. We might have several such
2238
		 * hooks installed and if two make a proposal, we need to give 
2239
		 * preference to one.
2240
		 */
2241
		for (i = 0; i < sslconn->alpn_proposefns->nelts; i++) {
2242
			ssl_alpn_propose_protos fn =
2243
				APR_ARRAY_IDX(sslconn->alpn_proposefns, i,
2244
							  ssl_alpn_propose_protos);
2245
			
2246
			if (fn(c, client_protos, proposed_protos) == DONE)
2247
				break;
2248
		}
2249
	}
2250
2251
	if (proposed_protos->nelts <= 0) {
2252
		ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02306)
2253
					  "none of the client alpn protocols are supported");
2254
		return SSL_TLSEXT_ERR_ALERT_FATAL;
2255
	}
2256
	
2257
	/* Now select the most preferred protocol from the proposals. */
2258
	*out = APR_ARRAY_IDX(proposed_protos, 0, const unsigned char *);
2259
	for (i = 1; i < proposed_protos->nelts; ++i) {
2260
		const unsigned char *proto = APR_ARRAY_IDX(proposed_protos, i,
2261
												   const unsigned char*);
2262
		/* Do we prefer it over existing candidate? */
2263
		if (ssl_cmp_alpn_protos(mctx, *out, proto) < 0) {
2264
			*out = proto;
2265
		}
2266
	}
2267
	
2268
	size_t len = strlen((const char*)*out);
2269
	if (len > 255) {
2270
		ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02306)
2271
					  "alpn negotiated protocol name too long");
2272
		return SSL_TLSEXT_ERR_ALERT_FATAL;
2273
	}
2274
	*outlen = (unsigned char)len;
2275
2276
	return SSL_TLSEXT_ERR_OK;
2277
}
2278
2279
#elif defined(HAVE_TLS_NPN)
2280
/*
2281
 * This callback function is executed when SSL needs to decide what protocols
2282
 * to advertise during Next Protocol Negotiation (NPN).  It must produce a
2283
 * string in wire format -- a sequence of length-prefixed strings -- indicating
2284
 * the advertised protocols.  Refer to SSL_CTX_set_next_protos_advertised_cb
2285
 * in OpenSSL for reference.
2286
 */
2287
int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out,
2288
                                     unsigned int *size_out, void *arg)
2289
{
2290
    conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
2291
    SSLConnRec *sslconn = myConnConfig(c);
2292
    server_rec *s       = mySrvFromConn(c);
2293
    SSLSrvConfigRec *sc = mySrvConfig(s);
2294
    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
2295
    apr_array_header_t *protos;
2296
    int num_protos;
2297
    unsigned int size;
2298
    int i, j;
2299
    unsigned char *data;
2300
    unsigned char *start;
2301
2302
    *data_out = NULL;
2303
    *size_out = 0;
2304
2305
    ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02306)
2306
                  "advertisingNextProtos");
2307
2308
    /* If the connection object is not available, or there are no NPN
2309
     * hooks registered, then there's nothing for us to do. */
2310
    if (c == NULL || sslconn->alpn_proposefns == NULL) {
2311
        return SSL_TLSEXT_ERR_OK;
2312
    }
2313
2314
    /* Invoke our alpn_propose_proto hook, giving other modules a chance to
2315
     * add alternate protocol names to advertise. */
2316
    protos = apr_array_make(c->pool, 0, sizeof(char *));
2317
    for (i = 0; i < sslconn->alpn_proposefns->nelts; i++) {
2318
        ssl_alpn_propose_protos fn =
2319
            APR_ARRAY_IDX(sslconn->alpn_proposefns, i, ssl_alpn_propose_protos);
2320
        
2321
        if (fn(c, NULL, protos) == DONE)
2322
            break;
2323
    }
2324
    if (ssl_array_index(ssl_alpn_propose_protos, "http/1.1") < 0) {
2325
		APR_ARRAY_PUSH(ssl_alpn_propose_protos, const unsigned char*) = "http/1.1";
2326
    }
2327
    num_protos = protos->nelts;
2328
2329
    ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(02306)
2330
                  "alpn protos %d to advertise, %d in pref config", num_protos, mctx->ssl_alpn_pref->nelts );
2331
	if (num_protos > 1 && mctx->ssl_alpn_pref && mctx->ssl_alpn_pref->nelts > 0) {
2332
		/* Sort the protocol names according to our configured preferences. */
2333
		int insert_idx = 0;
2334
		for (i = 0; i < mctx->ssl_alpn_pref->nelts; ++i) {
2335
			const char *proto = APR_ARRAY_IDX(mctx->ssl_alpn_pref, i, const char*);
2336
			int idx = ssl_array_index(protos, proto);
2337
			if (idx > insert_idx) {
2338
				/* bubble found protocol up */
2339
				for (j = idx; j > insert_idx; --j) {
2340
       ((const char **)protos->elts)[j] = ((const char **)protos->elts)[j-1];
2341
				}
2342
				((const char **)protos->elts)[insert_idx] = proto;
2343
				++insert_idx;
2344
			}
2345
		}
2346
	}
2347
    
2348
    /* We now have a list of null-terminated strings; we need to concatenate
2349
     * them together into a single string, where each protocol name is prefixed
2350
     * by its length.  First, calculate how long that string will be. */
2351
    size = 0;
2352
    for (i = 0; i < num_protos; ++i) {
2353
        const char *string = APR_ARRAY_IDX(protos, i, const char*);
2354
        unsigned int length = strlen(string);
2355
        /* If the protocol name is too long (the length must fit in one byte),
2356
         * then log an error and skip it. */
2357
        if (length > 255) {
2358
            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02307)
2359
                          "SSL NPN protocol name too long (length=%u): %s",
2360
                          length, string);
2361
            continue;
2362
        }
2363
        /* Leave room for the length prefix (one byte) plus the protocol name
2364
         * itself. */
2365
        size += 1 + length;
2366
    }
2367
2368
    /* If there is nothing to advertise (either because no modules added
2369
     * anything to the protos array, or because all strings added to the array
2370
     * were skipped), then we're done. */
2371
    if (size == 0) {
2372
        return SSL_TLSEXT_ERR_OK;
2373
    }
2374
2375
    /* Now we can build the string.  Copy each protocol name string into the
2376
     * larger string, prefixed by its length. */
2377
    data = apr_palloc(c->pool, size * sizeof(unsigned char));
2378
    start = data;
2379
    for (i = 0; i < num_protos; ++i) {
2380
        const char *string = APR_ARRAY_IDX(protos, i, const char*);
2381
        apr_size_t length = strlen(string);
2382
        if (length > 255)
2383
            continue;
2384
        *start = (unsigned char)length;
2385
        ++start;
2386
        memcpy(start, string, length * sizeof(unsigned char));
2387
        start += length;
2388
    }
2389
2390
    /* Success. */
2391
    *data_out = data;
2392
    *size_out = size;
2393
    return SSL_TLSEXT_ERR_OK;
2394
}
2395
2396
#endif /* HAVE_TLS_NPN */
2397
2139
#ifdef HAVE_SRP
2398
#ifdef HAVE_SRP
2140
2399
2141
int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
2400
int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
(-)gen/httpd-2.4.x/modules/ssl/ssl_private.h (+32 lines)
Lines 176-181 Link Here
176
#endif
169
#endif
177
#endif
170
#endif
178
171
172
/* ALPN Protocol Negotiation */
173
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
174
#define HAVE_TLS_ALPN
175
#endif
176
177
/* Next Protocol Negotiation */
178
#if !defined(OPENSSL_NO_NEXTPROTONEG) && defined(OPENSSL_NPN_NEGOTIATED)
179
#define HAVE_TLS_NPN
180
#endif
181
179
/* Secure Remote Password */
182
/* Secure Remote Password */
180
#if !defined(OPENSSL_NO_SRP) && defined(SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB)
183
#if !defined(OPENSSL_NO_SRP) && defined(SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB)
181
#define HAVE_SRP
184
#define HAVE_SRP
Lines 443-448 Link Here
443
                     * connection */
446
                     * connection */
444
    } reneg_state;
447
    } reneg_state;
445
448
449
#ifdef HAVE_TLS_NPN
450
    /* Poor man's inter-module optional hooks for NPN. */
451
    apr_array_header_t *alpn_proposefns; /* list of ssl_alpn_propose_protos callbacks */
452
    apr_array_header_t *alpn_negofns; /* list of ssl_alpn_proto_negotiated callbacks. */
453
#endif
454
446
    server_rec *server;
455
    server_rec *server;
447
} SSLConnRec;
456
} SSLConnRec;
448
457
Lines 622-627 Link Here
622
    SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
631
    SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
623
    apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
632
    apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
624
#endif
633
#endif
634
  
635
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
636
  apr_array_header_t *ssl_alpn_pref; /* protocol names in order of preference */
637
#endif
625
} modssl_ctx_t;
638
} modssl_ctx_t;
626
639
627
struct SSLSrvConfigRec {
640
struct SSLSrvConfigRec {
Lines 748-753 Link Here
748
const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
759
const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
749
#endif
760
#endif
750
761
762
#if defined(HAVE_ALPN_NPN) || defined(HAVE_TLS_NPN)
763
const char *ssl_cmd_SSLAlpnPreference(cmd_parms *cmd, void *dcfg, const char *protocol);
764
#endif
765
751
#ifdef HAVE_SRP
766
#ifdef HAVE_SRP
752
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
767
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
753
const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
768
const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
Lines 796-801 Link Here
796
                                       EVP_CIPHER_CTX *, HMAC_CTX *, int);
811
                                       EVP_CIPHER_CTX *, HMAC_CTX *, int);
797
#endif
812
#endif
798
813
814
#ifdef HAVE_TLS_ALPN
815
int ssl_callback_alpn_select(SSL *ssl, const unsigned char **out,
816
							 unsigned char *outlen, const unsigned char *in,
817
							 unsigned int inlen, void *arg);
818
#elif defined(HAVE_TLS_NPN)
819
int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg);
820
#endif
821
799
/**  Session Cache Support  */
822
/**  Session Cache Support  */
800
apr_status_t ssl_scache_init(server_rec *, apr_pool_t *);
823
apr_status_t ssl_scache_init(server_rec *, apr_pool_t *);
801
void         ssl_scache_status_register(apr_pool_t *p);
824
void         ssl_scache_status_register(apr_pool_t *p);

Return to bug 52210