Package: libssh2 / 1.8.0-2.1

CVE-2019-3859.patch Patch series | download
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
Description: Out-of-bounds reads with specially crafted payloads due to unchecked use of _libssh2_packet_require and _libssh2_packet_requirev
Origin: upstream, https://libssh2.org/1.8.0-CVE/CVE-2019-3859.patch
Bug-Debian: https://bugs.debian.org/924965
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3859
Forwarded: not-needed
Last-Update: 2019-03-30

--- a/src/channel.c
+++ b/src/channel.c
@@ -238,7 +238,20 @@ _libssh2_channel_open(LIBSSH2_SESSION *
             goto channel_error;
         }
 
+        if(session->open_data_len < 1) {
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Unexpected packet size");
+            goto channel_error;
+        }
+
         if (session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
+            
+             if(session->open_data_len < 17) {
+                _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                               "Unexpected packet size");
+                goto channel_error;
+            }
+
             session->open_channel->remote.id =
                 _libssh2_ntohu32(session->open_data + 5);
             session->open_channel->local.window_size =
@@ -518,7 +531,7 @@ channel_forward_listen(LIBSSH2_SESSION *
         if (rc == LIBSSH2_ERROR_EAGAIN) {
             _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
             return NULL;
-        } else if (rc) {
+        } else if (rc || data_len < 1) {
             _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
             session->fwdLstn_state = libssh2_NB_state_idle;
             return NULL;
@@ -855,6 +868,11 @@ static int channel_setenv(LIBSSH2_CHANNE
             channel->setenv_state = libssh2_NB_state_idle;
             return rc;
         }
+        else if(data_len < 1) {
+            channel->setenv_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet size");
+        }
 
         if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
             LIBSSH2_FREE(session, data);
@@ -971,7 +989,7 @@ static int channel_request_pty(LIBSSH2_C
                                       &channel->reqPTY_packet_requirev_state);
         if (rc == LIBSSH2_ERROR_EAGAIN) {
             return rc;
-        } else if (rc) {
+        } else if (rc || data_len < 1) {
             channel->reqPTY_state = libssh2_NB_state_idle;
             return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
                                   "Failed to require the PTY package");
@@ -1197,7 +1215,7 @@ channel_x11_req(LIBSSH2_CHANNEL *channel
                                       &channel->reqX11_packet_requirev_state);
         if (rc == LIBSSH2_ERROR_EAGAIN) {
             return rc;
-        } else if (rc) {
+        } else if (rc || data_len < 1) {
             channel->reqX11_state = libssh2_NB_state_idle;
             return _libssh2_error(session, rc,
                                   "waiting for x11-req response packet");
@@ -1324,7 +1342,7 @@ _libssh2_channel_process_startup(LIBSSH2
                                       &channel->process_packet_requirev_state);
         if (rc == LIBSSH2_ERROR_EAGAIN) {
             return rc;
-        } else if (rc) {
+        } else if (rc || data_len < 1) {
             channel->process_state = libssh2_NB_state_end;
             return _libssh2_error(session, rc,
                                   "Failed waiting for channel success");
--- a/src/kex.c
+++ b/src/kex.c
@@ -228,11 +228,23 @@ static int diffie_hellman_sha1(LIBSSH2_S
         }
 
         /* Parse KEXDH_REPLY */
+        if(exchange_state->s_packet_len < 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected packet length");
+            goto clean_exit;
+        }
+
         exchange_state->s = exchange_state->s_packet + 1;
 
         session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
         exchange_state->s += 4;
 
+        if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+                                "Host key length out of bounds");
+            goto clean_exit;
+        }
+
         if (session->server_hostkey)
             LIBSSH2_FREE(session, session->server_hostkey);
 
@@ -848,11 +860,23 @@ static int diffie_hellman_sha256(LIBSSH2
         }
 
         /* Parse KEXDH_REPLY */
+        if(exchange_state->s_packet_len < 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                 "Unexpected packet length");
+            goto clean_exit;
+        }
+        
         exchange_state->s = exchange_state->s_packet + 1;
 
         session->server_hostkey_len = _libssh2_ntohu32(exchange_state->s);
         exchange_state->s += 4;
 
+        if(session->server_hostkey_len > exchange_state->s_packet_len - 5) {
+            ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+                         "Host key length out of bounds");
+            goto clean_exit;
+        }
+
         if (session->server_hostkey)
             LIBSSH2_FREE(session, session->server_hostkey);
 
