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 <time.h>
13 #include "common/ieee802_11_defs.h"
14 #include "common.h"
15
16 // -Wimplicit-function-declaration
17 extern time_t mktime(struct tm*);
18
hex2num(char c)19 static int hex2num(char c)
20 {
21 if (c >= '0' && c <= '9')
22 return c - '0';
23 if (c >= 'a' && c <= 'f')
24 return c - 'a' + 10;
25 if (c >= 'A' && c <= 'F')
26 return c - 'A' + 10;
27 return -1;
28 }
29
30
hex2byte(const char * hex)31 int hex2byte(const char *hex)
32 {
33 int a, b;
34 a = hex2num(*hex++);
35 if (a < 0)
36 return -1;
37 b = hex2num(*hex++);
38 if (b < 0)
39 return -1;
40 return (a << 4) | b;
41 }
42
43
44 /**
45 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
46 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
47 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
48 * Returns: Characters used (> 0) on success, -1 on failure
49 */
hwaddr_aton2(const char * txt,u8 * addr)50 int hwaddr_aton2(const char *txt, u8 *addr)
51 {
52 int i;
53 const char *pos = txt;
54
55 for (i = 0; i < 6; i++) {
56 int a, b;
57
58 while (*pos == ':' || *pos == '.' || *pos == '-')
59 pos++;
60
61 a = hex2num(*pos++);
62 if (a < 0)
63 return -1;
64 b = hex2num(*pos++);
65 if (b < 0)
66 return -1;
67 *addr++ = (a << 4) | b;
68 }
69
70 return pos - txt;
71 }
72
73
74 /**
75 * hexstr2bin - Convert ASCII hex string into binary data
76 * @hex: ASCII hex string (e.g., "01ab")
77 * @buf: Buffer for the binary data
78 * @len: Length of the text to convert in bytes (of buf); hex will be double
79 * this size
80 * Returns: 0 on success, -1 on failure (invalid hex string)
81 */
hexstr2bin(const char * hex,u8 * buf,size_t len)82 int hexstr2bin(const char *hex, u8 *buf, size_t len)
83 {
84 size_t i;
85 int a;
86 const char *ipos = hex;
87 u8 *opos = buf;
88
89 for (i = 0; i < len; i++) {
90 a = hex2byte(ipos);
91 if (a < 0)
92 return -1;
93 *opos++ = a;
94 ipos += 2;
95 }
96 return 0;
97 }
98
99
100 /**
101 * inc_byte_array - Increment arbitrary length byte array by one
102 * @counter: Pointer to byte array
103 * @len: Length of the counter in bytes
104 *
105 * This function increments the last byte of the counter by one and continues
106 * rolling over to more significant bytes if the byte was incremented from
107 * 0xff to 0x00.
108 */
inc_byte_array(u8 * counter,size_t len)109 void inc_byte_array(u8 *counter, size_t len)
110 {
111 int pos = len - 1;
112 while (pos >= 0) {
113 counter[pos]++;
114 if (counter[pos] != 0)
115 break;
116 pos--;
117 }
118 }
119
120
buf_shift_right(u8 * buf,size_t len,size_t bits)121 void buf_shift_right(u8 *buf, size_t len, size_t bits)
122 {
123 size_t i;
124 for (i = len - 1; i > 0; i--)
125 buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
126 buf[0] >>= bits;
127 }
128
129
wpa_get_ntp_timestamp(u8 * buf)130 void wpa_get_ntp_timestamp(u8 *buf)
131 {
132 struct os_time now;
133 u32 sec, usec;
134 be32 tmp;
135
136 /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
137 os_get_time(&now);
138 sec = now.sec + 2208988800U; /* Epoch to 1900 */
139 /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
140 usec = now.usec;
141 usec = 4295 * usec - (usec >> 5) - (usec >> 9);
142 tmp = host_to_be32(sec);
143 os_memcpy(buf, (u8 *) &tmp, 4);
144 tmp = host_to_be32(usec);
145 os_memcpy(buf + 4, (u8 *) &tmp, 4);
146 }
printf_encode(char * txt,size_t maxlen,const u8 * data,size_t len)147 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
148 {
149 char *end = txt + maxlen;
150 size_t i;
151
152 for (i = 0; i < len; i++) {
153 if (txt + 4 >= end)
154 break;
155
156 switch (data[i]) {
157 case '\"':
158 *txt++ = '\\';
159 *txt++ = '\"';
160 break;
161 case '\\':
162 *txt++ = '\\';
163 *txt++ = '\\';
164 break;
165 case '\033':
166 *txt++ = '\\';
167 *txt++ = 'e';
168 break;
169 case '\n':
170 *txt++ = '\\';
171 *txt++ = 'n';
172 break;
173 case '\r':
174 *txt++ = '\\';
175 *txt++ = 'r';
176 break;
177 case '\t':
178 *txt++ = '\\';
179 *txt++ = 't';
180 break;
181 default:
182 if (data[i] >= 32 && data[i] <= 126) {
183 *txt++ = data[i];
184 } else {
185 txt += os_snprintf(txt, end - txt, "\\x%02x",
186 data[i]);
187 }
188 break;
189 }
190 }
191
192 *txt = '\0';
193 }
194
195
printf_decode(u8 * buf,size_t maxlen,const char * str)196 size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
197 {
198 const char *pos = str;
199 size_t len = 0;
200 int val;
201
202 while (*pos) {
203 if (len + 1 >= maxlen)
204 break;
205 switch (*pos) {
206 case '\\':
207 pos++;
208 switch (*pos) {
209 case '\\':
210 buf[len++] = '\\';
211 pos++;
212 break;
213 case '"':
214 buf[len++] = '"';
215 pos++;
216 break;
217 case 'n':
218 buf[len++] = '\n';
219 pos++;
220 break;
221 case 'r':
222 buf[len++] = '\r';
223 pos++;
224 break;
225 case 't':
226 buf[len++] = '\t';
227 pos++;
228 break;
229 case 'e':
230 buf[len++] = '\033';
231 pos++;
232 break;
233 case 'x':
234 pos++;
235 val = hex2byte(pos);
236 if (val < 0) {
237 val = hex2num(*pos);
238 if (val < 0)
239 break;
240 buf[len++] = val;
241 pos++;
242 } else {
243 buf[len++] = val;
244 pos += 2;
245 }
246 break;
247 case '0':
248 case '1':
249 case '2':
250 case '3':
251 case '4':
252 case '5':
253 case '6':
254 case '7':
255 val = *pos++ - '0';
256 if (*pos >= '0' && *pos <= '7')
257 val = val * 8 + (*pos++ - '0');
258 if (*pos >= '0' && *pos <= '7')
259 val = val * 8 + (*pos++ - '0');
260 buf[len++] = val;
261 break;
262 default:
263 break;
264 }
265 break;
266 default:
267 buf[len++] = *pos++;
268 break;
269 }
270 }
271 if (maxlen > len)
272 buf[len] = '\0';
273
274 return len;
275 }
276
277
278 /**
279 * wpa_ssid_txt - Convert SSID to a printable string
280 * @ssid: SSID (32-octet string)
281 * @ssid_len: Length of ssid in octets
282 * Returns: Pointer to a printable string
283 *
284 * This function can be used to convert SSIDs into printable form. In most
285 * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
286 * does not limit the used character set, so anything could be used in an SSID.
287 *
288 * This function uses a static buffer, so only one call can be used at the
289 * time, i.e., this is not re-entrant and the returned buffer must be used
290 * before calling this again.
291 */
wpa_ssid_txt(const u8 * ssid,size_t ssid_len)292 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
293 {
294 static char ssid_txt[SSID_MAX_LEN * 4 + 1];
295
296 if (ssid == NULL) {
297 ssid_txt[0] = '\0';
298 return ssid_txt;
299 }
300
301 printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
302 return ssid_txt;
303 }
304
305
__hide_aliasing_typecast(void * foo)306 void * __hide_aliasing_typecast(void *foo)
307 {
308 return foo;
309 }
310
311
wpa_config_parse_string(const char * value,size_t * len)312 char * wpa_config_parse_string(const char *value, size_t *len)
313 {
314 if (*value == '"') {
315 const char *pos;
316 char *str;
317 value++;
318 pos = os_strrchr(value, '"');
319 if (pos == NULL || pos[1] != '\0')
320 return NULL;
321 *len = pos - value;
322 str = dup_binstr(value, *len);
323 if (str == NULL)
324 return NULL;
325 return str;
326 } else if (*value == 'P' && value[1] == '"') {
327 const char *pos;
328 char *tstr, *str;
329 size_t tlen;
330 value += 2;
331 pos = os_strrchr(value, '"');
332 if (pos == NULL || pos[1] != '\0')
333 return NULL;
334 tlen = pos - value;
335 tstr = dup_binstr(value, tlen);
336 if (tstr == NULL)
337 return NULL;
338
339 str = os_malloc(tlen + 1);
340 if (str == NULL) {
341 os_free(tstr);
342 return NULL;
343 }
344
345 *len = printf_decode((u8 *) str, tlen + 1, tstr);
346 os_free(tstr);
347
348 return str;
349 } else {
350 u8 *str;
351 size_t tlen, hlen = os_strlen(value);
352 #ifndef ESP_SUPPLICANT
353 if (hlen & 1)
354 return NULL;
355 #else
356 if (hlen == 5 || hlen == 13) {
357 *len = hlen;
358 str = (u8 *)os_malloc(*len + 1);
359 if (str == NULL) {
360 return NULL;
361 }
362 memcpy(str, value, *len);
363 str[*len] = '\0';
364 return (char *) str;
365 }
366 #endif
367 tlen = hlen / 2;
368 str = os_malloc(tlen + 1);
369 if (str == NULL)
370 return NULL;
371 if (hexstr2bin(value, str, tlen)) {
372 os_free(str);
373 return NULL;
374 }
375 str[tlen] = '\0';
376 *len = tlen;
377 return (char *) str;
378 }
379 }
380
381
wpa_is_hex(const u8 * data,size_t len)382 int wpa_is_hex(const u8 *data, size_t len)
383 {
384 size_t i;
385
386 for (i = 0; i < len; i++) {
387 if (data[i] < 32 || data[i] >= 127)
388 return 1;
389 }
390 return 0;
391 }
392
393
has_ctrl_char(const u8 * data,size_t len)394 int has_ctrl_char(const u8 *data, size_t len)
395 {
396 size_t i;
397
398 for (i = 0; i < len; i++) {
399 if (data[i] < 32 || data[i] == 127)
400 return 1;
401 }
402 return 0;
403 }
404
405
406
wpa_merge_byte_arrays(u8 * res,size_t res_len,const u8 * src1,size_t src1_len,const u8 * src2,size_t src2_len)407 size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
408 const u8 *src1, size_t src1_len,
409 const u8 *src2, size_t src2_len)
410 {
411 size_t len = 0;
412
413 os_memset(res, 0, res_len);
414
415 if (src1) {
416 if (src1_len >= res_len) {
417 os_memcpy(res, src1, res_len);
418 return res_len;
419 }
420
421 os_memcpy(res, src1, src1_len);
422 len += src1_len;
423 }
424
425 if (src2) {
426 if (len + src2_len >= res_len) {
427 os_memcpy(res + len, src2, res_len - len);
428 return res_len;
429 }
430
431 os_memcpy(res + len, src2, src2_len);
432 len += src2_len;
433 }
434
435 return len;
436 }
437
438
dup_binstr(const void * src,size_t len)439 char * dup_binstr(const void *src, size_t len)
440 {
441 char *res;
442
443 if (src == NULL)
444 return NULL;
445 res = os_malloc(len + 1);
446 if (res == NULL)
447 return NULL;
448 os_memcpy(res, src, len);
449 res[len] = '\0';
450
451 return res;
452 }
453
454
int_array_len(const int * a)455 size_t int_array_len(const int *a)
456 {
457 size_t i;
458
459 for (i = 0; a && a[i]; i++)
460 ;
461 return i;
462 }
463
str_clear_free(char * str)464 void str_clear_free(char *str)
465 {
466 if (str) {
467 size_t len = os_strlen(str);
468 forced_memzero(str, len);
469 os_free(str);
470 }
471 }
472
473
bin_clear_free(void * bin,size_t len)474 void bin_clear_free(void *bin, size_t len)
475 {
476 if (bin) {
477 forced_memzero(bin, len);
478 os_free(bin);
479 }
480 }
481
482
os_gmtime(os_time_t t,struct os_tm * tm)483 int os_gmtime(os_time_t t, struct os_tm *tm)
484 {
485 struct tm *tm2;
486 time_t t2 = t;
487
488 tm2 = gmtime(&t2);
489 if (tm2 == NULL)
490 return -1;
491 tm->sec = tm2->tm_sec;
492 tm->min = tm2->tm_min;
493 tm->hour = tm2->tm_hour;
494 tm->day = tm2->tm_mday;
495 tm->month = tm2->tm_mon + 1;
496 tm->year = tm2->tm_year + 1900;
497 return 0;
498 }
499
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)500 int os_mktime(int year, int month, int day, int hour, int min, int sec,
501 os_time_t *t)
502 {
503 struct tm tm;
504
505 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
506 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
507 sec > 60)
508 return -1;
509
510 os_memset(&tm, 0, sizeof(tm));
511 tm.tm_year = year - 1900;
512 tm.tm_mon = month - 1;
513 tm.tm_mday = day;
514 tm.tm_hour = hour;
515 tm.tm_min = min;
516 tm.tm_sec = sec;
517
518 *t = (os_time_t) mktime(&tm);
519 return 0;
520 }
521
os_memdup(const void * src,size_t len)522 void * os_memdup(const void *src, size_t len)
523 {
524 void *r = os_malloc(len);
525
526 if (r && src)
527 os_memcpy(r, src, len);
528 return r;
529 }
530
os_reltime_expired(struct os_time * now,struct os_time * ts,os_time_t timeout_secs)531 int os_reltime_expired(struct os_time *now,
532 struct os_time *ts,
533 os_time_t timeout_secs)
534 {
535 struct os_time age;
536
537 os_time_sub(now, ts, &age);
538 return (age.sec > timeout_secs) ||
539 (age.sec == timeout_secs && age.usec > 0);
540 }
541
542
os_reltime_initialized(struct os_reltime * t)543 int os_reltime_initialized(struct os_reltime *t)
544 {
545 return t->sec != 0 || t->usec != 0;
546 }
547
548
rssi_to_rcpi(int rssi)549 u8 rssi_to_rcpi(int rssi)
550 {
551 if (!rssi)
552 return 255; /* not available */
553 if (rssi < -110)
554 return 0;
555 if (rssi > 0)
556 return 220;
557 return (rssi + 110) * 2;
558 }
559
560
get_param(const char * cmd,const char * param)561 char * get_param(const char *cmd, const char *param)
562 {
563 const char *pos, *end;
564 char *val;
565 size_t len;
566
567 pos = os_strstr(cmd, param);
568 if (!pos)
569 return NULL;
570
571 pos += os_strlen(param);
572 end = os_strchr(pos, ' ');
573 if (end)
574 len = end - pos;
575 else
576 len = os_strlen(pos);
577 val = os_malloc(len + 1);
578 if (!val)
579 return NULL;
580 os_memcpy(val, pos, len);
581 val[len] = '\0';
582 return val;
583 }
584