summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormillert <>1998-03-17 06:16:55 +0000
committermillert <>1998-03-17 06:16:55 +0000
commit355364933bc88bd48fdb07c2295844567e142748 (patch)
treed1bc836bbf5627f55a84ed9cc38b071eec85dbe7
parent7cc61258b3b66c62b0828fdaa234ee8ae2fee2dc (diff)
downloadopenbsd-355364933bc88bd48fdb07c2295844567e142748.tar.gz
openbsd-355364933bc88bd48fdb07c2295844567e142748.tar.bz2
openbsd-355364933bc88bd48fdb07c2295844567e142748.zip
Fix some improbable overflows:
o don't read in a hostname >= MAXHOSTNAMELEN o get rid of sscanf o check that octets passed in are <= 0xFF Also make the style consistent and add my copyright.
-rw-r--r--src/lib/libc/net/ethers.c167
1 files changed, 118 insertions, 49 deletions
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
index b2d18e9932..aa2d99c0a3 100644
--- a/src/lib/libc/net/ethers.c
+++ b/src/lib/libc/net/ethers.c
@@ -1,12 +1,43 @@
1/* 1/* $OpenBSD: ethers.c,v 1.5 1998/03/17 06:16:55 millert Exp $ */
2 * ethers(3N) a la Sun. 2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
3 * 6 *
4 * Written by Roland McGrath <roland@frob.com> 10/14/93. 7 * Redistribution and use in source and binary forms, with or without
5 * Public domain. 8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Todd C. Miller.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * ethers(3) a la Sun.
35 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
36 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
6 */ 37 */
7 38
8#if defined(LIBC_SCCS) && !defined(lint) 39#if defined(LIBC_SCCS) && !defined(lint)
9static char rcsid[] = "$OpenBSD: ethers.c,v 1.4 1998/03/16 05:06:53 millert Exp $"; 40static char rcsid[] = "$OpenBSD: ethers.c,v 1.5 1998/03/17 06:16:55 millert Exp $";
10#endif /* LIBC_SCCS and not lint */ 41#endif /* LIBC_SCCS and not lint */
11 42
12#include <sys/types.h> 43#include <sys/types.h>
@@ -20,22 +51,58 @@ static char rcsid[] = "$OpenBSD: ethers.c,v 1.4 1998/03/16 05:06:53 millert Exp
20#include <stdio.h> 51#include <stdio.h>
21#include <stdlib.h> 52#include <stdlib.h>
22#include <string.h> 53#include <string.h>
54#include <ctype.h>
23 55
24#ifndef _PATH_ETHERS 56#ifndef _PATH_ETHERS
25#define _PATH_ETHERS "/etc/ethers" 57#define _PATH_ETHERS "/etc/ethers"
26#endif 58#endif
27 59
60static char * _ether_aton __P((char *, struct ether_addr *));
61
28char * 62char *
29ether_ntoa(e) 63ether_ntoa(e)
30 struct ether_addr *e; 64 struct ether_addr *e;
31{ 65{
32 static char a[] = "xx:xx:xx:xx:xx:xx"; 66 static char a[] = "xx:xx:xx:xx:xx:xx";
33 67
34 sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", 68 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
69 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
70 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF)
71 return (NULL);
72
73 (void)sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x",
35 e->ether_addr_octet[0], e->ether_addr_octet[1], 74 e->ether_addr_octet[0], e->ether_addr_octet[1],
36 e->ether_addr_octet[2], e->ether_addr_octet[3], 75 e->ether_addr_octet[2], e->ether_addr_octet[3],
37 e->ether_addr_octet[4], e->ether_addr_octet[5]); 76 e->ether_addr_octet[4], e->ether_addr_octet[5]);
38 return a; 77
78 return (a);
79}
80
81static char *
82_ether_aton(s, e)
83 char *s;
84 struct ether_addr *e;
85{
86 int i;
87 long l;
88 char *pp;
89
90 while (isspace(*s))
91 s++;
92
93 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
94 for (i = 0; i < 6; i++) {
95 l = strtol(s, &pp, 16);
96 if (pp == s || l > 0xFF)
97 return (NULL);
98 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
99 return (NULL);
100 e->ether_addr_octet[i] = (u_char)l;
101 s = pp + 1;
102 }
103
104 /* return character after the octets ala strtol(3) */
105 return (pp);
39} 106}
40 107
41struct ether_addr * 108struct ether_addr *
@@ -43,19 +110,8 @@ ether_aton(s)
43 char *s; 110 char *s;
44{ 111{
45 static struct ether_addr n; 112 static struct ether_addr n;
46 u_int i[6]; 113
47 114 return (_ether_aton(s, &n) ? &n : NULL);
48 if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
49 &i[2], &i[3], &i[4], &i[5]) == 6) {
50 n.ether_addr_octet[0] = (u_char)i[0];
51 n.ether_addr_octet[1] = (u_char)i[1];
52 n.ether_addr_octet[2] = (u_char)i[2];
53 n.ether_addr_octet[3] = (u_char)i[3];
54 n.ether_addr_octet[4] = (u_char)i[4];
55 n.ether_addr_octet[5] = (u_char)i[5];
56 return &n;
57 }
58 return NULL;
59} 115}
60 116
61int 117int
@@ -68,8 +124,13 @@ ether_ntohost(hostname, e)
68 size_t len; 124 size_t len;
69 struct ether_addr try; 125 struct ether_addr try;
70 126
127 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
128 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
129 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF)
130 return (NULL);
131
71#ifdef YP 132#ifdef YP
72 char trybuf[sizeof "xx:xx:xx:xx:xx:xx"]; 133 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
73 int trylen; 134 int trylen;
74 135
75 sprintf(trybuf, "%x:%x:%x:%x:%x:%x", 136 sprintf(trybuf, "%x:%x:%x:%x:%x:%x",
@@ -81,18 +142,18 @@ ether_ntohost(hostname, e)
81 142
82 f = fopen(_PATH_ETHERS, "r"); 143 f = fopen(_PATH_ETHERS, "r");
83 if (f == NULL) 144 if (f == NULL)
84 return -1; 145 return (-1);
85 while ((p = fgetln(f, &len)) != NULL) { 146 while ((p = fgetln(f, &len)) != NULL) {
86 if (p[len-1] == '\n') 147 if (p[len-1] == '\n')
87 len--; 148 len--;
88 if (len > sizeof(buf) - 2) 149 if (len > sizeof(buf) - 2)
89 continue; 150 continue;
90 memcpy(buf, p, len); 151 (void)memcpy(buf, p, len);
91 buf[len] = '\n'; /* code assumes newlines later on */ 152 buf[len] = '\n'; /* code assumes newlines later on */
92 buf[len+1] = '\0'; 153 buf[len+1] = '\0';
93#ifdef YP 154#ifdef YP
94 /* A + in the file means try YP now. */ 155 /* A + in the file means try YP now. */
95 if (!strncmp(buf, "+\n", sizeof buf)) { 156 if (!strncmp(buf, "+\n", sizeof(buf))) {
96 char *ypbuf, *ypdom; 157 char *ypbuf, *ypdom;
97 int ypbuflen; 158 int ypbuflen;
98 159
@@ -104,21 +165,21 @@ ether_ntohost(hostname, e)
104 if (ether_line(ypbuf, &try, hostname) == 0) { 165 if (ether_line(ypbuf, &try, hostname) == 0) {
105 free(ypbuf); 166 free(ypbuf);
106 (void)fclose(f); 167 (void)fclose(f);
107 return 0; 168 return (0);
108 } 169 }
109 free(ypbuf); 170 free(ypbuf);
110 continue; 171 continue;
111 } 172 }
112#endif 173#endif
113 if (ether_line(buf, &try, hostname) == 0 && 174 if (ether_line(buf, &try, hostname) == 0 &&
114 memcmp((char *)&try, (char *)e, sizeof try) == 0) { 175 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
115 (void)fclose(f); 176 (void)fclose(f);
116 return 0; 177 return (0);
117 } 178 }
118 } 179 }
119 (void)fclose(f); 180 (void)fclose(f);
120 errno = ENOENT; 181 errno = ENOENT;
121 return -1; 182 return (-1);
122} 183}
123 184
124int 185int
@@ -136,7 +197,7 @@ ether_hostton(hostname, e)
136 197
137 f = fopen(_PATH_ETHERS, "r"); 198 f = fopen(_PATH_ETHERS, "r");
138 if (f==NULL) 199 if (f==NULL)
139 return -1; 200 return (-1);
140 201
141 while ((p = fgetln(f, &len)) != NULL) { 202 while ((p = fgetln(f, &len)) != NULL) {
142 if (p[len-1] == '\n') 203 if (p[len-1] == '\n')
@@ -148,7 +209,7 @@ ether_hostton(hostname, e)
148 buf[len+1] = '\0'; 209 buf[len+1] = '\0';
149#ifdef YP 210#ifdef YP
150 /* A + in the file means try YP now. */ 211 /* A + in the file means try YP now. */
151 if (!strncmp(buf, "+\n", sizeof buf)) { 212 if (!strncmp(buf, "+\n", sizeof(buf))) {
152 char *ypbuf, *ypdom; 213 char *ypbuf, *ypdom;
153 int ypbuflen; 214 int ypbuflen;
154 215
@@ -160,7 +221,7 @@ ether_hostton(hostname, e)
160 if (ether_line(ypbuf, e, try) == 0) { 221 if (ether_line(ypbuf, e, try) == 0) {
161 free(ypbuf); 222 free(ypbuf);
162 (void)fclose(f); 223 (void)fclose(f);
163 return 0; 224 return (0);
164 } 225 }
165 free(ypbuf); 226 free(ypbuf);
166 continue; 227 continue;
@@ -168,32 +229,40 @@ ether_hostton(hostname, e)
168#endif 229#endif
169 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) { 230 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
170 (void)fclose(f); 231 (void)fclose(f);
171 return 0; 232 return (0);
172 } 233 }
173 } 234 }
174 (void)fclose(f); 235 (void)fclose(f);
175 errno = ENOENT; 236 errno = ENOENT;
176 return -1; 237 return (-1);
177} 238}
178 239
179int 240int
180ether_line(l, e, hostname) 241ether_line(line, e, hostname)
181 char *l; 242 char *line;
182 struct ether_addr *e; 243 struct ether_addr *e;
183 char *hostname; 244 char *hostname;
184{ 245{
185 u_int i[6]; 246 char *p;
186 247 size_t n;
187 if (sscanf(l, " %x:%x:%x:%x:%x:%x %s\n", &i[0], &i[1], 248
188 &i[2], &i[3], &i[4], &i[5], hostname) == 7) { 249 /* Parse "xx:xx:xx:xx:xx:xx" */
189 e->ether_addr_octet[0] = (u_char)i[0]; 250 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
190 e->ether_addr_octet[1] = (u_char)i[1]; 251 goto bad;
191 e->ether_addr_octet[2] = (u_char)i[2]; 252
192 e->ether_addr_octet[3] = (u_char)i[3]; 253 /* Now get the hostname */
193 e->ether_addr_octet[4] = (u_char)i[4]; 254 while (isspace(*p))
194 e->ether_addr_octet[5] = (u_char)i[5]; 255 p++;
195 return 0; 256 if (*p == '\0')
196 } 257 goto bad;
258 n = strcspn(p, " \t\n");
259 if (n >= MAXHOSTNAMELEN)
260 goto bad;
261 (void)strncpy(hostname, p, n);
262 hostname[n] = '\0';
263 return (0);
264
265bad:
197 errno = EINVAL; 266 errno = EINVAL;
198 return -1; 267 return (-1);
199} 268}