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

(-)server/protocol.c (+55 lines)
Lines 985-990 AP_DECLARE(void) ap_get_mime_headers(request_rec * Link Here
985
    apr_brigade_destroy(tmp_bb);
985
    apr_brigade_destroy(tmp_bb);
986
}
986
}
987
987
988
static char *construct_host_header(request_rec *r)
989
{
990
    struct iovec iov[5];
991
    apr_size_t nvec = 0;
992
    int is_v6literal = 0;
993
994
    /*
995
     * We cannot use ap_get_server_name/port here, because we must
996
     * ignore UseCanonicalName/Port.
997
     */
998
    if (ap_strchr_c(r->hostname, ':')) {
999
        is_v6literal = 1;
1000
        iov[nvec].iov_base = "[";
1001
        iov[nvec].iov_len = 1;
1002
        nvec++;
1003
    }
1004
    iov[nvec].iov_base = (void *)r->hostname;
1005
    iov[nvec].iov_len = strlen(r->hostname);
1006
    nvec++;
1007
    if (is_v6literal) {
1008
        iov[nvec].iov_base = "]";
1009
        iov[nvec].iov_len = 1;
1010
        nvec++;
1011
    }
1012
    if (r->parsed_uri.port_str
1013
            && !ap_is_default_port(r->parsed_uri.port, r)) {
1014
        iov[nvec].iov_base = ":";
1015
        iov[nvec].iov_len = 1;
1016
        nvec++;
1017
        iov[nvec].iov_base = r->parsed_uri.port_str;
1018
        iov[nvec].iov_len = strlen(r->parsed_uri.port_str);
1019
        nvec++;
1020
    }
1021
    return apr_pstrcatv(r->pool, iov, nvec, NULL);
1022
}
1023
988
request_rec *ap_read_request(conn_rec *conn)
1024
request_rec *ap_read_request(conn_rec *conn)
989
{
1025
{
990
    request_rec *r;
1026
    request_rec *r;
Lines 1139-1144 request_rec *ap_read_request(conn_rec *conn) Link Here
1139
             */
1175
             */
1140
            apr_table_unset(r->headers_in, "Content-Length");
1176
            apr_table_unset(r->headers_in, "Content-Length");
1141
        }
1177
        }
1178
1179
        /*
1180
         * If we have both hostname from an absoluteURI and a Host header,
1181
         * we must ignore the Host header (RFC 7230, Section 5.4).
1182
         * To enforce this, we reset the Host header to the value from the
1183
         * request line.
1184
         */
1185
        if (r->hostname) {
1186
            const char *host = apr_table_get(r->headers_in, "Host");
1187
            if (host && strcasecmp(host, r->hostname) != 0) {
1188
                char *newhost = construct_host_header(r);
1189
                if (strcasecmp(host, newhost) != 0) {
1190
                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02417)
1191
                                  "Replacing Host header '%s' with host from "
1192
                                  "request uri: '%s'", host, newhost);
1193
                    apr_table_setn(r->headers_in, "Host", newhost);
1194
                }
1195
            }
1196
        }
1142
    }
1197
    }
1143
    else {
1198
    else {
1144
        if (r->header_only) {
1199
        if (r->header_only) {
(-)server/vhost.c (-90 / +25 lines)
Lines 811-818 bad: Link Here
811
 * Instead we just check for filesystem metacharacters: directory
811
 * Instead we just check for filesystem metacharacters: directory
812
 * separators / and \ and sequences of more than one dot.
812
 * separators / and \ and sequences of more than one dot.
813
 */
813
 */
814
static int fix_hostname(request_rec *r, const char *host_header,
814
static int fix_hostname(request_rec *r)
815
                        unsigned http_conformance)
816
{
815
{
817
    const char *src;
816
    const char *src;
818
    char *host, *scope_id;
817
    char *host, *scope_id;
Lines 819-833 bad: Link Here
819
    apr_port_t port;
818
    apr_port_t port;
820
    apr_status_t rv;
819
    apr_status_t rv;
821
    const char *c;
820
    const char *c;
822
    int is_v6literal = 0;
821
    int is_v6literal;
823
    int strict = http_conformance & AP_HTTP_CONFORMANCE_STRICT;
822
    core_server_config *conf =
824
    int strict_logonly = http_conformance & AP_HTTP_CONFORMANCE_LOGONLY;
823
        ap_get_core_module_config(r->server->module_config);
824
    int strict = conf->http_conformance & AP_HTTP_CONFORMANCE_STRICT;
825
    int strict_logonly = conf->http_conformance & AP_HTTP_CONFORMANCE_LOGONLY;
825
826
826
    src = host_header ? host_header : r->hostname;
827
    /*
828
     * If there was a host part in the Request-URI, ignore the 'Host'
829
     * header.
830
     */
831
    src = r->hostname ? r->hostname : apr_table_get(r->headers_in, "Host");
827
832
828
    /* According to RFC 2616, Host header field CAN be blank */
833
    /* According to RFC 2616, Host header field CAN be blank */
829
    if (!*src) {
834
    if (!src || !*src) {
830
        return is_v6literal;
835
        return 0;
831
    }
836
    }
832
837
833
    /* apr_parse_addr_port will interpret a bare integer as a port
838
    /* apr_parse_addr_port will interpret a bare integer as a port
Lines 845-854 bad: Link Here
845
                goto bad_nolog;
850
                goto bad_nolog;
846
        }
851
        }
847
        r->hostname = src;
852
        r->hostname = src;
848
        return is_v6literal;
853
        return 0;
849
    }
854
    }
850
855
851
    if (host_header) {
856
    if (r->hostname) {
857
        /*
858
         * Already parsed, surrounding [ ] (if IPv6 literal) and :port have
859
         * already been removed.
860
         */
861
        host = apr_pstrdup(r->pool, r->hostname);
862
        is_v6literal = (ap_strchr(host, ':') != NULL);
863
    }
864
    else {
852
        rv = apr_parse_addr_port(&host, &scope_id, &port, src, r->pool);
865
        rv = apr_parse_addr_port(&host, &scope_id, &port, src, r->pool);
853
        if (rv != APR_SUCCESS || scope_id)
866
        if (rv != APR_SUCCESS || scope_id)
854
            goto bad;
867
            goto bad;
Lines 861-878 bad: Link Here
861
            r->parsed_uri.port = port;
874
            r->parsed_uri.port = port;
862
            r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
875
            r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
863
        }
876
        }
864
        if (host_header[0] == '[')
877
        is_v6literal = (src[0] == '[');
865
            is_v6literal = 1;
866
    }
878
    }
867
    else {
868
        /*
869
         * Already parsed, surrounding [ ] (if IPv6 literal) and :port have
870
         * already been removed.
871
         */
872
        host = apr_pstrdup(r->pool, r->hostname);
873
        if (ap_strchr(host, ':') != NULL)
874
            is_v6literal = 1;
875
    }
876
879
877
    if (is_v6literal) {
880
    if (is_v6literal) {
878
        rv = fix_hostname_v6_literal(r, host);
881
        rv = fix_hostname_v6_literal(r, host);
Lines 1106-1185 static void check_serverpath(request_rec *r) Link Here
1106
    }
1109
    }
1107
}
1110
}
1108
1111
1109
static APR_INLINE const char *construct_host_header(request_rec *r,
1110
                                                    int is_v6literal)
