Package: libssh / 0.4.5-3+squeeze3

CVE-2012-4562.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
Description: Fix buffer overflows that could lead to denial of service or code execution (CVE-2012-4561)
Origin: backport, http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=8489521c0d7a9d1336b23a4a64e5df2d0f3ba57a
Origin: backport, http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=db81310d719878cc04b23e4033fbe19fa0b1f8a3
Origin: backport, http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=1699adfa036ffc66c62fdbb784610445cbebfc6e
Origin: backport, http://git.libssh.org/projects/libssh.git/commit/?h=v0-5&id=e3d9501b31a11b427afe1cc1cba5208adc2c3c39

--- a/libssh/buffer.c
+++ b/libssh/buffer.c
@@ -21,6 +21,7 @@
  * MA 02111-1307, USA.
  */
 
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -99,12 +100,17 @@ void buffer_free(struct ssh_buffer_struc
   SAFE_FREE(buffer);
 }
 
-static int realloc_buffer(struct ssh_buffer_struct *buffer, int needed) {
-  int smallest = 1;
-  char *new = NULL;
+static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
+  size_t smallest = 1;
+  char *new;
+
   buffer_verify(buffer);
+
   /* Find the smallest power of two which is greater or equal to needed */
   while(smallest < needed) {
+    if (smallest == 0) {
+       return -1;
+    }
     smallest <<= 1;
   }
   needed = smallest;
@@ -145,6 +151,10 @@ int buffer_reinit(struct ssh_buffer_stru
  */
 int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
   buffer_verify(buffer);
+
+  if (buffer->used + len < len)
+    return -1;
+
   if (buffer->allocated < (buffer->used + len)) {
     if (realloc_buffer(buffer, buffer->used + len) < 0) {
       return -1;
@@ -240,6 +250,8 @@ int buffer_add_u8(struct ssh_buffer_stru
 int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
     uint32_t len) {
   buffer_verify(buffer);
+  if (buffer->used + len < len)
+    return -1;
   if (buffer->allocated < (buffer->used + len)) {
     if (realloc_buffer(buffer, buffer->used + len) < 0) {
       return -1;
@@ -318,7 +330,7 @@ uint32_t buffer_get_rest_len(struct ssh_
  */
 uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
     buffer_verify(buffer);
-    if(buffer->used < buffer->pos+len)
+    if (buffer->pos + len < len || buffer->used < buffer->pos + len)
         return 0;
     buffer->pos+=len;
     /* if the buffer is empty after having passed the whole bytes into it, we can clean it */
@@ -338,8 +350,11 @@ uint32_t buffer_pass_bytes(struct ssh_bu
  */
 uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
   buffer_verify(buffer);
-  if(buffer->used < buffer->pos + len)
-    return 0;
+
+  if (buffer->used < len) {
+      return 0;
+  }
+
   buffer->used-=len;
   buffer_verify(buffer);
   return len;
@@ -412,7 +427,7 @@ struct ssh_string_struct *buffer_get_ssh
   }
   hostlen = ntohl(stringlen);
   /* verify if there is enough space in buffer to get it */
-  if ((buffer->pos + hostlen) > buffer->used) {
+  if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) {
     return NULL; /* it is indeed */
   }
   str = string_new(hostlen);
@@ -445,7 +460,7 @@ struct ssh_string_struct *buffer_get_mpi
   }
   bits = ntohs(bits);
   len = (bits + 7) / 8;
-  if ((buffer->pos + len) > buffer->used) {
+  if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
     return NULL;
   }
   str = string_new(len);
--- a/libssh/dh.c
+++ b/libssh/dh.c
@@ -44,6 +44,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifndef _WIN32
 #include <arpa/inet.h>
@@ -188,6 +189,9 @@ char *ssh_get_hexa(const unsigned char *
   char *hexa = NULL;
   size_t i;
 
+  if (len > (UINT_MAX - 1) / 3)
+    return NULL;
+
   hexa = malloc(len * 3 + 1);
   if (hexa == NULL) {
     return NULL;
--- a/libssh/string.c
+++ b/libssh/string.c
@@ -21,6 +21,7 @@
  * MA 02111-1307, USA.
  */
 
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -44,7 +45,11 @@
 struct ssh_string_struct *string_new(size_t size) {
   struct ssh_string_struct *str = NULL;
 
-  str = malloc(size + 4);
+  if (size > UINT_MAX - sizeof(struct ssh_string_struct)) {
+      return NULL;
+  }
+
+  str = malloc(sizeof(struct ssh_string_struct) + size);
   if (str == NULL) {
     return NULL;
   }
@@ -115,14 +120,24 @@ size_t string_len(struct ssh_string_stru
  * the output string may not be readable with regular libc functions.
  */
 char *string_to_char(struct ssh_string_struct *s) {
-  size_t len = ntohl(s->size) + 1;
-  char *new = malloc(len);
+  size_t len;
+  char *new;
+  if (s == NULL || s->string == NULL) {
+    return NULL;
+  }
 
+  len = string_len(s);
+  if (len + 1 < len) {
+    return NULL;
+  }
+
+  new = malloc(len + 1);
   if (new == NULL) {
     return NULL;
   }
-  memcpy(new, s->string, len - 1);
-  new[len - 1] = '\0';
+  memcpy(new, s->string, len);
+  new[len] = '\0';
+
   return new;
 }