radlib.c revision 128684
1233237Sjkim/*-
2233237Sjkim * Copyright 1998 Juniper Networks, Inc.
3233237Sjkim * All rights reserved.
4233237Sjkim *
5233237Sjkim * Redistribution and use in source and binary forms, with or without
6233237Sjkim * modification, are permitted provided that the following conditions
7233237Sjkim * are met:
8233237Sjkim * 1. Redistributions of source code must retain the above copyright
9245582Sjkim *    notice, this list of conditions and the following disclaimer.
10233237Sjkim * 2. Redistributions in binary form must reproduce the above copyright
11233237Sjkim *    notice, this list of conditions and the following disclaimer in the
12233237Sjkim *    documentation and/or other materials provided with the distribution.
13233237Sjkim *
14233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15233237Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16233237Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17233237Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18233237Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22233237Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23233237Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24233237Sjkim * SUCH DAMAGE.
25233237Sjkim */
26233237Sjkim
27233237Sjkim#include <sys/cdefs.h>
28233237Sjkim__FBSDID("$FreeBSD: head/lib/libradius/radlib.c 128684 2004-04-27 15:00:29Z ru $");
29233237Sjkim
30233237Sjkim#include <sys/types.h>
31233237Sjkim#include <sys/socket.h>
32233237Sjkim#include <sys/time.h>
33233237Sjkim#include <netinet/in.h>
34233237Sjkim#include <arpa/inet.h>
35233237Sjkim#ifdef WITH_SSL
36233237Sjkim#include <openssl/hmac.h>
37233237Sjkim#include <openssl/md5.h>
38233237Sjkim#define MD5Init MD5_Init
39233237Sjkim#define MD5Update MD5_Update
40233237Sjkim#define MD5Final MD5_Final
41233237Sjkim#else
42233237Sjkim#define MD5_DIGEST_LENGTH 16
43233237Sjkim#include <md5.h>
44233237Sjkim#endif
45233250Sjkim
46233250Sjkim/* We need the MPPE_KEY_LEN define */
47233237Sjkim#include <netgraph/ng_mppc.h>
48233237Sjkim
49233237Sjkim#include <errno.h>
50233237Sjkim#include <netdb.h>
51233237Sjkim#include <stdarg.h>
52233237Sjkim#include <stddef.h>
53233237Sjkim#include <stdio.h>
54233237Sjkim#include <stdlib.h>
55233237Sjkim#include <string.h>
56233237Sjkim#include <unistd.h>
57233237Sjkim
58233237Sjkim#include "radlib_private.h"
59233237Sjkim
60233237Sjkimstatic void	 clear_password(struct rad_handle *);
61233237Sjkimstatic void	 generr(struct rad_handle *, const char *, ...)
62233237Sjkim		    __printflike(2, 3);
63233237Sjkimstatic void	 insert_scrambled_password(struct rad_handle *, int);
64233237Sjkimstatic void	 insert_request_authenticator(struct rad_handle *, int);
65233237Sjkimstatic void	 insert_message_authenticator(struct rad_handle *, int);
66233237Sjkimstatic int	 is_valid_response(struct rad_handle *, int,
67233237Sjkim		    const struct sockaddr_in *);
68233237Sjkimstatic int	 put_password_attr(struct rad_handle *, int,
69233237Sjkim		    const void *, size_t);
70233237Sjkimstatic int	 put_raw_attr(struct rad_handle *, int,
71233237Sjkim		    const void *, size_t);
72233237Sjkimstatic int	 split(char *, char *[], int, char *, size_t);
73233237Sjkim
74233237Sjkimstatic void
75233237Sjkimclear_password(struct rad_handle *h)
76233237Sjkim{
77233237Sjkim	if (h->pass_len != 0) {
78233237Sjkim		memset(h->pass, 0, h->pass_len);
79233237Sjkim		h->pass_len = 0;
80233237Sjkim	}
81233237Sjkim	h->pass_pos = 0;
82233237Sjkim}
83233237Sjkim
84233237Sjkimstatic void
85233237Sjkimgenerr(struct rad_handle *h, const char *format, ...)
86233237Sjkim{
87233237Sjkim	va_list		 ap;
88233237Sjkim
89233237Sjkim	va_start(ap, format);
90233237Sjkim	vsnprintf(h->errmsg, ERRSIZE, format, ap);
91233237Sjkim	va_end(ap);
92233237Sjkim}
93233237Sjkim
94233237Sjkimstatic void
95233237Sjkiminsert_scrambled_password(struct rad_handle *h, int srv)
96233237Sjkim{
97233237Sjkim	MD5_CTX ctx;
98233237Sjkim	unsigned char md5[MD5_DIGEST_LENGTH];
99233237Sjkim	const struct rad_server *srvp;
100233237Sjkim	int padded_len;
101233237Sjkim	int pos;
102233237Sjkim
103233237Sjkim	srvp = &h->servers[srv];
104233237Sjkim	padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
105233237Sjkim
106233237Sjkim	memcpy(md5, &h->request[POS_AUTH], LEN_AUTH);
107233237Sjkim	for (pos = 0;  pos < padded_len;  pos += 16) {
108233237Sjkim		int i;
109233237Sjkim
110233237Sjkim		/* Calculate the new scrambler */
111233237Sjkim		MD5Init(&ctx);
112233237Sjkim		MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
113233237Sjkim		MD5Update(&ctx, md5, 16);
114233237Sjkim		MD5Final(md5, &ctx);
115233237Sjkim
116233237Sjkim		/*
117233237Sjkim		 * Mix in the current chunk of the password, and copy
118233237Sjkim		 * the result into the right place in the request.  Also
119233237Sjkim		 * modify the scrambler in place, since we will use this
120233237Sjkim		 * in calculating the scrambler for next time.
121233237Sjkim		 */
122233237Sjkim		for (i = 0;  i < 16;  i++)
123233237Sjkim			h->request[h->pass_pos + pos + i] =
124233237Sjkim			    md5[i] ^= h->pass[pos + i];
125233237Sjkim	}
126233237Sjkim}
127233237Sjkim
128233237Sjkimstatic void
129233237Sjkiminsert_request_authenticator(struct rad_handle *h, int srv)
130233237Sjkim{
131233237Sjkim	MD5_CTX ctx;
132233237Sjkim	const struct rad_server *srvp;
133233237Sjkim
134233237Sjkim	srvp = &h->servers[srv];
135233237Sjkim
136233237Sjkim	/* Create the request authenticator */
137233237Sjkim	MD5Init(&ctx);
138233237Sjkim	MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
139233237Sjkim	MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
140233237Sjkim	MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
141233237Sjkim	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
142233237Sjkim	MD5Final(&h->request[POS_AUTH], &ctx);
143233237Sjkim}
144233237Sjkim
145233237Sjkimstatic void
146233237Sjkiminsert_message_authenticator(struct rad_handle *h, int srv)
147233237Sjkim{
148233237Sjkim#ifdef WITH_SSL
149233237Sjkim	u_char md[EVP_MAX_MD_SIZE];
150233237Sjkim	u_int md_len;
151233237Sjkim	const struct rad_server *srvp;
152233237Sjkim	HMAC_CTX ctx;
153233237Sjkim	srvp = &h->servers[srv];
154233237Sjkim
155233237Sjkim	if (h->authentic_pos != 0) {
156233237Sjkim		HMAC_CTX_init(&ctx);
157233237Sjkim		HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
158233237Sjkim		HMAC_Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
159233237Sjkim		HMAC_Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
160233237Sjkim		HMAC_Update(&ctx, &h->request[POS_ATTRS],
161233237Sjkim		    h->req_len - POS_ATTRS);
162233237Sjkim		HMAC_Final(&ctx, md, &md_len);
163233237Sjkim		HMAC_CTX_cleanup(&ctx);
164233237Sjkim		HMAC_cleanup(&ctx);
165233237Sjkim		memcpy(&h->request[h->authentic_pos + 2], md, md_len);
166233237Sjkim	}
167233237Sjkim#endif
168233237Sjkim}
169233237Sjkim
170233237Sjkim/*
171233237Sjkim * Return true if the current response is valid for a request to the
172233237Sjkim * specified server.
173233237Sjkim */
174233237Sjkimstatic int
175233237Sjkimis_valid_response(struct rad_handle *h, int srv,
176233237Sjkim    const struct sockaddr_in *from)
177233237Sjkim{
178233237Sjkim	MD5_CTX ctx;
179233237Sjkim	unsigned char md5[MD5_DIGEST_LENGTH];
180233237Sjkim	const struct rad_server *srvp;
181233237Sjkim	int len;
182233237Sjkim#ifdef WITH_SSL
183233237Sjkim	HMAC_CTX hctx;
184233237Sjkim	u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
185233237Sjkim	int pos, md_len;
186233237Sjkim#endif
187233237Sjkim
188233237Sjkim	srvp = &h->servers[srv];
189233237Sjkim
190233237Sjkim	/* Check the source address */
191233237Sjkim	if (from->sin_family != srvp->addr.sin_family ||
192233237Sjkim	    from->sin_addr.s_addr != srvp->addr.sin_addr.s_addr ||
193233237Sjkim	    from->sin_port != srvp->addr.sin_port)
194233237Sjkim		return 0;
195233237Sjkim
196233237Sjkim	/* Check the message length */
197233237Sjkim	if (h->resp_len < POS_ATTRS)
198233237Sjkim		return 0;
199233237Sjkim	len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
200233237Sjkim	if (len > h->resp_len)
201233237Sjkim		return 0;
202233237Sjkim
203233237Sjkim	/* Check the response authenticator */
204233237Sjkim	MD5Init(&ctx);
205233237Sjkim	MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
206233237Sjkim	MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
207233237Sjkim	MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
208233237Sjkim	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
209233237Sjkim	MD5Final(md5, &ctx);
210233237Sjkim	if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
211233237Sjkim		return 0;
212233237Sjkim
213233237Sjkim#ifdef WITH_SSL
214233237Sjkim	/*
215233237Sjkim	 * For non accounting responses check the message authenticator,
216233237Sjkim	 * if any.
217233237Sjkim	 */
218233237Sjkim	if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
219233237Sjkim
220233237Sjkim		memcpy(resp, h->response, MSGSIZE);
221233237Sjkim		pos = POS_ATTRS;
222233237Sjkim
223233237Sjkim		/* Search and verify the Message-Authenticator */
224233237Sjkim		while (pos < len - 2) {
225233237Sjkim
226233237Sjkim			if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
227233237Sjkim				/* zero fill the Message-Authenticator */
228233237Sjkim				memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
229233237Sjkim
230233237Sjkim				HMAC_CTX_init(&hctx);
231233237Sjkim				HMAC_Init(&hctx, srvp->secret,
232233237Sjkim				    strlen(srvp->secret), EVP_md5());
233233237Sjkim				HMAC_Update(&hctx, &h->response[POS_CODE],
234233237Sjkim				    POS_AUTH - POS_CODE);
235233237Sjkim				HMAC_Update(&hctx, &h->request[POS_AUTH],
236233237Sjkim				    LEN_AUTH);
237233237Sjkim				HMAC_Update(&hctx, &resp[POS_ATTRS],
238233237Sjkim				    h->resp_len - POS_ATTRS);
239233237Sjkim				HMAC_Final(&hctx, md, &md_len);
240233237Sjkim				HMAC_CTX_cleanup(&hctx);
241233237Sjkim				HMAC_cleanup(&hctx);
242233237Sjkim				if (memcmp(md, &h->response[pos + 2],
243233237Sjkim				    MD5_DIGEST_LENGTH) != 0)
244233237Sjkim					return 0;
245233237Sjkim				break;
246233237Sjkim			}
247233237Sjkim			pos += h->response[pos + 1];
248233237Sjkim		}
249233237Sjkim	}
250233237Sjkim#endif
251233237Sjkim	return 1;
252233237Sjkim}
253233237Sjkim
254233237Sjkimstatic int
255233237Sjkimput_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
256233237Sjkim{
257233237Sjkim	int padded_len;
258233237Sjkim	int pad_len;
259233237Sjkim
260233237Sjkim	if (h->pass_pos != 0) {
261233237Sjkim		generr(h, "Multiple User-Password attributes specified");
262233237Sjkim		return -1;
263233237Sjkim	}
264233237Sjkim	if (len > PASSSIZE)
265233237Sjkim		len = PASSSIZE;
266233237Sjkim	padded_len = len == 0 ? 16 : (len+15) & ~0xf;
267233237Sjkim	pad_len = padded_len - len;
268233237Sjkim
269233237Sjkim	/*
270233237Sjkim	 * Put in a place-holder attribute containing all zeros, and
271233237Sjkim	 * remember where it is so we can fill it in later.
272233237Sjkim	 */
273233237Sjkim	clear_password(h);
274233237Sjkim	put_raw_attr(h, type, h->pass, padded_len);
275233237Sjkim	h->pass_pos = h->req_len - padded_len;
276233237Sjkim
277233237Sjkim	/* Save the cleartext password, padded as necessary */
278233237Sjkim	memcpy(h->pass, value, len);
279233237Sjkim	h->pass_len = len;
280233237Sjkim	memset(h->pass + len, 0, pad_len);
281233237Sjkim	return 0;
282233237Sjkim}
283233237Sjkim
284233237Sjkimstatic int
285put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
286{
287	if (len > 253) {
288		generr(h, "Attribute too long");
289		return -1;
290	}
291	if (h->req_len + 2 + len > MSGSIZE) {
292		generr(h, "Maximum message length exceeded");
293		return -1;
294	}
295	h->request[h->req_len++] = type;
296	h->request[h->req_len++] = len + 2;
297	memcpy(&h->request[h->req_len], value, len);
298	h->req_len += len;
299	return 0;
300}
301
302int
303rad_add_server(struct rad_handle *h, const char *host, int port,
304    const char *secret, int timeout, int tries)
305{
306	struct rad_server *srvp;
307
308	if (h->num_servers >= MAXSERVERS) {
309		generr(h, "Too many RADIUS servers specified");
310		return -1;
311	}
312	srvp = &h->servers[h->num_servers];
313
314	memset(&srvp->addr, 0, sizeof srvp->addr);
315	srvp->addr.sin_len = sizeof srvp->addr;
316	srvp->addr.sin_family = AF_INET;
317	if (!inet_aton(host, &srvp->addr.sin_addr)) {
318		struct hostent *hent;
319
320		if ((hent = gethostbyname(host)) == NULL) {
321			generr(h, "%s: host not found", host);
322			return -1;
323		}
324		memcpy(&srvp->addr.sin_addr, hent->h_addr,
325		    sizeof srvp->addr.sin_addr);
326	}
327	if (port != 0)
328		srvp->addr.sin_port = htons((u_short)port);
329	else {
330		struct servent *sent;
331
332		if (h->type == RADIUS_AUTH)
333			srvp->addr.sin_port =
334			    (sent = getservbyname("radius", "udp")) != NULL ?
335				sent->s_port : htons(RADIUS_PORT);
336		else
337			srvp->addr.sin_port =
338			    (sent = getservbyname("radacct", "udp")) != NULL ?
339				sent->s_port : htons(RADACCT_PORT);
340	}
341	if ((srvp->secret = strdup(secret)) == NULL) {
342		generr(h, "Out of memory");
343		return -1;
344	}
345	srvp->timeout = timeout;
346	srvp->max_tries = tries;
347	srvp->num_tries = 0;
348	h->num_servers++;
349	return 0;
350}
351
352void
353rad_close(struct rad_handle *h)
354{
355	int srv;
356
357	if (h->fd != -1)
358		close(h->fd);
359	for (srv = 0;  srv < h->num_servers;  srv++) {
360		memset(h->servers[srv].secret, 0,
361		    strlen(h->servers[srv].secret));
362		free(h->servers[srv].secret);
363	}
364	clear_password(h);
365	free(h);
366}
367
368int
369rad_config(struct rad_handle *h, const char *path)
370{
371	FILE *fp;
372	char buf[MAXCONFLINE];
373	int linenum;
374	int retval;
375
376	if (path == NULL)
377		path = PATH_RADIUS_CONF;
378	if ((fp = fopen(path, "r")) == NULL) {
379		generr(h, "Cannot open \"%s\": %s", path, strerror(errno));
380		return -1;
381	}
382	retval = 0;
383	linenum = 0;
384	while (fgets(buf, sizeof buf, fp) != NULL) {
385		int len;
386		char *fields[5];
387		int nfields;
388		char msg[ERRSIZE];
389		char *type;
390		char *host, *res;
391		char *port_str;
392		char *secret;
393		char *timeout_str;
394		char *maxtries_str;
395		char *end;
396		char *wanttype;
397		unsigned long timeout;
398		unsigned long maxtries;
399		int port;
400		int i;
401
402		linenum++;
403		len = strlen(buf);
404		/* We know len > 0, else fgets would have returned NULL. */
405		if (buf[len - 1] != '\n') {
406			if (len == sizeof buf - 1)
407				generr(h, "%s:%d: line too long", path,
408				    linenum);
409			else
410				generr(h, "%s:%d: missing newline", path,
411				    linenum);
412			retval = -1;
413			break;
414		}
415		buf[len - 1] = '\0';
416
417		/* Extract the fields from the line. */
418		nfields = split(buf, fields, 5, msg, sizeof msg);
419		if (nfields == -1) {
420			generr(h, "%s:%d: %s", path, linenum, msg);
421			retval = -1;
422			break;
423		}
424		if (nfields == 0)
425			continue;
426		/*
427		 * The first field should contain "auth" or "acct" for
428		 * authentication or accounting, respectively.  But older
429		 * versions of the file didn't have that field.  Default
430		 * it to "auth" for backward compatibility.
431		 */
432		if (strcmp(fields[0], "auth") != 0 &&
433		    strcmp(fields[0], "acct") != 0) {
434			if (nfields >= 5) {
435				generr(h, "%s:%d: invalid service type", path,
436				    linenum);
437				retval = -1;
438				break;
439			}
440			nfields++;
441			for (i = nfields;  --i > 0;  )
442				fields[i] = fields[i - 1];
443			fields[0] = "auth";
444		}
445		if (nfields < 3) {
446			generr(h, "%s:%d: missing shared secret", path,
447			    linenum);
448			retval = -1;
449			break;
450		}
451		type = fields[0];
452		host = fields[1];
453		secret = fields[2];
454		timeout_str = fields[3];
455		maxtries_str = fields[4];
456
457		/* Ignore the line if it is for the wrong service type. */
458		wanttype = h->type == RADIUS_AUTH ? "auth" : "acct";
459		if (strcmp(type, wanttype) != 0)
460			continue;
461
462		/* Parse and validate the fields. */
463		res = host;
464		host = strsep(&res, ":");
465		port_str = strsep(&res, ":");
466		if (port_str != NULL) {
467			port = strtoul(port_str, &end, 10);
468			if (*end != '\0') {
469				generr(h, "%s:%d: invalid port", path,
470				    linenum);
471				retval = -1;
472				break;
473			}
474		} else
475			port = 0;
476		if (timeout_str != NULL) {
477			timeout = strtoul(timeout_str, &end, 10);
478			if (*end != '\0') {
479				generr(h, "%s:%d: invalid timeout", path,
480				    linenum);
481				retval = -1;
482				break;
483			}
484		} else
485			timeout = TIMEOUT;
486		if (maxtries_str != NULL) {
487			maxtries = strtoul(maxtries_str, &end, 10);
488			if (*end != '\0') {
489				generr(h, "%s:%d: invalid maxtries", path,
490				    linenum);
491				retval = -1;
492				break;
493			}
494		} else
495			maxtries = MAXTRIES;
496
497		if (rad_add_server(h, host, port, secret, timeout, maxtries) ==
498		    -1) {
499			strcpy(msg, h->errmsg);
500			generr(h, "%s:%d: %s", path, linenum, msg);
501			retval = -1;
502			break;
503		}
504	}
505	/* Clear out the buffer to wipe a possible copy of a shared secret */
506	memset(buf, 0, sizeof buf);
507	fclose(fp);
508	return retval;
509}
510
511/*
512 * rad_init_send_request() must have previously been called.
513 * Returns:
514 *   0     The application should select on *fd with a timeout of tv before
515 *         calling rad_continue_send_request again.
516 *   < 0   Failure
517 *   > 0   Success
518 */
519int
520rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
521                          struct timeval *tv)
522{
523	int n;
524
525	if (selected) {
526		struct sockaddr_in from;
527		int fromlen;
528
529		fromlen = sizeof from;
530		h->resp_len = recvfrom(h->fd, h->response,
531		    MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
532		if (h->resp_len == -1) {
533			generr(h, "recvfrom: %s", strerror(errno));
534			return -1;
535		}
536		if (is_valid_response(h, h->srv, &from)) {
537			h->resp_len = h->response[POS_LENGTH] << 8 |
538			    h->response[POS_LENGTH+1];
539			h->resp_pos = POS_ATTRS;
540			return h->response[POS_CODE];
541		}
542	}
543
544	if (h->try == h->total_tries) {
545		generr(h, "No valid RADIUS responses received");
546		return -1;
547	}
548
549	/*
550         * Scan round-robin to the next server that has some
551         * tries left.  There is guaranteed to be one, or we
552         * would have exited this loop by now.
553	 */
554	while (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries)
555		if (++h->srv >= h->num_servers)
556			h->srv = 0;
557
558	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
559		/* Insert the request authenticator into the request */
560		insert_request_authenticator(h, h->srv);
561	else
562		/* Insert the scrambled password into the request */
563		if (h->pass_pos != 0)
564			insert_scrambled_password(h, h->srv);
565
566	insert_message_authenticator(h, h->srv);
567
568	/* Send the request */
569	n = sendto(h->fd, h->request, h->req_len, 0,
570	    (const struct sockaddr *)&h->servers[h->srv].addr,
571	    sizeof h->servers[h->srv].addr);
572	if (n != h->req_len) {
573		if (n == -1)
574			generr(h, "sendto: %s", strerror(errno));
575		else
576			generr(h, "sendto: short write");
577		return -1;
578	}
579
580	h->try++;
581	h->servers[h->srv].num_tries++;
582	tv->tv_sec = h->servers[h->srv].timeout;
583	tv->tv_usec = 0;
584	*fd = h->fd;
585
586	return 0;
587}
588
589int
590rad_create_request(struct rad_handle *h, int code)
591{
592	int i;
593
594	h->request[POS_CODE] = code;
595	h->request[POS_IDENT] = ++h->ident;
596	/* Create a random authenticator */
597	for (i = 0;  i < LEN_AUTH;  i += 2) {
598		long r;
599		r = random();
600		h->request[POS_AUTH+i] = (u_char)r;
601		h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
602	}
603	h->req_len = POS_ATTRS;
604	clear_password(h);
605	h->request_created = 1;
606	return 0;
607}
608
609struct in_addr
610rad_cvt_addr(const void *data)
611{
612	struct in_addr value;
613
614	memcpy(&value.s_addr, data, sizeof value.s_addr);
615	return value;
616}
617
618u_int32_t
619rad_cvt_int(const void *data)
620{
621	u_int32_t value;
622
623	memcpy(&value, data, sizeof value);
624	return ntohl(value);
625}
626
627char *
628rad_cvt_string(const void *data, size_t len)
629{
630	char *s;
631
632	s = malloc(len + 1);
633	if (s != NULL) {
634		memcpy(s, data, len);
635		s[len] = '\0';
636	}
637	return s;
638}
639
640/*
641 * Returns the attribute type.  If none are left, returns 0.  On failure,
642 * returns -1.
643 */
644int
645rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
646{
647	int type;
648
649	if (h->resp_pos >= h->resp_len)
650		return 0;
651	if (h->resp_pos + 2 > h->resp_len) {
652		generr(h, "Malformed attribute in response");
653		return -1;
654	}
655	type = h->response[h->resp_pos++];
656	*len = h->response[h->resp_pos++] - 2;
657	if (h->resp_pos + (int)*len > h->resp_len) {
658		generr(h, "Malformed attribute in response");
659		return -1;
660	}
661	*value = &h->response[h->resp_pos];
662	h->resp_pos += *len;
663	return type;
664}
665
666/*
667 * Returns -1 on error, 0 to indicate no event and >0 for success
668 */
669int
670rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
671{
672	int srv;
673
674	/* Make sure we have a socket to use */
675	if (h->fd == -1) {
676		struct sockaddr_in sin;
677
678		if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
679			generr(h, "Cannot create socket: %s", strerror(errno));
680			return -1;
681		}
682		memset(&sin, 0, sizeof sin);
683		sin.sin_len = sizeof sin;
684		sin.sin_family = AF_INET;
685		sin.sin_addr.s_addr = INADDR_ANY;
686		sin.sin_port = htons(0);
687		if (bind(h->fd, (const struct sockaddr *)&sin,
688		    sizeof sin) == -1) {
689			generr(h, "bind: %s", strerror(errno));
690			close(h->fd);
691			h->fd = -1;
692			return -1;
693		}
694	}
695
696	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
697		/* Make sure no password given */
698		if (h->pass_pos || h->chap_pass) {
699			generr(h, "User or Chap Password"
700			    " in accounting request");
701			return -1;
702		}
703	} else {
704		if (h->eap_msg == 0) {
705			/* Make sure the user gave us a password */
706			if (h->pass_pos == 0 && !h->chap_pass) {
707				generr(h, "No User or Chap Password"
708				    " attributes given");
709				return -1;
710			}
711			if (h->pass_pos != 0 && h->chap_pass) {
712				generr(h, "Both User and Chap Password"
713				    " attributes given");
714				return -1;
715			}
716		}
717	}
718
719	/* Fill in the length field in the message */
720	h->request[POS_LENGTH] = h->req_len >> 8;
721	h->request[POS_LENGTH+1] = h->req_len;
722
723	/*
724	 * Count the total number of tries we will make, and zero the
725	 * counter for each server.
726	 */
727	h->total_tries = 0;
728	for (srv = 0;  srv < h->num_servers;  srv++) {
729		h->total_tries += h->servers[srv].max_tries;
730		h->servers[srv].num_tries = 0;
731	}
732	if (h->total_tries == 0) {
733		generr(h, "No RADIUS servers specified");
734		return -1;
735	}
736
737	h->try = h->srv = 0;
738
739	return rad_continue_send_request(h, 0, fd, tv);
740}
741
742/*
743 * Create and initialize a rad_handle structure, and return it to the
744 * caller.  Can fail only if the necessary memory cannot be allocated.
745 * In that case, it returns NULL.
746 */
747struct rad_handle *
748rad_auth_open(void)
749{
750	struct rad_handle *h;
751
752	h = (struct rad_handle *)malloc(sizeof(struct rad_handle));
753	if (h != NULL) {
754		srandomdev();
755		h->fd = -1;
756		h->num_servers = 0;
757		h->ident = random();
758		h->errmsg[0] = '\0';
759		memset(h->pass, 0, sizeof h->pass);
760		h->pass_len = 0;
761		h->pass_pos = 0;
762		h->chap_pass = 0;
763		h->authentic_pos = 0;
764		h->type = RADIUS_AUTH;
765		h->request_created = 0;
766		h->eap_msg = 0;
767	}
768	return h;
769}
770
771struct rad_handle *
772rad_acct_open(void)
773{
774	struct rad_handle *h;
775
776	h = rad_open();
777	if (h != NULL)
778	        h->type = RADIUS_ACCT;
779	return h;
780}
781
782struct rad_handle *
783rad_open(void)
784{
785    return rad_auth_open();
786}
787
788int
789rad_put_addr(struct rad_handle *h, int type, struct in_addr addr)
790{
791	return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
792}
793
794int
795rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
796{
797	int result;
798
799	if (!h->request_created) {
800		generr(h, "Please call rad_create_request()"
801		    " before putting attributes");
802		return -1;
803	}
804
805	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
806		if (type == RAD_EAP_MESSAGE) {
807			generr(h, "EAP-Message attribute is not valid"
808			    " in accounting requests");
809			return -1;
810		}
811	}
812
813	/*
814	 * When proxying EAP Messages, the Message Authenticator
815	 * MUST be present; see RFC 3579.
816	 */
817	if (type == RAD_EAP_MESSAGE) {
818		if (rad_put_message_authentic(h) == -1)
819			return -1;
820	}
821
822	if (type == RAD_USER_PASSWORD) {
823		result = put_password_attr(h, type, value, len);
824	} else if (type == RAD_MESSAGE_AUTHENTIC) {
825		result = rad_put_message_authentic(h);
826	} else {
827		result = put_raw_attr(h, type, value, len);
828		if (result == 0) {
829			if (type == RAD_CHAP_PASSWORD)
830				h->chap_pass = 1;
831			else if (type == RAD_EAP_MESSAGE)
832				h->eap_msg = 1;
833		}
834	}
835
836	return result;
837}
838
839int
840rad_put_int(struct rad_handle *h, int type, u_int32_t value)
841{
842	u_int32_t nvalue;
843
844	nvalue = htonl(value);
845	return rad_put_attr(h, type, &nvalue, sizeof nvalue);
846}
847
848int
849rad_put_string(struct rad_handle *h, int type, const char *str)
850{
851	return rad_put_attr(h, type, str, strlen(str));
852}
853
854int
855rad_put_message_authentic(struct rad_handle *h)
856{
857#ifdef WITH_SSL
858	u_char md_zero[MD5_DIGEST_LENGTH];
859
860	if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
861		generr(h, "Message-Authenticator is not valid"
862		    " in accounting requests");
863		return -1;
864	}
865
866	if (h->authentic_pos == 0) {
867		h->authentic_pos = h->req_len;
868		memset(md_zero, 0, sizeof(md_zero));
869		return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
870		    sizeof(md_zero)));
871	}
872	return 0;
873#else
874	generr(h, "Message Authenticator not supported,"
875	    " please recompile libradius with SSL support");
876	return -1;
877#endif
878}
879
880/*
881 * Returns the response type code on success, or -1 on failure.
882 */
883int
884rad_send_request(struct rad_handle *h)
885{
886	struct timeval timelimit;
887	struct timeval tv;
888	int fd;
889	int n;
890
891	n = rad_init_send_request(h, &fd, &tv);
892
893	if (n != 0)
894		return n;
895
896	gettimeofday(&timelimit, NULL);
897	timeradd(&tv, &timelimit, &timelimit);
898
899	for ( ; ; ) {
900		fd_set readfds;
901
902		FD_ZERO(&readfds);
903		FD_SET(fd, &readfds);
904
905		n = select(fd + 1, &readfds, NULL, NULL, &tv);
906
907		if (n == -1) {
908			generr(h, "select: %s", strerror(errno));
909			return -1;
910		}
911
912		if (!FD_ISSET(fd, &readfds)) {
913			/* Compute a new timeout */
914			gettimeofday(&tv, NULL);
915			timersub(&timelimit, &tv, &tv);
916			if (tv.tv_sec > 0 || (tv.tv_sec == 0 && tv.tv_usec > 0))
917				/* Continue the select */
918				continue;
919		}
920
921		n = rad_continue_send_request(h, n, &fd, &tv);
922
923		if (n != 0)
924			return n;
925
926		gettimeofday(&timelimit, NULL);
927		timeradd(&tv, &timelimit, &timelimit);
928	}
929}
930
931const char *
932rad_strerror(struct rad_handle *h)
933{
934	return h->errmsg;
935}
936
937/*
938 * Destructively split a string into fields separated by white space.
939 * `#' at the beginning of a field begins a comment that extends to the
940 * end of the string.  Fields may be quoted with `"'.  Inside quoted
941 * strings, the backslash escapes `\"' and `\\' are honored.
942 *
943 * Pointers to up to the first maxfields fields are stored in the fields
944 * array.  Missing fields get NULL pointers.
945 *
946 * The return value is the actual number of fields parsed, and is always
947 * <= maxfields.
948 *
949 * On a syntax error, places a message in the msg string, and returns -1.
950 */
951static int
952split(char *str, char *fields[], int maxfields, char *msg, size_t msglen)
953{
954	char *p;
955	int i;
956	static const char ws[] = " \t";
957
958	for (i = 0;  i < maxfields;  i++)
959		fields[i] = NULL;
960	p = str;
961	i = 0;
962	while (*p != '\0') {
963		p += strspn(p, ws);
964		if (*p == '#' || *p == '\0')
965			break;
966		if (i >= maxfields) {
967			snprintf(msg, msglen, "line has too many fields");
968			return -1;
969		}
970		if (*p == '"') {
971			char *dst;
972
973			dst = ++p;
974			fields[i] = dst;
975			while (*p != '"') {
976				if (*p == '\\') {
977					p++;
978					if (*p != '"' && *p != '\\' &&
979					    *p != '\0') {
980						snprintf(msg, msglen,
981						    "invalid `\\' escape");
982						return -1;
983					}
984				}
985				if (*p == '\0') {
986					snprintf(msg, msglen,
987					    "unterminated quoted string");
988					return -1;
989				}
990				*dst++ = *p++;
991			}
992			*dst = '\0';
993			p++;
994			if (*fields[i] == '\0') {
995				snprintf(msg, msglen,
996				    "empty quoted string not permitted");
997				return -1;
998			}
999			if (*p != '\0' && strspn(p, ws) == 0) {
1000				snprintf(msg, msglen, "quoted string not"
1001				    " followed by white space");
1002				return -1;
1003			}
1004		} else {
1005			fields[i] = p;
1006			p += strcspn(p, ws);
1007			if (*p != '\0')
1008				*p++ = '\0';
1009		}
1010		i++;
1011	}
1012	return i;
1013}
1014
1015int
1016rad_get_vendor_attr(u_int32_t *vendor, const void **data, size_t *len)
1017{
1018	struct vendor_attribute *attr;
1019
1020	attr = (struct vendor_attribute *)*data;
1021	*vendor = ntohl(attr->vendor_value);
1022	*data = attr->attrib_data;
1023	*len = attr->attrib_len - 2;
1024
1025	return (attr->attrib_type);
1026}
1027
1028int
1029rad_put_vendor_addr(struct rad_handle *h, int vendor, int type,
1030    struct in_addr addr)
1031{
1032	return (rad_put_vendor_attr(h, vendor, type, &addr.s_addr,
1033	    sizeof addr.s_addr));
1034}
1035
1036int
1037rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
1038    const void *value, size_t len)
1039{
1040	struct vendor_attribute *attr;
1041	int res;
1042
1043	if (!h->request_created) {
1044		generr(h, "Please call rad_create_request()"
1045		    " before putting attributes");
1046		return -1;
1047	}
1048
1049	if ((attr = malloc(len + 6)) == NULL) {
1050		generr(h, "malloc failure (%d bytes)", len + 6);
1051		return -1;
1052	}
1053
1054	attr->vendor_value = htonl(vendor);
1055	attr->attrib_type = type;
1056	attr->attrib_len = len + 2;
1057	memcpy(attr->attrib_data, value, len);
1058
1059	res = put_raw_attr(h, RAD_VENDOR_SPECIFIC, attr, len + 6);
1060	free(attr);
1061	if (res == 0 && vendor == RAD_VENDOR_MICROSOFT
1062	    && (type == RAD_MICROSOFT_MS_CHAP_RESPONSE
1063	    || type == RAD_MICROSOFT_MS_CHAP2_RESPONSE)) {
1064		h->chap_pass = 1;
1065	}
1066	return (res);
1067}
1068
1069int
1070rad_put_vendor_int(struct rad_handle *h, int vendor, int type, u_int32_t i)
1071{
1072	u_int32_t value;
1073
1074	value = htonl(i);
1075	return (rad_put_vendor_attr(h, vendor, type, &value, sizeof value));
1076}
1077
1078int
1079rad_put_vendor_string(struct rad_handle *h, int vendor, int type,
1080    const char *str)
1081{
1082	return (rad_put_vendor_attr(h, vendor, type, str, strlen(str)));
1083}
1084
1085ssize_t
1086rad_request_authenticator(struct rad_handle *h, char *buf, size_t len)
1087{
1088	if (len < LEN_AUTH)
1089		return (-1);
1090	memcpy(buf, h->request + POS_AUTH, LEN_AUTH);
1091	if (len > LEN_AUTH)
1092		buf[LEN_AUTH] = '\0';
1093	return (LEN_AUTH);
1094}
1095
1096u_char *
1097rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen)
1098{
1099	char R[LEN_AUTH];
1100	const char *S;
1101	int i, Ppos;
1102	MD5_CTX Context;
1103	u_char b[MD5_DIGEST_LENGTH], *C, *demangled;
1104
1105	if ((mlen % 16 != 0) || mlen > 128) {
1106		generr(h, "Cannot interpret mangled data of length %lu",
1107		    (u_long)mlen);
1108		return NULL;
1109	}
1110
1111	C = (u_char *)mangled;
1112
1113	/* We need the shared secret as Salt */
1114	S = rad_server_secret(h);
1115
1116	/* We need the request authenticator */
1117	if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
1118		generr(h, "Cannot obtain the RADIUS request authenticator");
1119		return NULL;
1120	}
1121
1122	demangled = malloc(mlen);
1123	if (!demangled)
1124		return NULL;
1125
1126	MD5Init(&Context);
1127	MD5Update(&Context, S, strlen(S));
1128	MD5Update(&Context, R, LEN_AUTH);
1129	MD5Final(b, &Context);
1130	Ppos = 0;
1131	while (mlen) {
1132
1133		mlen -= 16;
1134		for (i = 0; i < 16; i++)
1135			demangled[Ppos++] = C[i] ^ b[i];
1136
1137		if (mlen) {
1138			MD5Init(&Context);
1139			MD5Update(&Context, S, strlen(S));
1140			MD5Update(&Context, C, 16);
1141			MD5Final(b, &Context);
1142		}
1143
1144		C += 16;
1145	}
1146
1147	return demangled;
1148}
1149
1150u_char *
1151rad_demangle_mppe_key(struct rad_handle *h, const void *mangled,
1152    size_t mlen, size_t *len)
1153{
1154	char R[LEN_AUTH];    /* variable names as per rfc2548 */
1155	const char *S;
1156	u_char b[MD5_DIGEST_LENGTH], *demangled;
1157	const u_char *A, *C;
1158	MD5_CTX Context;
1159	int Slen, i, Clen, Ppos;
1160	u_char *P;
1161
1162	if (mlen % 16 != SALT_LEN) {
1163		generr(h, "Cannot interpret mangled data of length %lu",
1164		    (u_long)mlen);
1165		return NULL;
1166	}
1167
1168	/* We need the RADIUS Request-Authenticator */
1169	if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) {
1170		generr(h, "Cannot obtain the RADIUS request authenticator");
1171		return NULL;
1172	}
1173
1174	A = (const u_char *)mangled;      /* Salt comes first */
1175	C = (const u_char *)mangled + SALT_LEN;  /* Then the ciphertext */
1176	Clen = mlen - SALT_LEN;
1177	S = rad_server_secret(h);    /* We need the RADIUS secret */
1178	Slen = strlen(S);
1179	P = alloca(Clen);        /* We derive our plaintext */
1180
1181	MD5Init(&Context);
1182	MD5Update(&Context, S, Slen);
1183	MD5Update(&Context, R, LEN_AUTH);
1184	MD5Update(&Context, A, SALT_LEN);
1185	MD5Final(b, &Context);
1186	Ppos = 0;
1187
1188	while (Clen) {
1189		Clen -= 16;
1190
1191		for (i = 0; i < 16; i++)
1192		    P[Ppos++] = C[i] ^ b[i];
1193
1194		if (Clen) {
1195			MD5Init(&Context);
1196			MD5Update(&Context, S, Slen);
1197			MD5Update(&Context, C, 16);
1198			MD5Final(b, &Context);
1199		}
1200
1201		C += 16;
1202	}
1203
1204	/*
1205	* The resulting plain text consists of a one-byte length, the text and
1206	* maybe some padding.
1207	*/
1208	*len = *P;
1209	if (*len > mlen - 1) {
1210		generr(h, "Mangled data seems to be garbage %d %d",
1211		    *len, mlen-1);
1212		return NULL;
1213	}
1214
1215	if (*len > MPPE_KEY_LEN * 2) {
1216		generr(h, "Key to long (%d) for me max. %d",
1217		    *len, MPPE_KEY_LEN * 2);
1218		return NULL;
1219	}
1220	demangled = malloc(*len);
1221	if (!demangled)
1222		return NULL;
1223
1224	memcpy(demangled, P + 1, *len);
1225	return demangled;
1226}
1227
1228const char *
1229rad_server_secret(struct rad_handle *h)
1230{
1231	return (h->servers[h->srv].secret);
1232}
1233