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/types.h> 30 #include <sys/socket.h> 31 #include <sys/time.h> 32 #include <netinet/in.h> 33 #include <arpa/inet.h> 34 #ifdef WITH_SSL 35 #include <openssl/hmac.h> 36 #include <openssl/md5.h> 37 #define MD5Init MD5_Init 38 #define MD5Update MD5_Update 39 #define MD5Final MD5_Final 40 #else 41 #define MD5_DIGEST_LENGTH 16 42 #include <md5.h> 43 #endif 44 45 #define MAX_FIELDS 7 46 47 /* We need the MPPE_KEY_LEN define */ 48 #include <netgraph/ng_mppc.h> 49 50 #include <errno.h> 51 #include <netdb.h> 52 #include <stdarg.h> 53 #include <stddef.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #include <unistd.h> 58 59 #include "radlib_private.h" 60 61 static void clear_password(struct rad_handle *); 62 static void generr(struct rad_handle *, const char *, ...) 63 __printflike(2, 3); 64 static void insert_scrambled_password(struct rad_handle *, int); 65 static void insert_request_authenticator(struct rad_handle *, int); 66 static void insert_message_authenticator(struct rad_handle *, int); 67 static int is_valid_response(struct rad_handle *, int, 68 const struct sockaddr_in *); 69 static int put_password_attr(struct rad_handle *, int, 70 const void *, size_t); 71 static int put_raw_attr(struct rad_handle *, int, 72 const void *, size_t); 73 static int split(char *, char *[], int, char *, size_t); 74 75 static void 76 clear_password(struct rad_handle *h) 77 { 78 if (h->pass_len != 0) { 79 explicit_bzero(h->pass, h->pass_len); 80 h->pass_len = 0; 81 } 82 h->pass_pos = 0; 83 } 84 85 static void 86 generr(struct rad_handle *h, const char *format, ...) 87 { 88 va_list ap; 89 90 va_start(ap, format); 91 vsnprintf(h->errmsg, ERRSIZE, format, ap); 92 va_end(ap); 93 } 94 95 static void 96 insert_scrambled_password(struct rad_handle *h, int srv) 97 { 98 MD5_CTX ctx; 99 unsigned char md5[MD5_DIGEST_LENGTH]; 100 const struct rad_server *srvp; 101 int padded_len; 102 int pos; 103 104 srvp = &h->servers[srv]; 105 padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf; 106 107 memcpy(md5, &h->out[POS_AUTH], LEN_AUTH); 108 for (pos = 0; pos < padded_len; pos += 16) { 109 int i; 110 111 /* Calculate the new scrambler */ 112 MD5Init(&ctx); 113 MD5Update(&ctx, srvp->secret, strlen(srvp->secret)); 114 MD5Update(&ctx, md5, 16); 115 MD5Final(md5, &ctx); 116 117 /* 118 * Mix in the current chunk of the password, and copy 119 * the result into the right place in the request. Also 120 * modify the scrambler in place, since we will use this 121 * in calculating the scrambler for next time. 122 */ 123 for (i = 0; i < 16; i++) 124 h->out[h->pass_pos + pos + i] = 125 md5[i] ^= h->pass[pos + i]; 126 } 127 } 128 129 static void 130 insert_request_authenticator(struct rad_handle *h, int resp) 131 { 132 MD5_CTX ctx; 133 const struct rad_server *srvp; 134 135 srvp = &h->servers[h->srv]; 136 137 /* Create the request authenticator */ 138 MD5Init(&ctx); 139 MD5Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE); 140 if (resp) 141 MD5Update(&ctx, &h->in[POS_AUTH], LEN_AUTH); 142 else 143 MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH); 144 MD5Update(&ctx, &h->out[POS_ATTRS], h->out_len - POS_ATTRS); 145 MD5Update(&ctx, srvp->secret, strlen(srvp->secret)); 146 MD5Final(&h->out[POS_AUTH], &ctx); 147 } 148 149 static void 150 insert_message_authenticator(struct rad_handle *h, int resp) 151 { 152 #ifdef WITH_SSL 153 u_char md[EVP_MAX_MD_SIZE]; 154 u_int md_len; 155 const struct rad_server *srvp; 156 HMAC_CTX *ctx; 157 srvp = &h->servers[h->srv]; 158 159 if (h->authentic_pos != 0) { 160 ctx = HMAC_CTX_new(); 161 HMAC_Init_ex(ctx, srvp->secret, strlen(srvp->secret), EVP_md5(), NULL); 162 HMAC_Update(ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE); 163 if (resp) 164 HMAC_Update(ctx, &h->in[POS_AUTH], LEN_AUTH); 165 else 166 HMAC_Update(ctx, &h->out[POS_AUTH], LEN_AUTH); 167 HMAC_Update(ctx, &h->out[POS_ATTRS], 168 h->out_len - POS_ATTRS); 169 HMAC_Final(ctx, md, &md_len); 170 HMAC_CTX_free(ctx); 171 memcpy(&h->out[h->authentic_pos + 2], md, md_len); 172 } 173 #endif 174 } 175 176 /* 177 * Return true if the current response is valid for a request to the 178 * specified server. 179 */ 180 static int 181 is_valid_response(struct rad_handle *h, int srv, 182 const struct sockaddr_in *from) 183 { 184 MD5_CTX ctx; 185 unsigned char md5[MD5_DIGEST_LENGTH]; 186 const struct rad_server *srvp; 187 188 int len; 189 #ifdef WITH_SSL 190 int alen; 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 < POS_ATTRS || 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 hctx = HMAC_CTX_new(); 234 while (pos < len - 2) { 235 if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) { 236 if (h->in[pos + 1] != MD5_DIGEST_LENGTH + 2) { 237 HMAC_CTX_free(hctx); 238 return 0; 239 } 240 if (len - pos < MD5_DIGEST_LENGTH + 2) { 241 HMAC_CTX_free(hctx); 242 return 0; 243 } 244 245 memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH); 246 247 HMAC_Init_ex(hctx, srvp->secret, 248 strlen(srvp->secret), EVP_md5(), NULL); 249 HMAC_Update(hctx, &h->in[POS_CODE], 250 POS_AUTH - POS_CODE); 251 HMAC_Update(hctx, &h->out[POS_AUTH], 252 LEN_AUTH); 253 HMAC_Update(hctx, &resp[POS_ATTRS], 254 h->in_len - POS_ATTRS); 255 HMAC_Final(hctx, md, &md_len); 256 HMAC_CTX_reset(hctx); 257 if (memcmp(md, &h->in[pos + 2], 258 MD5_DIGEST_LENGTH) != 0) { 259 HMAC_CTX_free(hctx); 260 return 0; 261 } 262 break; 263 } 264 alen = h->in[pos + 1]; 265 if (alen < 2) { 266 HMAC_CTX_free(hctx); 267 return 0; 268 } 269 pos += alen; 270 } 271 HMAC_CTX_free(hctx); 272 } 273 #endif 274 return 1; 275 } 276 277 /* 278 * Return true if the current request is valid for the specified server. 279 */ 280 static int 281 is_valid_request(struct rad_handle *h) 282 { 283 MD5_CTX ctx; 284 unsigned char md5[MD5_DIGEST_LENGTH]; 285 const struct rad_server *srvp; 286 int len; 287 #ifdef WITH_SSL 288 int alen; 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) { 968 generr(h, "Malformed attribute in response"); 969 return -1; 970 } 971 len -= 2; 972 if (h->in_pos + len > h->in_len) { 973 generr(h, "Malformed attribute in response"); 974 return -1; 975 } 976 *lenp = len; 977 *value = &h->in[h->in_pos]; 978 h->in_pos += len; 979 return type; 980 } 981 982 /* 983 * Returns -1 on error, 0 to indicate no event and >0 for success 984 */ 985 int 986 rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv) 987 { 988 int srv; 989 time_t now; 990 struct sockaddr_in sin; 991 992 if (h->type == RADIUS_SERVER) { 993 generr(h, "denied function call"); 994 return (-1); 995 } 996 /* Make sure we have a socket to use */ 997 if (h->fd == -1) { 998 if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 999 generr(h, "Cannot create socket: %s", strerror(errno)); 1000 return -1; 1001 } 1002 memset(&sin, 0, sizeof sin); 1003 sin.sin_len = sizeof sin; 1004 sin.sin_family = AF_INET; 1005 sin.sin_addr.s_addr = h->bindto; 1006 sin.sin_port = htons(0); 1007 if (bind(h->fd, (const struct sockaddr *)&sin, 1008 sizeof sin) == -1) { 1009 generr(h, "bind: %s", strerror(errno)); 1010 close(h->fd); 1011 h->fd = -1; 1012 return -1; 1013 } 1014 } 1015 1016 if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) { 1017 /* Make sure no password given */ 1018 if (h->pass_pos || h->chap_pass) { 1019 generr(h, "User or Chap Password" 1020 " in accounting request"); 1021 return -1; 1022 } 1023 } else { 1024 if (h->eap_msg == 0) { 1025 /* Make sure the user gave us a password */ 1026 if (h->pass_pos == 0 && !h->chap_pass) { 1027 generr(h, "No User or Chap Password" 1028 " attributes given"); 1029 return -1; 1030 } 1031 if (h->pass_pos != 0 && h->chap_pass) { 1032 generr(h, "Both User and Chap Password" 1033 " attributes given"); 1034 return -1; 1035 } 1036 } 1037 } 1038 1039 /* Fill in the length field in the message */ 1040 h->out[POS_LENGTH] = h->out_len >> 8; 1041 h->out[POS_LENGTH+1] = h->out_len; 1042 1043 h->srv = 0; 1044 now = time(NULL); 1045 for (srv = 0; srv < h->num_servers; srv++) 1046 h->servers[srv].num_tries = 0; 1047 /* Find a first good server. */ 1048 for (srv = 0; srv < h->num_servers; srv++) { 1049 if (h->servers[srv].is_dead == 0) 1050 break; 1051 if (h->servers[srv].dead_time && 1052 h->servers[srv].next_probe <= now) { 1053 h->servers[srv].is_dead = 0; 1054 break; 1055 } 1056 h->srv++; 1057 } 1058 1059 /* If all servers was dead on the last probe, try from beginning */ 1060 if (h->srv == h->num_servers) { 1061 for (srv = 0; srv < h->num_servers; srv++) { 1062 h->servers[srv].is_dead = 0; 1063 h->servers[srv].next_probe = 0; 1064 } 1065 h->srv = 0; 1066 } 1067 1068 return rad_continue_send_request(h, 0, fd, tv); 1069 } 1070 1071 /* 1072 * Create and initialize a rad_handle structure, and return it to the 1073 * caller. Can fail only if the necessary memory cannot be allocated. 1074 * In that case, it returns NULL. 1075 */ 1076 struct rad_handle * 1077 rad_auth_open(void) 1078 { 1079 struct rad_handle *h; 1080 1081 h = (struct rad_handle *)malloc(sizeof(struct rad_handle)); 1082 if (h != NULL) { 1083 h->fd = -1; 1084 h->num_servers = 0; 1085 h->ident = arc4random(); 1086 h->errmsg[0] = '\0'; 1087 memset(h->pass, 0, sizeof h->pass); 1088 h->pass_len = 0; 1089 h->pass_pos = 0; 1090 h->chap_pass = 0; 1091 h->authentic_pos = 0; 1092 h->type = RADIUS_AUTH; 1093 h->out_created = 0; 1094 h->eap_msg = 0; 1095 h->bindto = INADDR_ANY; 1096 } 1097 return h; 1098 } 1099 1100 struct rad_handle * 1101 rad_acct_open(void) 1102 { 1103 struct rad_handle *h; 1104 1105 h = rad_open(); 1106 if (h != NULL) 1107 h->type = RADIUS_ACCT; 1108 return h; 1109 } 1110 1111 struct rad_handle * 1112 rad_server_open(int fd) 1113 { 1114 struct rad_handle *h; 1115 1116 h = rad_open(); 1117 if (h != NULL) { 1118 h->type = RADIUS_SERVER; 1119 h->fd = fd; 1120 } 1121 return h; 1122 } 1123 1124 struct rad_handle * 1125 rad_open(void) 1126 { 1127 return rad_auth_open(); 1128 } 1129 1130 int 1131 rad_put_addr(struct rad_handle *h, int type, struct in_addr addr) 1132 { 1133 return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr); 1134 } 1135 1136 int 1137 rad_put_addr6(struct rad_handle *h, int type, struct in6_addr addr) 1138 { 1139 1140 return rad_put_attr(h, type, &addr.s6_addr, sizeof addr.s6_addr); 1141 } 1142 1143 int 1144 rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len) 1145 { 1146 int result; 1147 1148 if (!h->out_created) { 1149 generr(h, "Please call rad_create_request()" 1150 " before putting attributes"); 1151 return -1; 1152 } 1153 1154 if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) { 1155 if (type == RAD_EAP_MESSAGE) { 1156 generr(h, "EAP-Message attribute is not valid" 1157 " in accounting requests"); 1158 return -1; 1159 } 1160 } 1161 1162 /* 1163 * When proxying EAP Messages, the Message Authenticator 1164 * MUST be present; see RFC 3579. 1165 */ 1166 if (type == RAD_EAP_MESSAGE) { 1167 if (rad_put_message_authentic(h) == -1) 1168 return -1; 1169 } 1170 1171 if (type == RAD_USER_PASSWORD) { 1172 result = put_password_attr(h, type, value, len); 1173 } else if (type == RAD_MESSAGE_AUTHENTIC) { 1174 result = rad_put_message_authentic(h); 1175 } else { 1176 result = put_raw_attr(h, type, value, len); 1177 if (result == 0) { 1178 if (type == RAD_CHAP_PASSWORD) 1179 h->chap_pass = 1; 1180 else if (type == RAD_EAP_MESSAGE) 1181 h->eap_msg = 1; 1182 } 1183 } 1184 1185 return result; 1186 } 1187 1188 int 1189 rad_put_int(struct rad_handle *h, int type, u_int32_t value) 1190 { 1191 u_int32_t nvalue; 1192 1193 nvalue = htonl(value); 1194 return rad_put_attr(h, type, &nvalue, sizeof nvalue); 1195 } 1196 1197 int 1198 rad_put_string(struct rad_handle *h, int type, const char *str) 1199 { 1200 return rad_put_attr(h, type, str, strlen(str)); 1201 } 1202 1203 int 1204 rad_put_message_authentic(struct rad_handle *h) 1205 { 1206 #ifdef WITH_SSL 1207 u_char md_zero[MD5_DIGEST_LENGTH]; 1208 1209 if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) { 1210 generr(h, "Message-Authenticator is not valid" 1211 " in accounting requests"); 1212 return -1; 1213 } 1214 1215 if (h->authentic_pos == 0) { 1216 h->authentic_pos = h->out_len; 1217 memset(md_zero, 0, sizeof(md_zero)); 1218 return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero, 1219 sizeof(md_zero))); 1220 } 1221 return 0; 1222 #else 1223 generr(h, "Message Authenticator not supported," 1224 " please recompile libradius with SSL support"); 1225 return -1; 1226 #endif 1227 } 1228 1229 /* 1230 * Returns the response type code on success, or -1 on failure. 1231 */ 1232 int 1233 rad_send_request(struct rad_handle *h) 1234 { 1235 struct timeval timelimit; 1236 struct timeval tv; 1237 int fd; 1238 int n; 1239 1240 n = rad_init_send_request(h, &fd, &tv); 1241 1242 if (n != 0) 1243 return n; 1244 1245 gettimeofday(&timelimit, NULL); 1246 timeradd(&tv, &timelimit, &timelimit); 1247 1248 for ( ; ; ) { 1249 fd_set readfds; 1250 1251 FD_ZERO(&readfds); 1252 FD_SET(fd, &readfds); 1253 1254 n = select(fd + 1, &readfds, NULL, NULL, &tv); 1255 1256 if (n == -1) { 1257 generr(h, "select: %s", strerror(errno)); 1258 return -1; 1259 } 1260 1261 if (!FD_ISSET(fd, &readfds)) { 1262 /* Compute a new timeout */ 1263 gettimeofday(&tv, NULL); 1264 timersub(&timelimit, &tv, &tv); 1265 if (tv.tv_sec > 0 || (tv.tv_sec == 0 && tv.tv_usec > 0)) 1266 /* Continue the select */ 1267 continue; 1268 } 1269 1270 n = rad_continue_send_request(h, n, &fd, &tv); 1271 1272 if (n != 0) 1273 return n; 1274 1275 gettimeofday(&timelimit, NULL); 1276 timeradd(&tv, &timelimit, &timelimit); 1277 } 1278 } 1279 1280 const char * 1281 rad_strerror(struct rad_handle *h) 1282 { 1283 return h->errmsg; 1284 } 1285 1286 /* 1287 * Destructively split a string into fields separated by white space. 1288 * `#' at the beginning of a field begins a comment that extends to the 1289 * end of the string. Fields may be quoted with `"'. Inside quoted 1290 * strings, the backslash escapes `\"' and `\\' are honored. 1291 * 1292 * Pointers to up to the first maxfields fields are stored in the fields 1293 * array. Missing fields get NULL pointers. 1294 * 1295 * The return value is the actual number of fields parsed, and is always 1296 * <= maxfields. 1297 * 1298 * On a syntax error, places a message in the msg string, and returns -1. 1299 */ 1300 static int 1301 split(char *str, char *fields[], int maxfields, char *msg, size_t msglen) 1302 { 1303 char *p; 1304 int i; 1305 static const char ws[] = " \t"; 1306 1307 for (i = 0; i < maxfields; i++) 1308 fields[i] = NULL; 1309 p = str; 1310 i = 0; 1311 while (*p != '\0') { 1312 p += strspn(p, ws); 1313 if (*p == '#' || *p == '\0') 1314 break; 1315 if (i >= maxfields) { 1316 snprintf(msg, msglen, "line has too many fields"); 1317 return -1; 1318 } 1319 if (*p == '"') { 1320 char *dst; 1321 1322 dst = ++p; 1323 fields[i] = dst; 1324 while (*p != '"') { 1325 if (*p == '\\') { 1326 p++; 1327 if (*p != '"' && *p != '\\' && 1328 *p != '\0') { 1329 snprintf(msg, msglen, 1330 "invalid `\\' escape"); 1331 return -1; 1332 } 1333 } 1334 if (*p == '\0') { 1335 snprintf(msg, msglen, 1336 "unterminated quoted string"); 1337 return -1; 1338 } 1339 *dst++ = *p++; 1340 } 1341 *dst = '\0'; 1342 p++; 1343 if (*fields[i] == '\0') { 1344 snprintf(msg, msglen, 1345 "empty quoted string not permitted"); 1346 return -1; 1347 } 1348 if (*p != '\0' && strspn(p, ws) == 0) { 1349 snprintf(msg, msglen, "quoted string not" 1350 " followed by white space"); 1351 return -1; 1352 } 1353 } else { 1354 fields[i] = p; 1355 p += strcspn(p, ws); 1356 if (*p != '\0') 1357 *p++ = '\0'; 1358 } 1359 i++; 1360 } 1361 return i; 1362 } 1363 1364 int 1365 rad_get_vendor_attr(u_int32_t *vendor, const void **data, size_t *len) 1366 { 1367 struct vendor_attribute *attr; 1368 1369 attr = (struct vendor_attribute *)*data; 1370 *vendor = ntohl(attr->vendor_value); 1371 *data = attr->attrib_data; 1372 *len = attr->attrib_len - 2; 1373 1374 return (attr->attrib_type); 1375 } 1376 1377 int 1378 rad_put_vendor_addr(struct rad_handle *h, int vendor, int type, 1379 struct in_addr addr) 1380 { 1381 return (rad_put_vendor_attr(h, vendor, type, &addr.s_addr, 1382 sizeof addr.s_addr)); 1383 } 1384 1385 int 1386 rad_put_vendor_addr6(struct rad_handle *h, int vendor, int type, 1387 struct in6_addr addr) 1388 { 1389 1390 return (rad_put_vendor_attr(h, vendor, type, &addr.s6_addr, 1391 sizeof addr.s6_addr)); 1392 } 1393 1394 int 1395 rad_put_vendor_attr(struct rad_handle *h, int vendor, int type, 1396 const void *value, size_t len) 1397 { 1398 struct vendor_attribute *attr; 1399 int res; 1400 1401 if (!h->out_created) { 1402 generr(h, "Please call rad_create_request()" 1403 " before putting attributes"); 1404 return -1; 1405 } 1406 1407 if ((attr = malloc(len + 6)) == NULL) { 1408 generr(h, "malloc failure (%zu bytes)", len + 6); 1409 return -1; 1410 } 1411 1412 attr->vendor_value = htonl(vendor); 1413 attr->attrib_type = type; 1414 attr->attrib_len = len + 2; 1415 memcpy(attr->attrib_data, value, len); 1416 1417 res = put_raw_attr(h, RAD_VENDOR_SPECIFIC, attr, len + 6); 1418 free(attr); 1419 if (res == 0 && vendor == RAD_VENDOR_MICROSOFT 1420 && (type == RAD_MICROSOFT_MS_CHAP_RESPONSE 1421 || type == RAD_MICROSOFT_MS_CHAP2_RESPONSE)) { 1422 h->chap_pass = 1; 1423 } 1424 return (res); 1425 } 1426 1427 int 1428 rad_put_vendor_int(struct rad_handle *h, int vendor, int type, u_int32_t i) 1429 { 1430 u_int32_t value; 1431 1432 value = htonl(i); 1433 return (rad_put_vendor_attr(h, vendor, type, &value, sizeof value)); 1434 } 1435 1436 int 1437 rad_put_vendor_string(struct rad_handle *h, int vendor, int type, 1438 const char *str) 1439 { 1440 return (rad_put_vendor_attr(h, vendor, type, str, strlen(str))); 1441 } 1442 1443 ssize_t 1444 rad_request_authenticator(struct rad_handle *h, char *buf, size_t len) 1445 { 1446 if (len < LEN_AUTH) 1447 return (-1); 1448 memcpy(buf, h->out + POS_AUTH, LEN_AUTH); 1449 if (len > LEN_AUTH) 1450 buf[LEN_AUTH] = '\0'; 1451 return (LEN_AUTH); 1452 } 1453 1454 u_char * 1455 rad_demangle(struct rad_handle *h, const void *mangled, size_t mlen) 1456 { 1457 char R[LEN_AUTH]; 1458 const char *S; 1459 int i, Ppos; 1460 MD5_CTX Context; 1461 u_char b[MD5_DIGEST_LENGTH], *C, *demangled; 1462 1463 if ((mlen % 16 != 0) || mlen > 128) { 1464 generr(h, "Cannot interpret mangled data of length %lu", 1465 (u_long)mlen); 1466 return NULL; 1467 } 1468 1469 C = (u_char *)mangled; 1470 1471 /* We need the shared secret as Salt */ 1472 S = rad_server_secret(h); 1473 1474 /* We need the request authenticator */ 1475 if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) { 1476 generr(h, "Cannot obtain the RADIUS request authenticator"); 1477 return NULL; 1478 } 1479 1480 demangled = malloc(mlen); 1481 if (!demangled) 1482 return NULL; 1483 1484 MD5Init(&Context); 1485 MD5Update(&Context, S, strlen(S)); 1486 MD5Update(&Context, R, LEN_AUTH); 1487 MD5Final(b, &Context); 1488 Ppos = 0; 1489 while (mlen) { 1490 1491 mlen -= 16; 1492 for (i = 0; i < 16; i++) 1493 demangled[Ppos++] = C[i] ^ b[i]; 1494 1495 if (mlen) { 1496 MD5Init(&Context); 1497 MD5Update(&Context, S, strlen(S)); 1498 MD5Update(&Context, C, 16); 1499 MD5Final(b, &Context); 1500 } 1501 1502 C += 16; 1503 } 1504 1505 return demangled; 1506 } 1507 1508 u_char * 1509 rad_demangle_mppe_key(struct rad_handle *h, const void *mangled, 1510 size_t mlen, size_t *len) 1511 { 1512 char R[LEN_AUTH]; /* variable names as per rfc2548 */ 1513 const char *S; 1514 u_char b[MD5_DIGEST_LENGTH], *demangled; 1515 const u_char *A, *C; 1516 MD5_CTX Context; 1517 int Slen, i, Clen, Ppos; 1518 u_char *P; 1519 1520 if (mlen % 16 != SALT_LEN) { 1521 generr(h, "Cannot interpret mangled data of length %lu", 1522 (u_long)mlen); 1523 return NULL; 1524 } 1525 1526 /* We need the RADIUS Request-Authenticator */ 1527 if (rad_request_authenticator(h, R, sizeof R) != LEN_AUTH) { 1528 generr(h, "Cannot obtain the RADIUS request authenticator"); 1529 return NULL; 1530 } 1531 1532 A = (const u_char *)mangled; /* Salt comes first */ 1533 C = (const u_char *)mangled + SALT_LEN; /* Then the ciphertext */ 1534 Clen = mlen - SALT_LEN; 1535 S = rad_server_secret(h); /* We need the RADIUS secret */ 1536 Slen = strlen(S); 1537 P = alloca(Clen); /* We derive our plaintext */ 1538 1539 MD5Init(&Context); 1540 MD5Update(&Context, S, Slen); 1541 MD5Update(&Context, R, LEN_AUTH); 1542 MD5Update(&Context, A, SALT_LEN); 1543 MD5Final(b, &Context); 1544 Ppos = 0; 1545 1546 while (Clen) { 1547 Clen -= 16; 1548 1549 for (i = 0; i < 16; i++) 1550 P[Ppos++] = C[i] ^ b[i]; 1551 1552 if (Clen) { 1553 MD5Init(&Context); 1554 MD5Update(&Context, S, Slen); 1555 MD5Update(&Context, C, 16); 1556 MD5Final(b, &Context); 1557 } 1558 1559 C += 16; 1560 } 1561 1562 /* 1563 * The resulting plain text consists of a one-byte length, the text and 1564 * maybe some padding. 1565 */ 1566 *len = *P; 1567 if (*len > mlen - 1) { 1568 generr(h, "Mangled data seems to be garbage %zu %zu", 1569 *len, mlen-1); 1570 return NULL; 1571 } 1572 1573 if (*len > MPPE_KEY_LEN * 2) { 1574 generr(h, "Key to long (%zu) for me max. %d", 1575 *len, MPPE_KEY_LEN * 2); 1576 return NULL; 1577 } 1578 demangled = malloc(*len); 1579 if (!demangled) 1580 return NULL; 1581 1582 memcpy(demangled, P + 1, *len); 1583 return demangled; 1584 } 1585 1586 const char * 1587 rad_server_secret(struct rad_handle *h) 1588 { 1589 return (h->servers[h->srv].secret); 1590 } 1591