Navigation


Changeset 550:4c935aecee6c in freeDiameter for extensions/app_radgw/radius.c


Ignore:
Timestamp:
Sep 15, 2010, 2:24:45 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Hide and automate the Proxy-State attributes management in RADIUS gateway

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
    236/* freeDiameter author note:
    3  *  The content from this file comes directly from the hostap project.
     37 *  The content from this file comes for the main part from the hostap project.
    438 * It is redistributed under the terms of the BSD license, as allowed
    539 * 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.
    841 */
    9 #include "rgw_common.h"
    10 
    11 /* Overwrite printf */
    12 #define printf(args...) fd_log_debug(args)
    13 
    14 /*********************************************************************************/
    15 
    1642
    1743/*
     
    2955 */
    3056
     57/*********************************************************************************/
     58#include "rgw.h"
     59
     60/* Overwrite printf */
     61#define printf(args...) fd_log_debug(args)
     62
     63
    3164static struct radius_attr_hdr *
    3265radius_get_attr_hdr(struct radius_msg *msg, int idx)
     
    104137}
    105138
    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 */
     140void 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
    122150
    123151
     
    219247
    220248
    221 void radius_msg_dump_attr_val(struct radius_attr_hdr *hdr)
     249static void radius_msg_dump_attr_val(struct radius_attr_hdr *hdr)
    222250{
    223251        struct radius_attr_type *attr;
     
    282310}
    283311
    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) */
     313void rgw_msg_dump(struct rgw_radius_msg_meta * msg)
     314{
     315        unsigned char *auth;
    299316        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");
    309342}
    310343
     
    407440
    408441
    409 static int radius_msg_add_attr_to_array(struct radius_msg *msg,
     442int radius_msg_add_attr_to_array(struct radius_msg *msg,
    410443                                        struct radius_attr_hdr *attr)
    411444{
     
    474507
    475508
    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 */
     510int 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;
    479513        struct radius_hdr *hdr;
    480514        struct radius_attr_hdr *attr;
    481515        size_t msg_len;
    482516        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;
    489527        msg_len = ntohs(hdr->length);
    490528        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;
    493531        }
    494532
    495533        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",
    497535                       (unsigned long) len - msg_len);
    498536        }
    499537
    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       
    512551        /* 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       
    515555        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                       
    519562                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;
    528578
    529579                pos += attr->length;
    530580        }
    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
    539617
    540618
Note: See TracChangeset for help on using the changeset viewer.