Skip to content

Commit 8f6a2a1

Browse files
committed
After some productive feedback and no negative feedback, introduce SSLEngine upgrade so that we can begin and continue to support these facilities. This makes it simpler to keep this effort (while we have no known clients that support Connection: upgrade at this time), and begin refactoring more of SSL into smaller and tighter (and then optional) components. Submitted by: Ryan Bloom Reviewed by: William Rowe, Joe Orton git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97912 13f79535-47bb-0310-9956-ffa450edef68
1 parent 3200e5b commit 8f6a2a1

6 files changed

Lines changed: 129 additions & 8 deletions

File tree

modules/ssl/mod_ssl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ const char *ssl_cmd_SSLMutex(cmd_parms *, void *, const char *);
541541
const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, void *, const char *);
542542
const char *ssl_cmd_SSLCryptoDevice(cmd_parms *, void *, const char *);
543543
const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
544-
const char *ssl_cmd_SSLEngine(cmd_parms *, void *, int);
544+
const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *);
545545
const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *);
546546
const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *);
547547
const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *);
@@ -588,6 +588,7 @@ int ssl_hook_UserCheck(request_rec *);
588588
int ssl_hook_Access(request_rec *);
589589
int ssl_hook_Fixup(request_rec *);
590590
int ssl_hook_ReadReq(request_rec *);
591+
int ssl_hook_Upgrade(request_rec *);
591592

592593
/* OpenSSL callbacks */
593594
RSA *ssl_callback_TmpRSA(SSL *, int, int);
@@ -709,6 +710,8 @@ ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *);
709710
char *ssl_util_algotypestr(ssl_algo_t);
710711
char *ssl_util_ptxtsub(apr_pool_t *, const char *, const char *, char *);
711712
void ssl_util_thread_setup(apr_pool_t *);
713+
int ssl_init_ssl_connection(conn_rec *c);
714+
712715

713716
#define APR_SHM_MAXSIZE (64 * 1024 * 1024)
714717
#endif /* __MOD_SSL_H__ */

modules/ssl/ssl_engine_config.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ static SSLSrvConfigRec *ssl_config_server_new(apr_pool_t *p)
205205
SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
206206

207207
sc->mc = NULL;
208-
sc->enabled = UNSET;
208+
sc->enabled = FALSE;
209209
sc->proxy_enabled = UNSET;
210210
sc->vhost_id = NULL; /* set during module init */
211211
sc->vhost_id_len = 0; /* set during module init */
@@ -581,13 +581,24 @@ const char *ssl_cmd_SSLRandomSeed(cmd_parms *cmd,
581581
return NULL;
582582
}
583583

584-
const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, int flag)
584+
const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg)
585585
{
586586
SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
587587

588-
sc->enabled = flag ? TRUE : FALSE;
589-
588+
if (!strcasecmp(arg, "On")) {
589+
sc->enabled = TRUE;
590590
return NULL;
591+
}
592+
else if (!strcasecmp(arg, "Off")) {
593+
sc->enabled = FALSE;
594+
return NULL;
595+
}
596+
else if (!strcasecmp(arg, "Optional")) {
597+
sc->enabled = UNSET;
598+
return NULL;
599+
}
600+
601+
return "Argument must be On, Off, or Optional";
591602
}
592603

