• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * wpa_supplicant/hostapd / common helper functions, etc.
3  * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 #include <limits.h>
11 
12 #include "common/ieee802_11_defs.h"
13 #include "common.h"
14 #ifdef CONFIG_EAP_AUTH
15 #include "securec.h"
16 #define GAP_SIZE 2
17 #endif
hex2num(char c)18 static int hex2num(char c)
19 {
20 	if (c >= '0' && c <= '9')
21 		return c - '0';
22 	if (c >= 'a' && c <= 'f')
23 		return c - 'a' + 10;
24 	if (c >= 'A' && c <= 'F')
25 		return c - 'A' + 10;
26 	return -1;
27 }
28 
29 
hex2byte(const char * hex)30 int hex2byte(const char *hex)
31 {
32 	int a, b;
33 	a = hex2num(*hex++);
34 	if (a < 0)
35 		return -1;
36 	b = hex2num(*hex++);
37 	if (b < 0)
38 		return -1;
39 	return (a << 4) | b;
40 }
41 
mac_to_str(const u8 * addr)42 const char *mac_to_str(const u8 *addr)
43 {
44 	const int macAddrIndexOne = 0;
45 	const int macAddrIndexTwo = 1;
46 	const int macAddrIndexThree = 2;
47 	const int macAddrIndexFour = 3;
48 	const int macAddrIndexFive = 4;
49 	const int macAddrIndexSix = 5;
50 	static char macToStr[18];
51 	if (disable_anonymized_print()) {
52 		if (os_snprintf(macToStr, sizeof(macToStr), "%02x:%02x:%02x:%02x:%02x:%02x", addr[macAddrIndexOne],
53 			addr[macAddrIndexTwo], addr[macAddrIndexThree], addr[macAddrIndexFour],
54 			addr[macAddrIndexFive], addr[macAddrIndexSix]) < 0) {
55 				return NULL;
56 		}
57 		return macToStr;
58 	} else {
59 		if (os_snprintf(macToStr, sizeof(macToStr), "%02x:%02x:**:**:**:%02x", addr[macAddrIndexOne],
60 			addr[macAddrIndexTwo], addr[macAddrIndexSix]) < 0) {
61 			return NULL;
62 		}
63 		return macToStr;
64 	}
65 }
66 
hwaddr_parse(const char * txt,u8 * addr)67 static const char * hwaddr_parse(const char *txt, u8 *addr)
68 {
69 	size_t i;
70 
71 	for (i = 0; i < ETH_ALEN; i++) {
72 		int a;
73 
74 		a = hex2byte(txt);
75 		if (a < 0)
76 			return NULL;
77 		txt += 2;
78 		addr[i] = a;
79 		if (i < ETH_ALEN - 1 && *txt++ != ':')
80 			return NULL;
81 	}
82 	return txt;
83 }
84 
85 
86 /**
87  * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
88  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
89  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
90  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
91  */
hwaddr_aton(const char * txt,u8 * addr)92 int hwaddr_aton(const char *txt, u8 *addr)
93 {
94 	return hwaddr_parse(txt, addr) ? 0 : -1;
95 }
96 
97 
98 /**
99  * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format)
100  * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00")
101  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
102  * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes)
103  * @maskable: Flag to indicate whether a mask is allowed
104  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
105  */
hwaddr_masked_aton(const char * txt,u8 * addr,u8 * mask,u8 maskable)106 int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
107 {
108 	const char *r;
109 
110 	/* parse address part */
111 	r = hwaddr_parse(txt, addr);
112 	if (!r)
113 		return -1;
114 
115 	/* check for optional mask */
116 	if (*r == '\0' || isspace((unsigned char) *r)) {
117 		/* no mask specified, assume default */
118 		os_memset(mask, 0xff, ETH_ALEN);
119 	} else if (maskable && *r == '/') {
120 		/* mask specified and allowed */
121 		r = hwaddr_parse(r + 1, mask);
122 		/* parser error? */
123 		if (!r)
124 			return -1;
125 	} else {
126 		/* mask specified but not allowed or trailing garbage */
127 		return -1;
128 	}
129 
130 	return 0;
131 }
132 
133 
134 /**
135  * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
136  * @txt: MAC address as a string (e.g., "001122334455")
137  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
138  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
139  */
hwaddr_compact_aton(const char * txt,u8 * addr)140 int hwaddr_compact_aton(const char *txt, u8 *addr)
141 {
142 	int i;
143 
144 	for (i = 0; i < 6; i++) {
145 		int a, b;
146 
147 		a = hex2num(*txt++);
148 		if (a < 0)
149 			return -1;
150 		b = hex2num(*txt++);
151 		if (b < 0)
152 			return -1;
153 		*addr++ = (a << 4) | b;
154 	}
155 
156 	return 0;
157 }
158 
159 /**
160  * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
161  * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
162  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
163  * Returns: Characters used (> 0) on success, -1 on failure
164  */
hwaddr_aton2(const char * txt,u8 * addr)165 int hwaddr_aton2(const char *txt, u8 *addr)
166 {
167 	int i;
168 	const char *pos = txt;
169 
170 	for (i = 0; i < 6; i++) {
171 		int a, b;
172 
173 		while (*pos == ':' || *pos == '.' || *pos == '-')
174 			pos++;
175 
176 		a = hex2num(*pos++);
177 		if (a < 0)
178 			return -1;
179 		b = hex2num(*pos++);
180 		if (b < 0)
181 			return -1;
182 		*addr++ = (a << 4) | b;
183 	}
184 
185 	return pos - txt;
186 }
187 
188 
189 /**
190  * hexstr2bin - Convert ASCII hex string into binary data
191  * @hex: ASCII hex string (e.g., "01ab")
192  * @buf: Buffer for the binary data
193  * @len: Length of the text to convert in bytes (of buf); hex will be double
194  * this size
195  * Returns: 0 on success, -1 on failure (invalid hex string)
196  */
hexstr2bin(const char * hex,u8 * buf,size_t len)197 int hexstr2bin(const char *hex, u8 *buf, size_t len)
198 {
199 	size_t i;
200 	int a;
201 	const char *ipos = hex;
202 	u8 *opos = buf;
203 
204 	for (i = 0; i < len; i++) {
205 		a = hex2byte(ipos);
206 		if (a < 0)
207 			return -1;
208 		*opos++ = a;
209 		ipos += 2;
210 	}
211 	return 0;
212 }
213 
214 #ifdef CONFIG_EAP_AUTH
bin2hexstr(const unsigned char * bin,size_t bin_len,char * hexstr,size_t hexstr_len)215 void bin2hexstr(const unsigned char* bin, size_t bin_len, char* hexstr, size_t hexstr_len)
216 {
217 	size_t hexstr_index = 0;
218 	for (size_t i = 0; i < bin_len; i++) {
219 		if (os_snprintf(hexstr + hexstr_index, hexstr_len - hexstr_index, "%02x", bin[i]) <= 0) {
220 			printf("bin2hexstr fail\n");
221 		}
222 		hexstr_index += GAP_SIZE;
223 		if (hexstr_index >= hexstr_len) {
224 			break;
225 		}
226 	}
227 }
228 #endif
229 
hwaddr_mask_txt(char * buf,size_t len,const u8 * addr,const u8 * mask)230 int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask)
231 {
232 	size_t i;
233 	int print_mask = 0;
234 	int res;
235 
236 	for (i = 0; i < ETH_ALEN; i++) {
237 		if (mask[i] != 0xff) {
238 			print_mask = 1;
239 			break;
240 		}
241 	}
242 
243 	if (print_mask)
244 		res = os_snprintf(buf, len, MACSTR "/" MACSTR,
245 				  MAC2STR(addr), MAC2STR(mask));
246 	else
247 		res = os_snprintf(buf, len, MACSTR, MAC2STR(addr));
248 	if (os_snprintf_error(len, res))
249 		return -1;
250 	return res;
251 }
252 
253 
254 /**
255  * inc_byte_array - Increment arbitrary length byte array by one
256  * @counter: Pointer to byte array
257  * @len: Length of the counter in bytes
258  *
259  * This function increments the last byte of the counter by one and continues
260  * rolling over to more significant bytes if the byte was incremented from
261  * 0xff to 0x00.
262  */
inc_byte_array(u8 * counter,size_t len)263 void inc_byte_array(u8 *counter, size_t len)
264 {
265 	int pos = len - 1;
266 	while (pos >= 0) {
267 		counter[pos]++;
268 		if (counter[pos] != 0)
269 			break;
270 		pos--;
271 	}
272 }
273 
274 
buf_shift_right(u8 * buf,size_t len,size_t bits)275 void buf_shift_right(u8 *buf, size_t len, size_t bits)
276 {
277 	size_t i;
278 
279 	for (i = len - 1; i > 0; i--)
280 		buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
281 	buf[0] >>= bits;
282 }
283 
284 
wpa_get_ntp_timestamp(u8 * buf)285 void wpa_get_ntp_timestamp(u8 *buf)
286 {
287 	struct os_time now;
288 	u32 sec, usec;
289 	be32 tmp;
290 
291 	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
292 	os_get_time(&now);
293 	sec = now.sec + 2208988800U; /* Epoch to 1900 */
294 	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
295 	usec = now.usec;
296 	usec = 4295 * usec - (usec >> 5) - (usec >> 9);
297 	tmp = host_to_be32(sec);
298 	os_memcpy(buf, (u8 *) &tmp, 4);
299 	tmp = host_to_be32(usec);
300 	os_memcpy(buf + 4, (u8 *) &tmp, 4);
301 }
302 
303 /**
304  * wpa_scnprintf - Simpler-to-use snprintf function
305  * @buf: Output buffer
306  * @size: Buffer size
307  * @fmt: format
308  *
309  * Simpler snprintf version that doesn't require further error checks - the
310  * return value only indicates how many bytes were actually written, excluding
311  * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough).
312  */
wpa_scnprintf(char * buf,size_t size,const char * fmt,...)313 int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...)
314 {
315 	va_list ap;
316 	int ret;
317 
318 	if (!size)
319 		return 0;
320 
321 	va_start(ap, fmt);
322 	ret = vsnprintf(buf, size, fmt, ap);
323 	va_end(ap);
324 
325 	if (ret < 0)
326 		return 0;
327 	if ((size_t) ret >= size)
328 		return size - 1;
329 
330 	return ret;
331 }
332 
333 
wpa_snprintf_hex_sep(char * buf,size_t buf_size,const u8 * data,size_t len,char sep)334 int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
335 			 char sep)
336 {
337 	size_t i;
338 	char *pos = buf, *end = buf + buf_size;
339 	int ret;
340 
341 	if (buf_size == 0)
342 		return 0;
343 
344 	for (i = 0; i < len; i++) {
345 		ret = os_snprintf(pos, end - pos, "%02x%c",
346 				  data[i], sep);
347 		if (os_snprintf_error(end - pos, ret)) {
348 			end[-1] = '\0';
349 			return pos - buf;
350 		}
351 		pos += ret;
352 	}
353 	pos[-1] = '\0';
354 	return pos - buf;
355 }
356 
357 
_wpa_snprintf_hex(char * buf,size_t buf_size,const u8 * data,size_t len,int uppercase)358 static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
359 				    size_t len, int uppercase)
360 {
361 	size_t i;
362 	char *pos = buf, *end = buf + buf_size;
363 	int ret;
364 	if (buf_size == 0)
365 		return 0;
366 	for (i = 0; i < len; i++) {
367 		ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x",
368 				  data[i]);
369 		if (os_snprintf_error(end - pos, ret)) {
370 			end[-1] = '\0';
371 			return pos - buf;
372 		}
373 		pos += ret;
374 	}
375 	end[-1] = '\0';
376 	return pos - buf;
377 }
378 
379 /**
380  * wpa_snprintf_hex - Print data as a hex string into a buffer
381  * @buf: Memory area to use as the output buffer
382  * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
383  * @data: Data to be printed
384  * @len: Length of data in bytes
385  * Returns: Number of bytes written
386  */
wpa_snprintf_hex(char * buf,size_t buf_size,const u8 * data,size_t len)387 int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
388 {
389 	return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
390 }
391 
392 
393 /**
394  * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
395  * @buf: Memory area to use as the output buffer
396  * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
397  * @data: Data to be printed
398  * @len: Length of data in bytes
399  * Returns: Number of bytes written
400  */
wpa_snprintf_hex_uppercase(char * buf,size_t buf_size,const u8 * data,size_t len)401 int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
402 			       size_t len)
403 {
404 	return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
405 }
406 
407 
408 #ifdef CONFIG_ANSI_C_EXTRA
409 
410 #ifdef _WIN32_WCE
perror(const char * s)411 void perror(const char *s)
412 {
413 	wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
414 		   s, (int) GetLastError());
415 }
416 #endif /* _WIN32_WCE */
417 
418 
419 int optind = 1;
420 int optopt;
421 char *optarg;
422 
getopt(int argc,char * const argv[],const char * optstring)423 int getopt(int argc, char *const argv[], const char *optstring)
424 {
425 	static int optchr = 1;
426 	char *cp;
427 
428 	if (optchr == 1) {
429 		if (optind >= argc) {
430 			/* all arguments processed */
431 			return EOF;
432 		}
433 
434 		if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
435 			/* no option characters */
436 			return EOF;
437 		}
438 	}
439 
440 	if (os_strcmp(argv[optind], "--") == 0) {
441 		/* no more options */
442 		optind++;
443 		return EOF;
444 	}
445 
446 	optopt = argv[optind][optchr];
447 	cp = os_strchr(optstring, optopt);
448 	if (cp == NULL || optopt == ':') {
449 		if (argv[optind][++optchr] == '\0') {
450 			optchr = 1;
451 			optind++;
452 		}
453 		return '?';
454 	}
455 
456 	if (cp[1] == ':') {
457 		/* Argument required */
458 		optchr = 1;
459 		if (argv[optind][optchr + 1]) {
460 			/* No space between option and argument */
461 			optarg = &argv[optind++][optchr + 1];
462 		} else if (++optind >= argc) {
463 			/* option requires an argument */
464 			return '?';
465 		} else {
466 			/* Argument in the next argv */
467 			optarg = argv[optind++];
468 		}
469 	} else {
470 		/* No argument */
471 		if (argv[optind][++optchr] == '\0') {
472 			optchr = 1;
473 			optind++;
474 		}
475 		optarg = NULL;
476 	}
477 	return *cp;
478 }
479 #endif /* CONFIG_ANSI_C_EXTRA */
480 
481 
482 #ifdef CONFIG_NATIVE_WINDOWS
483 /**
484  * wpa_unicode2ascii_inplace - Convert unicode string into ASCII
485  * @str: Pointer to string to convert
486  *
487  * This function converts a unicode string to ASCII using the same
488  * buffer for output. If UNICODE is not set, the buffer is not
489  * modified.
490  */
wpa_unicode2ascii_inplace(TCHAR * str)491 void wpa_unicode2ascii_inplace(TCHAR *str)
492 {
493 #ifdef UNICODE
494 	char *dst = (char *) str;
495 	while (*str)
496 		*dst++ = (char) *str++;
497 	*dst = '\0';
498 #endif /* UNICODE */
499 }
500 
501 
wpa_strdup_tchar(const char * str)502 TCHAR * wpa_strdup_tchar(const char *str)
503 {
504 #ifdef UNICODE
505 	TCHAR *buf;
506 	buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
507 	if (buf == NULL)
508 		return NULL;
509 	wsprintf(buf, L"%S", str);
510 	return buf;
511 #else /* UNICODE */
512 	return os_strdup(str);
513 #endif /* UNICODE */
514 }
515 #endif /* CONFIG_NATIVE_WINDOWS */
516 
517 
printf_encode(char * txt,size_t maxlen,const u8 * data,size_t len)518 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
519 {
520 	char *end = txt + maxlen;
521 	size_t i;
522 
523 	for (i = 0; i < len; i++) {
524 		if (txt + 4 >= end)
525 			break;
526 
527 		switch (data[i]) {
528 		case '\"':
529 			*txt++ = '\\';
530 			*txt++ = '\"';
531 			break;
532 		case '\\':
533 			*txt++ = '\\';
534 			*txt++ = '\\';
535 			break;
536 		case '\033':
537 			*txt++ = '\\';
538 			*txt++ = 'e';
539 			break;
540 		case '\n':
541 			*txt++ = '\\';
542 			*txt++ = 'n';
543 			break;
544 		case '\r':
545 			*txt++ = '\\';
546 			*txt++ = 'r';
547 			break;
548 		case '\t':
549 			*txt++ = '\\';
550 			*txt++ = 't';
551 			break;
552 		default:
553 			if (data[i] >= 32 && data[i] <= 126) {
554 				*txt++ = data[i];
555 			} else {
556 				txt += os_snprintf(txt, end - txt, "\\x%02x",
557 						   data[i]);
558 			}
559 			break;
560 		}
561 	}
562 
563 	*txt = '\0';
564 }
565 
566 
printf_decode(u8 * buf,size_t maxlen,const char * str)567 size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
568 {
569 	const char *pos = str;
570 	size_t len = 0;
571 	int val;
572 
573 	while (*pos) {
574 		if (len + 1 >= maxlen)
575 			break;
576 		switch (*pos) {
577 		case '\\':
578 			pos++;
579 			switch (*pos) {
580 			case '\\':
581 				buf[len++] = '\\';
582 				pos++;
583 				break;
584 			case '"':
585 				buf[len++] = '"';
586 				pos++;
587 				break;
588 			case 'n':
589 				buf[len++] = '\n';
590 				pos++;
591 				break;
592 			case 'r':
593 				buf[len++] = '\r';
594 				pos++;
595 				break;
596 			case 't':
597 				buf[len++] = '\t';
598 				pos++;
599 				break;
600 			case 'e':
601 				buf[len++] = '\033';
602 				pos++;
603 				break;
604 			case 'x':
605 				pos++;
606 				val = hex2byte(pos);
607 				if (val < 0) {
608 					val = hex2num(*pos);
609 					if (val < 0)
610 						break;
611 					buf[len++] = val;
612 					pos++;
613 				} else {
614 					buf[len++] = val;
615 					pos += 2;
616 				}
617 				break;
618 			case '0':
619 			case '1':
620 			case '2':
621 			case '3':
622 			case '4':
623 			case '5':
624 			case '6':
625 			case '7':
626 				val = *pos++ - '0';
627 				if (*pos >= '0' && *pos <= '7')
628 					val = val * 8 + (*pos++ - '0');
629 				if (*pos >= '0' && *pos <= '7')
630 					val = val * 8 + (*pos++ - '0');
631 				buf[len++] = val;
632 				break;
633 			default:
634 				break;
635 			}
636 			break;
637 		default:
638 			buf[len++] = *pos++;
639 			break;
640 		}
641 	}
642 	if (maxlen > len)
643 		buf[len] = '\0';
644 
645 	return len;
646 }
647 
648 
649 /**
650  * wpa_ssid_txt - Convert SSID to a printable string
651  * @ssid: SSID (32-octet string)
652  * @ssid_len: Length of ssid in octets
653  * Returns: Pointer to a printable string
654  *
655  * This function can be used to convert SSIDs into printable form. In most
656  * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
657  * does not limit the used character set, so anything could be used in an SSID.
658  *
659  * This function uses a static buffer, so only one call can be used at the
660  * time, i.e., this is not re-entrant and the returned buffer must be used
661  * before calling this again.
662  */
wpa_ssid_txt(const u8 * ssid,size_t ssid_len)663 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
664 {
665 	static char ssid_txt[SSID_MAX_LEN * 4 + 1];
666 
667 	if (ssid == NULL) {
668 		ssid_txt[0] = '\0';
669 		return ssid_txt;
670 	}
671 
672 	printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
673 	return ssid_txt;
674 }
675 
676 
__hide_aliasing_typecast(void * foo)677 void * __hide_aliasing_typecast(void *foo)
678 {
679 	return foo;
680 }
681 
682 
wpa_config_parse_string(const char * value,size_t * len)683 char * wpa_config_parse_string(const char *value, size_t *len)
684 {
685 	if (*value == '"') {
686 		const char *pos;
687 		char *str;
688 		value++;
689 		pos = os_strrchr(value, '"');
690 		if (pos == NULL || pos[1] != '\0')
691 			return NULL;
692 		*len = pos - value;
693 		str = dup_binstr(value, *len);
694 		if (str == NULL)
695 			return NULL;
696 		return str;
697 	} else if (*value == 'P' && value[1] == '"') {
698 		const char *pos;
699 		char *tstr, *str;
700 		size_t tlen;
701 		value += 2;
702 		pos = os_strrchr(value, '"');
703 		if (pos == NULL || pos[1] != '\0')
704 			return NULL;
705 		tlen = pos - value;
706 		tstr = dup_binstr(value, tlen);
707 		if (tstr == NULL)
708 			return NULL;
709 
710 		str = os_malloc(tlen + 1);
711 		if (str == NULL) {
712 			os_free(tstr);
713 			return NULL;
714 		}
715 
716 		*len = printf_decode((u8 *) str, tlen + 1, tstr);
717 		os_free(tstr);
718 
719 		return str;
720 	} else {
721 		u8 *str;
722 		size_t tlen, hlen = os_strlen(value);
723 		if (hlen & 1)
724 			return NULL;
725 		tlen = hlen / 2;
726 		str = os_malloc(tlen + 1);
727 		if (str == NULL)
728 			return NULL;
729 		if (hexstr2bin(value, str, tlen)) {
730 			os_free(str);
731 			return NULL;
732 		}
733 		str[tlen] = '\0';
734 		*len = tlen;
735 		return (char *) str;
736 	}
737 }
738 
739 
is_hex(const u8 * data,size_t len)740 int is_hex(const u8 *data, size_t len)
741 {
742 	size_t i;
743 
744 	for (i = 0; i < len; i++) {
745 		if (data[i] < 32 || data[i] >= 127)
746 			return 1;
747 	}
748 	return 0;
749 }
750 
751 
has_ctrl_char(const u8 * data,size_t len)752 int has_ctrl_char(const u8 *data, size_t len)
753 {
754 	size_t i;
755 
756 	for (i = 0; i < len; i++) {
757 		if (data[i] < 32 || data[i] == 127)
758 			return 1;
759 	}
760 	return 0;
761 }
762 
763 
has_newline(const char * str)764 int has_newline(const char *str)
765 {
766 	while (*str) {
767 		if (*str == '\n' || *str == '\r')
768 			return 1;
769 		str++;
770 	}
771 	return 0;
772 }
773 
774 
merge_byte_arrays(u8 * res,size_t res_len,const u8 * src1,size_t src1_len,const u8 * src2,size_t src2_len)775 size_t merge_byte_arrays(u8 *res, size_t res_len,
776 			 const u8 *src1, size_t src1_len,
777 			 const u8 *src2, size_t src2_len)
778 {
779 	size_t len = 0;
780 
781 	os_memset(res, 0, res_len);
782 
783 	if (src1) {
784 		if (src1_len >= res_len) {
785 			os_memcpy(res, src1, res_len);
786 			return res_len;
787 		}
788 
789 		os_memcpy(res, src1, src1_len);
790 		len += src1_len;
791 	}
792 
793 	if (src2) {
794 		if (len + src2_len >= res_len) {
795 			os_memcpy(res + len, src2, res_len - len);
796 			return res_len;
797 		}
798 
799 		os_memcpy(res + len, src2, src2_len);
800 		len += src2_len;
801 	}
802 
803 	return len;
804 }
805 
806 
dup_binstr(const void * src,size_t len)807 char * dup_binstr(const void *src, size_t len)
808 {
809 	char *res;
810 
811 	if (src == NULL)
812 		return NULL;
813 	res = os_malloc(len + 1);
814 	if (res == NULL)
815 		return NULL;
816 	os_memcpy(res, src, len);
817 	res[len] = '\0';
818 
819 	return res;
820 }
821 
822 
freq_range_list_parse(struct wpa_freq_range_list * res,const char * value)823 int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
824 {
825 	struct wpa_freq_range *freq = NULL, *n;
826 	unsigned int count = 0;
827 	const char *pos, *pos2, *pos3;
828 
829 	/*
830 	 * Comma separated list of frequency ranges.
831 	 * For example: 2412-2432,2462,5000-6000
832 	 */
833 	pos = value;
834 	while (pos && pos[0]) {
835 		if (count == UINT_MAX) {
836 			os_free(freq);
837 			return -1;
838 		}
839 		n = os_realloc_array(freq, count + 1,
840 				     sizeof(struct wpa_freq_range));
841 		if (n == NULL) {
842 			os_free(freq);
843 			return -1;
844 		}
845 		freq = n;
846 		freq[count].min = atoi(pos);
847 		pos2 = os_strchr(pos, '-');
848 		pos3 = os_strchr(pos, ',');
849 		if (pos2 && (!pos3 || pos2 < pos3)) {
850 			pos2++;
851 			freq[count].max = atoi(pos2);
852 		} else
853 			freq[count].max = freq[count].min;
854 		pos = pos3;
855 		if (pos)
856 			pos++;
857 		count++;
858 	}
859 
860 	os_free(res->range);
861 	res->range = freq;
862 	res->num = count;
863 
864 	return 0;
865 }
866 
867 
freq_range_list_includes(const struct wpa_freq_range_list * list,unsigned int freq)868 int freq_range_list_includes(const struct wpa_freq_range_list *list,
869 			     unsigned int freq)
870 {
871 	unsigned int i;
872 
873 	if (list == NULL)
874 		return 0;
875 
876 	for (i = 0; i < list->num; i++) {
877 		if (freq >= list->range[i].min && freq <= list->range[i].max)
878 			return 1;
879 	}
880 
881 	return 0;
882 }
883 
884 
freq_range_list_str(const struct wpa_freq_range_list * list)885 char * freq_range_list_str(const struct wpa_freq_range_list *list)
886 {
887 	char *buf, *pos, *end;
888 	size_t maxlen;
889 	unsigned int i;
890 	int res;
891 
892 	if (list->num == 0)
893 		return NULL;
894 
895 	maxlen = list->num * 30;
896 	buf = os_malloc(maxlen);
897 	if (buf == NULL)
898 		return NULL;
899 	pos = buf;
900 	end = buf + maxlen;
901 
902 	for (i = 0; i < list->num; i++) {
903 		struct wpa_freq_range *range = &list->range[i];
904 
905 		if (range->min == range->max)
906 			res = os_snprintf(pos, end - pos, "%s%u",
907 					  i == 0 ? "" : ",", range->min);
908 		else
909 			res = os_snprintf(pos, end - pos, "%s%u-%u",
910 					  i == 0 ? "" : ",",
911 					  range->min, range->max);
912 		if (os_snprintf_error(end - pos, res)) {
913 			os_free(buf);
914 			return NULL;
915 		}
916 		pos += res;
917 	}
918 
919 	return buf;
920 }
921 
922 
int_array_len(const int * a)923 size_t int_array_len(const int *a)
924 {
925 	size_t i;
926 
927 	for (i = 0; a && a[i]; i++)
928 		;
929 	return i;
930 }
931 
932 
int_array_concat(int ** res,const int * a)933 void int_array_concat(int **res, const int *a)
934 {
935 	size_t reslen, alen, i, max_size;
936 	int *n;
937 
938 	reslen = int_array_len(*res);
939 	alen = int_array_len(a);
940 	max_size = (size_t) -1;
941 	if (alen >= max_size - reslen) {
942 		/* This should not really happen, but if it did, something
943 		 * would overflow. Do not try to merge the arrays; instead, make
944 		 * this behave like memory allocation failure to avoid messing
945 		 * up memory. */
946 		os_free(*res);
947 		*res = NULL;
948 		return;
949 	}
950 	n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
951 	if (n == NULL) {
952 		os_free(*res);
953 		*res = NULL;
954 		return;
955 	}
956 	for (i = 0; i <= alen; i++)
957 		n[reslen + i] = a[i];
958 	*res = n;
959 }
960 
961 
freq_cmp(const void * a,const void * b)962 static int freq_cmp(const void *a, const void *b)
963 {
964 	int _a = *(int *) a;
965 	int _b = *(int *) b;
966 
967 	if (_a == 0)
968 		return 1;
969 	if (_b == 0)
970 		return -1;
971 	return _a - _b;
972 }
973 
974 
int_array_sort_unique(int * a)975 void int_array_sort_unique(int *a)
976 {
977 	size_t alen, i, j;
978 
979 	if (a == NULL)
980 		return;
981 
982 	alen = int_array_len(a);
983 	qsort(a, alen, sizeof(int), freq_cmp);
984 
985 	i = 0;
986 	j = 1;
987 	while (a[i] && a[j]) {
988 		if (a[i] == a[j]) {
989 			j++;
990 			continue;
991 		}
992 		a[++i] = a[j++];
993 	}
994 	if (a[i])
995 		i++;
996 	a[i] = 0;
997 }
998 
999 
int_array_add_unique(int ** res,int a)1000 void int_array_add_unique(int **res, int a)
1001 {
1002 	size_t reslen, max_size;
1003 	int *n;
1004 
1005 	for (reslen = 0; *res && (*res)[reslen]; reslen++) {
1006 		if ((*res)[reslen] == a)
1007 			return; /* already in the list */
1008 	}
1009 
1010 	max_size = (size_t) -1;
1011 	if (reslen > max_size - 2) {
1012 		/* This should not really happen in practice, but if it did,
1013 		 * something would overflow. Do not try to add the new value;
1014 		 * instead, make this behave like memory allocation failure to
1015 		 * avoid messing up memory. */
1016 		os_free(*res);
1017 		*res = NULL;
1018 		return;
1019 	}
1020 	n = os_realloc_array(*res, reslen + 2, sizeof(int));
1021 	if (n == NULL) {
1022 		os_free(*res);
1023 		*res = NULL;
1024 		return;
1025 	}
1026 
1027 	n[reslen] = a;
1028 	n[reslen + 1] = 0;
1029 
1030 	*res = n;
1031 }
1032 
1033 
str_clear_free(char * str)1034 void str_clear_free(char *str)
1035 {
1036 	if (str) {
1037 		size_t len = os_strlen(str);
1038 		forced_memzero(str, len);
1039 		os_free(str);
1040 	}
1041 }
1042 
1043 
bin_clear_free(void * bin,size_t len)1044 void bin_clear_free(void *bin, size_t len)
1045 {
1046 	if (bin) {
1047 		forced_memzero(bin, len);
1048 		os_free(bin);
1049 	}
1050 }
1051 
1052 
random_mac_addr(u8 * addr)1053 int random_mac_addr(u8 *addr)
1054 {
1055 	if (os_get_random(addr, ETH_ALEN) < 0)
1056 		return -1;
1057 	addr[0] &= 0xfe; /* unicast */
1058 	addr[0] |= 0x02; /* locally administered */
1059 	return 0;
1060 }
1061 
1062 
random_mac_addr_keep_oui(u8 * addr)1063 int random_mac_addr_keep_oui(u8 *addr)
1064 {
1065 	if (os_get_random(addr + 3, 3) < 0)
1066 		return -1;
1067 	addr[0] &= 0xfe; /* unicast */
1068 	addr[0] |= 0x02; /* locally administered */
1069 	return 0;
1070 }
1071 
1072 
1073 /**
1074  * cstr_token - Get next token from const char string
1075  * @str: a constant string to tokenize
1076  * @delim: a string of delimiters
1077  * @last: a pointer to a character following the returned token
1078  *      It has to be set to NULL for the first call and passed for any
1079  *      further call.
1080  * Returns: a pointer to token position in str or NULL
1081  *
1082  * This function is similar to str_token, but it can be used with both
1083  * char and const char strings. Differences:
1084  * - The str buffer remains unmodified
1085  * - The returned token is not a NULL terminated string, but a token
1086  *   position in str buffer. If a return value is not NULL a size
1087  *   of the returned token could be calculated as (last - token).
1088  */
cstr_token(const char * str,const char * delim,const char ** last)1089 const char * cstr_token(const char *str, const char *delim, const char **last)
1090 {
1091 	const char *end, *token = str;
1092 
1093 	if (!str || !delim || !last)
1094 		return NULL;
1095 
1096 	if (*last)
1097 		token = *last;
1098 
1099 	while (*token && os_strchr(delim, *token))
1100 		token++;
1101 
1102 	if (!*token)
1103 		return NULL;
1104 
1105 	end = token + 1;
1106 
1107 	while (*end && !os_strchr(delim, *end))
1108 		end++;
1109 
1110 	*last = end;
1111 	return token;
1112 }
1113 
1114 
1115 /**
1116  * str_token - Get next token from a string
1117  * @buf: String to tokenize. Note that the string might be modified.
1118  * @delim: String of delimiters
1119  * @context: Pointer to save our context. Should be initialized with
1120  *	NULL on the first call, and passed for any further call.
1121  * Returns: The next token, NULL if there are no more valid tokens.
1122  */
str_token(char * str,const char * delim,char ** context)1123 char * str_token(char *str, const char *delim, char **context)
1124 {
1125 	char *token = (char *) cstr_token(str, delim, (const char **) context);
1126 
1127 	if (token && **context)
1128 		*(*context)++ = '\0';
1129 
1130 	return token;
1131 }
1132 
1133 
utf8_unescape(const char * inp,size_t in_size,char * outp,size_t out_size)1134 size_t utf8_unescape(const char *inp, size_t in_size,
1135 		     char *outp, size_t out_size)
1136 {
1137 	size_t res_size = 0;
1138 
1139 	if (!inp || !outp)
1140 		return 0;
1141 
1142 	if (!in_size)
1143 		in_size = os_strlen(inp);
1144 
1145 	/* Advance past leading single quote */
1146 	if (*inp == '\'' && in_size) {
1147 		inp++;
1148 		in_size--;
1149 	}
1150 
1151 	while (in_size) {
1152 		in_size--;
1153 		if (res_size >= out_size)
1154 			return 0;
1155 
1156 		switch (*inp) {
1157 		case '\'':
1158 			/* Terminate on bare single quote */
1159 			*outp = '\0';
1160 			return res_size;
1161 
1162 		case '\\':
1163 			if (!in_size)
1164 				return 0;
1165 			in_size--;
1166 			inp++;
1167 			/* fall through */
1168 
1169 		default:
1170 			*outp++ = *inp++;
1171 			res_size++;
1172 		}
1173 	}
1174 
1175 	/* NUL terminate if space allows */
1176 	if (res_size < out_size)
1177 		*outp = '\0';
1178 
1179 	return res_size;
1180 }
1181 
1182 
utf8_escape(const char * inp,size_t in_size,char * outp,size_t out_size)1183 size_t utf8_escape(const char *inp, size_t in_size,
1184 		   char *outp, size_t out_size)
1185 {
1186 	size_t res_size = 0;
1187 
1188 	if (!inp || !outp)
1189 		return 0;
1190 
1191 	/* inp may or may not be NUL terminated, but must be if 0 size
1192 	 * is specified */
1193 	if (!in_size)
1194 		in_size = os_strlen(inp);
1195 
1196 	while (in_size) {
1197 		in_size--;
1198 		if (res_size++ >= out_size)
1199 			return 0;
1200 
1201 		switch (*inp) {
1202 		case '\\':
1203 		case '\'':
1204 			if (res_size++ >= out_size)
1205 				return 0;
1206 			*outp++ = '\\';
1207 			/* fall through */
1208 
1209 		default:
1210 			*outp++ = *inp++;
1211 			break;
1212 		}
1213 	}
1214 
1215 	/* NUL terminate if space allows */
1216 	if (res_size < out_size)
1217 		*outp = '\0';
1218 
1219 	return res_size;
1220 }
1221 
1222 
is_ctrl_char(char c)1223 int is_ctrl_char(char c)
1224 {
1225 	return c > 0 && c < 32;
1226 }
1227 
1228 
1229 /**
1230  * ssid_parse - Parse a string that contains SSID in hex or text format
1231  * @buf: Input NULL terminated string that contains the SSID
1232  * @ssid: Output SSID
1233  * Returns: 0 on success, -1 otherwise
1234  *
1235  * The SSID has to be enclosed in double quotes for the text format or space
1236  * or NULL terminated string of hex digits for the hex format. buf can include
1237  * additional arguments after the SSID.
1238  */
ssid_parse(const char * buf,struct wpa_ssid_value * ssid)1239 int ssid_parse(const char *buf, struct wpa_ssid_value *ssid)
1240 {
1241 	char *tmp, *res, *end;
1242 	size_t len;
1243 
1244 	ssid->ssid_len = 0;
1245 
1246 	tmp = os_strdup(buf);
1247 	if (!tmp)
1248 		return -1;
1249 
1250 	if (*tmp != '"') {
1251 		end = os_strchr(tmp, ' ');
1252 		if (end)
1253 			*end = '\0';
1254 	} else {
1255 		end = os_strchr(tmp + 1, '"');
1256 		if (!end) {
1257 			os_free(tmp);
1258 			return -1;
1259 		}
1260 
1261 		end[1] = '\0';
1262 	}
1263 
1264 	res = wpa_config_parse_string(tmp, &len);
1265 	if (res && len <= SSID_MAX_LEN) {
1266 		ssid->ssid_len = len;
1267 		os_memcpy(ssid->ssid, res, len);
1268 	}
1269 
1270 	os_free(tmp);
1271 	os_free(res);
1272 
1273 	return ssid->ssid_len ? 0 : -1;
1274 }
1275 
1276 
str_starts(const char * str,const char * start)1277 int str_starts(const char *str, const char *start)
1278 {
1279 	return os_strncmp(str, start, os_strlen(start)) == 0;
1280 }
1281 
1282 
1283 /**
1284  * rssi_to_rcpi - Convert RSSI to RCPI
1285  * @rssi: RSSI to convert
1286  * Returns: RCPI corresponding to the given RSSI value, or 255 if not available.
1287  *
1288  * It's possible to estimate RCPI based on RSSI in dBm. This calculation will
1289  * not reflect the correct value for high rates, but it's good enough for Action
1290  * frames which are transmitted with up to 24 Mbps rates.
1291  */
rssi_to_rcpi(int rssi)1292 u8 rssi_to_rcpi(int rssi)
1293 {
1294 	if (!rssi)
1295 		return 255; /* not available */
1296 	if (rssi < -110)
1297 		return 0;
1298 	if (rssi > 0)
1299 		return 220;
1300 	return (rssi + 110) * 2;
1301 }
1302 
1303 
get_param(const char * cmd,const char * param)1304 char * get_param(const char *cmd, const char *param)
1305 {
1306 	const char *pos, *end;
1307 	char *val;
1308 	size_t len;
1309 
1310 	pos = os_strstr(cmd, param);
1311 	if (!pos)
1312 		return NULL;
1313 
1314 	pos += os_strlen(param);
1315 	end = os_strchr(pos, ' ');
1316 	if (end)
1317 		len = end - pos;
1318 	else
1319 		len = os_strlen(pos);
1320 	val = os_malloc(len + 1);
1321 	if (!val)
1322 		return NULL;
1323 	os_memcpy(val, pos, len);
1324 	val[len] = '\0';
1325 	return val;
1326 }
1327 
1328 
1329 /* Try to prevent most compilers from optimizing out clearing of memory that
1330  * becomes unaccessible after this function is called. This is mostly the case
1331  * for clearing local stack variables at the end of a function. This is not
1332  * exactly perfect, i.e., someone could come up with a compiler that figures out
1333  * the pointer is pointing to memset and then end up optimizing the call out, so
1334  * try go a bit further by storing the first octet (now zero) to make this even
1335  * a bit more difficult to optimize out. Once memset_s() is available, that
1336  * could be used here instead. */
1337 static void * (* const volatile memset_func)(void *, int, size_t) = memset;
1338 static u8 forced_memzero_val;
1339 
forced_memzero(void * ptr,size_t len)1340 void forced_memzero(void *ptr, size_t len)
1341 {
1342 	memset_func(ptr, 0, len);
1343 	if (len)
1344 		forced_memzero_val = ((u8 *) ptr)[0];
1345 }
1346