http transport: cap number of authentication replays Put a limit on the number of authentication replays in the HTTP transport. Standardize on 7 replays for authentication or redirects, which matches the behavior of the WinHTTP transport.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
diff --git a/src/transports/http.c b/src/transports/http.c
index 29924a0..5c060f4 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -66,7 +66,7 @@ typedef struct {
unsigned sent_request : 1,
received_response : 1,
chunked : 1,
- redirect_count : 3;
+ replay_count : 3;
} http_stream;
typedef struct {
@@ -424,6 +424,12 @@ static int on_headers_complete(http_parser *parser)
git_buf buf = GIT_BUF_INIT;
int allowed_proxy_auth_types = 0, allowed_www_auth_types = 0;
+ /* Enforce a reasonable cap on the number of replays */
+ if (s->replay_count++ >= GIT_HTTP_REPLAY_MAX) {
+ giterr_set(GITERR_NET, "too many redirects or authentication replays");
+ return t->parse_error = PARSE_ERROR_GENERIC;
+ }
+
/* Both parse_header_name and parse_header_value are populated
* and ready for consumption. */
if (VALUE == t->last_cb)
@@ -472,11 +478,6 @@ static int on_headers_complete(http_parser *parser)
parser->status_code == 308) &&
t->location) {
- if (s->redirect_count >= 7) {
- giterr_set(GITERR_NET, "too many redirects");
- return t->parse_error = PARSE_ERROR_GENERIC;
- }
-
if (gitno_connection_data_from_url(&t->gitserver_data, t->location, s->service_url) < 0)
return t->parse_error = PARSE_ERROR_GENERIC;
@@ -489,8 +490,6 @@ static int on_headers_complete(http_parser *parser)
t->location = NULL;
t->connected = 0;
- s->redirect_count++;
-
t->parse_error = PARSE_ERROR_REPLAY;
return 0;
}
diff --git a/src/transports/http.h b/src/transports/http.h
index 6c4ecc9..b094757 100644
--- a/src/transports/http.h
+++ b/src/transports/http.h
@@ -10,6 +10,8 @@
#include "buffer.h"
+#define GIT_HTTP_REPLAY_MAX 7
+
GIT_INLINE(int) git_http__user_agent(git_buf *buf)
{
const char *ua = git_libgit2__user_agent();
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index 5e7bde7..30e2ecb 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -932,7 +932,7 @@ static int winhttp_stream_read(
replay:
/* Enforce a reasonable cap on the number of replays */
- if (++replay_count >= 7) {
+ if (replay_count++ >= GIT_HTTP_REPLAY_MAX) {
giterr_set(GITERR_NET, "too many redirects or authentication replays");
return -1;
}