Navigation


Changeset 273:bce8e5b7bf78 in freeDiameter


Ignore:
Timestamp:
Apr 21, 2010, 2:23:04 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Children:
274:c8e57b3ca75f, 275:0941db40bcba
Phase:
public
Message:

Added code to send an STR after a STOP accounting record in RADIUS

Location:
extensions/app_radgw
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • extensions/app_radgw/rgw_common.h

    r271 r273  
    9393#define RGW_PLG_TYPE_AUTH       1
    9494#define RGW_PLG_TYPE_ACCT       2
     95
     96/* Class attribute prefix to store the Auth Application Id (required to send STR) */
     97#define CLASS_AAI_PREFIX        "fD/rgwx/aai:"
    9598
    9699/* Attributes missing from radius.h (not used in EAP) */
  • extensions/app_radgw/rgwx_acct.c

    r271 r273  
    8282                struct dict_object * CHAP_Response;             /* CHAP-Response */
    8383                struct dict_object * Connect_Info;              /* Connect-Info */
     84                struct dict_object * Destination_Host;          /* Destination-Host */
     85                struct dict_object * Destination_Realm;         /* Destination-Realm */
    8486                struct dict_object * EAP_Payload;               /* EAP-Payload */
    8587                struct dict_object * Error_Message;             /* Error-Message */
     
    130132                struct dict_object * Session_Timeout;           /* Session-Timeout */
    131133                struct dict_object * State;                     /* State */
     134                struct dict_object * Termination_Cause;         /* Termination-Cause */
    132135                struct dict_object * Tunneling;                 /* Tunneling */
    133136                struct dict_object * Tunnel_Type;               /* Tunnel-Type */
     
    141144                struct dict_object * Tunnel_Server_Auth_Id;     /* Tunnel-Server-Auth-Id */
    142145                struct dict_object * User_Name;                 /* User-Name */
     146               
     147                struct dict_object * Session_Termination_Request;/* STR */
    143148        } dict; /* cache of the dictionary objects we use */
    144149        struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */
     
    148153/* The state we store in the session */
    149154struct sess_state {
    150         uint8_t  req_auth[16];  /* The request authenticator */
    151         int      send_str;      /* If not 0, we must send a STR when the ACA is received. */
    152         uint32_t term_cause;    /* If not 0, the Termination-Cause to put in the STR. */
     155        uint8_t          req_auth[16];  /* The request authenticator */
     156        application_id_t auth_appl;     /* Auth-Application-Id used for this session, if available (stored in a Class attribute) */
     157        int              send_str;      /* If not 0, we must send a STR when the ACA is received. */
     158        uint32_t         term_cause;    /* If not 0, the Termination-Cause to put in the STR. */
    153159};
    154160
     
    193199        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Class", &new->dict.Class, ENOENT) );
    194200        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) );
     201        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &new->dict.Destination_Host, ENOENT) );
     202        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &new->dict.Destination_Realm, ENOENT) );
    195203        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) );
    196204        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) );
     
    241249        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Timeout", &new->dict.Session_Timeout, ENOENT) );
    242250        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "State", &new->dict.State, ENOENT) );
     251        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Termination-Cause", &new->dict.Termination_Cause, ENOENT) );
    243252        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunneling", &new->dict.Tunneling, ENOENT) );
    244253        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Assignment-Id", &new->dict.Tunnel_Assignment_Id, ENOENT) );
     
    253262        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) );
    254263       
     264        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &new->dict.Session_Termination_Request, ENOENT) );
     265       
    255266        /* This plugin provides the following Diameter authentication applications support: */
    256267        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &app, ENOENT) );
     
    276287        int send_str=0;
    277288        uint32_t str_cause=0;
     289        application_id_t auth_appl=0;
    278290        int got_id = 0;
    279291        uint32_t status_type;
     
    557569                        case RADIUS_ATTR_CLASS:
    558570                                CONV2DIAM_STR( Class );
     571                                /* In addition, save the data in the session if it is "our" CLASS_AAI_PREFIX Class attribute */
     572                                {
     573                                        char buf[32];
     574                                        char * attr_val, *auth_val;
     575                                        attr_val = (char *)(attr + 1);
     576                                        auth_val = attr_val + strlen(CLASS_AAI_PREFIX);
     577                                        if (    (attr->length > sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX)  )
     578                                                && (attr->length < sizeof(struct radius_attr_hdr) + strlen(CLASS_AAI_PREFIX) + sizeof(buf))
     579                                                && ! strncmp(attr_val, CLASS_AAI_PREFIX, strlen(CLASS_AAI_PREFIX))) {
     580                                       
     581                                                memset(buf, 0, sizeof(buf));
     582                                                memcpy(buf, auth_val, attr->length - sizeof(struct radius_attr_hdr) - strlen(CLASS_AAI_PREFIX));
     583                                                if (sscanf(buf, "%u", &auth_appl) == 1) {
     584                                                        TRACE_DEBUG(ANNOYING, "Found Class attribute with '%s' prefix (attr #%d), AAI:%u.", CLASS_AAI_PREFIX, idx, auth_appl);
     585                                                }
     586                                        }
     587                                }
    559588                                break;
    560589                       
     
    10431072                memset(st, 0, sizeof(struct sess_state));
    10441073                memcpy(&st->req_auth, &rad_req->hdr->authenticator[0], 16);
     1074                st->auth_appl = auth_appl;
    10451075                st->send_str = send_str;
    10461076                st->term_cause = str_cause;
     
    10491079       
    10501080        return 0;
     1081}
     1082
     1083/* Callback when an STA is received after having sent an STR. */
     1084static void handle_sta(void * data, struct msg ** answer)
     1085{
     1086        struct rgwp_config * cs = data;
     1087        struct avp *avp;
     1088        struct avp_hdr *ahdr;
     1089       
     1090        CHECK_PARAMS_DO( data && answer && *answer, goto out );
     1091       
     1092        /* Check the Diameter error code */
     1093        CHECK_FCT_DO( fd_msg_search_avp (*answer, cs->dict.Result_Code, &avp), goto out );
     1094        CHECK_PARAMS_DO( avp, goto out );
     1095        CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), goto out );
     1096        if (ahdr->avp_value->u32 != ER_DIAMETER_SUCCESS)
     1097                goto out;
     1098       
     1099        /* OK, discard the message without complaining */
     1100        fd_msg_free(*answer);
     1101        *answer = NULL;
     1102               
     1103out:
     1104        if (answer && *answer) {
     1105                TRACE_DEBUG(INFO, "Received the following problematic STA message, discarding...");
     1106                fd_msg_dump_walk( INFO, *answer );
     1107                fd_msg_free(*answer);
     1108                *answer = NULL;
     1109        }
     1110        return;
    10511111}
    10521112
     
    11181178        /* If it was a response to a STOP record, we must send an STR for this session */
    11191179        if (st->send_str) {
    1120                 TODO("Send STR, including sid, [Dest-Host=oh,] Dest-Realm=or, Term-Cause=st->term_cause... Register to receive the answer.");
     1180                struct msg * str = NULL;
     1181                char * fqdn;
     1182                char * realm;
     1183                union avp_value avp_val;
     1184               
     1185                /* Create a new STR message */
     1186                CHECK_FCT(  fd_msg_new ( cs->dict.Session_Termination_Request, MSGFL_ALLOC_ETEID, &str )  );
     1187               
     1188                /* Add the Session-Id AVP as first AVP */
     1189                CHECK_FCT( fd_msg_avp_new (  cs->dict.Session_Id, 0, &avp ) );
     1190                CHECK_FCT( fd_msg_avp_setvalue ( avp, sid->avp_value ) );
     1191                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_FIRST_CHILD, avp) );
     1192
     1193                /* Add the Destination-Realm as next AVP */
     1194                CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) );
     1195                CHECK_FCT( fd_msg_avp_setvalue ( avp, or->avp_value ) );
     1196                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1197
     1198                /* Add the Destination-Host as next AVP */
     1199                CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Host, 0, &avp ) );
     1200                CHECK_FCT( fd_msg_avp_setvalue ( avp, oh->avp_value ) );
     1201                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1202               
     1203                /* Get information on the NAS */
     1204                CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) );
     1205
     1206                /* Add the Origin-Host as next AVP */
     1207                CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Host, 0, &avp ) );
     1208                memset(&avp_val, 0, sizeof(avp_val));
     1209                avp_val.os.data = (unsigned char *)fqdn;
     1210                avp_val.os.len = strlen(fqdn);
     1211                CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
     1212                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1213
     1214                /* Add the Origin-Realm as next AVP */
     1215                CHECK_FCT( fd_msg_avp_new ( cs->dict.Origin_Realm, 0, &avp ) );
     1216                memset(&avp_val, 0, sizeof(avp_val));
     1217                avp_val.os.data = (unsigned char *)realm;
     1218                avp_val.os.len = strlen(realm);
     1219                CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
     1220                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1221               
     1222                /* Auth-Application-Id -- if we did not get it from our Class attribute, we just set "0" */
     1223                CHECK_FCT( fd_msg_avp_new ( cs->dict.Auth_Application_Id, 0, &avp ) );
     1224                avp_val.u32 = st->auth_appl;
     1225                CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
     1226                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1227               
     1228                /* Termination-Cause */
     1229                CHECK_FCT( fd_msg_avp_new ( cs->dict.Termination_Cause, 0, &avp ) );
     1230                avp_val.u32 = st->term_cause;
     1231                CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
     1232                CHECK_FCT( fd_msg_avp_add ( str, MSG_BRW_LAST_CHILD, avp) );
     1233               
     1234                /* Send this message */
     1235                CHECK_FCT( fd_msg_send ( &str, handle_sta, cs ) );
    11211236        }
    1122        
    11231237       
    11241238        /*
  • extensions/app_radgw/rgwx_auth.c

    r271 r273  
    915915static int auth_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli )
    916916{
     917        struct msg_hdr * hdr;
    917918        struct avp *avp, *next, *avp_x, *avp_y, *asid, *aoh;
    918919        struct avp_hdr *ahdr, *sid, *oh;
     
    10491050        /* The RFC text says that this should always be the case, but it seems odd... */
    10501051        if ((*rad_fw)->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
     1052                /* Add the Session-Id */
    10511053                if (sizeof(buf) < snprintf(buf, sizeof(buf), "Diameter/%.*s",
    10521054                                sid->avp_value->os.len, sid->avp_value->os.data)) {
     1055                        TRACE_DEBUG(INFO, "Data truncated in Class attribute: %s", buf);
     1056                }
     1057                CONV2RAD_STR(RADIUS_ATTR_CLASS, buf, strlen(buf), 0);
     1058               
     1059                /* Add the auth-application-id required for STR */
     1060                CHECK_FCT( fd_msg_hdr( *diam_ans, &hdr ) );
     1061                if (sizeof(buf) < snprintf(buf, sizeof(buf), CLASS_AAI_PREFIX "%u",
     1062                                hdr->msg_appl)) {
    10531063                        TRACE_DEBUG(INFO, "Data truncated in Class attribute: %s", buf);
    10541064                }
Note: See TracChangeset for help on using the changeset viewer.