593604
const char *ssl_cmd_SSLCipherSuite(cmd_parms *cmd,

modules/ssl/ssl_engine_init.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,13 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
247247
sc->vhost_id = ssl_util_vhostid(p, s);
248248
sc->vhost_id_len = strlen(sc->vhost_id);
249249

250+
#if 0
251+
/* If sc->enabled is UNSET, then SSL is optional on this vhost */
250252
/* Fix up stuff that may not have been set */
251253
if (sc->enabled == UNSET) {
252254
sc->enabled = FALSE;
253255
}
254-
256+
#endif
255257
if (sc->proxy_enabled == UNSET) {
256258
sc->proxy_enabled = FALSE;
257259
}
@@ -982,6 +984,9 @@ void ssl_init_ConfigureServer(server_rec *s,
982984
apr_pool_t *ptemp,
983985
SSLSrvConfigRec *sc)
984986
{
987+
/* A bit of a hack, but initialize the server if SSL is optional or
988+
* not.
989+
*/
985990
if (sc->enabled) {
986991
ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
987992
"Configuring server for SSL protocol");
@@ -1010,7 +1015,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
10101015
for (s = base_server; s; s = s->next) {
10111016
sc = mySrvConfig(s);
10121017

1013-
if (sc->enabled && (s->port == DEFAULT_HTTP_PORT)) {
1018+
if ((sc->enabled == TRUE) && (s->port == DEFAULT_HTTP_PORT)) {
10141019
ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
10151020
base_server,
10161021
"Init: (%s) You configured HTTPS(%d) "

modules/ssl/ssl_engine_io.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,89 @@ static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx)
11811181
return APR_SUCCESS;
11821182
}
11831183

1184+
static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
1185+
apr_bucket_brigade *bb)
1186+
1187+
{
1188+
#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
1189+
#define UPGRADE_HEADER "Upgrade: TLS/1.0 HTTP/1.1"
1190+
#define CONNECTION_HEADER "Connection: Upgrade"
1191+
const char *upgrade;
1192+
const char *connection;
1193+
apr_bucket_brigade *upgradebb;
1194+
request_rec *r = f->r;
1195+
SSLConnRec *sslconn;
1196+
SSL *ssl;
1197+
1198+
/* Just remove the filter, if it doesn't work the first time, it won't
1199+
* work at all for this request.
1200+
*/
1201+
ap_remove_output_filter(f);
1202+
1203+
/* No need to ensure that this is a server with optional SSL, the filter
1204+
* is only inserted if that is true.
1205+
*/
1206+
1207+
upgrade = apr_table_get(r->headers_in, "Upgrade");
1208+
if (upgrade == NULL) {
1209+
return ap_pass_brigade(f->next, bb);
1210+
}
1211+
connection = apr_table_get(r->headers_in, "Connection");
1212+
1213+
apr_table_unset(r->headers_out, "Upgrade");
1214+
1215+
/* XXX: I don't think the requirement that the client sends exactly
1216+
* "Connection: Upgrade" is correct; the only requirement here is
1217+
* on the client to send a Connection header including the "upgrade"
1218+
* token.
1219+
*/
1220+
if (strcmp(connection, "Upgrade") || strcmp(upgrade, "TLS/1.0")) {
1221+
return ap_pass_brigade(f->next, bb);
1222+
}
1223+
1224+
if (r->method_number == M_OPTIONS) {
1225+
apr_bucket *b = NULL;
1226+
/* This is a mandatory SSL upgrade. */
1227+
1228+
upgradebb = apr_brigade_create(r->pool, f->c->bucket_alloc);
1229+
1230+
ap_fputstrs(f->next, upgradebb, SWITCH_STATUS_LINE, CRLF,
1231+
UPGRADE_HEADER, CRLF, CONNECTION_HEADER, CRLF, CRLF, NULL);
1232+
1233+
b = apr_bucket_flush_create(f->c->bucket_alloc);
1234+
APR_BRIGADE_INSERT_TAIL(upgradebb, b);
1235+
1236+
ap_pass_brigade(f->next, upgradebb);
1237+
}
1238+
else {
1239+
/* This is optional, and should be configurable, for now don't bother
1240+
* doing anything.
1241+
*/
1242+
return ap_pass_brigade(f->next, bb);
1243+
}
1244+
1245+
ssl_init_ssl_connection(f->c);
1246+
1247+
ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
1248+
"Awaiting re-negotiation handshake");
1249+
1250+
sslconn = myConnConfig(f->c);
1251+
ssl = sslconn->ssl;
1252+
1253+
SSL_set_state(ssl, SSL_ST_ACCEPT);
1254+
SSL_do_handshake(ssl);
1255+
1256+
if (SSL_get_state(ssl) != SSL_ST_OK) {
1257+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
1258+
"Re-negotiation handshake failed: "
1259+
"Not accepted by client!?");
1260+
1261+
return AP_FILTER_ERROR;
1262+
}
1263+
1264+
return OK;
1265+
}
1266+
11841267
static apr_status_t ssl_io_filter_input(ap_filter_t *f,
11851268
apr_bucket_brigade *bb,
11861269
ap_input_mode_t mode,
@@ -1393,6 +1476,11 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl)
13931476

13941477
void ssl_io_filter_register(apr_pool_t *p)
13951478
{
1479+
/* This filter MUST be after the HTTP_HEADER filter, but it also must be
1480+
* a resource-level filter so it has the request_rec.
1481+
*/
1482+
ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
1483+
13961484
ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5);
13971485
ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
13981486
return;

modules/ssl/ssl_engine_kernel.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,16 @@ int ssl_hook_Access(request_rec *r)
223223
* Support for SSLRequireSSL directive
224224
*/
225225
if (dc->bSSLRequired && !ssl) {
226+
if (sc->enabled == UNSET) {
227+
/* This vhost was configured for optional SSL, just tell the
228+
* client that we need to upgrade.
229+
*/
230+
apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
231+
apr_table_setn(r->err_headers_out, "Connection", "Upgrade");
232+
233+
return HTTP_UPGRADE_REQUIRED;
234+
}
235+
226236
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
227237
"access to %s failed, reason: %s",
228238
r->filename, "SSL connection required");
@@ -1014,6 +1024,10 @@ int ssl_hook_Fixup(request_rec *r)
10141024
SSL *ssl;
10151025
int i;
10161026

1027+
if (sc->enabled == UNSET) {
1028+
apr_table_setn(r->headers_out, "Upgrade", "TLS/1.0, HTTP/1.1");
1029+
}
1030+
10171031
/*
10181032
* Check to see if SSL is on
10191033
*/

modules/ssl/ssl_util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ char *ssl_util_vhostid(apr_pool_t *p, server_rec *s)
8484
port = s->port;
8585
else {
8686
sc = mySrvConfig(s);
87-
if (sc->enabled)
87+
if (sc->enabled == TRUE)
8888
port = DEFAULT_HTTPS_PORT;
8989
else
9090
port = DEFAULT_HTTP_PORT;

0 commit comments

Comments
 (0)