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