@@ -1170,14 +1170,17 @@ static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
11701170
11711171{
11721172#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
1173- #define UPGRADE_HEADER "Upgrade: TLS/1.0 HTTP/1.1"
1173+ #define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
11741174#define CONNECTION_HEADER "Connection: Upgrade"
11751175 const char * upgrade ;
11761176 const char * connection ;
11771177 apr_bucket_brigade * upgradebb ;
11781178 request_rec * r = f -> r ;
11791179 SSLConnRec * sslconn ;
11801180 SSL * ssl ;
1181+ char * token_string ;
1182+ char * token ;
1183+ char * token_state ;
11811184
11821185 /* Just remove the filter, if it doesn't work the first time, it won't
11831186 * work at all for this request.
@@ -1192,19 +1195,30 @@ static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
11921195 if (upgrade == NULL ) {
11931196 return ap_pass_brigade (f -> next , bb );
11941197 }
1195- connection = apr_table_get (r -> headers_in , "Connection" );
1198+ token_string = apr_pstrdup (r -> pool ,upgrade );
1199+ token = apr_strtok (token_string ,", " ,& token_state );
1200+ while (token && strcmp (token ,"TLS/1.0" )) {
1201+ apr_strtok (NULL ,", " ,& token_state );
1202+ }
1203+ /* "Upgrade: TLS/1.0" header not found, don't do Upgrade */
1204+ if (!token ) {
1205+ return ap_pass_brigade (f -> next , bb );
1206+ }
11961207
1197- apr_table_unset (r -> headers_out , "Upgrade " );
1208+ connection = apr_table_get (r -> headers_in , "Connection " );
11981209
1199- /* XXX: I don't think the requirement that the client sends exactly
1200- * "Connection: Upgrade" is correct; the only requirement here is
1201- * on the client to send a Connection header including the "upgrade"
1202- * token.
1203- */
1204- if (strcmp (connection , "Upgrade" ) || strcmp (upgrade , "TLS/1.0" )) {
1210+ token_string = apr_pstrdup (r -> pool ,connection );
1211+ token = apr_strtok (token_string ,"," ,& token_state );
1212+ while (token && strcmp (token ,"Upgrade" )) {
1213+ apr_strtok (NULL ,"," ,& token_state );
1214+ }
1215+ /* "Connection: Upgrade" header not found, don't do Upgrade */
1216+ if (!token ) {
12051217 return ap_pass_brigade (f -> next , bb );
12061218 }
12071219
1220+ apr_table_unset (r -> headers_out , "Upgrade" );
1221+
12081222 if (r -> method_number == M_OPTIONS ) {
12091223 apr_bucket * b = NULL ;
12101224 /* This is a mandatory SSL upgrade. */
@@ -1238,18 +1252,22 @@ static apr_status_t ssl_io_filter_Upgrade(ap_filter_t *f,
12381252 * However, this causes failures in perl-framework currently,
12391253 * perhaps pre-test if we have already negotiated?
12401254 */
1241- SSL_set_state (ssl , SSL_ST_ACCEPT );
1255+ SSL_set_accept_state (ssl );
12421256 SSL_do_handshake (ssl );
12431257
12441258 if (SSL_get_state (ssl ) != SSL_ST_OK ) {
12451259 ap_log_error (APLOG_MARK , APLOG_ERR , 0 , r -> server ,
1246- "Re-negotiation handshake failed: "
1260+ "TLS Upgrade handshake failed: "
12471261 "Not accepted by client!?" );
12481262
12491263 return AP_FILTER_ERROR ;
12501264 }
12511265
1252- return OK ;
1266+ /* Now that we have initialized the ssl connection which added the ssl_io_filter,
1267+ pass the brigade off to the connection based output filters so that the
1268+ request can complete encrypted */
1269+ return ap_pass_brigade (f -> c -> output_filters , bb );
1270+
12531271}
12541272
12551273static apr_status_t ssl_io_filter_input (ap_filter_t * f ,
0 commit comments