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