Fixup code formatting in EAP-LEAP, and use R*log functions
[freeradius.git] / src / lib / misc.c
1 /*
2  * misc.c       Various miscellaneous functions.
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 RCSID("$Id$")
24
25 #include        <freeradius-devel/libradius.h>
26
27 #include        <ctype.h>
28 #include        <sys/file.h>
29 #include        <fcntl.h>
30 #include        <signal.h>
31
32 #define FR_PUT_LE16(a, val)\
33         do {\
34                 a[1] = ((uint16_t) (val)) >> 8;\
35                 a[0] = ((uint16_t) (val)) & 0xff;\
36         } while (0)
37
38 static int      fr_debugger_present = -1;
39
40 int     fr_dns_lookups = 0;
41 int     fr_debug_flag = 0;
42
43 /** Allocates a new talloc context from the root autofree context
44  *
45  * @param signum signal raised.
46  */
47 static void _sigtrap_handler(UNUSED int signum)
48 {
49     fr_debugger_present = 0;
50     signal(SIGTRAP, SIG_DFL);
51 }
52
53 /** Break in GDB (if were running under GDB)
54  *
55  * If the server is running under GDB this will raise a SIGTRAP which
56  * will pause the running process.
57  *
58  * If the server is not running under GDB then this will do nothing.
59  */
60 void fr_debug_break(void)
61 {
62     if (fr_debugger_present == -1) {
63         fr_debugger_present = 0;
64         signal(SIGTRAP, _sigtrap_handler);
65         raise(SIGTRAP);
66     } else if (fr_debugger_present == 1) {
67         raise(SIGTRAP);
68     }
69 }
70
71 /*
72  *      Return an IP address in standard dot notation
73  *
74  *      FIXME: DELETE THIS
75  */
76 char const *ip_ntoa(char *buffer, uint32_t ipaddr)
77 {
78         ipaddr = ntohl(ipaddr);
79
80         sprintf(buffer, "%d.%d.%d.%d",
81                 (ipaddr >> 24) & 0xff,
82                 (ipaddr >> 16) & 0xff,
83                 (ipaddr >>  8) & 0xff,
84                 (ipaddr      ) & 0xff);
85         return buffer;
86 }
87
88 /*
89  *      Internal wrapper for locking, to minimize the number of ifdef's
90  *
91  *      Use fcntl or error
92  */
93 int rad_lockfd(int fd, int lock_len)
94 {
95 #ifdef F_WRLCK
96         struct flock fl;
97
98         fl.l_start = 0;
99         fl.l_len = lock_len;
100         fl.l_pid = getpid();
101         fl.l_type = F_WRLCK;
102         fl.l_whence = SEEK_CUR;
103
104         return fcntl(fd, F_SETLKW, (void *)&fl);
105 #else
106 #error "missing definition for F_WRLCK, all file locks will fail"
107
108         return -1;
109 #endif
110 }
111
112 /*
113  *      Internal wrapper for locking, to minimize the number of ifdef's
114  *
115  *      Lock an fd, prefer lockf() over flock()
116  *      Nonblocking version.
117  */
118 int rad_lockfd_nonblock(int fd, int lock_len)
119 {
120 #ifdef F_WRLCK
121         struct flock fl;
122
123         fl.l_start = 0;
124         fl.l_len = lock_len;
125         fl.l_pid = getpid();
126         fl.l_type = F_WRLCK;
127         fl.l_whence = SEEK_CUR;
128
129         return fcntl(fd, F_SETLK, (void *)&fl);
130 #else
131 #error "missing definition for F_WRLCK, all file locks will fail"
132
133         return -1;
134 #endif
135 }
136
137 /*
138  *      Internal wrapper for unlocking, to minimize the number of ifdef's
139  *      in the source.
140  *
141  *      Unlock an fd, prefer lockf() over flock()
142  */
143 int rad_unlockfd(int fd, int lock_len)
144 {
145 #ifdef F_WRLCK
146         struct flock fl;
147
148         fl.l_start = 0;
149         fl.l_len = lock_len;
150         fl.l_pid = getpid();
151         fl.l_type = F_WRLCK;
152         fl.l_whence = SEEK_CUR;
153
154         return fcntl(fd, F_UNLCK, (void *)&fl);
155 #else
156 #error "missing definition for F_WRLCK, all file locks will fail"
157
158         return -1;
159 #endif
160 }
161
162 /*
163  *      Return an interface-id in standard colon notation
164  */
165 char *ifid_ntoa(char *buffer, size_t size, uint8_t const *ifid)
166 {
167         snprintf(buffer, size, "%x:%x:%x:%x",
168                  (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
169                  (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
170         return buffer;
171 }
172
173
174 /*
175  *      Return an interface-id from
176  *      one supplied in standard colon notation.
177  */
178 uint8_t *ifid_aton(char const *ifid_str, uint8_t *ifid)
179 {
180         static char const xdigits[] = "0123456789abcdef";
181         char const *p, *pch;
182         int num_id = 0, val = 0, idx = 0;
183
184         for (p = ifid_str; ; ++p) {
185                 if (*p == ':' || *p == '\0') {
186                         if (num_id <= 0)
187                                 return NULL;
188
189                         /*
190                          *      Drop 'val' into the array.
191                          */
192                         ifid[idx] = (val >> 8) & 0xff;
193                         ifid[idx + 1] = val & 0xff;
194                         if (*p == '\0') {
195                                 /*
196                                  *      Must have all entries before
197                                  *      end of the string.
198                                  */
199                                 if (idx != 6)
200                                         return NULL;
201                                 break;
202                         }
203                         val = 0;
204                         num_id = 0;
205                         if ((idx += 2) > 6)
206                                 return NULL;
207                 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
208                         if (++num_id > 4)
209                                 return NULL;
210                         /*
211                          *      Dumb version of 'scanf'
212                          */
213                         val <<= 4;
214                         val |= (pch - xdigits);
215                 } else
216                         return NULL;
217         }
218         return ifid;
219 }
220
221
222 #ifndef HAVE_INET_PTON
223 static int inet_pton4(char const *src, struct in_addr *dst)
224 {
225         int octet;
226         unsigned int num;
227         char const *p, *off;
228         uint8_t tmp[4];
229         static char const digits[] = "0123456789";
230
231         octet = 0;
232         p = src;
233         while (1) {
234                 num = 0;
235                 while (*p && ((off = strchr(digits, *p)) != NULL)) {
236                         num *= 10;
237                         num += (off - digits);
238
239                         if (num > 255) return 0;
240
241                         p++;
242                 }
243                 if (!*p) break;
244
245                 /*
246                  *      Not a digit, MUST be a dot, else we
247                  *      die.
248                  */
249                 if (*p != '.') {
250                         return 0;
251                 }
252
253                 tmp[octet++] = num;
254                 p++;
255         }
256
257         /*
258          *      End of the string.  At the fourth
259          *      octet is OK, anything else is an
260          *      error.
261          */
262         if (octet != 3) {
263                 return 0;
264         }
265         tmp[3] = num;
266
267         memcpy(dst, &tmp, sizeof(tmp));
268         return 1;
269 }
270
271
272 #ifdef HAVE_STRUCT_SOCKADDR_IN6
273 /* int
274  * inet_pton6(src, dst)
275  *      convert presentation level address to network order binary form.
276  * return:
277  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
278  * notice:
279  *      (1) does not touch `dst' unless it's returning 1.
280  *      (2) :: in a full address is silently ignored.
281  * credit:
282  *      inspired by Mark Andrews.
283  * author:
284  *      Paul Vixie, 1996.
285  */
286 static int
287 inet_pton6(char const *src, unsigned char *dst)
288 {
289         static char const xdigits_l[] = "0123456789abcdef",
290                           xdigits_u[] = "0123456789ABCDEF";
291         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
292         char const *xdigits, *curtok;
293         int ch, saw_xdigit;
294         u_int val;
295
296         memset((tp = tmp), 0, IN6ADDRSZ);
297         endp = tp + IN6ADDRSZ;
298         colonp = NULL;
299         /* Leading :: requires some special handling. */
300         if (*src == ':')
301                 if (*++src != ':')
302                         return (0);
303         curtok = src;
304         saw_xdigit = 0;
305         val = 0;
306         while ((ch = *src++) != '\0') {
307                 char const *pch;
308
309                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
310                         pch = strchr((xdigits = xdigits_u), ch);
311                 if (pch != NULL) {
312                         val <<= 4;
313                         val |= (pch - xdigits);
314                         if (val > 0xffff)
315                                 return (0);
316                         saw_xdigit = 1;
317                         continue;
318                 }
319                 if (ch == ':') {
320                         curtok = src;
321                         if (!saw_xdigit) {
322                                 if (colonp)
323                                         return (0);
324                                 colonp = tp;
325                                 continue;
326                         }
327                         if (tp + INT16SZ > endp)
328                                 return (0);
329                         *tp++ = (u_char) (val >> 8) & 0xff;
330                         *tp++ = (u_char) val & 0xff;
331                         saw_xdigit = 0;
332                         val = 0;
333                         continue;
334                 }
335                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
336                     inet_pton4(curtok, (struct in_addr *) tp) > 0) {
337                         tp += INADDRSZ;
338                         saw_xdigit = 0;
339                         break;  /* '\0' was seen by inet_pton4(). */
340                 }
341                 return (0);
342         }
343         if (saw_xdigit) {
344                 if (tp + INT16SZ > endp)
345                         return (0);
346                 *tp++ = (u_char) (val >> 8) & 0xff;
347                 *tp++ = (u_char) val & 0xff;
348         }
349         if (colonp != NULL) {
350                 /*
351                  * Since some memmove()'s erroneously fail to handle
352                  * overlapping regions, we'll do the shift by hand.
353                  */
354                 int const n = tp - colonp;
355                 int i;
356
357                 for (i = 1; i <= n; i++) {
358                         endp[- i] = colonp[n - i];
359                         colonp[n - i] = 0;
360                 }
361                 tp = endp;
362         }
363         if (tp != endp)
364                 return (0);
365         /* bcopy(tmp, dst, IN6ADDRSZ); */
366         memcpy(dst, tmp, IN6ADDRSZ);
367         return (1);
368 }
369 #endif
370
371 /*
372  *      Utility function, so that the rest of the server doesn't
373  *      have ifdef's around IPv6 support
374  */
375 int inet_pton(int af, char const *src, void *dst)
376 {
377         if (af == AF_INET) {
378                 return inet_pton4(src, dst);
379         }
380 #ifdef HAVE_STRUCT_SOCKADDR_IN6
381
382         if (af == AF_INET6) {
383                 return inet_pton6(src, dst);
384         }
385 #endif
386
387         return -1;
388 }
389 #endif
390
391
392 #ifndef HAVE_INET_NTOP
393 /*
394  *      Utility function, so that the rest of the server doesn't
395  *      have ifdef's around IPv6 support
396  */
397 char const *inet_ntop(int af, void const *src, char *dst, size_t cnt)
398 {
399         if (af == AF_INET) {
400                 uint8_t const *ipaddr = src;
401
402                 if (cnt <= INET_ADDRSTRLEN) return NULL;
403
404                 snprintf(dst, cnt, "%d.%d.%d.%d",
405                          ipaddr[0], ipaddr[1],
406                          ipaddr[2], ipaddr[3]);
407                 return dst;
408         }
409
410         /*
411          *      If the system doesn't define this, we define it
412          *      in missing.h
413          */
414         if (af == AF_INET6) {
415                 struct const in6_addr *ipaddr = src;
416
417                 if (cnt <= INET6_ADDRSTRLEN) return NULL;
418
419                 snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
420                          (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
421                          (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
422                          (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
423                          (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
424                          (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
425                          (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
426                          (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
427                          (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
428                 return dst;
429         }
430
431         return NULL;            /* don't support IPv6 */
432 }
433 #endif
434
435
436 /*
437  *      Wrappers for IPv4/IPv6 host to IP address lookup.
438  *      This API returns only one IP address, of the specified
439  *      address family, or the first address (of whatever family),
440  *      if AF_UNSPEC is used.
441  */
442 int ip_hton(char const *src, int af, fr_ipaddr_t *dst)
443 {
444         int rcode;
445         struct addrinfo hints, *ai = NULL, *res = NULL;
446
447         memset(&hints, 0, sizeof(hints));
448         hints.ai_family = af;
449
450         if ((rcode = getaddrinfo(src, NULL, &hints, &res)) != 0) {
451                 fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
452                 return -1;
453         }
454
455         for (ai = res; ai; ai = ai->ai_next) {
456                 if ((af == ai->ai_family) || (af == AF_UNSPEC))
457                         break;
458         }
459
460         if (!ai) {
461                 fr_strerror_printf("ip_hton failed to find requested information for host %.100s", src);
462                 freeaddrinfo(ai);
463                 return -1;
464         }
465
466         rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
467                                    ai->ai_addrlen, dst, NULL);
468         freeaddrinfo(ai);
469         if (!rcode) return -1;
470
471         return 0;
472 }
473
474 /*
475  *      Look IP addresses up, and print names (depending on DNS config)
476  */
477 char const *ip_ntoh(fr_ipaddr_t const *src, char *dst, size_t cnt)
478 {
479         struct sockaddr_storage ss;
480         int error;
481         socklen_t salen;
482
483         /*
484          *      No DNS lookups
485          */
486         if (!fr_dns_lookups) {
487                 return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
488         }
489
490         if (!fr_ipaddr2sockaddr(src, 0, &ss, &salen)) {
491                 return NULL;
492         }
493
494         if ((error = getnameinfo((struct sockaddr *)&ss, salen, dst, cnt, NULL, 0,
495                                  NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
496                 fr_strerror_printf("ip_ntoh: %s", gai_strerror(error));
497                 return NULL;
498         }
499         return dst;
500 }
501
502
503 static char const *hextab = "0123456789abcdef";
504
505 /** Convert hex strings to binary data
506  *
507  * @param bin Buffer to write output to.
508  * @param hex input string.
509  * @param outlen length of output buffer (or length of input string / 2).
510  * @return length of data written to buffer.
511  */
512 size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
513 {
514         size_t i;
515         char *c1, *c2;
516
517         for (i = 0; i < outlen; i++) {
518                 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
519                    !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
520                         break;
521                  bin[i] = ((c1-hextab)<<4) + (c2-hextab);
522         }
523
524         return i;
525 }
526
527
528 /** Convert binary data to a hex string
529  *
530  * Ascii encoded hex string will not be prefixed with '0x'
531  *
532  * @warning If the output buffer isn't long enough, we have a buffer overflow.
533  *
534  * @param[out] hex Buffer to write hex output.
535  * @param[in] bin input.
536  * @param[in] inlen of bin input.
537  * @return length of data written to buffer.
538  */
539 size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
540 {
541         size_t i;
542
543         for (i = 0; i < inlen; i++) {
544                 hex[0] = hextab[((*bin) >> 4) & 0x0f];
545                 hex[1] = hextab[*bin & 0x0f];
546                 hex += 2;
547                 bin++;
548         }
549
550         *hex = '\0';
551         return inlen * 2;
552 }
553
554
555 /*
556  *      So we don't have ifdef's in the rest of the code
557  */
558 #ifndef HAVE_CLOSEFROM
559 int closefrom(int fd)
560 {
561         int i;
562         int maxfd = 256;
563
564 #ifdef _SC_OPEN_MAX
565         maxfd = sysconf(_SC_OPEN_MAX);
566         if (maxfd < 0) {
567           maxfd = 256;
568         }
569 #endif
570
571         if (fd > maxfd) return 0;
572
573         /*
574          *      FIXME: return EINTR?
575          *
576          *      Use F_CLOSEM?
577          */
578         for (i = fd; i < maxfd; i++) {
579                 close(i);
580         }
581
582         return 0;
583 }
584 #endif
585
586 int fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
587 {
588         if (a->af < b->af) return -1;
589         if (a->af > b->af) return +1;
590
591         switch (a->af) {
592         case AF_INET:
593                 return memcmp(&a->ipaddr.ip4addr,
594                               &b->ipaddr.ip4addr,
595                               sizeof(a->ipaddr.ip4addr));
596                 break;
597
598 #ifdef HAVE_STRUCT_SOCKADDR_IN6
599         case AF_INET6:
600                 if (a->scope < b->scope) return -1;
601                 if (a->scope > b->scope) return +1;
602
603                 return memcmp(&a->ipaddr.ip6addr,
604                               &b->ipaddr.ip6addr,
605                               sizeof(a->ipaddr.ip6addr));
606                 break;
607 #endif
608
609         default:
610                 break;
611         }
612
613         return -1;
614 }
615
616 int fr_ipaddr2sockaddr(fr_ipaddr_t const *ipaddr, int port,
617                        struct sockaddr_storage *sa, socklen_t *salen)
618 {
619         if (ipaddr->af == AF_INET) {
620                 struct sockaddr_in s4;
621
622                 *salen = sizeof(s4);
623
624                 memset(&s4, 0, sizeof(s4));
625                 s4.sin_family = AF_INET;
626                 s4.sin_addr = ipaddr->ipaddr.ip4addr;
627                 s4.sin_port = htons(port);
628                 memset(sa, 0, sizeof(*sa));
629                 memcpy(sa, &s4, sizeof(s4));
630
631 #ifdef HAVE_STRUCT_SOCKADDR_IN6
632         } else if (ipaddr->af == AF_INET6) {
633                 struct sockaddr_in6 s6;
634
635                 *salen = sizeof(s6);
636
637                 memset(&s6, 0, sizeof(s6));
638                 s6.sin6_family = AF_INET6;
639                 s6.sin6_addr = ipaddr->ipaddr.ip6addr;
640                 s6.sin6_port = htons(port);
641                 s6.sin6_scope_id = ipaddr->scope;
642                 memset(sa, 0, sizeof(*sa));
643                 memcpy(sa, &s6, sizeof(s6));
644 #endif
645         } else {
646                 return 0;
647         }
648
649         return 1;
650 }
651
652
653 int fr_sockaddr2ipaddr(struct sockaddr_storage const *sa, socklen_t salen,
654                        fr_ipaddr_t *ipaddr, int *port)
655 {
656         if (sa->ss_family == AF_INET) {
657                 struct sockaddr_in      s4;
658
659                 if (salen < sizeof(s4)) {
660                         fr_strerror_printf("IPv4 address is too small");
661                         return 0;
662                 }
663
664                 memcpy(&s4, sa, sizeof(s4));
665                 ipaddr->af = AF_INET;
666                 ipaddr->ipaddr.ip4addr = s4.sin_addr;
667                 if (port) *port = ntohs(s4.sin_port);
668
669 #ifdef HAVE_STRUCT_SOCKADDR_IN6
670         } else if (sa->ss_family == AF_INET6) {
671                 struct sockaddr_in6     s6;
672
673                 if (salen < sizeof(s6)) {
674                         fr_strerror_printf("IPv6 address is too small");
675                         return 0;
676                 }
677
678                 memcpy(&s6, sa, sizeof(s6));
679                 ipaddr->af = AF_INET6;
680                 ipaddr->ipaddr.ip6addr = s6.sin6_addr;
681                 if (port) *port = ntohs(s6.sin6_port);
682                 ipaddr->scope = s6.sin6_scope_id;
683 #endif
684
685         } else {
686                 fr_strerror_printf("Unsupported address famility %d",
687                                    sa->ss_family);
688                 return 0;
689         }
690
691         return 1;
692 }
693
694 /** Convert UTF8 string to UCS2 encoding
695  *
696  * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
697  *
698  * @param[out] out Where to write the ucs2 string.
699  * @param[in] outlen Size of output buffer.
700  * @param[in] in UTF8 string to convert.
701  * @param[in] inlen length of UTF8 string.
702  * @return the size of the UCS2 string written to the output buffer (in bytes).
703  */
704 ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
705 {
706         size_t i;
707         uint8_t *start = out;
708
709         for (i = 0; i < inlen; i++) {
710                 uint8_t c, c2, c3;
711
712                 c = in[i];
713                 if ((size_t)(out - start) >= outlen) {
714                         /* input too long */
715                         return -1;
716                 }
717
718                 /* One-byte encoding */
719                 if (c <= 0x7f) {
720                         FR_PUT_LE16(out, c);
721                         out += 2;
722                         continue;
723                 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
724                         /* Incomplete surrogate */
725                         return -1;
726                 }
727
728                 c2 = in[++i];
729                 /* Two-byte encoding */
730                 if ((c & 0xe0) == 0xc0) {
731                         FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
732                         out += 2;
733                         continue;
734                 }
735                 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
736                         /* Incomplete surrogate */
737                         return -1;
738                 }
739
740                 /* Three-byte encoding */
741                 c3 = in[++i];
742                 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
743                 out += 2;
744         }
745
746         return out - start;
747 }
748