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