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