1111
{
1112
    struct iovec iov[5];
1113
    apr_size_t nvec = 0;
1114
    /*
1115
     * We cannot use ap_get_server_name/port here, because we must
1116
     * ignore UseCanonicalName/Port.
1117
     */
1118
    if (is_v6literal) {
1119
        iov[nvec].iov_base = "[";
1120
        iov[nvec].iov_len = 1;
1121
        nvec++;
1122
    }
1123
    iov[nvec].iov_base = (void *)r->hostname;
1124
    iov[nvec].iov_len = strlen(r->hostname);
1125
    nvec++;
1126
    if (is_v6literal) {
1127
        iov[nvec].iov_base = "]";
1128
        iov[nvec].iov_len = 1;
1129
        nvec++;
1130
    }
1131
    if (r->parsed_uri.port_str) {
1132
        iov[nvec].iov_base = ":";
1133
        iov[nvec].iov_len = 1;
1134
        nvec++;
1135
        iov[nvec].iov_base = r->parsed_uri.port_str;
1136
        iov[nvec].iov_len = strlen(r->parsed_uri.port_str);
1137
        nvec++;
1138
    }
1139
    return apr_pstrcatv(r->pool, iov, nvec, NULL);
1140
}
1141
1142
AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
1112
AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
1143
{
1113
{
1144
    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
1114
    fix_hostname(r);
1145
    const char *host_header = apr_table_get(r->headers_in, "Host");
1146
    int is_v6literal = 0;
1147
    int have_hostname_from_url = 0;
1148
1149
    if (r->hostname) {
1150
        /*
1151
         * If there was a host part in the Request-URI, ignore the 'Host'
1152
         * header.
1153
         */
1154
        have_hostname_from_url = 1;
1155
        is_v6literal = fix_hostname(r, NULL, conf->http_conformance);
1156
    }
1157
    else if (host_header != NULL) {
1158
        is_v6literal = fix_hostname(r, host_header, conf->http_conformance);
1159
    }
1160
    if (r->status != HTTP_OK)
1115
    if (r->status != HTTP_OK)
1161
        return;
1116
        return;
1162
1117
1163
    if (conf->http_conformance & AP_HTTP_CONFORMANCE_STRICT) {
1164
        /*
1165
         * If we have both hostname from an absoluteURI and a Host header,
1166
         * we must ignore the Host header (RFC 2616 5.2).
1167
         * To enforce this, we reset the Host header to the value from the
1168
         * request line.
1169
         */
1170
        if (have_hostname_from_url && host_header != NULL) {
1171
            const char *info = "Would replace";
1172
            const char *new = construct_host_header(r, is_v6literal);
1173
            if (!(conf->http_conformance & AP_HTTP_CONFORMANCE_LOGONLY)) {
1174
                apr_table_set(r->headers_in, "Host", r->hostname);
1175
                info = "Replacing";
1176
            }
1177
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02417)
1178
                          "%s Host header '%s' with host from request uri: "
1179
                          "'%s'", info, host_header, new);
1180
        }
1181
    }
1182
1183
    /* check if we tucked away a name_chain */
1118
    /* check if we tucked away a name_chain */
1184
    if (r->connection->vhost_lookup_data) {
1119
    if (r->connection->vhost_lookup_data) {
1185
        if (r->hostname)
1120
        if (r->hostname)

Return to bug 56718