diff --git a/CHANGES b/CHANGES index 66a3375621..c0f607d73b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_proxy: Ensure network errors detected by the proxy are returned as + 504 Gateway Timout as opposed to 502 Bad Gateway, in order to be + compliant with RFC2616 14.9.4 Cache Revalidation and Reload Controls. + [Graham Leggett, Co-Advisor ] + *) mod_cache: Ensure that we don't attempt to replace a cached response with an older response as per RFC2616 13.12. [Graham Leggett, Co-Advisor ] diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c index b93f58768c..6be17c0d9a 100644 --- a/modules/proxy/mod_proxy_ftp.c +++ b/modules/proxy/mod_proxy_ftp.c @@ -859,7 +859,11 @@ static int ftp_set_TYPE(char xfer_type, request_rec *r, conn_rec *ftp_ctrl, /* 501 Syntax error in parameters or arguments. */ /* 504 Command not implemented for that parameter. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { + if (rc == -1) { + ret = ap_proxyerror(r, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { ret = ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server"); } @@ -891,6 +895,10 @@ static char *ftp_get_PWD(request_rec *r, conn_rec *ftp_ctrl, apr_bucket_brigade /* 550 Requested action not taken. */ switch (proxy_ftp_command("PWD" CRLF, r, ftp_ctrl, bb, &ftpmessage)) { case -1: + ap_proxyerror(r, HTTP_GATEWAY_TIME_OUT, + "Failed to read PWD on ftp server"); + break; + case 421: case 550: ap_proxyerror(r, HTTP_BAD_GATEWAY, @@ -1140,7 +1148,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, * them until we get a successful connection */ if (APR_SUCCESS != err) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p, + return ap_proxyerror(r, HTTP_GATEWAY_TIME_OUT, apr_pstrcat(p, "DNS lookup failure for: ", connectname, NULL)); } @@ -1212,10 +1220,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 220 Service ready for new user. */ /* 421 Service not available, closing control connection. */ rc = proxy_ftp_command(NULL, r, origin, bb, &ftpmessage); - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc == 120) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc == 120) { /* * RFC2616 states: 14.37 Retry-After * @@ -1241,7 +1254,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, } return ftp_proxyerror(r, backend, HTTP_SERVICE_UNAVAILABLE, ftpmessage); } - if (rc != 220) { + else if (rc != 220) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } @@ -1257,15 +1270,20 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* (This may include errors such as command line too long.) */ /* 501 Syntax error in parameters or arguments. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc == 530) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc == 530) { proxy_ftp_cleanup(r, backend); return ftp_unauthorized(r, 1); /* log it: user name guessing * attempt? */ } - if (rc != 230 && rc != 331) { + else if (rc != 230 && rc != 331) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } @@ -1285,21 +1303,25 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 501 Syntax error in parameters or arguments. */ /* 503 Bad sequence of commands. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, "Error reading from remote server"); } - if (rc == 332) { + else if (rc == 332) { return ftp_proxyerror(r, backend, HTTP_UNAUTHORIZED, apr_pstrcat(p, "Need account for login: ", ftpmessage, NULL)); } /* @@@ questionable -- we might as well return a 403 Forbidden here */ - if (rc == 530) { + else if (rc == 530) { proxy_ftp_cleanup(r, backend); return ftp_unauthorized(r, 1); /* log it: passwd guessing * attempt? */ } - if (rc != 230 && rc != 202) { + else if (rc != 230 && rc != 202) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } } @@ -1315,9 +1337,14 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, ++path; rc = proxy_ftp_command("CWD /" CRLF, r, origin, bb, &ftpmessage); - if (rc == -1 || rc == 421) + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + "Error reading from remote server"); + } } /* @@ -1354,14 +1381,18 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 502 Command not implemented. */ /* 530 Not logged in. */ /* 550 Requested action not taken. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc == 550) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc == 550) { return ftp_proxyerror(r, backend, HTTP_NOT_FOUND, ftpmessage); } - if (rc != 250) { + else if (rc != 250) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } @@ -1395,11 +1426,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 501 Syntax error in parameters or arguments. */ /* 502 Command not implemented. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc != 229 && rc != 500 && rc != 501 && rc != 502) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc != 229 && rc != 500 && rc != 501 && rc != 502) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } else if (rc == 229) { @@ -1461,8 +1496,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01043) "EPSV attempt to connect to %pI failed - " "Firewall/NAT?", &epsv_addr); - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, apr_psprintf(r->pool, - "EPSV attempt to connect to %pI failed - firewall/NAT?", &epsv_addr)); + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + apr_psprintf(r->pool, + "EPSV attempt to connect to %pI failed - firewall/NAT?", + &epsv_addr)); } else { ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, @@ -1484,11 +1521,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 501 Syntax error in parameters or arguments. */ /* 502 Command not implemented. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc != 227 && rc != 502) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc != 227 && rc != 502) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } else if (rc == 227) { @@ -1550,8 +1591,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01048) "PASV attempt to connect to %pI failed - Firewall/NAT?", pasv_addr); - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, apr_psprintf(r->pool, - "PASV attempt to connect to %pI failed - firewall/NAT?", pasv_addr)); + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + apr_psprintf(r->pool, + "PASV attempt to connect to %pI failed - firewall/NAT?", + pasv_addr)); } else { connect = 1; @@ -1621,11 +1664,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 501 Syntax error in parameters or arguments. */ /* 502 Command not implemented. */ /* 530 Not logged in. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc != 200) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc != 200) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, buffer); } @@ -1686,9 +1733,13 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, rc = proxy_ftp_command(apr_pstrcat(p, "SIZE ", ftp_escape_globbingchars(p, path, fdconf), CRLF, NULL), r, origin, bb, &ftpmessage); - if (rc == -1 || rc == 421) { + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + "Error reading from remote server"); } else if (rc == 213) {/* Size command ok */ int j; @@ -1713,14 +1764,18 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 502 Command not implemented. */ /* 530 Not logged in. */ /* 550 Requested action not taken. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc == 550) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc == 550) { return ftp_proxyerror(r, backend, HTTP_NOT_FOUND, ftpmessage); } - if (rc != 250) { + else if (rc != 250) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } path = ""; @@ -1827,11 +1882,15 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 501 Syntax error in parameters or arguments. */ /* 530 Not logged in. */ /* 550 Requested action not taken. */ - if (rc == -1 || rc == 421) { + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, "Error reading from remote server"); } - if (rc == 550) { + else if (rc == 550) { ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "RETR failed, trying LIST instead"); @@ -1850,14 +1909,18 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* 502 Command not implemented. */ /* 530 Not logged in. */ /* 550 Requested action not taken. */ - if (rc == -1 || rc == 421) { - return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); } - if (rc == 550) { + else if (rc == 421) { + return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + else if (rc == 550) { return ftp_proxyerror(r, backend, HTTP_NOT_FOUND, ftpmessage); } - if (rc != 250) { + else if (rc != 250) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); } @@ -1873,9 +1936,14 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, r, origin, bb, &ftpmessage); /* rc is an intermediate response for the LIST command (125 transfer starting, 150 opening data connection) */ - if (rc == -1 || rc == 421) + if (rc == -1) { + return ftp_proxyerror(r, backend, HTTP_GATEWAY_TIME_OUT, + "Error reading from remote server"); + } + else if (rc == 421) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + "Error reading from remote server"); + } } if (rc != 125 && rc != 150 && rc != 226 && rc != 250) { return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, ftpmessage); @@ -1947,7 +2015,7 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01053) "failed to accept data connection"); proxy_ftp_cleanup(r, backend); - return HTTP_BAD_GATEWAY; + return HTTP_GATEWAY_TIME_OUT; } } } diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 0712b61d5f..2038be306d 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1374,7 +1374,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, " failed.", backend->hostname, backend->port); } - return ap_proxyerror(r, HTTP_BAD_GATEWAY, + return ap_proxyerror(r, HTTP_GATEWAY_TIME_OUT, "Error reading from remote server"); } /* XXX: Is this a real headers length send from remote? */ @@ -1722,7 +1722,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, } else if (rv != APR_SUCCESS) { /* In this case, we are in real trouble because - * our backend bailed on us. Pass along a 502 error + * our backend bailed on us. Pass along a 504 error * error bucket */ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110) diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 1baf4fe49c..d5cfb86548 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2203,7 +2203,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, } if (err != APR_SUCCESS) { - return ap_proxyerror(r, HTTP_BAD_GATEWAY, + return ap_proxyerror(r, HTTP_GATEWAY_TIME_OUT, apr_pstrcat(p, "DNS lookup failure for: ", conn->hostname, NULL)); } @@ -2761,7 +2761,7 @@ PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r, */ if (r->main) r->main->no_cache = 1; - e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL, c->pool, + e = ap_bucket_error_create(HTTP_GATEWAY_TIME_OUT, NULL, c->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(brigade, e); e = apr_bucket_eos_create(c->bucket_alloc); @@ -3281,7 +3281,7 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc, "Error during SSL Handshake with" " remote server"); } - return APR_STATUS_IS_TIMEUP(status) ? HTTP_GATEWAY_TIME_OUT : HTTP_BAD_GATEWAY; + return HTTP_GATEWAY_TIME_OUT; } else { return HTTP_BAD_REQUEST;