--- a/src/session.c
+++ b/src/session.c
@@ -765,6 +765,11 @@ session_startup(LIBSSH2_SESSION *session
         if (rc)
             return rc;
 
+        if(session->startup_data_len < 5) {
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet length");
+        }
+
         session->startup_service_length =
             _libssh2_ntohu32(session->startup_data + 1);
 
--- a/src/userauth.c
+++ b/src/userauth.c
@@ -107,7 +107,7 @@ static char *userauth_list(LIBSSH2_SESSI
         LIBSSH2_FREE(session, session->userauth_list_data);
         session->userauth_list_data = NULL;
 
-        if (rc) {
+        if (rc || (session->userauth_list_data_len < 1)) {
             _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
                            "Unable to send userauth-none request");
             session->userauth_list_state = libssh2_NB_state_idle;
@@ -143,8 +143,20 @@ static char *userauth_list(LIBSSH2_SESSI
             return NULL;
         }
 
-        methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
+         if(session->userauth_list_data_len < 5) {
+            LIBSSH2_FREE(session, session->userauth_list_data);
+            session->userauth_list_data = NULL;
+            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                           "Unexpected packet size");
+            return NULL;
+        }
 
+        methods_len = _libssh2_ntohu32(session->userauth_list_data + 1);
+        if(methods_len >= session->userauth_list_data_len - 5) {
+            _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
+                           "Unexpected userauth list size");
+            return NULL;
+        }
         /* Do note that the memory areas overlap! */
         memmove(session->userauth_list_data, session->userauth_list_data + 5,
                 methods_len);
@@ -285,6 +297,11 @@ userauth_password(LIBSSH2_SESSION *sessi
                 return _libssh2_error(session, rc,
                                       "Waiting for password response");
             }
+            else if(session->userauth_pswd_data_len < 1) {
+                session->userauth_pswd_state = libssh2_NB_state_idle;
+                return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                      "Unexpected packet size");
+            }
 
             if (session->userauth_pswd_data[0] == SSH_MSG_USERAUTH_SUCCESS) {
                 _libssh2_debug(session, LIBSSH2_TRACE_AUTH,
@@ -312,6 +329,12 @@ userauth_password(LIBSSH2_SESSION *sessi
             session->userauth_pswd_state = libssh2_NB_state_sent1;
         }
 
+        if(session->userauth_pswd_data_len < 1) {
+            session->userauth_pswd_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Unexpected packet size");
+        }
+
         if ((session->userauth_pswd_data[0] ==
              SSH_MSG_USERAUTH_PASSWD_CHANGEREQ)
             || (session->userauth_pswd_data0 ==
@@ -976,7 +999,7 @@ userauth_hostbased_fromfile(LIBSSH2_SESS
         }
 
         session->userauth_host_state = libssh2_NB_state_idle;
-        if (rc) {
+        if (rc || data_len < 1) {
             return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
                                   "Auth failed");
         }
@@ -1149,7 +1172,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESS
                                      NULL, 0);
         if (rc == LIBSSH2_ERROR_EAGAIN)
             return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
-        else if (rc) {
+        else if (rc || (session->userauth_pblc_data_len < 1)) {
             LIBSSH2_FREE(session, session->userauth_pblc_packet);
             session->userauth_pblc_packet = NULL;
             LIBSSH2_FREE(session, session->userauth_pblc_method);
@@ -1332,7 +1355,7 @@ _libssh2_userauth_publickey(LIBSSH2_SESS
     if (rc == LIBSSH2_ERROR_EAGAIN) {
         return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
                               "Would block requesting userauth list");
-    } else if (rc) {
+    } else if (rc || session->userauth_pblc_data_len < 1) {
         session->userauth_pblc_state = libssh2_NB_state_idle;
         return _libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED,
                               "Waiting for publickey USERAUTH response");
@@ -1654,7 +1677,7 @@ userauth_keyboard_interactive(LIBSSH2_SE
             if (rc == LIBSSH2_ERROR_EAGAIN) {
                 return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
                                       "Would block");
-            } else if (rc) {
+            } else if (rc || session->userauth_kybd_data_len < 1) {
                 session->userauth_kybd_state = libssh2_NB_state_idle;
                 return _libssh2_error(session,
                                       LIBSSH2_ERROR_AUTHENTICATION_FAILED,