summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--auth-options.c8
-rw-r--r--auth1.c6
-rw-r--r--auth2.c10
-rw-r--r--bufaux.c35
-rw-r--r--buffer.h4
-rw-r--r--kex.c4
-rw-r--r--key.c13
-rw-r--r--packet.c9
-rw-r--r--packet.h3
-rw-r--r--ssh-dss.c4
-rw-r--r--ssh-rsa.c4
12 files changed, 83 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index a56f04349..2f4acd9de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,20 @@
11 - djm@cvs.openbsd.org 2010/08/16 04:06:06 11 - djm@cvs.openbsd.org 2010/08/16 04:06:06
12 [ssh-add.c ssh-agent.c ssh-keygen.c ssh-keysign.c ssh.c sshd.c] 12 [ssh-add.c ssh-agent.c ssh-keygen.c ssh-keysign.c ssh.c sshd.c]
13 backout previous temporarily; discussed with deraadt@ 13 backout previous temporarily; discussed with deraadt@
14 - djm@cvs.openbsd.org 2010/08/31 09:58:37
15 [auth-options.c auth1.c auth2.c bufaux.c buffer.h kex.c key.c packet.c]
16 [packet.h ssh-dss.c ssh-rsa.c]
17 Add buffer_get_cstring() and related functions that verify that the
18 string extracted from the buffer contains no embedded \0 characters*
19 This prevents random (possibly malicious) crap from being appended to
20 strings where it would not be noticed if the string is used with
21 a string(3) function.
22
23 Use the new API in a few sensitive places.
24
25 * actually, we allow a single one at the end of the string for now because
26 we don't know how many deployed implementations get this wrong, but don't
27 count on this to remain indefinitely.
14 28
1520100827 2920100827
16 - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated, 30 - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated,
diff --git a/auth-options.c b/auth-options.c
index a7040247f..a9c26add6 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.53 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -444,7 +444,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
444 buffer_append(&c, optblob, optblob_len); 444 buffer_append(&c, optblob, optblob_len);
445 445
446 while (buffer_len(&c) > 0) { 446 while (buffer_len(&c) > 0) {
447 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 447 if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
448 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { 448 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
449 error("Certificate options corrupt"); 449 error("Certificate options corrupt");
450 goto out; 450 goto out;
@@ -479,7 +479,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
479 } 479 }
480 if (!found && (which & OPTIONS_CRITICAL) != 0) { 480 if (!found && (which & OPTIONS_CRITICAL) != 0) {
481 if (strcmp(name, "force-command") == 0) { 481 if (strcmp(name, "force-command") == 0) {
482 if ((command = buffer_get_string_ret(&data, 482 if ((command = buffer_get_cstring_ret(&data,
483 &clen)) == NULL) { 483 &clen)) == NULL) {
484 error("Certificate constraint \"%s\" " 484 error("Certificate constraint \"%s\" "
485 "corrupt", name); 485 "corrupt", name);
@@ -500,7 +500,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
500 found = 1; 500 found = 1;
501 } 501 }
502 if (strcmp(name, "source-address") == 0) { 502 if (strcmp(name, "source-address") == 0) {
503 if ((allowed = buffer_get_string_ret(&data, 503 if ((allowed = buffer_get_cstring_ret(&data,
504 &clen)) == NULL) { 504 &clen)) == NULL) {
505 error("Certificate constraint " 505 error("Certificate constraint "
506 "\"%s\" corrupt", name); 506 "\"%s\" corrupt", name);
diff --git a/auth1.c b/auth1.c
index bf442dbf6..cc85aec74 100644
--- a/auth1.c
+++ b/auth1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth1.c,v 1.74 2010/06/25 08:46:17 djm Exp $ */ 1/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -167,7 +167,7 @@ auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
167 * trust the client; root on the client machine can 167 * trust the client; root on the client machine can
168 * claim to be any user. 168 * claim to be any user.
169 */ 169 */
170 client_user = packet_get_string(&ulen); 170 client_user = packet_get_cstring(&ulen);
171 171
172 /* Get the client host key. */ 172 /* Get the client host key. */
173 client_host_key = key_new(KEY_RSA1); 173 client_host_key = key_new(KEY_RSA1);
@@ -389,7 +389,7 @@ do_authentication(Authctxt *authctxt)
389 packet_read_expect(SSH_CMSG_USER); 389 packet_read_expect(SSH_CMSG_USER);
390 390
391 /* Get the user name. */ 391 /* Get the user name. */
392 user = packet_get_string(&ulen); 392 user = packet_get_cstring(&ulen);
393 packet_check_eom(); 393 packet_check_eom();
394 394
395 if ((style = strchr(user, ':')) != NULL) 395 if ((style = strchr(user, ':')) != NULL)
diff --git a/auth2.c b/auth2.c
index 5d5468559..95820f96f 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.121 2009/06/22 05:39:28 dtucker Exp $ */ 1/* $OpenBSD: auth2.c,v 1.122 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -182,7 +182,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
182 Authctxt *authctxt = ctxt; 182 Authctxt *authctxt = ctxt;
183 u_int len; 183 u_int len;
184 int acceptit = 0; 184 int acceptit = 0;
185 char *service = packet_get_string(&len); 185 char *service = packet_get_cstring(&len);
186 packet_check_eom(); 186 packet_check_eom();
187 187
188 if (authctxt == NULL) 188 if (authctxt == NULL)
@@ -221,9 +221,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
221 if (authctxt == NULL) 221 if (authctxt == NULL)
222 fatal("input_userauth_request: no authctxt"); 222 fatal("input_userauth_request: no authctxt");
223 223
224 user = packet_get_string(NULL); 224 user = packet_get_cstring(NULL);
225 service = packet_get_string(NULL); 225 service = packet_get_cstring(NULL);
226 method = packet_get_string(NULL); 226 method = packet_get_cstring(NULL);
227 debug("userauth-request for user %s service %s method %s", user, service, method); 227 debug("userauth-request for user %s service %s method %s", user, service, method);
228 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 228 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
229 229
diff --git a/bufaux.c b/bufaux.c
index 854fd510a..00208ca27 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bufaux.c,v 1.49 2010/03/26 03:13:17 djm Exp $ */ 1/* $OpenBSD: bufaux.c,v 1.50 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -202,6 +202,39 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
202 return (ret); 202 return (ret);
203} 203}
204 204
205char *
206buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
207{
208 u_int length;
209 char *cp, *ret = buffer_get_string_ret(buffer, &length);
210
211 if (ret == NULL)
212 return NULL;
213 if ((cp = memchr(ret, '\0', length)) != NULL) {
214 /* XXX allow \0 at end-of-string for a while, remove later */
215 if (cp == ret + length - 1)
216 error("buffer_get_cstring_ret: string contains \\0");
217 else {
218 bzero(ret, length);
219 xfree(ret);
220 return NULL;
221 }
222 }
223 if (length_ptr != NULL)
224 *length_ptr = length;
225 return ret;
226}
227
228char *
229buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
230{
231 char *ret;
232
233 if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
234 fatal("buffer_get_cstring: buffer error");
235 return ret;
236}
237
205void * 238void *
206buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) 239buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
207{ 240{
diff --git a/buffer.h b/buffer.h
index 4ef4f80b3..93baae2c8 100644
--- a/buffer.h
+++ b/buffer.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: buffer.h,v 1.19 2010/02/09 03:56:28 djm Exp $ */ 1/* $OpenBSD: buffer.h,v 1.20 2010/08/31 09:58:37 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -68,6 +68,7 @@ void buffer_put_char(Buffer *, int);
68void *buffer_get_string(Buffer *, u_int *); 68void *buffer_get_string(Buffer *, u_int *);
69void *buffer_get_string_ptr(Buffer *, u_int *); 69void *buffer_get_string_ptr(Buffer *, u_int *);
70void buffer_put_string(Buffer *, const void *, u_int); 70void buffer_put_string(Buffer *, const void *, u_int);
71char *buffer_get_cstring(Buffer *, u_int *);
71void buffer_put_cstring(Buffer *, const char *); 72void buffer_put_cstring(Buffer *, const char *);
72 73
73#define buffer_skip_string(b) \ 74#define buffer_skip_string(b) \
@@ -81,6 +82,7 @@ int buffer_get_short_ret(u_short *, Buffer *);
81int buffer_get_int_ret(u_int *, Buffer *); 82int buffer_get_int_ret(u_int *, Buffer *);
82int buffer_get_int64_ret(u_int64_t *, Buffer *); 83int buffer_get_int64_ret(u_int64_t *, Buffer *);
83void *buffer_get_string_ret(Buffer *, u_int *); 84void *buffer_get_string_ret(Buffer *, u_int *);
85char *buffer_get_cstring_ret(Buffer *, u_int *);
84void *buffer_get_string_ptr_ret(Buffer *, u_int *); 86void *buffer_get_string_ptr_ret(Buffer *, u_int *);
85int buffer_get_char_ret(char *, Buffer *); 87int buffer_get_char_ret(char *, Buffer *);
86 88
diff --git a/kex.c b/kex.c
index 148cfee80..ca5aae3e4 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.82 2009/10/24 11:13:54 andreas Exp $ */ 1/* $OpenBSD: kex.c,v 1.83 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -98,7 +98,7 @@ kex_buf2prop(Buffer *raw, int *first_kex_follows)
98 buffer_get_char(&b); 98 buffer_get_char(&b);
99 /* extract kex init proposal strings */ 99 /* extract kex init proposal strings */
100 for (i = 0; i < PROPOSAL_MAX; i++) { 100 for (i = 0; i < PROPOSAL_MAX; i++) {
101 proposal[i] = buffer_get_string(&b,NULL); 101 proposal[i] = buffer_get_cstring(&b,NULL);
102 debug2("kex_parse_kexinit: %s", proposal[i]); 102 debug2("kex_parse_kexinit: %s", proposal[i]);
103 } 103 }
104 /* first kex follows / reserved */ 104 /* first kex follows / reserved */
diff --git a/key.c b/key.c
index e4aa25c03..aed4678cb 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.90 2010/07/13 23:13:16 djm Exp $ */ 1/* $OpenBSD: key.c,v 1.91 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * read_bignum(): 3 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1067,7 +1067,7 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1067 principals = exts = critical = sig_key = sig = NULL; 1067 principals = exts = critical = sig_key = sig = NULL;
1068 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) || 1068 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1069 buffer_get_int_ret(&key->cert->type, b) != 0 || 1069 buffer_get_int_ret(&key->cert->type, b) != 0 ||
1070 (key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL || 1070 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
1071 (principals = buffer_get_string_ret(b, &plen)) == NULL || 1071 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1072 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || 1072 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1073 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || 1073 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
@@ -1105,15 +1105,10 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1105 error("%s: Too many principals", __func__); 1105 error("%s: Too many principals", __func__);
1106 goto out; 1106 goto out;
1107 } 1107 }
1108 if ((principal = buffer_get_string_ret(&tmp, &plen)) == NULL) { 1108 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
1109 error("%s: Principals data invalid", __func__); 1109 error("%s: Principals data invalid", __func__);
1110 goto out; 1110 goto out;
1111 } 1111 }
1112 if (strlen(principal) != plen) {
1113 error("%s: Principal contains \\0 character",
1114 __func__);
1115 goto out;
1116 }
1117 key->cert->principals = xrealloc(key->cert->principals, 1112 key->cert->principals = xrealloc(key->cert->principals,
1118 key->cert->nprincipals + 1, sizeof(*key->cert->principals)); 1113 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1119 key->cert->principals[key->cert->nprincipals++] = principal; 1114 key->cert->principals[key->cert->nprincipals++] = principal;
@@ -1200,7 +1195,7 @@ key_from_blob(const u_char *blob, u_int blen)
1200#endif 1195#endif
1201 buffer_init(&b); 1196 buffer_init(&b);
1202 buffer_append(&b, blob, blen); 1197 buffer_append(&b, blob, blen);
1203 if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) { 1198 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
1204 error("key_from_blob: can't read key type"); 1199 error("key_from_blob: can't read key type");
1205 goto out; 1200 goto out;
1206 } 1201 }
diff --git a/packet.c b/packet.c
index 48f7fe613..49aa97335 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.168 2010/07/13 23:13:16 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.169 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1546,6 +1546,13 @@ packet_get_string_ptr(u_int *length_ptr)
1546 return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); 1546 return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr);
1547} 1547}
1548 1548
1549/* Ensures the returned string has no embedded \0 characters in it. */
1550char *
1551packet_get_cstring(u_int *length_ptr)
1552{
1553 return buffer_get_cstring(&active_state->incoming_packet, length_ptr);
1554}
1555
1549/* 1556/*
1550 * Sends a diagnostic message from the server to the client. This message 1557 * Sends a diagnostic message from the server to the client. This message
1551 * can be sent at any time (but not while constructing another message). The 1558 * can be sent at any time (but not while constructing another message). The
diff --git a/packet.h b/packet.h
index 33523d750..fd0b056fd 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.h,v 1.52 2009/06/27 09:29:06 andreas Exp $ */ 1/* $OpenBSD: packet.h,v 1.53 2010/08/31 09:58:37 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -61,6 +61,7 @@ void packet_get_bignum(BIGNUM * value);
61void packet_get_bignum2(BIGNUM * value); 61void packet_get_bignum2(BIGNUM * value);
62void *packet_get_raw(u_int *length_ptr); 62void *packet_get_raw(u_int *length_ptr);
63void *packet_get_string(u_int *length_ptr); 63void *packet_get_string(u_int *length_ptr);
64char *packet_get_cstring(u_int *length_ptr);
64void *packet_get_string_ptr(u_int *length_ptr); 65void *packet_get_string_ptr(u_int *length_ptr);
65void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2))); 66void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
66void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); 67void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
diff --git a/ssh-dss.c b/ssh-dss.c
index 175e4d030..ede5e21e5 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-dss.c,v 1.26 2010/04/16 01:47:26 djm Exp $ */ 1/* $OpenBSD: ssh-dss.c,v 1.27 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -133,7 +133,7 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
133 char *ktype; 133 char *ktype;
134 buffer_init(&b); 134 buffer_init(&b);
135 buffer_append(&b, signature, signaturelen); 135 buffer_append(&b, signature, signaturelen);
136 ktype = buffer_get_string(&b, NULL); 136 ktype = buffer_get_cstring(&b, NULL);
137 if (strcmp("ssh-dss", ktype) != 0) { 137 if (strcmp("ssh-dss", ktype) != 0) {
138 error("ssh_dss_verify: cannot handle type %s", ktype); 138 error("ssh_dss_verify: cannot handle type %s", ktype);
139 buffer_free(&b); 139 buffer_free(&b);
diff --git a/ssh-rsa.c b/ssh-rsa.c
index c471ff323..c6355fa09 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.44 2010/07/16 14:07:35 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.45 2010/08/31 09:58:37 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -127,7 +127,7 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
127 } 127 }
128 buffer_init(&b); 128 buffer_init(&b);
129 buffer_append(&b, signature, signaturelen); 129 buffer_append(&b, signature, signaturelen);
130 ktype = buffer_get_string(&b, NULL); 130 ktype = buffer_get_cstring(&b, NULL);
131 if (strcmp("ssh-rsa", ktype) != 0) { 131 if (strcmp("ssh-rsa", ktype) != 0) {
132 error("ssh_rsa_verify: cannot handle type %s", ktype); 132 error("ssh_rsa_verify: cannot handle type %s", ktype);
133 buffer_free(&b); 133 buffer_free(&b);