Changeset 550:4c935aecee6c in freeDiameter for extensions/app_radgw/radius.c
- Timestamp:
- Sep 15, 2010, 2:24:45 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/app_radgw/radius.c
r540 r550 1 /*********************************************************************************/ 1 /********************************************************************************************************* 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@nict.go.jp> * 4 * * 5 * Copyright (c) 2010, WIDE Project and NICT * 6 * All rights reserved. * 7 * * 8 * Redistribution and use of this software in source and binary forms, with or without modification, are * 9 * permitted provided that the following conditions are met: * 10 * * 11 * * Redistributions of source code must retain the above * 12 * copyright notice, this list of conditions and the * 13 * following disclaimer. * 14 * * 15 * * Redistributions in binary form must reproduce the above * 16 * copyright notice, this list of conditions and the * 17 * following disclaimer in the documentation and/or other * 18 * materials provided with the distribution. * 19 * * 20 * * Neither the name of the WIDE Project or NICT nor the * 21 * names of its contributors may be used to endorse or * 22 * promote products derived from this software without * 23 * specific prior written permission of WIDE Project and * 24 * NICT. * 25 * * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * 28 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * 29 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * 30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * 32 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * 34 *********************************************************************************************************/ 35 2 36 /* freeDiameter author note: 3 * The content from this file comes directlyfrom the hostap project.37 * The content from this file comes for the main part from the hostap project. 4 38 * It is redistributed under the terms of the BSD license, as allowed 5 39 * by the original copyright reproduced bellow. 6 * In addition to this notice, the following changes have been done: 7 * - created the radius_msg_dump_attr_val function 40 * The modifications to this file are placed under the copyright of the freeDiameter project. 8 41 */ 9 #include "rgw_common.h"10 11 /* Overwrite printf */12 #define printf(args...) fd_log_debug(args)13 14 /*********************************************************************************/15 16 42 17 43 /* … … 29 55 */ 30 56 57 /*********************************************************************************/ 58 #include "rgw.h" 59 60 /* Overwrite printf */ 61 #define printf(args...) fd_log_debug(args) 62 63 31 64 static struct radius_attr_hdr * 32 65 radius_get_attr_hdr(struct radius_msg *msg, int idx) … … 104 137 } 105 138 106 107 static const char *radius_code_string(u8 code) 108 { 109 switch (code) { 110 case RADIUS_CODE_ACCESS_REQUEST: return "Access-Request"; 111 case RADIUS_CODE_ACCESS_ACCEPT: return "Access-Accept"; 112 case RADIUS_CODE_ACCESS_REJECT: return "Access-Reject"; 113 case RADIUS_CODE_ACCOUNTING_REQUEST: return "Accounting-Request"; 114 case RADIUS_CODE_ACCOUNTING_RESPONSE: return "Accounting-Response"; 115 case RADIUS_CODE_ACCESS_CHALLENGE: return "Access-Challenge"; 116 case RADIUS_CODE_STATUS_SERVER: return "Status-Server"; 117 case RADIUS_CODE_STATUS_CLIENT: return "Status-Client"; 118 case RADIUS_CODE_RESERVED: return "Reserved"; 119 default: return "?Unknown?"; 120 } 121 } 139 /* Destroy a message */ 140 void rgw_msg_free(struct rgw_radius_msg_meta ** msg) 141 { 142 if (!msg || !*msg) 143 return; 144 145 radius_msg_free(&(*msg)->radius); 146 free(*msg); 147 *msg = NULL; 148 } 149 122 150 123 151 … … 219 247 220 248 221 void radius_msg_dump_attr_val(struct radius_attr_hdr *hdr)249 static void radius_msg_dump_attr_val(struct radius_attr_hdr *hdr) 222 250 { 223 251 struct radius_attr_type *attr; … … 282 310 } 283 311 284 static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) 285 { 286 struct radius_attr_type *attr; 287 288 attr = radius_get_attr_type(hdr->type); 289 290 printf(" Attribute %d (%s) length=%d\n", 291 hdr->type, attr ? attr->name : "?Unknown?", hdr->length); 292 293 radius_msg_dump_attr_val(hdr); 294 } 295 296 297 void radius_msg_dump(struct radius_msg *msg) 298 { 312 /* Dump a message -- can be used safely with a struct radius_msg as parameter (we don't dump the metadata) */ 313 void rgw_msg_dump(struct rgw_radius_msg_meta * msg) 314 { 315 unsigned char *auth; 299 316 size_t i; 300 301 printf("RADIUS message: code=%d (%s) identifier=%d length=%d\n", 302 msg->hdr->code, radius_code_string(msg->hdr->code), 303 msg->hdr->identifier, ntohs(msg->hdr->length)); 304 305 for (i = 0; i < msg->attr_used; i++) { 306 struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); 307 radius_msg_dump_attr(attr); 308 } 317 if (! TRACE_BOOL(FULL) ) 318 return; 319 320 auth = &(msg->radius.hdr->authenticator[0]); 321 322 fd_log_debug("------ RADIUS msg dump -------\n"); 323 fd_log_debug(" id : 0x%02hhx, code : %hhd (%s), length : %d\n", msg->radius.hdr->identifier, msg->radius.hdr->code, rgw_msg_code_str(msg->radius.hdr->code), ntohs(msg->radius.hdr->length)); 324 fd_log_debug(" auth: %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", 325 auth[0], auth[1], auth[2], auth[3], auth[4], auth[5], auth[6], auth[7]); 326 fd_log_debug(" %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx\n", 327 auth[8], auth[9], auth[10], auth[11], auth[12], auth[13], auth[14], auth[15]); 328 for (i = 0; i < msg->radius.attr_used; i++) { 329 struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[i]); 330 fd_log_debug(" - Type: 0x%02hhx (%s)\n Len: %-3hhu", attr->type, rgw_msg_attrtype_str(attr->type), attr->length); 331 radius_msg_dump_attr_val(attr); 332 } 333 if (msg->ps_nb) { 334 fd_log_debug("---- hidden attributes:\n"); 335 for (i = msg->ps_first; i < msg->ps_first + msg->ps_nb; i++) { 336 struct radius_attr_hdr *attr = (struct radius_attr_hdr *)(msg->radius.buf + msg->radius.attr_pos[i]); 337 fd_log_debug(" - Type: 0x%02hhx (%s)\n Len: %-3hhu", attr->type, rgw_msg_attrtype_str(attr->type), attr->length); 338 radius_msg_dump_attr_val(attr); 339 } 340 } 341 fd_log_debug("-----------------------------\n"); 309 342 } 310 343 … … 407 440 408 441 409 staticint radius_msg_add_attr_to_array(struct radius_msg *msg,442 int radius_msg_add_attr_to_array(struct radius_msg *msg, 410 443 struct radius_attr_hdr *attr) 411 444 { … … 474 507 475 508 476 struct radius_msg *radius_msg_parse(const u8 *data, size_t len) 477 { 478 struct radius_msg *msg; 509 /* Modified version of radius_msg_parse */ 510 int rgw_msg_parse(unsigned char * buf, size_t len, struct rgw_radius_msg_meta ** msg) 511 { 512 struct rgw_radius_msg_meta * temp_msg = NULL; 479 513 struct radius_hdr *hdr; 480 514 struct radius_attr_hdr *attr; 481 515 size_t msg_len; 482 516 unsigned char *pos, *end; 483 484 if (data == NULL || len < sizeof(*hdr)) 485 return NULL; 486 487 hdr = (struct radius_hdr *) data; 488 517 int ret = 0; 518 519 TRACE_ENTRY("%p %g %p", buf, len, msg); 520 521 CHECK_PARAMS( buf && len >= sizeof(*hdr) && msg ); 522 523 *msg = NULL; 524 525 /* Parse the RADIUS message */ 526 hdr = (struct radius_hdr *) buf; 489 527 msg_len = ntohs(hdr->length); 490 528 if (msg_len < sizeof(*hdr) || msg_len > len) { 491 printf("Invalid RADIUS message length\n");492 return NULL;529 TRACE_DEBUG(INFO, "Invalid RADIUS message length\n"); 530 return EINVAL; 493 531 } 494 532 495 533 if (msg_len < len) { 496 printf("Ignored %lu extra bytes after RADIUS message\n",534 TRACE_DEBUG(INFO, "Ignored %lu extra bytes after RADIUS message\n", 497 535 (unsigned long) len - msg_len); 498 536 } 499 537 500 msg = os_malloc(sizeof(*msg)); 501 if (msg == NULL) 502 return NULL; 503 504 if (radius_msg_initialize(msg, msg_len)) { 505 os_free(msg); 506 return NULL; 507 } 508 509 os_memcpy(msg->buf, data, msg_len); 510 msg->buf_size = msg->buf_used = msg_len; 511 538 CHECK_MALLOC( temp_msg = malloc(sizeof(struct rgw_radius_msg_meta)) ); 539 memset(temp_msg, 0, sizeof(struct rgw_radius_msg_meta)); 540 541 if (radius_msg_initialize(&temp_msg->radius, msg_len)) { 542 TRACE_DEBUG(INFO, "Error in radius_msg_initialize, returning ENOMEM."); 543 free(temp_msg); 544 return ENOMEM; 545 } 546 547 /* Store the received data in the alloc'd buffer */ 548 memcpy(temp_msg->radius.buf, buf, msg_len); 549 temp_msg->radius.buf_size = temp_msg->radius.buf_used = msg_len; 550 512 551 /* parse attributes */ 513 pos = (unsigned char *) (msg->hdr + 1); 514 end = msg->buf + msg->buf_used; 552 pos = (unsigned char *) (temp_msg->radius.hdr + 1); 553 end = temp_msg->radius.buf + temp_msg->radius.buf_used; 554 515 555 while (pos < end) { 516 if ((size_t) (end - pos) < sizeof(*attr)) 517 goto fail; 518 556 if ((size_t) (end - pos) < sizeof(*attr)) { 557 TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL."); 558 ret = EINVAL; 559 break; 560 } 561 519 562 attr = (struct radius_attr_hdr *) pos; 520 521 if (pos + attr->length > end || attr->length < sizeof(*attr)) 522 goto fail; 523 524 /* TODO: check that attr->length is suitable for attr->type */ 525 526 if (radius_msg_add_attr_to_array(msg, attr)) 527 goto fail; 563 564 if (pos + attr->length > end || attr->length < sizeof(*attr)) { 565 TRACE_DEBUG(INFO, "Trucated attribute found in RADIUS buffer, EINVAL."); 566 ret = EINVAL; 567 break; 568 } 569 570 if (radius_msg_add_attr_to_array(&temp_msg->radius, attr)) { 571 TRACE_DEBUG(INFO, "Error in radius_msg_add_attr_to_array, ENOMEM"); 572 ret = ENOMEM; 573 break; 574 } 575 576 if (attr->type == RADIUS_ATTR_PROXY_STATE) 577 temp_msg->ps_nb += 1; 528 578 529 579 pos += attr->length; 530 580 } 531 532 return msg; 533 534 fail: 535 radius_msg_free(msg); 536 os_free(msg); 537 return NULL; 538 } 581 582 if (ret != 0) { 583 radius_msg_free(&temp_msg->radius); 584 free(temp_msg); 585 return ret; 586 } 587 588 /* Now move all the proxy-state attributes at the end of the attr_pos array */ 589 if (temp_msg->ps_nb) { 590 size_t *temp_ps = NULL; 591 int n, new_n = 0, p = 0; 592 593 CHECK_MALLOC( temp_ps = calloc(temp_msg->ps_nb, sizeof(size_t *)) ); 594 595 /* Move all the Proxy-State attributes into the temp_ps array */ 596 for (n=0; n < temp_msg->radius.attr_used; n++) { 597 struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(temp_msg->radius.buf + temp_msg->radius.attr_pos[n]); 598 599 if (attr->type == RADIUS_ATTR_PROXY_STATE) { 600 temp_ps[p++] = temp_msg->radius.attr_pos[n]; 601 } else { 602 temp_msg->radius.attr_pos[new_n++] = temp_msg->radius.attr_pos[n]; 603 } 604 } 605 temp_msg->radius.attr_used = new_n; /* hide the proxy-state to other modules */ 606 temp_msg->ps_first = new_n; 607 608 /* And back into the array */ 609 memcpy(temp_msg->radius.attr_pos + new_n, temp_ps, p * sizeof(size_t *)); 610 free(temp_ps); 611 } 612 613 *msg = temp_msg; 614 return 0; 615 } 616 539 617 540 618
Note: See TracChangeset
for help on using the changeset viewer.