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