95b8c54266109031177335184206ca0c7e3e473c
[freeradius.git] / src / lib / missing.c
1 /*
2  * missing.c    Replacements for functions that are or can be
3  *              missing on some platforms.
4  *
5  * Version:     $Id$
6  *
7  *   This library is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU Lesser General Public
9  *   License as published by the Free Software Foundation; either
10  *   version 2.1 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  *   Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public
18  *   License along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * Copyright 2000,2006  The FreeRADIUS server project
22  */
23
24 RCSID("$Id$")
25
26 #include        <freeradius-devel/libradius.h>
27
28 #include        <ctype.h>
29
30 #ifndef HAVE_CRYPT
31 char *crypt(UNUSED char *key, char *salt)
32 {
33         /*log(L_ERR, "crypt() called but not implemented");*/
34         return salt;
35 }
36 #endif
37
38 #ifndef HAVE_STRNCASECMP
39 int strncasecmp(char *s1, char *s2, int n)
40 {
41         int             dif;
42         unsigned char   *p1, *p2;
43         int             c1, c2;
44
45         p1 = (unsigned char *)s1;
46         p2 = (unsigned char *)s2;
47         dif = 0;
48
49         while (n != 0) {
50                 if (*p1 == 0 && *p2 == 0)
51                         break;
52                 c1 = *p1;
53                 c2 = *p2;
54
55                 if (islower(c1)) c1 = toupper(c1);
56                 if (islower(c2)) c2 = toupper(c2);
57
58                 if ((dif = c1 - c2) != 0)
59                         break;
60                 p1++;
61                 p2++;
62                 n--;
63         }
64         return dif;
65 }
66 #endif
67
68 #ifndef HAVE_STRCASECMP
69 int strcasecmp(char *s1, char *s2)
70 {
71         int             l1, l2;
72
73         l1 = strlen(s1);
74         l2 = strlen(s2);
75         if (l2 > l1) l1 = l2;
76
77         return strncasecmp(s1, s2, l1);
78 }
79 #endif
80
81 #ifndef HAVE_INET_ATON
82 int inet_aton(char const *cp, struct in_addr *inp)
83 {
84         int     a1, a2, a3, a4;
85
86         if (sscanf(cp, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) != 4)
87                 return 0;
88
89         inp->s_addr = htonl((a1 << 24) + (a2 << 16) + (a3 << 8) + a4);
90         return 1;
91 }
92 #endif
93
94 #ifndef HAVE_STRSEP
95 /*
96  *      Get next token from string *stringp, where tokens are
97  *      possibly-empty strings separated by characters from delim.
98  *
99  *      Writes NULs into the string at *stringp to end tokens.
100  *      delim need not remain constant from call to call.  On
101  *      return, *stringp points past the last NUL written (if there
102  *      might be further tokens), or is NULL (if there are
103  *      definitely no more tokens).
104  *
105  *      If *stringp is NULL, strsep returns NULL.
106  */
107 char *
108 strsep(char **stringp, char const *delim)
109 {
110         char *s;
111         char const *spanp;
112         int c, sc;
113         char *tok;
114
115         if ((s = *stringp) == NULL)
116                 return (NULL);
117
118         for (tok = s;;) {
119                 c = *s++;
120                 spanp = delim;
121                 do {
122                         if ((sc = *spanp++) == c) {
123                                 if (c == 0)
124                                         s = NULL;
125                                 else
126                                         s[-1] = 0;
127                                 *stringp = s;
128                                 return (tok);
129                         }
130                 } while (sc != 0);
131         }
132
133         return NULL;            /* NOTREACHED, but the compiler complains */
134 }
135 #endif
136
137 #ifndef HAVE_LOCALTIME_R
138 /*
139  *      We use localtime_r() by default in the server.
140  *
141  *      For systems which do NOT have localtime_r(), we make the
142  *      assumption that localtime() is re-entrant, and returns a
143  *      per-thread data structure.
144  *
145  *      Even if localtime is NOT re-entrant, this function will
146  *      lower the possibility of race conditions.
147  */
148 struct tm *localtime_r(time_t const *l_clock, struct tm *result)
149 {
150   memcpy(result, localtime(l_clock), sizeof(*result));
151
152   return result;
153 }
154 #endif
155
156 #ifndef HAVE_CTIME_R
157 /*
158  *      We use ctime_r() by default in the server.
159  *
160  *      For systems which do NOT have ctime_r(), we make the
161  *      assumption that ctime() is re-entrant, and returns a
162  *      per-thread data structure.
163  *
164  *      Even if ctime is NOT re-entrant, this function will
165  *      lower the possibility of race conditions.
166  */
167 char *ctime_r(time_t const *l_clock, char *l_buf)
168 {
169   strcpy(l_buf, ctime(l_clock));
170
171   return l_buf;
172 }
173 #endif
174
175 #ifndef HAVE_GMTIME_R
176 /*
177  *      We use gmtime_r() by default in the server.
178  *
179  *      For systems which do NOT have gmtime_r(), we make the
180  *      assumption that gmtime() is re-entrant, and returns a
181  *      per-thread data structure.
182  *
183  *      Even if gmtime is NOT re-entrant, this function will
184  *      lower the possibility of race conditions.
185  */
186 struct tm *gmtime_r(time_t const *l_clock, struct tm *result)
187 {
188   memcpy(result, gmtime(l_clock), sizeof(*result));
189
190   return result;
191 }
192 #endif
193
194 #ifndef HAVE_VDPRINTF
195 int vdprintf (int fd, char const *format, va_list args)
196 {
197         int     ret;
198         FILE    *fp;
199         int     dup_fd;
200
201         dup_fd = dup(fd);
202         if (dup_fd < 0) return -1;
203
204         fp = fdopen(fd, "w");
205         if (!fp) {
206                 close(dup_fd);
207                 return -1;
208         }
209
210         ret = vfprintf(fp, format, args);
211         fclose(fp);     /* Also closes dup_fd */
212
213         return ret;
214 }
215 #endif
216
217 #ifndef HAVE_GETTIMEOFDAY
218 #ifdef WIN32
219 /*
220  * Number of micro-seconds between the beginning of the Windows epoch
221  * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
222  *
223  * This assumes all Win32 compilers have 64-bit support.
224  */
225 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
226 #define DELTA_EPOCH_IN_USEC  11644473600000000Ui64
227 #else
228 #define DELTA_EPOCH_IN_USEC  11644473600000000ULL
229 #endif
230
231 static uint64_t filetime_to_unix_epoch (FILETIME const *ft)
232 {
233         uint64_t res = (uint64_t) ft->dwHighDateTime << 32;
234
235         res |= ft->dwLowDateTime;
236         res /= 10;                 /* from 100 nano-sec periods to usec */
237         res -= DELTA_EPOCH_IN_USEC;  /* from Win epoch to Unix epoch */
238         return (res);
239 }
240
241 int gettimeofday (struct timeval *tv, UNUSED void *tz)
242 {
243         FILETIME  ft;
244         uint64_t tim;
245
246         if (!tv) {
247                 errno = EINVAL;
248                 return (-1);
249         }
250         GetSystemTimeAsFileTime (&ft);
251         tim = filetime_to_unix_epoch (&ft);
252         tv->tv_sec  = (long) (tim / 1000000L);
253         tv->tv_usec = (long) (tim % 1000000L);
254         return (0);
255 }
256 #endif
257 #endif
258
259 #define NTP_EPOCH_OFFSET        2208988800ULL
260
261 /*
262  *      Convert 'struct timeval' into NTP format (32-bit integer
263  *      of seconds, 32-bit integer of fractional seconds)
264  */
265 void
266 timeval2ntp(struct timeval const *tv, uint8_t *ntp)
267 {
268         uint32_t sec, usec;
269
270         sec = tv->tv_sec + NTP_EPOCH_OFFSET;
271         usec = tv->tv_usec * 4295; /* close enough to 2^32 / USEC */
272         usec -= ((tv->tv_usec * 2143) >> 16); /*  */
273
274         sec = htonl(sec);
275         usec = htonl(usec);
276
277         memcpy(ntp, &sec, sizeof(sec));
278         memcpy(ntp + sizeof(sec), &usec, sizeof(usec));
279 }
280
281 /*
282  *      Inverse of timeval2ntp
283  */
284 void
285 ntp2timeval(struct timeval *tv, char const *ntp)
286 {
287         uint32_t sec, usec;
288
289         memcpy(&sec, ntp, sizeof(sec));
290         memcpy(&usec, ntp + sizeof(sec), sizeof(usec));
291
292         sec = ntohl(sec);
293         usec = ntohl(usec);
294
295         tv->tv_sec = sec - NTP_EPOCH_OFFSET;
296         tv->tv_usec = usec / 4295; /* close enough */
297 }
298
299 #if !defined(HAVE_128BIT_INTEGERS) && defined(FR_LITTLE_ENDIAN)
300 /** Swap byte order of 128 bit integer
301  *
302  * @param num 128bit integer to swap.
303  * @return 128bit integer reversed.
304  */
305 uint128_t ntohlll(uint128_t const num)
306 {
307         uint64_t const *p = (uint64_t const *) &num;
308         uint64_t ret[2];
309
310         /* swapsies */
311         ret[1] = ntohll(p[0]);
312         ret[0] = ntohll(p[1]);
313
314         return *(uint128_t *)ret;
315 }
316 #endif
317
318 #ifdef HAVE_OPENSSL_HMAC_H
319 #  ifndef HAVE_HMAC_CTX_NEW
320 HMAC_CTX *HMAC_CTX_new(void)
321 {
322         HMAC_CTX *ctx;
323         ctx = OPENSSL_malloc(sizeof(*ctx));
324         if (!ctx) return NULL;
325
326         memset(ctx, 0, sizeof(*ctx));
327         HMAC_CTX_init(ctx);
328         return ctx;
329 }
330 #  endif
331 #  ifndef HAVE_HMAC_CTX_FREE
332 void HMAC_CTX_free(HMAC_CTX *ctx)
333 {
334         if (ctx == NULL) {
335                 return;
336         }
337         HMAC_CTX_cleanup(ctx);
338         OPENSSL_free(ctx);
339 }
340 #  endif
341 #endif
342
343 #ifdef HAVE_OPENSSL_SSL_H
344 #  ifndef HAVE_SSL_GET_CLIENT_RANDOM
345 size_t SSL_get_client_random(const SSL *s, unsigned char *out, size_t outlen)
346 {
347         if (!outlen) return sizeof(s->s3->client_random);
348
349         if (outlen > sizeof(s->s3->client_random)) outlen = sizeof(s->s3->client_random);
350
351         memcpy(out, s->s3->client_random, outlen);
352         return outlen;
353 }
354 #  endif
355 #  ifndef HAVE_SSL_GET_SERVER_RANDOM
356 size_t SSL_get_server_random(const SSL *s, unsigned char *out, size_t outlen)
357 {
358         if (!outlen) return sizeof(s->s3->server_random);
359
360         if (outlen > sizeof(s->s3->server_random)) outlen = sizeof(s->s3->server_random);
361
362         memcpy(out, s->s3->server_random, outlen);
363         return outlen;
364 }
365 #  endif
366 #  ifndef HAVE_SSL_SESSION_GET_MASTER_KEY
367 size_t SSL_SESSION_get_master_key(const SSL_SESSION *s,
368                                   unsigned char *out, size_t outlen)
369 {
370         if (!outlen) return s->master_key_length;
371
372         if (outlen > (size_t)s->master_key_length) outlen = (size_t)s->master_key_length;
373
374         memcpy(out, s->master_key, outlen);
375         return outlen;
376 }
377 #  endif
378 #endif
379
380 /** Call talloc strdup, setting the type on the new chunk correctly
381  *
382  * For some bizarre reason the talloc string functions don't set the
383  * memory chunk type to char, which causes all kinds of issues with
384  * verifying VALUE_PAIRs.
385  *
386  * @param[in] t The talloc context to hang the result off.
387  * @param[in] p The string you want to duplicate.
388  * @return The duplicated string, NULL on error.
389  */
390 char *talloc_typed_strdup(void const *t, char const *p)
391 {
392         char *n;
393
394         n = talloc_strdup(t, p);
395         if (!n) return NULL;
396         talloc_set_type(n, char);
397
398         return n;
399 }
400
401 /** Call talloc vasprintf, setting the type on the new chunk correctly
402  *
403  * For some bizarre reason the talloc string functions don't set the
404  * memory chunk type to char, which causes all kinds of issues with
405  * verifying VALUE_PAIRs.
406  *
407  * @param[in] t The talloc context to hang the result off.
408  * @param[in] fmt The format string.
409  * @return The formatted string, NULL on error.
410  */
411 char *talloc_typed_asprintf(void const *t, char const *fmt, ...)
412 {
413         char *n;
414         va_list ap;
415
416         va_start(ap, fmt);
417         n = talloc_vasprintf(t, fmt, ap);
418         va_end(ap);
419         if (!n) return NULL;
420         talloc_set_type(n, char);
421
422         return n;
423 }
424
425 /** Binary safe strndup function
426  *
427  * @param[in] t The talloc context o allocate new buffer in.
428  * @param[in] in String to dup, may contain embedded '\0'.
429  * @param[in] inlen Number of bytes to dup.
430  * @return duped string.
431  */
432 char *talloc_bstrndup(void const *t, char const *in, size_t inlen)
433 {
434         char *p;
435
436         p = talloc_array(t, char, inlen + 1);
437         if (!p) return NULL;
438         memcpy(p, in, inlen);
439         p[inlen] = '\0';
440
441         return p;
442 }
443