aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-03-24 16:11:32 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-03-24 16:11:32 +0100
commit702f7d6c0bb3242e66efb4d1c55b51e535935eab (patch)
treea84e3b3fde9a7fbf1a4bd311588dd9f0405fbf80
parenta14a9d73b1274eb7065167914b1b47d3f5e62f6b (diff)
downloadbusybox-w32-702f7d6c0bb3242e66efb4d1c55b51e535935eab.tar.gz
busybox-w32-702f7d6c0bb3242e66efb4d1c55b51e535935eab.tar.bz2
busybox-w32-702f7d6c0bb3242e66efb4d1c55b51e535935eab.zip
udhcp: we call DNS name encoder with NULL, this can SEGV. added a check
function old new delta dname_enc 418 415 -3 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/domain_codec.c80
1 files changed, 43 insertions, 37 deletions
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c
index 93dfd9a4e..c81372ad2 100644
--- a/networking/udhcp/domain_codec.c
+++ b/networking/udhcp/domain_codec.c
@@ -7,8 +7,6 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 8 */
9 9
10#if ENABLE_FEATURE_UDHCP_RFC3397
11
12#include "common.h" 10#include "common.h"
13 11
14#define NS_MAXDNAME 1025 /* max domain name length */ 12#define NS_MAXDNAME 1025 /* max domain name length */
@@ -63,7 +61,7 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
63 if (dst) 61 if (dst)
64 dst[len - 1] = '.'; 62 dst[len - 1] = '.';
65 } else { 63 } else {
66 /* null: end of current domain name */ 64 /* NUL: end of current domain name */
67 if (retpos == 0) { 65 if (retpos == 0) {
68 /* toplevel? keep going */ 66 /* toplevel? keep going */
69 crtpos++; 67 crtpos++;
@@ -107,38 +105,39 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
107 */ 105 */
108static uint8_t *convert_dname(const char *src) 106static uint8_t *convert_dname(const char *src)
109{ 107{
110 uint8_t c, *res, *lp, *rp; 108 uint8_t c, *res, *lenptr, *dst;
111 int len; 109 int len;
112 110
113 res = xmalloc(strlen(src) + 2); 111 res = xmalloc(strlen(src) + 2);
114 rp = lp = res; 112 dst = lenptr = res;
115 rp++; 113 dst++;
116 114
117 for (;;) { 115 for (;;) {
118 c = (uint8_t)*src++; 116 c = (uint8_t)*src++;
119 if (c == '.' || c == '\0') { /* end of label */ 117 if (c == '.' || c == '\0') { /* end of label */
120 len = rp - lp - 1; 118 len = dst - lenptr - 1;
121 /* label too long, too short, or two '.'s in a row? abort */ 119 /* label too long, too short, or two '.'s in a row? abort */
122 if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { 120 if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) {
123 free(res); 121 free(res);
124 return NULL; 122 return NULL;
125 } 123 }
126 *lp = len; 124 *lenptr = len;
127 lp = rp++; 125 if (c == '\0' || *src == '\0') /* "" or ".": end of src */
128 if (c == '\0' || *src == '\0') /* end of dname */
129 break; 126 break;
130 } else { 127 lenptr = dst++;
131 if (c >= 0x41 && c <= 0x5A) /* uppercase? convert to lower */ 128 continue;
132 c += 0x20;
133 *rp++ = c;
134 } 129 }
130 if (c >= 'A' && c <= 'Z') /* uppercase? convert to lower */
131 c += ('a' - 'A');
132 *dst++ = c;
135 } 133 }
136 134
137 *lp = 0; 135 if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */
138 if (rp - res > NS_MAXCDNAME) { /* dname too long? abort */
139 free(res); 136 free(res);
140 return NULL; 137 return NULL;
141 } 138 }
139
140 *dst = 0;
142 return res; 141 return res;
143} 142}
144 143
@@ -147,30 +146,35 @@ static uint8_t *convert_dname(const char *src)
147static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) 146static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname)
148{ 147{
149 const uint8_t *c, *d; 148 const uint8_t *c, *d;
150 int off, inc; 149 int off;
151 150
152 /* find all labels in cstr */ 151 /* find all labels in cstr */
153 off = 0; 152 off = 0;
154 while (off < clen) { 153 while (off < clen) {
155 c = cstr + off; 154 c = cstr + off;
156 155
157 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { /* pointer, skip */ 156 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { /* pointer, skip */
158 off += 2; 157 off += 2;
159 } else if (*c) { /* label, try matching dname */ 158 continue;
160 inc = *c + 1; 159 }
160 if (*c) { /* label, try matching dname */
161 d = dname; 161 d = dname;
162 while (*c == *d && memcmp(c + 1, d + 1, *c) == 0) { 162 while (1) {
163 if (*c == 0) /* match, return offset */ 163 unsigned len1 = *c + 1;
164 if (memcmp(c, d, len1) != 0)
165 break;
166 if (len1 == 1) /* at terminating NUL - match, return offset */
164 return off; 167 return off;
165 d += *c + 1; 168 d += len1;
166 c += *c + 1; 169 c += len1;
167 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) /* pointer, jump */ 170 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) /* pointer, jump */
168 c = cstr + (((c[0] & 0x3f) << 8) | c[1]); 171 c = cstr + (((c[0] & 0x3f) << 8) | c[1]);
169 } 172 }
170 off += inc; 173 off += cstr[off] + 1;
171 } else { /* null, skip */ 174 continue;
172 off++;
173 } 175 }
176 /* NUL, skip */
177 off++;
174 } 178 }
175 179
176 return -1; 180 return -1;
@@ -178,7 +182,7 @@ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname)
178 182
179/* computes string to be appended to cstr so that src would be added to 183/* computes string to be appended to cstr so that src would be added to
180 * the compression (best case, it's a 2-byte pointer to some offset within 184 * the compression (best case, it's a 2-byte pointer to some offset within
181 * cstr; worst case, it's all of src, converted to rfc3011 format). 185 * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format).
182 * The computed string is returned directly; its length is returned via retlen; 186 * The computed string is returned directly; its length is returned via retlen;
183 * NULL and 0, respectively, are returned if an error occurs. 187 * NULL and 0, respectively, are returned if an error occurs.
184 */ 188 */
@@ -193,17 +197,19 @@ uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int
193 return NULL; 197 return NULL;
194 } 198 }
195 199
196 for (d = dname; *d != 0; d += *d + 1) { 200 d = dname;
197 off = find_offset(cstr, clen, d); 201 while (*d) {
198 if (off >= 0) { /* found a match, add pointer and terminate string */ 202 if (cstr) {
199 *d++ = NS_CMPRSFLGS + (off >> 8); 203 off = find_offset(cstr, clen, d);
200 *d = off; 204 if (off >= 0) { /* found a match, add pointer and return */
201 break; 205 *d++ = NS_CMPRSFLGS | (off >> 8);
206 *d = off;
207 break;
208 }
202 } 209 }
210 d += *d + 1;
203 } 211 }
204 212
205 *retlen = d - dname + 1; 213 *retlen = d - dname + 1;
206 return dname; 214 return dname;
207} 215}
208
209#endif /* ENABLE_FEATURE_UDHCP_RFC3397 */