xref: /freebsd/lib/libradius/radlib.c (revision 8ab2f5ecc596131f6ca790d6ae35540c06ed7985)
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$");
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 
60 static void	 clear_password(struct rad_handle *);
61 static void	 generr(struct rad_handle *, const char *, ...)
62 		    __printflike(2, 3);
63 static void	 insert_scrambled_password(struct rad_handle *, int);
64 static void	 insert_request_authenticator(struct rad_handle *, int);
65 static void	 insert_message_authenticator(struct rad_handle *, int);
66 static int	 is_valid_response(struct rad_handle *, int,
67 		    const struct sockaddr_in *);
68 static int	 put_password_attr(struct rad_handle *, int,
69 		    const void *, size_t);
70 static int	 put_raw_attr(struct rad_handle *, int,
71 		    const void *, size_t);
72 static int	 split(char *, char *[], int, char *, size_t);
73 
74 static void
75 clear_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 
84 static void
85 generr(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 
94 static void
95 insert_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->request[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->request[h->pass_pos + pos + i] =
124 			    md5[i] ^= h->pass[pos + i];
125 	}
126 }
127 
128 static void
129 insert_request_authenticator(struct rad_handle *h, int srv)
130 {
131 	MD5_CTX ctx;
132 	const struct rad_server *srvp;
133 
134 	srvp = &h->servers[srv];
135 
136 	/* Create the request authenticator */
137 	MD5Init(&ctx);
138 	MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
139 	MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
140 	MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
141 	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
142 	MD5Final(&h->request[POS_AUTH], &ctx);
143 }
144 
145 static void
146 insert_message_authenticator(struct rad_handle *h, int srv)
147 {
148 #ifdef WITH_SSL
149 	u_char md[EVP_MAX_MD_SIZE];
150 	u_int md_len;
151 	const struct rad_server *srvp;
152 	HMAC_CTX ctx;
153 	srvp = &h->servers[srv];
154 
155 	if (h->authentic_pos != 0) {
156 		HMAC_CTX_init(&ctx);
157 		HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
158 		HMAC_Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
159 		HMAC_Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
160 		HMAC_Update(&ctx, &h->request[POS_ATTRS],
161 		    h->req_len - POS_ATTRS);
162 		HMAC_Final(&ctx, md, &md_len);
163 		HMAC_CTX_cleanup(&ctx);
164 		HMAC_cleanup(&ctx);
165 		memcpy(&h->request[h->authentic_pos + 2], md, md_len);
166 	}
167 #endif
168 }
169 
170 /*
171  * Return true if the current response is valid for a request to the
172  * specified server.
173  */
174 static int
175 is_valid_response(struct rad_handle *h, int srv,
176     const struct sockaddr_in *from)
177 {
178 	MD5_CTX ctx;
179 	unsigned char md5[MD5_DIGEST_LENGTH];
180 	const struct rad_server *srvp;
181 	int len;
182 #ifdef WITH_SSL
183 	HMAC_CTX hctx;
184 	u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
185 	int pos, md_len;
186 #endif
187 
188 	srvp = &h->servers[srv];
189 
190 	/* Check the source address */
191 	if (from->sin_family != srvp->addr.sin_family ||
192 	    from->sin_addr.s_addr != srvp->addr.sin_addr.s_addr ||
193 	    from->sin_port != srvp->addr.sin_port)
194 		return 0;
195 
196 	/* Check the message length */
197 	if (h->resp_len < POS_ATTRS)
198 		return 0;
199 	len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
200 	if (len > h->resp_len)
201 		return 0;
202 
203 	/* Check the response authenticator */
204 	MD5Init(&ctx);
205 	MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
206 	MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
207 	MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
208 	MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
209 	MD5Final(md5, &ctx);
210 	if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
211 		return 0;
212 
213 #ifdef WITH_SSL
214 	/*
215 	 * For non accounting responses check the message authenticator,
216 	 * if any.
217 	 */
218 	if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
219 
220 		memcpy(resp, h->response, MSGSIZE);
221 		pos = POS_ATTRS;
222 
223 		/* Search and verify the Message-Authenticator */
224 		while (pos < len - 2) {
225 
226 			if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
227 				/* zero fill the Message-Authenticator */
228 				memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
229 
230 				HMAC_CTX_init(&hctx);
231 				HMAC_Init(&hctx, srvp->secret,
232 				    strlen(srvp->secret), EVP_md5());
233 				HMAC_Update(&hctx, &h->response[POS_CODE],
234 				    POS_AUTH - POS_CODE);
235 				HMAC_Update(&hctx, &h->request[POS_AUTH],
236 				    LEN_AUTH);
237 				HMAC_Update(&hctx, &resp[POS_ATTRS],
238 				    h->resp_len - POS_ATTRS);
239 				HMAC_Final(&hctx, md, &md_len);
240 				HMAC_CTX_cleanup(&hctx);
241 				HMAC_cleanup(&hctx);
242 				if (memcmp(md, &h->response[pos + 2],
243 				    MD5_DIGEST_LENGTH) != 0)
244 					return 0;
245 				break;
246 			}
247 			pos += h->response[pos + 1];
248 		}
249 	}
250 #endif
251 	return 1;
252 }
253 
254 static int
255 put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
256 {
257 	int padded_len;
258 	int pad_len;
259 
260 	if (h->pass_pos != 0) {
261 		generr(h, "Multiple User-Password attributes specified");
262 		return -1;
263 	}
264 	if (len > PASSSIZE)
265 		len = PASSSIZE;
266 	padded_len = len == 0 ? 16 : (len+15) & ~0xf;
267 	pad_len = padded_len - len;
268 
269 	/*
270 	 * Put in a place-holder attribute containing all zeros, and
271 	 * remember where it is so we can fill it in later.
272 	 */
273 	clear_password(h);
274 	put_raw_attr(h, type, h->pass, padded_len);
275 	h->pass_pos = h->req_len - padded_len;
276 
277 	/* Save the cleartext password, padded as necessary */
278 	memcpy(h->pass, value, len);
279 	h->pass_len = len;
280 	memset(h->pass + len, 0, pad_len);
281 	return 0;
282 }
283 
284 static int
285 put_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 
302 int
303 rad_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 
352 void
353 rad_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 
368 int
369 rad_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  */
519 int
520 rad_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 
589 int
590 rad_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 
609 struct in_addr
610 rad_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 
618 u_int32_t
619 rad_cvt_int(const void *data)
620 {
621 	u_int32_t value;
622 
623 	memcpy(&value, data, sizeof value);
624 	return ntohl(value);
625 }
626 
627 char *
628 rad_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  */
644 int
645 rad_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  */
669 int
670 rad_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  */
747 struct rad_handle *
748 rad_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 
771 struct rad_handle *
772 rad_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 
782 struct rad_handle *
783 rad_open(void)
784 {
785     return rad_auth_open();
786 }
787 
788 int
789 rad_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 
794 int
795 rad_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 
839 int
840 rad_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 
848 int
849 rad_put_string(struct rad_handle *h, int type, const char *str)
850 {
851 	return rad_put_attr(h, type, str, strlen(str));
852 }
853 
854 int
855 rad_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  */
883 int
884 rad_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 
931 const char *
932 rad_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  */
951 static int
952 split(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 
1015 int
1016 rad_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 
1028 int
1029 rad_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 
1036 int
1037 rad_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 (%zu 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 
1069 int
1070 rad_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 
1078 int
1079 rad_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 
1085 ssize_t
1086 rad_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 
1096 u_char *
1097 rad_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 
1150 u_char *
1151 rad_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 %zu %zu",
1211 		    *len, mlen-1);
1212 		return NULL;
1213 	}
1214 
1215 	if (*len > MPPE_KEY_LEN * 2) {
1216 		generr(h, "Key to long (%zu) 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 
1228 const char *
1229 rad_server_secret(struct rad_handle *h)
1230 {
1231 	return (h->servers[h->srv].secret);
1232 }
1233