summaryrefslogtreecommitdiff
blob: fb20641b5b228c9718a8b8fe948ba2df35254983 (plain)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Fixes https://bugs.gentoo.org/727352

From 2a41e236716da4c41ebc1132bd36d9273bd0321f Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 8 Jun 2020 14:05:22 +0200
Subject: [PATCH] socks: detect connection close during handshake

The SOCKS4/5 state machines weren't properly terminated when the proxy
connection got closed, leading to a busy-loop.

Reported-By: zloi-user on github
Fixes #5532
Closes #5542
---
 lib/socks.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/lib/socks.c b/lib/socks.c
index 4c1af7b9de7..b2215fef30c 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -382,6 +382,11 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
             curl_easy_strerror(result));
       return CURLE_COULDNT_CONNECT;
     }
+    else if(!result && !actualread) {
+      /* connection closed */
+      failf(data, "connection to proxy closed");
+      return CURLE_COULDNT_CONNECT;
+    }
     else if(actualread != sx->outstanding) {
       /* remain in reading state */
       sx->outstanding -= actualread;
@@ -592,6 +597,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       failf(data, "Unable to receive initial SOCKS5 response.");
       return CURLE_COULDNT_CONNECT;
     }
+    else if(!result && !actualread) {
+      /* connection closed */
+      failf(data, "Connection to proxy closed");
+      return CURLE_COULDNT_CONNECT;
+    }
     else if(actualread != sx->outstanding) {
       /* remain in reading state */
       sx->outstanding -= actualread;
@@ -717,15 +727,19 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
       return CURLE_COULDNT_CONNECT;
     }
-    if(actualread != sx->outstanding) {
+    else if(!result && !actualread) {
+      /* connection closed */
+      failf(data, "connection to proxy closed");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
       sx->outp += actualread;
       return CURLE_OK;
     }
-
     /* ignore the first (VER) byte */
-    if(socksreq[1] != 0) { /* status */
+    else if(socksreq[1] != 0) { /* status */
       failf(data, "User was rejected by the SOCKS5 server (%d %d).",
             socksreq[0], socksreq[1]);
       return CURLE_COULDNT_CONNECT;
@@ -890,6 +904,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       failf(data, "Failed to receive SOCKS5 connect request ack.");
       return CURLE_COULDNT_CONNECT;
     }
+    else if(!result && !actualread) {
+      /* connection closed */
+      failf(data, "connection to proxy closed");
+      return CURLE_COULDNT_CONNECT;
+    }
     else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
@@ -967,7 +986,12 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       failf(data, "Failed to receive SOCKS5 connect request ack.");
       return CURLE_COULDNT_CONNECT;
     }
-    if(actualread != sx->outstanding) {
+    else if(!result && !actualread) {
+      /* connection closed */
+      failf(data, "connection to proxy closed");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(actualread != sx->outstanding) {
       /* remain in state */
       sx->outstanding -= actualread;
       sx->outp += actualread;