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