1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*-
24 * Copyright 1998 Juniper Networks, Inc.
25 * All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 *    notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 *    notice, this list of conditions and the following disclaimer in the
34 *    documentation and/or other materials provided with the distribution.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 */
48
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <sys/time.h>
52#include <netinet/in.h>
53#include <arpa/inet.h>
54
55#include <CommonCrypto/CommonHMAC.h>
56
57#define MD5Init MD5_Init
58#define MD5Update MD5_Update
59#define MD5Final MD5_Final
60
61/* We need the MPPE_KEY_LEN define */
62#ifndef __APPLE__
63#include <netgraph/ng_mppc.h>
64#else
65#define MPPE_KEY_LEN         16
66#endif
67
68#include <errno.h>
69#include <netdb.h>
70#include <stdarg.h>
71#include <stddef.h>
72#include <stdio.h>
73#include <stdlib.h>
74#include <string.h>
75#include <unistd.h>
76
77#include "radlib_private.h"
78
79#ifndef __APPLE__
80#define RADLIB_SRANDOMDEV()  srandomdev()
81#define RADLIB_RANDOM()      random()
82#else
83#define RADLIB_SRANDOMDEV() /* no need to seed arc4random */
84#define RADLIB_RANDOM()     (arc4random() % ((unsigned)RAND_MAX + 1))
85#endif /* __APPLE__ */
86
87static void	 clear_password(struct rad_handle *);
88static void	 generr(struct rad_handle *, const char *, ...);
89//		    __printflike(2, 3);
90static void	 insert_scrambled_password(struct rad_handle *, int);
91static void	 insert_request_authenticator(struct rad_handle *, int);
92static void	 insert_message_authenticator(struct rad_handle *, int);
93static int	 is_valid_response(struct rad_handle *, int,
94		    const struct sockaddr_in *);
95static int	 put_password_attr(struct rad_handle *, int,
96		    const void *, size_t);
97static int	 put_raw_attr(struct rad_handle *, int,
98		    const void *, size_t);
99static int	 split(char *, char *[], int, char *, size_t);
100
101static void
102clear_password(struct rad_handle *h)
103{
104	if (h->pass_len != 0) {
105		memset(h->pass, 0, h->pass_len);
106		h->pass_len = 0;
107	}
108	h->pass_pos = 0;
109}
110
111static void
112generr(struct rad_handle *h, const char *format, ...)
113{
114	va_list		 ap;
115
116	va_start(ap, format);
117	vsnprintf(h->errmsg, ERRSIZE, format, ap);
118	va_end(ap);
119}
120
121static void
122insert_scrambled_password(struct rad_handle *h, int srv)
123{
124	MD5_CTX ctx;
125	unsigned char md5[MD5_DIGEST_LENGTH];
126	const struct rad_server *srvp;
127	int padded_len;
128	int pos;
129
130	srvp = &h->servers[srv];
131	padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
132
133	memcpy(md5, &h->request[POS_AUTH], LEN_AUTH);
134	for (pos = 0;  pos < padded_len;  pos += 16) {
135		int i;
136
137		/* Calculate the new scrambler */
138		MD5_Init(&ctx);
139		MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
140		MD5Update(&ctx, md5, 16);
141		MD5Final(md5, &ctx);
142
143		/*
144		 * Mix in the current chunk of the password, and copy
145		 * the result into the right place in the request.  Also
146		 * modify the scrambler in place, since we will use this
147		 * in calculating the scrambler for next time.
148		 */
149		for (i = 0;  i < 16;  i++)
150			h->request[h->pass_pos + pos + i] =
151			    md5[i] ^= h->pass[pos + i];
152	}
153}
154
155static void
156insert_request_authenticator(struct rad_handle *h, int srv)
157{
158	MD5_CTX ctx;
159	const struct rad_server *srvp;
160
161	srvp = &h->servers[srv];
162
163	/* Create the request authenticator */
164	MD5Init(&ctx);
165	MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
166	MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
167	MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
168	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
169	MD5Final(&h->request[POS_AUTH], &ctx);
170}
171
172static void
173insert_message_authenticator(struct rad_handle *h, int srv)
174{
175	u_char md[CC_MD5_DIGEST_LENGTH];
176	const struct rad_server *srvp;
177	CCHmacContext ctx;
178	srvp = &h->servers[srv];
179
180	if (h->authentic_pos != 0) {
181		// first clear the authenticator field of the request
182		memset(&h->request[h->authentic_pos + 2], 0, MD5_DIGEST_LENGTH);
183
184		CCHmacInit(&ctx, kCCHmacAlgMD5, srvp->secret, strlen(srvp->secret));
185		CCHmacUpdate(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
186		CCHmacUpdate(&ctx, &h->request[POS_AUTH], LEN_AUTH);
187		CCHmacUpdate(&ctx, &h->request[POS_ATTRS],
188		    h->req_len - POS_ATTRS);
189		CCHmacFinal(&ctx, md);
190		memcpy(&h->request[h->authentic_pos + 2], md, CC_MD5_DIGEST_LENGTH);
191	}
192}
193
194/*
195 * Return true if the current response is valid for a request to the
196 * specified server.
197 */
198static int
199is_valid_response(struct rad_handle *h, int srv,
200    const struct sockaddr_in *from)
201{
202	MD5_CTX ctx;
203	unsigned char md5[MD5_DIGEST_LENGTH];
204	const struct rad_server *srvp;
205	int len;
206	CCHmacContext hctx;
207	u_char resp[MSGSIZE], md[CC_MD5_DIGEST_LENGTH];
208	int pos;
209
210	srvp = &h->servers[srv];
211
212	/* Check the source address */
213	if (from->sin_family != srvp->addr.sin_family ||
214	    from->sin_addr.s_addr != srvp->addr.sin_addr.s_addr ||
215	    from->sin_port != srvp->addr.sin_port)
216		return 0;
217
218	/* Check the message length */
219	if (h->resp_len < POS_ATTRS)
220		return 0;
221	len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
222	if (len > h->resp_len)
223		return 0;
224
225	/* Check the response authenticator */
226	MD5Init(&ctx);
227	MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
228	MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
229	MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
230	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
231	MD5Final(md5, &ctx);
232	if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
233		return 0;
234
235	/*
236	 * For non accounting responses check the message authenticator,
237	 * if any.
238	 */
239	if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
240
241		memcpy(resp, h->response, MSGSIZE);
242		pos = POS_ATTRS;
243
244		/* Search and verify the Message-Authenticator */
245		while (pos < len - 2) {
246
247			if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
248				/* zero fill the Message-Authenticator */
249				memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
250
251				CCHmacInit(&hctx, kCCHmacAlgMD5, srvp->secret,
252				    strlen(srvp->secret));
253				CCHmacUpdate(&hctx, &h->response[POS_CODE],
254				    POS_AUTH - POS_CODE);
255				CCHmacUpdate(&hctx, &h->request[POS_AUTH],
256				    LEN_AUTH);
257				CCHmacUpdate(&hctx, &resp[POS_ATTRS],
258				    h->resp_len - POS_ATTRS);
259				CCHmacFinal(&hctx, md);
260				if (memcmp(md, &h->response[pos + 2],
261				    MD5_DIGEST_LENGTH) != 0)
262					return 0;
263				break;
264			}
265			pos += h->response[pos + 1];
266		}
267	}
268	return 1;
269}
270
271static int
272put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
273{
274	int padded_len;
275	int pad_len;
276
277	if (h->pass_pos != 0) {
278		generr(h, "Multiple User-Password attributes specified");
279		return -1;
280	}
281	if (len > PASSSIZE)
282		len = PASSSIZE;
283	padded_len = len == 0 ? 16 : (len+15) & ~0xf;
284	pad_len = padded_len - len;
285
286	/*
287	 * Put in a place-holder attribute containing all zeros, and
288	 * remember where it is so we can fill it in later.
289	 */
290	clear_password(h);
291	put_raw_attr(h, type, h->pass, padded_len);
292	h->pass_pos = h->req_len - padded_len;
293
294	/* Save the cleartext password, padded as necessary */
295	memcpy(h->pass, value, len);
296	h->pass_len = len;
297	memset(h->pass + len, 0, pad_len);
298	return 0;
299}
300
301static int
302put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
303{
304	if (len > 253) {
305		generr(h, "Attribute too long");
306		return -1;
307	}
308	if (h->req_len + 2 + len > MSGSIZE) {
309		generr(h, "Maximum message length exceeded");
310		return -1;
311	}
312	h->request[h->req_len++] = type;
313	h->request[h->req_len++] = len + 2;
314	memcpy(&h->request[h->req_len], value, len);
315	h->req_len += len;
316	return 0;
317}
318
319int
320rad_add_server(struct rad_handle *h, const char *host, int port,
321    const char *secret, int timeout, int tries)
322{
323	struct rad_server *srvp;
324
325	if (h->num_servers >= MAXSERVERS) {
326		generr(h, "Too many RADIUS servers specified");
327		return -1;
328	}
329	srvp = &h->servers[h->num_servers];
330
331	memset(&srvp->addr, 0, sizeof srvp->addr);
332	srvp->addr.sin_len = sizeof srvp->addr;
333	srvp->addr.sin_family = AF_INET;
334	if (!inet_aton(host, &srvp->addr.sin_addr)) {
335		struct hostent *hent;
336
337		if ((hent = gethostbyname(host)) == NULL) {
338			generr(h, "%s: host not found", host);
339			return -1;
340		}
341		memcpy(&srvp->addr.sin_addr, hent->h_addr,
342		    sizeof srvp->addr.sin_addr);
343	}
344	if (port != 0)
345		srvp->addr.sin_port = htons((u_short)port);
346	else {
347		struct servent *sent;
348
349		if (h->type == RADIUS_AUTH)
350			srvp->addr.sin_port =
351			    (sent = getservbyname("radius", "udp")) != NULL ?
352				sent->s_port : htons(RADIUS_PORT);
353		else
354			srvp->addr.sin_port =
355			    (sent = getservbyname("radacct", "udp")) != NULL ?
356				sent->s_port : htons(RADACCT_PORT);
357	}
358	if ((srvp->secret = strdup(secret)) == NULL) {
359		generr(h, "Out of memory");
360		return -1;
361	}
362	srvp->timeout = timeout;
363	srvp->max_tries = tries;
364	srvp->num_tries = 0;
365	h->num_servers++;
366	return 0;
367}
368
369void
370rad_close(struct rad_handle *h)
371{
372	int srv;
373
374	if (h->fd != -1)
375		close(h->fd);
376	for (srv = 0;  srv < h->num_servers;  srv++) {
377		memset(h->servers[srv].secret, 0,
378		    strlen(h->servers[srv].secret));
379		free(h->servers[srv].secret);
380	}
381	clear_password(h);
382	free(h);
383}
384
385int
386rad_config(struct rad_handle *h, const char *path)
387{
388	FILE *fp;
389	char buf[MAXCONFLINE];
390	int linenum;
391	int retval;
392
393	if (path == NULL)
394		path = PATH_RADIUS_CONF;
395	if ((fp = fopen(path, "r")) == NULL) {
396		generr(h, "Cannot open \"%s\": %s", path, strerror(errno));
397		return -1;
398	}
399	retval = 0;
400	linenum = 0;
401	while (fgets(buf, sizeof buf, fp) != NULL) {
402		int len;
403		char *fields[5];
404		int nfields;
405		char msg[ERRSIZE];
406		char *type;
407		char *host, *res;
408		char *port_str;
409		char *secret;
410		char *timeout_str;
411		char *maxtries_str;
412		char *end;
413		char *wanttype;
414		unsigned long timeout;
415		unsigned long maxtries;
416		int port;
417		int i;
418
419		linenum++;
420		len = strlen(buf);
421		/* We know len > 0, else fgets would have returned NULL. */
422		if (buf[len - 1] != '\n') {
423			if (len == sizeof buf - 1)
424				generr(h, "%s:%d: line too long", path,
425				    linenum);
426			else
427				generr(h, "%s:%d: missing newline", path,
428				    linenum);
429			retval = -1;
430			break;
431		}
432		buf[len - 1] = '\0';
433
434		/* Extract the fields from the line. */
435		nfields = split(buf, fields, 5, msg, sizeof msg);
436		if (nfields == -1) {
437			generr(h, "%s:%d: %s", path, linenum, msg);
438			retval = -1;
439			break;
440		}
441		if (nfields == 0)
442			continue;
443		/*
444		 * The first field should contain "auth" or "acct" for
445		 * authentication or accounting, respectively.  But older
446		 * versions of the file didn't have that field.  Default
447		 * it to "auth" for backward compatibility.
448		 */
449		if (strcmp(fields[0], "auth") != 0 &&
450		    strcmp(fields[0], "acct") != 0) {
451			if (nfields >= 5) {
452				generr(h, "%s:%d: invalid service type", path,
453				    linenum);
454				retval = -1;
455				break;
456			}
457			nfields++;
458			for (i = nfields;  --i > 0;  )
459				fields[i] = fields[i - 1];
460			fields[0] = "auth";
461		}
462		if (nfields < 3) {
463			generr(h, "%s:%d: missing shared secret", path,
464			    linenum);
465			retval = -1;
466			break;
467		}
468		type = fields[0];
469		host = fields[1];
470		secret = fields[2];
471		timeout_str = fields[3];
472		maxtries_str = fields[4];
473
474		/* Ignore the line if it is for the wrong service type. */
475		wanttype = h->type == RADIUS_AUTH ? "auth" : "acct";
476		if (strcmp(type, wanttype) != 0)
477			continue;
478
479		/* Parse and validate the fields. */
480		res = host;
481		host = strsep(&res, ":");
482		port_str = strsep(&res, ":");
483		if (port_str != NULL) {
484			port = strtoul(port_str, &end, 10);
485			if (*end != '\0') {
486				generr(h, "%s:%d: invalid port", path,
487				    linenum);
488				retval = -1;
489				break;
490			}
491		} else
492			port = 0;
493		if (timeout_str != NULL) {
494			timeout = strtoul(timeout_str, &end, 10);
495			if (*end != '\0') {
496				generr(h, "%s:%d: invalid timeout", path,
497				    linenum);
498				retval = -1;
499				break;
500			}
501		} else
502			timeout = TIMEOUT;
503		if (maxtries_str != NULL) {
504			maxtries = strtoul(maxtries_str, &end, 10);
505			if (*end != '\0') {
506				generr(h, "%s:%d: invalid maxtries", path,
507				    linenum);
508				retval = -1;
509				break;
510			}
511		} else
512			maxtries = MAXTRIES;
513
514		if (rad_add_server(h, host, port, secret, timeout, maxtries) ==
515		    -1) {
516			strlcpy(msg, h->errmsg, sizeof(msg));
517			generr(h, "%s:%d: %s", path, linenum, msg);
518			retval = -1;
519			break;
520		}
521	}
522	/* Clear out the buffer to wipe a possible copy of a shared secret */
523	memset(buf, 0, sizeof buf);
524	fclose(fp);
525	return retval;
526}
527
528/*
529 * rad_init_send_request() must have previously been called.
530 * Returns:
531 *   0     The application should select on *fd with a timeout of tv before
532 *         calling rad_continue_send_request again.
533 *   < 0   Failure
534 *   > 0   Success
535 */
536int
537rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
538                          struct timeval *tv)
539{
540	int n;
541
542	if (selected) {
543		struct sockaddr_in from;
544		uint32_t fromlen;
545
546		fromlen = sizeof from;
547		h->resp_len = recvfrom(h->fd, h->response,
548		    MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
549		if (h->resp_len == -1) {
550			generr(h, "recvfrom: %s", strerror(errno));
551			return -1;
552		}
553		if (is_valid_response(h, h->srv, &from)) {
554			h->resp_len = h->response[POS_LENGTH] << 8 |
555			    h->response[POS_LENGTH+1];
556			h->resp_pos = POS_ATTRS;
557			return h->response[POS_CODE];
558		}
559	}
560
561	if (h->try == h->total_tries) {
562		generr(h, "No valid RADIUS responses received");
563		return -1;
564	}
565
566retry:
567	/*
568         * Scan round-robin to the next server that has some
569         * tries left.  There is guaranteed to be one, or we
570         * would have exited this loop by now.
571	 */
572	while (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries)
573		if (++h->srv >= h->num_servers)
574			h->srv = 0;
575
576	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
577		/* Insert the request authenticator into the request */
578		insert_request_authenticator(h, h->srv);
579	else
580		/* Insert the scrambled password into the request */
581		if (h->pass_pos != 0)
582			insert_scrambled_password(h, h->srv);
583
584	insert_message_authenticator(h, h->srv);
585
586	/* Send the request */
587	n = sendto(h->fd, h->request, h->req_len, 0,
588	    (const struct sockaddr *)&h->servers[h->srv].addr,
589	    sizeof h->servers[h->srv].addr);
590	if (n != h->req_len) {
591		if (n == -1)
592			generr(h, "sendto: %s", strerror(errno));
593		else
594			generr(h, "sendto: short write");
595#ifdef __APPLE__
596		// skip to next server
597		int skip_tries = h->servers[h->srv].max_tries - h->servers[h->srv].num_tries;
598		h->try += skip_tries;
599		h->servers[h->srv].num_tries += skip_tries;
600		if (h->try < h->total_tries)
601			goto retry;
602#endif
603		return -1;
604	}
605
606	h->try++;
607	h->servers[h->srv].num_tries++;
608	tv->tv_sec = h->servers[h->srv].timeout;
609	tv->tv_usec = 0;
610	*fd = h->fd;
611
612	return 0;
613}
614
615int
616rad_create_request(struct rad_handle *h, int code)
617{
618	int i;
619
620	h->request[POS_CODE] = code;
621	h->request[POS_IDENT] = ++h->ident;
622	/* Create a random authenticator */
623	for (i = 0;  i < LEN_AUTH;  i += 2) {
624		long r;
625		r = RADLIB_RANDOM();
626		h->request[POS_AUTH+i] = (u_char)r;
627		h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
628	}
629	h->req_len = POS_ATTRS;
630	clear_password(h);
631	h->request_created = 1;
632#ifdef __APPLE__
633	h->authentic_pos = 0;
634	h->eap_msg = 0;
635	h->chap_pass = 0;
636#endif
637	return 0;
638}
639
640struct in_addr
641rad_cvt_addr(const void *data)
642{
643	struct in_addr value;
644
645	memcpy(&value.s_addr, data, sizeof value.s_addr);
646	return value;
647}
648
649u_int32_t
650rad_cvt_int(const void *data)
651{
652	u_int32_t value;
653
654	memcpy(&value, data, sizeof value);
655	return ntohl(value);
656}
657
658char *
659rad_cvt_string(const void *data, size_t len)
660{
661	char *s;
662
663	s = malloc(len + 1);
664	if (s != NULL) {
665		memcpy(s, data, len);
666		s[len] = '\0';
667	}
668	return s;
669}
670
671/*
672 * Returns the attribute type.  If none are left, returns 0.  On failure,
673 * returns -1.
674 */
675int
676rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
677{
678	int type;
679	size_t tmp_len;
680
681	if (h->resp_pos >= h->resp_len)
682		return 0;
683	if (h->resp_pos + 2 > h->resp_len) {
684		generr(h, "Malformed attribute in response");
685		return -1;
686	}
687	type = h->response[h->resp_pos++];
688	tmp_len = h->response[h->resp_pos++];
689	if (tmp_len < 2) {
690		generr(h, "Malformed attribute in response");
691		return -1;
692	}
693	*len = tmp_len - 2;
694	if (h->resp_pos + (int)*len > h->resp_len) {
695		generr(h, "Malformed attribute in response");
696		return -1;
697	}
698	*value = &h->response[h->resp_pos];
699	h->resp_pos += *len;
700	return type;
701}
702
703/*
704 * Returns -1 on error, 0 to indicate no event and >0 for success
705 */
706int
707rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
708{
709	int srv;
710
711	/* Make sure we have a socket to use */
712	if (h->fd == -1) {
713		struct sockaddr_in sin;
714
715		if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
716			generr(h, "Cannot create socket: %s", strerror(errno));
717			return -1;
718		}
719		memset(&sin, 0, sizeof sin);
720		sin.sin_len = sizeof sin;
721		sin.sin_family = AF_INET;
722		sin.sin_addr.s_addr = INADDR_ANY;
723		sin.sin_port = htons(0);
724		if (bind(h->fd, (const struct sockaddr *)&sin,
725		    sizeof sin) == -1) {
726			generr(h, "bind: %s", strerror(errno));
727			close(h->fd);
728			h->fd = -1;
729			return -1;
730		}
731	}
732
733	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
734		/* Make sure no password given */
735		if (h->pass_pos || h->chap_pass) {
736			generr(h, "User or Chap Password"
737			    " in accounting request");
738			return -1;
739		}
740	} else {
741		if (h->eap_msg == 0) {
742			/* Make sure the user gave us a password */
743			if (h->pass_pos == 0 && !h->chap_pass) {
744				generr(h, "No User or Chap Password"
745				    " attributes given");
746				return -1;
747			}
748			if (h->pass_pos != 0 && h->chap_pass) {
749				generr(h, "Both User and Chap Password"
750				    " attributes given");
751				return -1;
752			}
753		}
754	}
755
756	/* Fill in the length field in the message */
757	h->request[POS_LENGTH] = h->req_len >> 8;
758	h->request[POS_LENGTH+1] = h->req_len;
759
760	/*
761	 * Count the total number of tries we will make, and zero the
762	 * counter for each server.
763	 */
764	h->total_tries = 0;
765	for (srv = 0;  srv < h->num_servers;  srv++) {
766		h->total_tries += h->servers[srv].max_tries;
767		h->servers[srv].num_tries = 0;
768	}
769	if (h->total_tries == 0) {
770		generr(h, "No RADIUS servers specified");
771		return -1;
772	}
773
774#ifdef __APPLE__
775	h->try = 0;
776	// restart from the server that replied last time.
777#else
778	h->try = h->srv = 0;
779#endif
780
781	return rad_continue_send_request(h, 0, fd, tv);
782}
783
784/*
785 * Create and initialize a rad_handle structure, and return it to the
786 * caller.  Can fail only if the necessary memory cannot be allocated.
787 * In that case, it returns NULL.
788 */
789struct rad_handle *
790rad_auth_open(void)
791{
792	struct rad_handle *h;
793
794	h = (struct rad_handle *)malloc(sizeof(struct rad_handle));
795	if (h != NULL) {
796		RADLIB_SRANDOMDEV();
797		h->fd = -1;
798		h->num_servers = 0;
799		h->srv = 0;
800		h->ident = RADLIB_RANDOM();
801		h->errmsg[0] = '\0';
802		memset(h->pass, 0, sizeof h->pass);
803		h->pass_len = 0;
804		h->pass_pos = 0;
805		h->chap_pass = 0;
806		h->authentic_pos = 0;
807		h->type = RADIUS_AUTH;
808		h->request_created = 0;
809		h->eap_msg = 0;
810	}
811	return h;
812}
813
814struct rad_handle *
815rad_acct_open(void)
816{
817	struct rad_handle *h;
818
819	h = rad_open();
820	if (h != NULL)
821	        h->type = RADIUS_ACCT;
822	return h;
823}
824
825struct rad_handle *
826rad_open(void)
827{
828    return rad_auth_open();
829}
830
831int
832rad_put_addr(struct rad_handle *h, int type, struct in_addr addr)
833{
834	return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
835}
836
837int
838rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
839{
840	int result;
841
842	if (!h->request_created) {
843		generr(h, "Please call rad_create_request()"
844		    " before putting attributes");
845		return -1;
846	}
847
848	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
849		if (type == RAD_EAP_MESSAGE) {
850			generr(h, "EAP-Message attribute is not valid"
851			    " in accounting requests");
852			return -1;
853		}
854	}
855
856	/*
857	 * When proxying EAP Messages, the Message Authenticator
858	 * MUST be present; see RFC 3579.
859	 */
860	if (type == RAD_EAP_MESSAGE) {
861		if (rad_put_message_authentic(h) == -1)
862			return -1;
863	}
864
865	if (type == RAD_USER_PASSWORD) {
866		result = put_password_attr(h, type, value, len);
867	} else if (type == RAD_MESSAGE_AUTHENTIC) {
868		result = rad_put_message_authentic(h);
869	} else {
870		result = put_raw_attr(h, type, value, len);
871		if (result == 0) {
872			if (type == RAD_CHAP_PASSWORD)
873				h->chap_pass = 1;
874			else if (type == RAD_EAP_MESSAGE)
875				h->eap_msg = 1;
876		}
877	}
878
879	return result;
880}
881
882int
883rad_put_int(struct rad_handle *h, int type, u_int32_t value)
884{
885	u_int32_t nvalue;
886
887	nvalue = htonl(value);
888	return rad_put_attr(h, type, &nvalue, sizeof nvalue);
889}
890
891int
892rad_put_string(struct rad_handle *h, int type, const char *str)
893{
894	return rad_put_attr(h, type, str, strlen(str));
895}
896
897int
898rad_put_message_authentic(struct rad_handle *h)
899{
900	u_char md_zero[MD5_DIGEST_LENGTH];
901
902	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
903		generr(h, "Message-Authenticator is not valid"
904		    " in accounting requests");
905		return -1;
906	}
907
908	if (h->authentic_pos == 0) {
909		h->authentic_pos = h->req_len;
910		memset(md_zero, 0, sizeof(md_zero));
911		return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
912		    sizeof(md_zero)));
913	}
914	return 0;
915}
916
917/*
918 * Returns the response type code on success, or -1 on failure.
919 */
920int
921rad_send_request(struct rad_handle *h)
922{
923	struct timeval timelimit;
924	struct timeval tv;
925	int fd;
926	int n;
927
928	n = rad_init_send_request(h, &fd, &tv);
929
930	if (n != 0)
931		return n;
932
933	gettimeofday(&timelimit, NULL);
934	timeradd(&tv, &timelimit, &timelimit);
935
936	for ( ; ; ) {
937		fd_set readfds;
938
939		FD_ZERO(&readfds);
940		FD_SET(fd, &readfds);
941
942		n = select(fd + 1, &readfds, NULL, NULL, &tv);
943
944		if (n == -1) {
945			generr(h, "select: %s", strerror(errno));
946			return -1;
947		}
948
949		if (!FD_ISSET(fd, &readfds)) {
950			/* Compute a new timeout */
951			gettimeofday(&tv, NULL);
952			timersub(&timelimit, &tv, &tv);
953			if (tv.tv_sec > 0 || (tv.tv_sec == 0 && tv.tv_usec > 0))
954				/* Continue the select */
955				continue;
956		}
957
958		n = rad_continue_send_request(h, n, &fd, &tv);
959
960		if (n != 0)
961			return n;
962
963		gettimeofday(&timelimit, NULL);
964		timeradd(&tv, &timelimit, &timelimit);
965	}
966}
967
968const char *
969rad_strerror(struct rad_handle *h)
970{
971	return h->errmsg;
972}
973
974/*
975 * Destructively split a string into fields separated by white space.
976 * `#' at the beginning of a field begins a comment that extends to the
977 * end of the string.  Fields may be quoted with `"'.  Inside quoted
978 * strings, the backslash escapes `\"' and `\\' are honored.
979 *
980 * Pointers to up to the first maxfields fields are stored in the fields
981 * array.  Missing fields get NULL pointers.
982 *
983 * The return value is the actual number of fields parsed, and is always
984 * <= maxfields.
985 *
986 * On a syntax error, places a message in the msg string, and returns -1.
987 */
988static int
989split(char *str, char *fields[], int maxfields, char *msg, size_t msglen)
990{
991	char *p;
992	int i;
993	static const char ws[] = " \t";
994
995	for (i = 0;  i < maxfields;  i++)
996		fields[i] = NULL;
997	p = str;
998	i = 0;
999	while (*p != '\0') {
1000		p += strspn(p, ws);
1001		if (*p == '#' || *p == '\0')
1002			break;
1003		if (i >= maxfields) {
1004			snprintf(msg, msglen, "line has too many fields");
1005			return -1;
1006		}
1007		if (*p == '"') {
1008			char *dst;
1009
1010			dst = ++p;
1011			fields[i] = dst;
1012			while (*p != '"') {
1013				if (*p == '\\') {
1014					p++;
1015					if (*p != '"' && *p != '\\' &&
1016					    *p != '\0') {
1017						snprintf(msg, msglen,
1018						    "invalid `\\' escape");
1019						return -1;
1020					}
1021				}
1022				if (*p == '\0') {
1023					snprintf(msg, msglen,
1024					    "unterminated quoted string");
1025					return -1;
1026				}
1027				*dst++ = *p++;
1028			}
1029			*dst = '\0';
1030			p++;
1031			if (*fields[i] == '\0') {
1032				snprintf(msg, msglen,
1033				    "empty quoted string not permitted");
1034				return -1;
1035			}
1036			if (*p != '\0' && strspn(p, ws) == 0) {
1037				snprintf(msg, msglen, "quoted string not"
1038				    " followed by white space");
1039				return -1;
1040			}
1041		} else {
1042			fields[i] = p;
1043			p += strcspn(p, ws);
1044			if (*p != '\0')
1045				*p++ = '\0';
1046		}
1047		i++;
1048	}
1049	return i;
1050}
1051
1052int
1053rad_get_vendor_attr(u_int32_t *vendor, const void **data, size_t *len)
1054{
1055	struct vendor_attribute *attr;
1056
1057	attr = (struct vendor_attribute *)*data;
1058	*vendor = ntohl(attr->vendor_value);
1059	*data = attr->attrib_data;
1060	*len = attr->attrib_len - 2;
1061
1062	return (attr->attrib_type);
1063}
1064
1065int
1066rad_put_vendor_addr(struct rad_handle *h, int vendor, int type,
1067    struct in_addr addr)
1068{
1069	return (rad_put_vendor_attr(h, vendor, type, &addr.s_addr,
1070	    sizeof addr.s_addr));
1071}
1072
1073int
1074rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
1075    const void *value, size_t len)
1076{
1077	struct vendor_attribute *attr;
1078	int res;
1079
1080	if (!h->request_created) {
1081		generr(h, "Please call rad_create_request()"
1082		    " before putting attributes");
1083		return -1;
1084	}
1085
1086	if ((attr = malloc(len + 6)) == NULL) {
1087		generr(h, "malloc failure (%zu bytes)", len + 6);
1088		return -1;
1089	}
1090
1091	attr->vendor_value = htonl(vendor);
1092	attr->attrib_type = type;
1093	attr->attrib_len = len + 2;
1094	memcpy(attr->attrib_data, value, len);
1095
1096	res = put_raw_attr(h, RAD_VENDOR_SPECIFIC, attr, len + 6);
1097	free(attr);
1098	if (res == 0 && vendor == RAD_VENDOR_MICROSOFT
1099	    && (type == RAD_MICROSOFT_MS_CHAP_RESPONSE
1100	    || type == RAD_MICROSOFT_MS_CHAP2_RESPONSE
1101#ifdef __APPLE__
1102		/* for password change */
1103		|| type == RAD_MICROSOFT_MS_CHAP_NT_ENC_PW
1104#endif
1105		)) {
1106		h->chap_pass = 1;
1107	}
1108	return (res);
1109}
1110
1111int
1112rad_put_vendor_int(struct rad_handle *h, int vendor, int type, u_int32_t i)
1113{
1114	u_int32_t value;
1115
1116	value = htonl(i);
1117	return (rad_put_vendor_attr(h, vendor, type, &value, sizeof value));
1118}
1119
1120int
1121rad_put_vendor_string(struct rad_handle *h, int vendor, int type,
1122    const char *str)
1123{
1124	return (rad_put_vendor_attr(h, vendor, type, str, strlen(str)));
1125}
1126
1127ssize_t
1128rad_request_authenticator(struct rad_handle *h, char *buf, size_t len)
1129{
1130	if (len < LEN_AUTH)
1131		return (-1);
1132	memcpy(buf, h->request + POS_AUTH, LEN_AUTH);
1133	if (len > LEN_AUTH)
1134		buf[LEN_AUTH] = '\0';
1135	return (LEN_AUTH);
1136}
1137
1138u_char *
1139rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen)
1140{
1141	char R[LEN_AUTH];
1142	const char *S;
1143	int i, Ppos;
1144	MD5_CTX Context;
1145	u_char b[MD5_DIGEST_LENGTH], *C, *demangled;
1146
1147	if ((mlen % 16 != 0) || mlen > 128) {
1148		generr(h, "Cannot interpret mangled data of length %lu",
1149		    (u_long)mlen);
1150		return NULL;
1151	}
1152
1153	C = (u_char *)mangled;
1154
1155	/* We need the shared secret as Salt */
1156	S = rad_server_secret(h);
1157
1158	/* We need the request authenticator */
1159	if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
1160		generr(h, "Cannot obtain the RADIUS request authenticator");
1161		return NULL;
1162	}
1163
1164	demangled = malloc(mlen);
1165	if (!demangled)
1166		return NULL;
1167
1168	MD5Init(&Context);
1169	MD5Update(&Context, S, strlen(S));
1170	MD5Update(&Context, R, LEN_AUTH);
1171	MD5Final(b, &Context);
1172	Ppos = 0;
1173	while (mlen) {
1174
1175		mlen -= 16;
1176		for (i = 0; i < 16; i++)
1177			demangled[Ppos++] = C[i] ^ b[i];
1178
1179		if (mlen) {
1180			MD5Init(&Context);
1181			MD5Update(&Context, S, strlen(S));
1182			MD5Update(&Context, C, 16);
1183			MD5Final(b, &Context);
1184		}
1185
1186		C += 16;
1187	}
1188
1189	return demangled;
1190}
1191
1192u_char *
1193rad_demangle_mppe_key(struct rad_handle *h, const void *mangled,
1194    size_t mlen, size_t *len)
1195{
1196	char R[LEN_AUTH];    /* variable names as per rfc2548 */
1197	const char *S;
1198	u_char b[MD5_DIGEST_LENGTH], *demangled;
1199	const u_char *A, *C;
1200	MD5_CTX Context;
1201	int Slen, i, Clen, Ppos;
1202	u_char *P;
1203
1204	if (mlen % 16 != SALT_LEN) {
1205		generr(h, "Cannot interpret mangled data of length %lu",
1206		    (u_long)mlen);
1207		return NULL;
1208	}
1209
1210	/* We need the RADIUS Request-Authenticator */
1211	if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
1212		generr(h, "Cannot obtain the RADIUS request authenticator");
1213		return NULL;
1214	}
1215
1216	A = (const u_char *)mangled;      /* Salt comes first */
1217	C = (const u_char *)mangled + SALT_LEN;  /* Then the ciphertext */
1218	Clen = mlen - SALT_LEN;
1219	S = rad_server_secret(h);    /* We need the RADIUS secret */
1220	Slen = strlen(S);
1221	P = calloc(Clen, 1);        /* We derive our plaintext */
1222	if (!P) {
1223		generr(h, "Cannot obtain the RADIUS MPPE plaintext buffer");
1224		return NULL;
1225	}
1226
1227	MD5Init(&Context);
1228	MD5Update(&Context, S, Slen);
1229	MD5Update(&Context, R, LEN_AUTH);
1230	MD5Update(&Context, A, SALT_LEN);
1231	MD5Final(b, &Context);
1232	Ppos = 0;
1233
1234	while (Clen) {
1235		Clen -= 16;
1236
1237		for (i = 0; i < 16; i++)
1238		    P[Ppos++] = C[i] ^ b[i];
1239
1240		if (Clen) {
1241			MD5Init(&Context);
1242			MD5Update(&Context, S, Slen);
1243			MD5Update(&Context, C, 16);
1244			MD5Final(b, &Context);
1245		}
1246
1247		C += 16;
1248	}
1249
1250	/*
1251	* The resulting plain text consists of a one-byte length, the text and
1252	* maybe some padding.
1253	*/
1254	*len = *P;
1255	if (*len > mlen - 1) {
1256		generr(h, "Mangled data seems to be garbage %zu %zu",
1257		    *len, mlen-1);
1258		free(P);
1259		return NULL;
1260	}
1261
1262	if (*len > MPPE_KEY_LEN * 2) {
1263		generr(h, "Key to long (%zu) for me max. %d",
1264		    *len, MPPE_KEY_LEN * 2);
1265		free(P);
1266		return NULL;
1267	}
1268	demangled = malloc(*len);
1269	if (!demangled) {
1270		free(P);
1271		return NULL;
1272	}
1273
1274	memcpy(demangled, P + 1, *len);
1275	free(P);
1276	return demangled;
1277}
1278
1279const char *
1280rad_server_secret(struct rad_handle *h)
1281{
1282	return (h->servers[h->srv].secret);
1283}
1284