Changeset 271:411314907b43 in freeDiameter
- Timestamp:
- Apr 20, 2010, 7:34:59 PM (14 years ago)
- Branch:
- default
- Phase:
- public
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/app_radgw.conf.sample
r254 r271 40 40 # an error is logged if some RADIUS attributes of the message have not been handled. 41 41 42 RGWX = "extensions/echodrop.rgwx" : "echodrop.rgwx.conf"; # See echodrop.rgwx.conf.sample file 43 RGWX = "extensions/auth.rgwx" : auth; 44 RGWX = "extensions/acct.rgwx" : acct; 45 # RGWX = "extensions/debug.rgwx"; # Uncomment to see the result of the translation plugins. 42 46 43 47 ################## -
extensions/app_radgw/rgw.h
r258 r271 103 103 int rgw_clients_check_origin(struct rgw_radius_msg_meta *msg, struct rgw_client *cli); 104 104 int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm); 105 char * rgw_clients_id(struct rgw_client *cli); 105 106 int rgw_client_finish_send(struct radius_msg ** msg, struct rgw_radius_msg_meta * req, struct rgw_client * cli); 106 107 void rgw_clients_dispose(struct rgw_client ** ref); -
extensions/app_radgw/rgw_clients.c
r261 r271 444 444 } 445 445 446 char * rgw_clients_id(struct rgw_client *cli) 447 { 448 return cli->fqdn; 449 } 450 446 451 447 452 void rgw_clients_dispose(struct rgw_client ** ref) -
extensions/app_radgw/rgw_common.h
r258 r271 130 130 RADIUS_ATTR_PROMPT = 76, 131 131 RADIUS_ATTR_CONFIGURATION_TOKEN = 78, 132 RADIUS_ATTR_TUNNEL_ASSIGN EMENT_ID = 82,132 RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID = 82, 133 133 RADIUS_ATTR_TUNNEL_PREFERENCE = 83, 134 134 RADIUS_ATTR_ARAP_CHALLENGE_RESPONSE = 84, … … 149 149 enum { DIAM_ATTR_USER_NAME = 1, 150 150 DIAM_ATTR_USER_PASSWORD = 2, 151 DIAM_ATTR_NAS_IP_ADDRESS = 4, 152 DIAM_ATTR_NAS_PORT = 5, 151 153 DIAM_ATTR_SERVICE_TYPE = 6, 152 154 DIAM_ATTR_FRAMED_PROTOCOL = 7, … … 168 170 DIAM_ATTR_CLASS = 25, 169 171 DIAM_ATTR_IDLE_TIMEOUT = 28, 172 DIAM_ATTR_NAS_IDENTIFIER = 32, 170 173 DIAM_ATTR_LOGIN_LAT_SERVICE = 34, 171 174 DIAM_ATTR_LOGIN_LAT_NODE = 35, … … 174 177 DIAM_ATTR_FRAMED_APPLETALK_NETWORK = 38, 175 178 DIAM_ATTR_FRAMED_APPLETALK_ZONE = 39, 179 DIAM_ATTR_ACCT_SESSION_ID = 44, 180 DIAM_ATTR_ACCT_MULTI_SESSION_ID = 50, 181 DIAM_ATTR_EVENT_TIMESTAMP = 55, 182 DIAM_ATTR_NAS_PORT_TYPE = 61, 176 183 DIAM_ATTR_PORT_LIMIT = 62, 177 184 DIAM_ATTR_LOGIN_LAT_PORT = 63, … … 189 196 DIAM_ATTR_CONFIGURATION_TOKEN = 78, 190 197 DIAM_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81, 191 DIAM_ATTR_TUNNEL_ASSIGN EMENT_ID = 82,198 DIAM_ATTR_TUNNEL_ASSIGNMENT_ID = 82, 192 199 DIAM_ATTR_TUNNEL_PREFERENCE = 83, 193 200 DIAM_ATTR_ARAP_CHALLENGE_RESPONSE = 84, 194 201 DIAM_ATTR_ACCT_INTERIM_INTERVAL = 85, 202 DIAM_ATTR_NAS_PORT_ID = 87, 195 203 DIAM_ATTR_FRAMED_POOL = 88, 196 204 DIAM_ATTR_TUNNEL_CLIENT_AUTH_ID = 90, 197 205 DIAM_ATTR_TUNNEL_SERVER_AUTH_ID = 91, 206 DIAM_ATTR_NAS_IPV6_ADDRESS = 95, 198 207 DIAM_ATTR_FRAMED_INTERFACE_ID = 96, 199 208 DIAM_ATTR_FRAMED_IPV6_PREFIX = 97, … … 203 212 DIAM_ATTR_EAP_KEY_NAME = 102, 204 213 DIAM_ATTR_AUTH_APPLICATION_ID = 258, 214 DIAM_ATTR_ACCT_APPLICATION_ID = 259, 215 DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID = 260, 216 DIAM_ATTR_SESSION_ID = 263, 217 DIAM_ATTR_ORIGIN_HOST = 264, 205 218 DIAM_ATTR_MULTI_ROUND_TIMEOUT = 272, 206 219 DIAM_ATTR_AUTH_REQUEST_TYPE = 274, … … 212 225 DIAM_ATTR_ROUTE_RECORD = 282, 213 226 DIAM_ATTR_PROXY_INFO = 284, 227 DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID = 287, 214 228 DIAM_ATTR_ERROR_REPORTING_HOST = 294, 229 DIAM_ATTR_TERMINATION_CAUSE = 295, 230 DIAM_ATTR_ORIGIN_REALM = 296, 215 231 DIAM_ATTR_NAS_FILTER_RULE = 400, 216 232 DIAM_ATTR_TUNNELING = 401, … … 220 236 DIAM_ATTR_EAP_REISSUED_PAYLOAD = 463, 221 237 DIAM_ATTR_EAP_MASTER_SESSION_KEY = 464, 222 DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD = 465 238 DIAM_ATTR_ACCOUNTING_EAP_AUTH_METHOD = 465, 239 DIAM_ATTR_ACCOUNTING_RECORD_TYPE = 480, 240 DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED = 483, 241 DIAM_ATTR_ACCOUNTING_RECORD_NUMBER = 485 223 242 }; 224 243 -
extensions/app_radgw/rgw_plugins.c
r258 r271 381 381 if (ret > 0) { 382 382 /* Critical error, log and exit */ 383 fd_log_debug("An error occurred while handling a RADIUS message, turn on DEBUG for details: %s\n", strerror(ret));383 TRACE_DEBUG(NONE, "An error occurred while handling a RADIUS message from '%s': %s\n", rgw_clients_id(cli), strerror(ret)); 384 384 return ret; 385 385 } … … 438 438 439 439 /* We might define other return values with special meaning here (ret == -1, ...) for example create a new Diameter request */ 440 441 /* -1: just abord the translation with no more processing. */ 440 442 441 443 return 0; -
extensions/app_radgw/rgw_worker.c
r258 r271 248 248 /* Pass the Diameter answer to the same extensions as the request */ 249 249 CHECK_FCT_DO( rgw_plg_loop_ans(pa->rad, pa->sess, ans, &rad_ans, pa->cli), goto out ); 250 251 /* Now check what AVPs remain in the diameter answer. If AVPs with the 'M' flag are here, we have a problem... */ 252 CHECK_FCT_DO( fd_msg_browse(*ans, MSG_BRW_FIRST_CHILD, &avp, NULL), { avp = NULL; pb++; } ); 253 while (avp) { 254 CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), { pb++; continue; } ); 255 if (ahdr->avp_flags & AVP_FLAG_MANDATORY) { 256 if (ahdr->avp_flags & AVP_FLAG_VENDOR) { 257 TRACE_DEBUG(FULL, "Remaining Mandatory Vendor AVP, code %d", ahdr->avp_code); 258 pb++; 259 } else { 260 switch (ahdr->avp_code) { 261 /* A few AVPs can be safely ignored here: */ 262 case DIAM_ATTR_ROUTE_RECORD: 263 case DIAM_ATTR_PROXY_INFO: 264 265 266 /* just ignore */ 267 break; 268 269 default: 270 TRACE_DEBUG(FULL, "Remaining Mandatory AVP, code %d", ahdr->avp_code); 271 pb++; 250 251 if (*ans != NULL) { 252 253 /* Now check what AVPs remain in the diameter answer. If AVPs with the 'M' flag are here, we have a problem... */ 254 CHECK_FCT_DO( fd_msg_browse(*ans, MSG_BRW_FIRST_CHILD, &avp, NULL), { avp = NULL; pb++; } ); 255 while (avp) { 256 CHECK_FCT_DO( fd_msg_avp_hdr ( avp, &ahdr ), { pb++; continue; } ); 257 if (ahdr->avp_flags & AVP_FLAG_MANDATORY) { 258 if (ahdr->avp_flags & AVP_FLAG_VENDOR) { 259 TRACE_DEBUG(FULL, "Remaining Mandatory Vendor AVP, code %d", ahdr->avp_code); 260 pb++; 261 } else { 262 switch (ahdr->avp_code) { 263 /* A few AVPs can be safely ignored here: */ 264 case DIAM_ATTR_ROUTE_RECORD: 265 case DIAM_ATTR_PROXY_INFO: 266 267 268 /* just ignore */ 269 break; 270 271 default: 272 TRACE_DEBUG(FULL, "Remaining Mandatory AVP, code %d", ahdr->avp_code); 273 pb++; 274 } 272 275 } 273 276 } 274 }275 CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { pb++; break; } );276 } 277 278 if (pb) {279 TRACE_DEBUG(INFO, "[radgw] WARNING: %d mandatory AVP in the Diameter answer have not been translated to RADIUS!\n Please use plg_debug.rgwx for more information.", pb);277 CHECK_FCT_DO( fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL), { pb++; break; } ); 278 } 279 280 if (pb) { 281 TRACE_DEBUG(INFO, "[radgw] WARNING: %d mandatory AVP in the Diameter answer have not been translated to RADIUS!\n Please use plg_debug.rgwx for more information.", pb); 282 } 280 283 } 281 284 -
extensions/app_radgw/rgwx_acct.c
r268 r271 38 38 #include "rgw_common.h" 39 39 40 41 /* Other constants we use */ 42 #define AI_ACCT 3 /* Diameter Base Accounting application */ 43 #define CC_AC 271 /* ACR/ACA */ 44 #define ACV_ART_START_RECORD 2 /* START_RECORD */ 45 #define ACV_ART_INTERIM_RECORD 3 /* INTERIM_RECORD */ 46 #define ACV_ART_STOP_RECORD 4 /* STOP_RECORD */ 47 #define ACV_ART_AUTHORIZE_AUTHENTICATE 3 /* AUTHORIZE_AUTHENTICATE */ 48 #define ER_DIAMETER_LIMITED_SUCCESS 2002 49 50 40 51 /* The state we keep for this plugin */ 41 52 struct rgwp_config { 42 53 struct { 54 struct dict_object * Accounting_Record_Type; /* Accounting-Record-Type */ 55 struct dict_object * Acct_Application_Id; /* Acct-Application-Id */ 56 struct dict_object * Acct_Delay_Time; /* Acct-Delay-Time */ 57 struct dict_object * Accounting_Input_Octets; /* Accounting-Input-Octets */ 58 struct dict_object * Accounting_Output_Octets; /* Accounting-Output-Octets */ 59 struct dict_object * Accounting_Input_Packets; /* Accounting-Input-Packets */ 60 struct dict_object * Accounting_Output_Packets; /* Accounting-Output-Packets */ 61 struct dict_object * Acct_Link_Count; /* Acct-Link-Count */ 62 struct dict_object * Acct_Authentic; /* Acct-Authentic */ 63 struct dict_object * Acct_Multi_Session_Id; /* Acct-Multi-Session-Id */ 64 struct dict_object * Acct_Session_Id; /* Acct-Session-Id */ 65 struct dict_object * Acct_Session_Time; /* Acct-Session-Time */ 66 67 struct dict_object * ARAP_Password; /* ARAP-Password */ 68 struct dict_object * ARAP_Security; /* ARAP-Security */ 69 struct dict_object * ARAP_Security_Data; /* ARAP-Security-Data */ 70 struct dict_object * Auth_Application_Id; /* Auth-Application-Id */ 71 struct dict_object * Auth_Request_Type; /* Auth-Request-Type */ 72 struct dict_object * Authorization_Lifetime; /* Authorization-Lifetime */ 73 struct dict_object * Callback_Number; /* Callback-Number */ 74 struct dict_object * Callback_Id; /* Callback-Id */ 75 struct dict_object * Called_Station_Id; /* Called-Station-Id */ 76 struct dict_object * Calling_Station_Id; /* Calling-Station-Id */ 77 struct dict_object * Class; /* Class */ 78 struct dict_object * CHAP_Algorithm; /* CHAP-Algorithm */ 79 struct dict_object * CHAP_Auth; /* CHAP-Auth */ 80 struct dict_object * CHAP_Challenge; /* CHAP-Challenge */ 81 struct dict_object * CHAP_Ident; /* CHAP-Ident */ 82 struct dict_object * CHAP_Response; /* CHAP-Response */ 83 struct dict_object * Connect_Info; /* Connect-Info */ 84 struct dict_object * EAP_Payload; /* EAP-Payload */ 43 85 struct dict_object * Error_Message; /* Error-Message */ 44 86 struct dict_object * Error_Reporting_Host; /* Error-Reporting-Host */ 87 struct dict_object * Event_Timestamp; /* Event-Timestamp */ 45 88 struct dict_object * Failed_AVP; /* Failed-AVP */ 89 struct dict_object * Framed_AppleTalk_Link; /* Framed-AppleTalk-Link */ 90 struct dict_object * Framed_AppleTalk_Network; /* Framed-AppleTalk-Network */ 91 struct dict_object * Framed_AppleTalk_Zone; /* Framed-AppleTalk-Zone */ 92 struct dict_object * Framed_Compression; /* Framed-Compression */ 93 struct dict_object * Framed_IP_Address; /* Framed-IP-Address */ 94 struct dict_object * Framed_IP_Netmask; /* Framed-IP-Netmask */ 95 struct dict_object * Framed_Interface_Id; /* Framed-Interface-Id */ 96 struct dict_object * Framed_IPv6_Prefix; /* Framed-IPv6-Prefix */ 97 struct dict_object * Framed_IPX_Network; /* Framed-IPX-Network */ 98 struct dict_object * Framed_MTU; /* Framed-MTU */ 99 struct dict_object * Framed_Protocol; /* Framed-Protocol */ 100 struct dict_object * Framed_Pool; /* Framed-Pool */ 101 struct dict_object * Framed_IPv6_Route; /* Framed-IPv6-Route */ 102 struct dict_object * Framed_IPv6_Pool; /* Framed-IPv6-Pool */ 103 struct dict_object * Framed_Route; /* Framed-Route */ 104 struct dict_object * Framed_Routing; /* Framed-Routing */ 105 struct dict_object * Filter_Id; /* Filter-Id */ 106 struct dict_object * Idle_Timeout; /* Idle-Timeout */ 107 struct dict_object * Login_IP_Host; /* Login-IP-Host */ 108 struct dict_object * Login_IPv6_Host; /* Login-IPv6-Host */ 109 struct dict_object * Login_LAT_Group; /* Login-LAT-Group */ 110 struct dict_object * Login_LAT_Node; /* Login-LAT-Node */ 111 struct dict_object * Login_LAT_Port; /* Login-LAT-Port */ 112 struct dict_object * Login_LAT_Service; /* Login-LAT-Service */ 113 struct dict_object * Login_Service; /* Login-Service */ 114 struct dict_object * Login_TCP_Port; /* Login-TCP-Port */ 115 struct dict_object * NAS_Identifier; /* NAS-Identifier */ 116 struct dict_object * NAS_IP_Address; /* NAS-IP-Address */ 117 struct dict_object * NAS_IPv6_Address; /* NAS-IPv6-Address */ 118 struct dict_object * NAS_Port; /* NAS-Port */ 119 struct dict_object * NAS_Port_Id; /* NAS-Port-Id */ 120 struct dict_object * NAS_Port_Type; /* NAS-Port-Type */ 121 struct dict_object * Origin_AAA_Protocol; /* Origin-AAA-Protocol */ 46 122 struct dict_object * Origin_Host; /* Origin-Host */ 47 123 struct dict_object * Origin_Realm; /* Origin-Realm */ 124 struct dict_object * Originating_Line_Info; /* Originating-Line-Info */ 125 struct dict_object * Port_Limit; /* Port-Limit */ 126 struct dict_object * Re_Auth_Request_Type; /* Re-Auth-Request-Type */ 48 127 struct dict_object * Result_Code; /* Result-Code */ 128 struct dict_object * Service_Type; /* Service-Type */ 49 129 struct dict_object * Session_Id; /* Session-Id */ 130 struct dict_object * Session_Timeout; /* Session-Timeout */ 50 131 struct dict_object * State; /* State */ 132 struct dict_object * Tunneling; /* Tunneling */ 133 struct dict_object * Tunnel_Type; /* Tunnel-Type */ 134 struct dict_object * Tunnel_Assignment_Id; /* Tunnel-Assignment-Id */ 135 struct dict_object * Tunnel_Medium_Type; /* Tunnel-Medium-Type */ 136 struct dict_object * Tunnel_Client_Endpoint; /* Tunnel-Client-Endpoint */ 137 struct dict_object * Tunnel_Server_Endpoint; /* Tunnel-Server-Endpoint */ 138 struct dict_object * Tunnel_Private_Group_Id; /* Tunnel-Private-Group-Id */ 139 struct dict_object * Tunnel_Preference; /* Tunnel-Preference */ 140 struct dict_object * Tunnel_Client_Auth_Id; /* Tunnel-Client-Auth-Id */ 141 struct dict_object * Tunnel_Server_Auth_Id; /* Tunnel-Server-Auth-Id */ 51 142 struct dict_object * User_Name; /* User-Name */ 52 143 } dict; /* cache of the dictionary objects we use */ 144 struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */ 53 145 char * confstr; 146 }; 147 148 /* The state we store in the session */ 149 struct 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. */ 54 153 }; 55 154 … … 58 157 { 59 158 struct rgwp_config * new; 159 struct dict_object * app; 60 160 61 161 TRACE_ENTRY("%p %p", conffile, state); … … 68 168 69 169 /* Resolve all dictionary objects we use */ 170 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Record-Type", &new->dict.Accounting_Record_Type, ENOENT) ); 171 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Application-Id", &new->dict.Acct_Application_Id, ENOENT) ); 172 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Delay-Time", &new->dict.Acct_Delay_Time, ENOENT) ); 173 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Octets", &new->dict.Accounting_Input_Octets, ENOENT) ); 174 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Octets", &new->dict.Accounting_Output_Octets, ENOENT) ); 175 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Input-Packets", &new->dict.Accounting_Input_Packets, ENOENT) ); 176 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Accounting-Output-Packets", &new->dict.Accounting_Output_Packets, ENOENT) ); 177 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Authentic", &new->dict.Acct_Authentic, ENOENT) ); 178 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Link-Count", &new->dict.Acct_Link_Count, ENOENT) ); 179 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Multi-Session-Id", &new->dict.Acct_Multi_Session_Id, ENOENT) ); 180 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Id", &new->dict.Acct_Session_Id, ENOENT) ); 181 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Acct-Session-Time", &new->dict.Acct_Session_Time, ENOENT) ); 182 183 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Password", &new->dict.ARAP_Password, ENOENT) ); 184 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security", &new->dict.ARAP_Security, ENOENT) ); 185 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "ARAP-Security-Data", &new->dict.ARAP_Security_Data, ENOENT) ); 186 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &new->dict.Auth_Application_Id, ENOENT) ); 187 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Request-Type", &new->dict.Auth_Request_Type, ENOENT) ); 188 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Authorization-Lifetime", &new->dict.Authorization_Lifetime, ENOENT) ); 189 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Number", &new->dict.Callback_Number, ENOENT) ); 190 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Callback-Id", &new->dict.Callback_Id, ENOENT) ); 191 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Called-Station-Id", &new->dict.Called_Station_Id, ENOENT) ); 192 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Calling-Station-Id", &new->dict.Calling_Station_Id, ENOENT) ); 193 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Class", &new->dict.Class, ENOENT) ); 194 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) ); 195 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) ); 70 196 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) ); 71 197 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &new->dict.Error_Reporting_Host, ENOENT) ); 198 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Event-Timestamp", &new->dict.Event_Timestamp, ENOENT) ); 72 199 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP", &new->dict.Failed_AVP, ENOENT) ); 200 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Link", &new->dict.Framed_AppleTalk_Link, ENOENT) ); 201 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Network", &new->dict.Framed_AppleTalk_Network, ENOENT) ); 202 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-AppleTalk-Zone", &new->dict.Framed_AppleTalk_Zone, ENOENT) ); 203 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Compression", &new->dict.Framed_Compression, ENOENT) ); 204 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Address", &new->dict.Framed_IP_Address, ENOENT) ); 205 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IP-Netmask", &new->dict.Framed_IP_Netmask, ENOENT) ); 206 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Interface-Id", &new->dict.Framed_Interface_Id, ENOENT) ); 207 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Prefix", &new->dict.Framed_IPv6_Prefix, ENOENT) ); 208 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPX-Network", &new->dict.Framed_IPX_Network, ENOENT) ); 209 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-MTU", &new->dict.Framed_MTU, ENOENT) ); 210 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Protocol", &new->dict.Framed_Protocol, ENOENT) ); 211 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Pool", &new->dict.Framed_Pool, ENOENT) ); 212 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Route", &new->dict.Framed_Route, ENOENT) ); 213 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Route", &new->dict.Framed_IPv6_Route, ENOENT) ); 214 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-IPv6-Pool", &new->dict.Framed_IPv6_Pool, ENOENT) ); 215 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Framed-Routing", &new->dict.Framed_Routing, ENOENT) ); 216 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Filter-Id", &new->dict.Filter_Id, ENOENT) ); 217 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Idle-Timeout", &new->dict.Idle_Timeout, ENOENT) ); 218 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IP-Host", &new->dict.Login_IP_Host, ENOENT) ); 219 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-IPv6-Host", &new->dict.Login_IPv6_Host, ENOENT) ); 220 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Group", &new->dict.Login_LAT_Group, ENOENT) ); 221 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Node", &new->dict.Login_LAT_Node, ENOENT) ); 222 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Port", &new->dict.Login_LAT_Port, ENOENT) ); 223 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-LAT-Service", &new->dict.Login_LAT_Service, ENOENT) ); 224 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-Service", &new->dict.Login_Service, ENOENT) ); 225 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Login-TCP-Port", &new->dict.Login_TCP_Port, ENOENT) ); 226 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Identifier", &new->dict.NAS_Identifier, ENOENT) ); 227 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IP-Address", &new->dict.NAS_IP_Address, ENOENT) ); 228 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-IPv6-Address", &new->dict.NAS_IPv6_Address, ENOENT) ); 229 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port", &new->dict.NAS_Port, ENOENT) ); 230 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Id", &new->dict.NAS_Port_Id, ENOENT) ); 231 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "NAS-Port-Type", &new->dict.NAS_Port_Type, ENOENT) ); 232 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-AAA-Protocol", &new->dict.Origin_AAA_Protocol, ENOENT) ); 73 233 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &new->dict.Origin_Host, ENOENT) ); 74 234 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Origin-Realm", &new->dict.Origin_Realm, ENOENT) ); 235 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Originating-Line-Info", &new->dict.Originating_Line_Info, ENOENT) ); 236 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Port-Limit", &new->dict.Port_Limit, ENOENT) ); 237 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Re-Auth-Request-Type", &new->dict.Re_Auth_Request_Type, ENOENT) ); 75 238 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Result-Code", &new->dict.Result_Code, ENOENT) ); 239 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Service-Type", &new->dict.Service_Type, ENOENT) ); 76 240 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &new->dict.Session_Id, ENOENT) ); 241 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Timeout", &new->dict.Session_Timeout, ENOENT) ); 77 242 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "State", &new->dict.State, ENOENT) ); 243 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunneling", &new->dict.Tunneling, ENOENT) ); 244 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Assignment-Id", &new->dict.Tunnel_Assignment_Id, ENOENT) ); 245 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Type", &new->dict.Tunnel_Type, ENOENT) ); 246 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Medium-Type", &new->dict.Tunnel_Medium_Type, ENOENT) ); 247 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Endpoint", &new->dict.Tunnel_Client_Endpoint, ENOENT) ); 248 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Endpoint", &new->dict.Tunnel_Server_Endpoint, ENOENT) ); 249 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Private-Group-Id", &new->dict.Tunnel_Private_Group_Id, ENOENT) ); 250 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Preference", &new->dict.Tunnel_Preference, ENOENT) ); 251 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Client-Auth-Id", &new->dict.Tunnel_Client_Auth_Id, ENOENT) ); 252 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Tunnel-Server-Auth-Id", &new->dict.Tunnel_Server_Auth_Id, ENOENT) ); 78 253 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "User-Name", &new->dict.User_Name, ENOENT) ); 79 254 80 TODO("Advertize application support..."); 255 /* This plugin provides the following Diameter authentication applications support: */ 256 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &app, ENOENT) ); 257 CHECK_FCT( fd_disp_app_support ( app, NULL, 0, 1 ) ); 81 258 82 259 *state = new; … … 97 274 { 98 275 int idx; 276 int send_str=0; 277 uint32_t str_cause=0; 99 278 int got_id = 0; 100 279 uint32_t status_type; 280 uint32_t termination_action = 0; 281 uint32_t gigawords_in=0, gigawords_out=0; 282 size_t nattr_used = 0; 283 union avp_value value; 284 struct avp ** avp_tun = NULL, *avp = NULL; 101 285 102 286 TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli); 103 287 CHECK_PARAMS(rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCOUNTING_REQUEST) && rad_ans && diam_fw && *diam_fw); 104 288 105 /* Check the message contains the NAS identification */ 289 /* 290 Either NAS-IP-Address or NAS-Identifier MUST be present in a 291 RADIUS Accounting-Request. It SHOULD contain a NAS-Port or NAS- 292 Port-Type attribute or both unless the service does not involve a 293 port or the NAS does not distinguish among its ports. 294 */ 106 295 for (idx = 0; idx < rad_req->attr_used; idx++) { 107 296 struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]); 297 uint8_t * v = (uint8_t *)(attr + 1); 108 298 switch (attr->type) { 109 299 case RADIUS_ATTR_NAS_IP_ADDRESS: … … 112 302 got_id = 1; 113 303 break; 304 305 case RADIUS_ATTR_TERMINATION_ACTION: 306 CHECK_PARAMS( attr->length == 6 ); 307 termination_action = (v[0] << 24) 308 | (v[1] << 16) 309 | (v[2] << 8) 310 | v[3] ; 311 break; 312 313 case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS: 314 CHECK_PARAMS( attr->length == 6 ); 315 gigawords_in = (v[0] << 24) 316 | (v[1] << 16) 317 | (v[2] << 8) 318 | v[3] ; 319 break; 320 321 case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS: 322 CHECK_PARAMS( attr->length == 6 ); 323 gigawords_out = (v[0] << 24) 324 | (v[1] << 16) 325 | (v[2] << 8) 326 | v[3] ; 327 break; 114 328 } 115 329 } … … 117 331 /* Check basic information is there */ 118 332 if (!got_id || radius_msg_get_attr_int32(rad_req, RADIUS_ATTR_ACCT_STATUS_TYPE, &status_type)) { 119 TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request did not contain a NAS ip/identifier or Acct-Status-Type attribute, reject.");333 TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request from %s did not contain a NAS ip/identifier or Acct-Status-Type attribute, reject.", rgw_clients_id(cli)); 120 334 return EINVAL; 121 335 } 122 336 123 /* Handle the Accounting-On/Off case: nothing to do, just reply OK, since Diameter does not support this */ 124 if ((status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) || (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF)) { 337 /* 338 -- RFC2866: 339 In Accounting-Request Packets, the Authenticator value is a 16 340 octet MD5 [5] checksum, called the Request Authenticator. 341 342 The NAS and RADIUS accounting server share a secret. The Request 343 Authenticator field in Accounting-Request packets contains a one- 344 way MD5 hash calculated over a stream of octets consisting of the 345 Code + Identifier + Length + 16 zero octets + request attributes + 346 shared secret (where + indicates concatenation). The 16 octet MD5 347 hash value is stored in the Authenticator field of the 348 Accounting-Request packet. 349 350 Note that the Request Authenticator of an Accounting-Request can 351 not be done the same way as the Request Authenticator of a RADIUS 352 Access-Request, because there is no User-Password attribute in an 353 Accounting-Request. 354 355 356 -- RFC5080: 357 The Request Authenticator field MUST contain the correct data, as 358 given by the above calculation. Invalid packets are silently 359 discarded. Note that some early implementations always set the 360 Request Authenticator to all zeros. New implementations of RADIUS 361 clients MUST use the above algorithm to calculate the Request 362 Authenticator field. New RADIUS server implementations MUST 363 silently discard invalid packets. 364 365 */ 366 { 367 uint8_t save[MD5_MAC_LEN]; 368 uint8_t * secret; 369 size_t secret_len; 370 371 /* Get the shared secret */ 372 CHECK_FCT(rgw_clients_getkey(cli, &secret, &secret_len)); 373 374 /* Copy the received Request Authenticator */ 375 memcpy(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN); 376 377 /* Compute the same authenticator */ 378 radius_msg_finish_acct(rad_req, secret, secret_len); 379 380 /* And now compare with the received value */ 381 if (memcmp(&save[0], &rad_req->hdr->authenticator[0], MD5_MAC_LEN)) { 382 /* Invalid authenticator */ 383 TRACE_DEBUG_BUFFER(FULL+1, "Received ReqAuth: ", &save[0], MD5_MAC_LEN, "" ); 384 TRACE_DEBUG_BUFFER(FULL+1, "Expected ReqAuth: ", &rad_req->hdr->authenticator[0], MD5_MAC_LEN, "" ); 385 TRACE_DEBUG(INFO, "[acct.rgwx] Invalid Request Authenticator in Account-Request from %s, discarding the message.", rgw_clients_id(cli)); 386 return EINVAL; 387 } 388 } 389 390 391 /* Handle the Accounting-On case: nothing to do, just reply OK */ 392 if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON) { 125 393 TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-On Acct-Status-Type attribute, replying without translation to Diameter."); 126 394 CHECK_MALLOC( *rad_ans = radius_msg_new(RADIUS_CODE_ACCOUNTING_RESPONSE, rad_req->hdr->identifier) ); … … 128 396 } 129 397 130 /* Other cases */ 131 return ENOTSUP; 132 /* 133 - If the RADIUS message received is an Accounting-Request, the 134 Acct-Status-Type attribute value must be converted to a 135 Accounting-Record-Type AVP value. If the Acct-Status-Type 136 attribute value is STOP, the local server MUST issue a 137 Session-Termination-Request message once the Diameter 138 Accounting-Answer message has been received. 398 if (status_type == RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF) { 399 TRACE_DEBUG(FULL, "[acct.rgwx] Received Accounting-Off Acct-Status-Type attribute, we must terminate all active sessions."); 400 TODO("RADIUS side is rebooting, send STR on all sessions?"); 401 return ENOTSUP; 402 } 403 404 /* Add the command code */ 405 { 406 struct msg_hdr * header = NULL; 407 CHECK_FCT( fd_msg_hdr ( *diam_fw, &header ) ); 408 header->msg_flags = CMD_FLAG_REQUEST | CMD_FLAG_PROXIABLE; 409 header->msg_code = CC_AC; 410 header->msg_appl = AI_ACCT; 411 412 /* Add the Acct-Application-Id */ 413 CHECK_FCT( fd_msg_avp_new ( cs->dict.Acct_Application_Id, 0, &avp ) ); 414 value.i32 = header->msg_appl; 415 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 416 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 417 } 418 419 /* Convert the RADIUS attributes, as they appear in the message */ 420 for (idx = 0; idx < rad_req->attr_used; idx++) { 421 struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]); 422 423 switch (attr->type) { 424 /* 425 Any attribute valid in a RADIUS Access-Request or Access-Accept 426 packet is valid in a RADIUS Accounting-Request packet, except that 427 the following attributes MUST NOT be present in an Accounting- 428 Request: User-Password, CHAP-Password, Reply-Message, State. 139 429 */ 140 141 /* 142 - If the Accounting message contains an Acct-Termination-Cause 143 attribute, it should be translated to the equivalent 144 Termination-Cause AVP value. (see below) 145 */ 146 430 case RADIUS_ATTR_USER_PASSWORD: 431 case RADIUS_ATTR_CHAP_PASSWORD: 432 case RADIUS_ATTR_REPLY_MESSAGE: 433 case RADIUS_ATTR_STATE: 434 case RADIUS_ATTR_MESSAGE_AUTHENTICATOR: 435 case RADIUS_ATTR_EAP_MESSAGE: 436 TRACE_DEBUG(INFO, "[acct.rgwx] RADIUS Account-Request contains a forbidden attribute (%hhd), reject.", attr->type); 437 return EINVAL; 438 439 440 /* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */ 441 #define CONV2DIAM_STR( _dictobj_ ) \ 442 CHECK_PARAMS( attr->length >= 2 ); \ 443 /* Create the AVP with the specified dictionary model */ \ 444 CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \ 445 value.os.len = attr->length - 2; \ 446 value.os.data = (unsigned char *)(attr + 1); \ 447 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \ 448 /* Add the AVP in the Diameter message. */ \ 449 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); \ 450 451 /* Same thing, for scalar AVPs of 32 bits */ 452 #define CONV2DIAM_32B( _dictobj_ ) \ 453 CHECK_PARAMS( attr->length == 6 ); \ 454 CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \ 455 { \ 456 uint8_t * v = (uint8_t *)(attr + 1); \ 457 value.u32 = (v[0] << 24) \ 458 | (v[1] << 16) \ 459 | (v[2] << 8) \ 460 | v[3] ; \ 461 } \ 462 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \ 463 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); \ 464 465 /* And the 64b version */ 466 #define CONV2DIAM_64B( _dictobj_ ) \ 467 CHECK_PARAMS( attr->length == 10); \ 468 CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \ 469 { \ 470 uint8_t * v = (uint8_t *)(attr + 1); \ 471 value.u64 = ((uint64_t)(v[0]) << 56) \ 472 | ((uint64_t)(v[1]) << 48) \ 473 | ((uint64_t)(v[2]) << 40) \ 474 | ((uint64_t)(v[3]) << 32) \ 475 | ((uint64_t)(v[4]) << 24) \ 476 | ((uint64_t)(v[5]) << 16) \ 477 | ((uint64_t)(v[6]) << 8) \ 478 | (uint64_t)(v[7]) ; \ 479 } \ 480 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \ 481 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); \ 482 483 484 /* Attributes as listed in RFC2866, section 5.13 and RFC4005, section 10.2.1 */ 485 case RADIUS_ATTR_USER_NAME: 486 CONV2DIAM_STR( User_Name ); 487 break; 488 489 case RADIUS_ATTR_NAS_IP_ADDRESS: 490 CONV2DIAM_STR( NAS_IP_Address ); 491 break; 492 493 case RADIUS_ATTR_NAS_PORT: 494 CONV2DIAM_32B( NAS_Port ); 495 break; 496 497 case RADIUS_ATTR_SERVICE_TYPE: 498 CONV2DIAM_32B( Service_Type ); 499 break; 500 501 case RADIUS_ATTR_FRAMED_PROTOCOL: 502 CONV2DIAM_32B( Framed_Protocol ); 503 break; 504 505 case RADIUS_ATTR_FRAMED_IP_ADDRESS: 506 CONV2DIAM_STR( Framed_IP_Address ); 507 break; 508 509 case RADIUS_ATTR_FRAMED_IP_NETMASK: 510 CONV2DIAM_STR( Framed_IP_Netmask ); 511 break; 512 513 case RADIUS_ATTR_FRAMED_ROUTING: 514 CONV2DIAM_32B( Framed_Routing ); 515 break; 516 517 case RADIUS_ATTR_FILTER_ID: 518 CONV2DIAM_STR( Filter_Id ); 519 break; 520 521 case RADIUS_ATTR_FRAMED_MTU: 522 CONV2DIAM_32B( Framed_MTU ); 523 break; 524 525 case RADIUS_ATTR_FRAMED_COMPRESSION: 526 CONV2DIAM_32B( Framed_Compression ); 527 break; 528 529 case RADIUS_ATTR_LOGIN_IP_HOST: 530 CONV2DIAM_STR( Login_IP_Host ); 531 break; 532 533 case RADIUS_ATTR_LOGIN_SERVICE: 534 CONV2DIAM_32B( Login_Service ); 535 break; 536 537 case RADIUS_ATTR_LOGIN_TCP_PORT: 538 CONV2DIAM_32B( Login_TCP_Port ); 539 break; 540 541 case RADIUS_ATTR_CALLBACK_NUMBER: 542 CONV2DIAM_STR( Callback_Number ); 543 break; 544 545 case RADIUS_ATTR_CALLBACK_ID: 546 CONV2DIAM_STR( Callback_Id ); 547 break; 548 549 case RADIUS_ATTR_FRAMED_ROUTE: 550 CONV2DIAM_STR( Framed_Route ); 551 break; 552 553 case RADIUS_ATTR_FRAMED_IPX_NETWORK: 554 CONV2DIAM_32B( Framed_IPX_Network ); 555 break; 556 557 case RADIUS_ATTR_CLASS: 558 CONV2DIAM_STR( Class ); 559 break; 560 561 case RADIUS_ATTR_VENDOR_SPECIFIC: 562 if (attr->length >= 6) { 563 uint32_t vendor_id; 564 uint8_t * c = (uint8_t *)(attr + 1); 565 566 vendor_id = c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3]; 567 c += 4; 568 569 switch (vendor_id) { 570 571 /* For the vendors we KNOW they follow the VSA recommended format, we convert following the rules of RFC4005 (9.6.2) */ 572 case RADIUS_VENDOR_ID_MICROSOFT : /* RFC 2548 */ 573 /* other vendors ? */ 574 { 575 size_t left; 576 struct radius_attr_vendor *vtlv; 577 578 left = attr->length - 6; 579 vtlv = (struct radius_attr_vendor *)c; 580 581 while ((left >= 2) && (vtlv->vendor_length <= left)) { 582 /* Search our dictionary for corresponding Vendor's AVP */ 583 struct dict_avp_request req; 584 struct dict_object * avp_model = NULL; 585 memset(&req, 0, sizeof(struct dict_avp_request)); 586 req.avp_vendor = vendor_id; 587 req.avp_code = vtlv->vendor_type; 588 589 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE_AND_VENDOR, &req, &avp_model, 0) ); 590 if (!avp_model) { 591 TRACE_DEBUG(FULL, "Unknown attribute (vendor 0x%x, code 0x%x) ignored.", req.avp_vendor, req.avp_code); 592 } else { 593 CHECK_FCT( fd_msg_avp_new ( avp_model, 0, &avp ) ); 594 value.os.len = vtlv->vendor_length - 2; 595 value.os.data = (unsigned char *)(vtlv + 1); 596 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 597 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 598 } 599 c += vtlv->vendor_length; 600 left -= vtlv->vendor_length; 601 vtlv = (struct radius_attr_vendor *)c; 602 } 603 } 604 break; 605 606 /* Other vendors we KNOw how to convert the attributes would be added here... */ 607 /* case RADIUS_VENDOR_ID_CISCO : 608 break; */ 609 /* case RADIUS_VENDOR_ID_IETF : (extended RADIUS attributes) 610 break; */ 611 612 /* When we don't know, just discard the attribute... VSA are optional with regards to RADIUS anyway */ 613 default: 614 /* do nothing */ 615 TRACE_DEBUG(FULL, "VSA attribute from vendor %d discarded", vendor_id); 616 617 } 618 } 619 break; 620 621 case RADIUS_ATTR_SESSION_TIMEOUT: 622 /* Translation depends on Termination-Action : rfc4005#section-9.2.1 */ 623 if (termination_action != RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { 624 CONV2DIAM_32B( Session_Timeout ); 625 } else { 626 CONV2DIAM_32B( Authorization_Lifetime ); 627 /* And add this additional AVP */ 628 CHECK_FCT( fd_msg_avp_new ( cs->dict.Re_Auth_Request_Type, 0, &avp ) ); 629 value.u32 = ACV_ART_AUTHORIZE_AUTHENTICATE; 630 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 631 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 632 } 633 break; 634 635 case RADIUS_ATTR_IDLE_TIMEOUT: 636 CONV2DIAM_32B( Idle_Timeout ); 637 break; 638 639 case RADIUS_ATTR_TERMINATION_ACTION: 640 /* Just remove */ 641 break; 642 643 case RADIUS_ATTR_CALLED_STATION_ID: 644 CONV2DIAM_STR( Called_Station_Id ); 645 break; 646 647 case RADIUS_ATTR_CALLING_STATION_ID: 648 CONV2DIAM_STR( Calling_Station_Id ); 649 break; 650 651 case RADIUS_ATTR_NAS_IDENTIFIER: 652 CONV2DIAM_STR( NAS_Identifier ); 653 break; 654 655 /* Proxy-State is handled by echo_drop.rgwx plugin, we ignore it here */ 656 657 case RADIUS_ATTR_LOGIN_LAT_SERVICE: 658 CONV2DIAM_STR( Login_LAT_Service ); 659 break; 660 661 case RADIUS_ATTR_LOGIN_LAT_NODE: 662 CONV2DIAM_STR( Login_LAT_Node ); 663 break; 664 665 case RADIUS_ATTR_LOGIN_LAT_GROUP: 666 CONV2DIAM_STR( Login_LAT_Group ); 667 break; 668 669 case RADIUS_ATTR_FRAMED_APPLETALK_LINK: 670 CONV2DIAM_32B( Framed_AppleTalk_Link ); 671 break; 672 673 case RADIUS_ATTR_FRAMED_APPLETALK_NETWORK: 674 CONV2DIAM_32B( Framed_AppleTalk_Network ); 675 break; 676 677 case RADIUS_ATTR_FRAMED_APPLETALK_ZONE: 678 CONV2DIAM_STR( Framed_AppleTalk_Zone ); 679 break; 680 681 case RADIUS_ATTR_ACCT_STATUS_TYPE: 682 /* 683 - If the RADIUS message received is an Accounting-Request, the 684 Acct-Status-Type attribute value must be converted to a 685 Accounting-Record-Type AVP value. If the Acct-Status-Type 686 attribute value is STOP, the local server MUST issue a 687 Session-Termination-Request message once the Diameter 688 Accounting-Answer message has been received. 689 */ 690 switch (status_type) { 691 case RADIUS_ACCT_STATUS_TYPE_START: 692 value.u32 = ACV_ART_START_RECORD; 693 break; 694 case RADIUS_ACCT_STATUS_TYPE_STOP: 695 value.u32 = ACV_ART_STOP_RECORD; 696 send_str = 1; /* Register this info in the session */ 697 break; 698 case RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE: 699 value.u32 = ACV_ART_INTERIM_RECORD; 700 break; 701 default: 702 TRACE_DEBUG(INFO, "Unknown RADIUS_ATTR_ACCT_STATUS_TYPE value %d, abording...", status_type); 703 return ENOTSUP; 704 } 705 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Record_Type, 0, &avp ) ); 706 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 707 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 708 break; 709 710 case RADIUS_ATTR_ACCT_DELAY_TIME: 711 CONV2DIAM_32B( Acct_Delay_Time ); 712 break; 713 147 714 /* 148 715 - If the RADIUS message contains the Accounting-Input-Octets, … … 154 721 AVPs. 155 722 */ 723 case RADIUS_ATTR_ACCT_INPUT_OCTETS: 724 memset(&value, 0, sizeof(value)); 725 { 726 uint8_t * v = (uint8_t *)(attr + 1); 727 value.u64 = (v[0] << 24) 728 | (v[1] << 16) 729 | (v[2] << 8) 730 | v[3] ; 731 } 732 value.u64 += ((uint64_t)gigawords_in << 32); 733 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Octets, 0, &avp ) ); 734 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 735 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 736 break; 737 738 case RADIUS_ATTR_ACCT_OUTPUT_OCTETS: 739 memset(&value, 0, sizeof(value)); 740 { 741 uint8_t * v = (uint8_t *)(attr + 1); 742 value.u64 = (v[0] << 24) 743 | (v[1] << 16) 744 | (v[2] << 8) 745 | v[3] ; 746 } 747 value.u64 += ((uint64_t)gigawords_out << 32); 748 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Octets, 0, &avp ) ); 749 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 750 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 751 break; 752 753 case RADIUS_ATTR_ACCT_SESSION_ID: 754 CONV2DIAM_STR( Acct_Session_Id ); 755 break; 756 757 case RADIUS_ATTR_ACCT_AUTHENTIC: 758 CONV2DIAM_32B( Acct_Authentic ); 759 break; 760 761 case RADIUS_ATTR_ACCT_SESSION_TIME: 762 CONV2DIAM_32B( Acct_Session_Time ); 763 break; 764 765 case RADIUS_ATTR_ACCT_INPUT_PACKETS: 766 memset(&value, 0, sizeof(value)); 767 { 768 uint8_t * v = (uint8_t *)(attr + 1); 769 value.u64 = (v[0] << 24) 770 | (v[1] << 16) 771 | (v[2] << 8) 772 | v[3] ; 773 } 774 /* value.u64 += (gigawords_in << 32); */ 775 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Input_Packets, 0, &avp ) ); 776 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 777 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 778 break; 779 780 case RADIUS_ATTR_ACCT_OUTPUT_PACKETS: 781 memset(&value, 0, sizeof(value)); 782 { 783 uint8_t * v = (uint8_t *)(attr + 1); 784 value.u64 = (v[0] << 24) 785 | (v[1] << 16) 786 | (v[2] << 8) 787 | v[3] ; 788 } 789 /* value.u64 += (gigawords_out << 32); */ 790 CHECK_FCT( fd_msg_avp_new ( cs->dict.Accounting_Output_Packets, 0, &avp ) ); 791 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 792 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 793 break; 794 795 /* 796 - If the Accounting message contains an Acct-Termination-Cause 797 attribute, it should be translated to the equivalent 798 Termination-Cause AVP value. 799 */ 800 case RADIUS_ATTR_ACCT_TERMINATE_CAUSE: 801 /* rfc4005#section-9.3.5 */ 802 { 803 uint8_t * v = (uint8_t *)(attr + 1); 804 str_cause = (v[0] << 24) 805 | (v[1] << 16) 806 | (v[2] << 8) 807 | v[3] ; 808 } 809 str_cause += 10; /* This seems to be the rule, we can modify later if needed */ 810 break; 811 812 case RADIUS_ATTR_ACCT_MULTI_SESSION_ID: 813 CONV2DIAM_STR( Acct_Multi_Session_Id ); 814 break; 815 816 case RADIUS_ATTR_ACCT_LINK_COUNT: 817 CONV2DIAM_32B( Acct_Link_Count ); 818 break; 819 820 /* CHAP-Challenge is not present in Accounting-Request */ 821 822 case RADIUS_ATTR_NAS_PORT_TYPE: 823 CONV2DIAM_32B( NAS_Port_Type ); 824 break; 825 826 case RADIUS_ATTR_PORT_LIMIT: 827 CONV2DIAM_32B( Port_Limit ); 828 break; 829 830 case RADIUS_ATTR_LOGIN_LAT_PORT: 831 CONV2DIAM_STR( Login_LAT_Port ); 832 break; 833 834 /* RFC 3162 */ 835 case RADIUS_ATTR_NAS_IPV6_ADDRESS: 836 CONV2DIAM_STR( NAS_IPv6_Address ); 837 break; 838 839 case RADIUS_ATTR_FRAMED_INTERFACE_ID: 840 CONV2DIAM_64B( Framed_Interface_Id ); 841 break; 842 843 case RADIUS_ATTR_FRAMED_IPV6_PREFIX: 844 CONV2DIAM_STR( Framed_IPv6_Prefix ); 845 break; 846 847 case RADIUS_ATTR_LOGIN_IPV6_HOST: 848 CONV2DIAM_STR( Login_IPv6_Host ); 849 break; 850 851 case RADIUS_ATTR_FRAMED_IPV6_ROUTE: 852 CONV2DIAM_STR( Framed_IPv6_Route ); 853 break; 854 855 case RADIUS_ATTR_FRAMED_IPV6_POOL: 856 CONV2DIAM_STR( Framed_IPv6_Pool ); 857 break; 858 859 /* RFC 2868 */ 860 /* Prepare the top-level Tunneling AVP for each tag values, as needed, and add to the Diameter message. 861 This macro is called when an AVP is added inside the group, so we will not have empty grouped AVPs */ 862 #define AVP_TUN_PREPARE() { \ 863 if (avp_tun == NULL) { \ 864 CHECK_MALLOC( avp_tun = calloc(sizeof(struct avp *), 32 ) ); \ 865 } \ 866 tag = *(uint8_t *)(attr + 1); \ 867 if (tag > 0x1F) tag = 0; \ 868 if (avp_tun[tag] == NULL) { \ 869 CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) ); \ 870 CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\ 871 } \ 872 } 873 874 /* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */ 875 #define CONV2DIAM_TUN_STR( _dictobj_ ) { \ 876 uint8_t tag; \ 877 CHECK_PARAMS( attr->length >= 3); \ 878 AVP_TUN_PREPARE(); \ 879 CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \ 880 value.os.len = attr->length - (tag ? 3 : 2); \ 881 value.os.data = ((unsigned char *)(attr + 1)) + (tag ? 1 : 0); \ 882 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \ 883 CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) ); \ 884 } 885 886 /* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */ 887 #define CONV2DIAM_TUN_24B( _dictobj_ ) { \ 888 uint8_t tag; \ 889 CHECK_PARAMS( attr->length == 6); \ 890 AVP_TUN_PREPARE(); \ 891 CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) ); \ 892 { \ 893 uint8_t * v = (uint8_t *)(attr + 1); \ 894 value.u32 = (v[1] << 16) | (v[2] <<8) | v[3] ; \ 895 } \ 896 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); \ 897 CHECK_FCT( fd_msg_avp_add ( avp_tun[tag], MSG_BRW_LAST_CHILD, avp) ); \ 898 } 899 900 /* 901 - If the RADIUS message contains Tunnel information [RADTunnels], 902 the attributes or tagged groups should each be converted to a 903 Diameter Tunneling Grouped AVP set. If the tunnel information 904 contains a Tunnel-Password attribute, the RADIUS encryption 905 must be resolved, and the password forwarded, by using Diameter 906 security methods. 907 -> If the RADIUS message does not use properly the Tag info, result is unpredictable here.. 908 */ 909 case RADIUS_ATTR_TUNNEL_TYPE: 910 CONV2DIAM_TUN_24B( Tunnel_Type ); 911 break; 912 913 case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE: 914 CONV2DIAM_TUN_24B( Tunnel_Medium_Type ); 915 break; 916 917 case RADIUS_ATTR_TUNNEL_CLIENT_ENDPOINT: 918 CONV2DIAM_TUN_STR( Tunnel_Client_Endpoint ); 919 break; 920 921 case RADIUS_ATTR_TUNNEL_SERVER_ENDPOINT: 922 CONV2DIAM_TUN_STR( Tunnel_Server_Endpoint ); 923 break; 924 925 /* Tunnel-Password never present in an Accounting-Request */ 926 927 case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID: 928 CONV2DIAM_TUN_STR( Tunnel_Private_Group_Id ); 929 break; 930 931 case RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID: 932 CONV2DIAM_TUN_STR( Tunnel_Assignment_Id ); 933 break; 934 935 /* Tunnel-Reference never present in an Accounting-Request */ 936 937 case RADIUS_ATTR_TUNNEL_CLIENT_AUTH_ID: 938 CONV2DIAM_TUN_STR( Tunnel_Client_Auth_Id ); 939 break; 940 941 case RADIUS_ATTR_TUNNEL_SERVER_AUTH_ID: 942 CONV2DIAM_TUN_STR( Tunnel_Server_Auth_Id ); 943 break; 944 945 /* RFC 2869 */ 946 /* 947 Acct-Input-Gigawords, Acct-Output- 948 Gigawords, Event-Timestamp, and NAS-Port-Id may have 0-1 instances in 949 an Accounting-Request packet. Connect-Info may have 0+ instances in 950 an Accounting-Request packet. The other attributes added in this 951 document must not be present in an Accounting-Request. 952 */ 953 case RADIUS_ATTR_ACCT_INPUT_GIGAWORDS: 954 break; /* we already saved the value in gigawords_in */ 955 956 case RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS: 957 break; /* we already saved the value in gigawords_out */ 958 959 case RADIUS_ATTR_EVENT_TIMESTAMP: 960 /* RADIUS: 961 The Value field is four octets encoding an unsigned integer with 962 the number of seconds since January 1, 1970 00:00 UTC. 963 Diameter: 964 The Time format is derived from the OctetString AVP Base Format. 965 The string MUST contain four octets, in the same format as the 966 first four bytes are in the NTP timestamp format. The NTP 967 Timestamp format is defined in Chapter 3 of [RFC4330]. 968 969 This represents the number of seconds since 0h on 1 January 1900 970 with respect to the Coordinated Universal Time (UTC). 971 972 -- RFC4330: 973 NTP timestamps are represented as a 64-bit unsigned 974 fixed-point number, in seconds relative to 0h on 1 January 1900. The 975 integer part is in the first 32 bits, and the fraction part in the 976 last 32 bits. In the fraction part, the non-significant low-order 977 bits are not specified and are ordinarily set to 0. 978 */ 979 { 980 uint32_t ts; 981 982 uint8_t * v = (uint8_t *)(attr + 1); 983 /* Read the RADIUS attribute value */ 984 ts = (v[0] << 24) 985 | (v[1] << 16) 986 | (v[2] << 8) 987 | v[3] ; 988 989 /* Add the 70 missing years */ 990 ts += 2208988800U; /* 60 * 60 * 24 * ( 365 * 70 + 17 ) */ 991 992 /* Convert to network byte order */ 993 ts = htonl(ts); 994 995 /* Diameter Time datatype is derived from OctetString */ 996 value.os.data = (void *) &ts; 997 value.os.len = sizeof(uint32_t); 998 999 CHECK_FCT( fd_msg_avp_new ( cs->dict.Event_Timestamp, 0, &avp ) ); 1000 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 1001 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 1002 } 1003 break; 1004 1005 case RADIUS_ATTR_NAS_PORT_ID: 1006 CONV2DIAM_STR( NAS_Port_Id ); 1007 break; 1008 1009 case RADIUS_ATTR_CONNECT_INFO: 1010 CONV2DIAM_STR( Connect_Info ); 1011 break; 1012 1013 case RADIUS_ATTR_FRAMED_POOL: /* To follow the IPv6 version */ 1014 CONV2DIAM_STR( Framed_Pool ); 1015 break; 1016 1017 1018 /* RFC 3579 */ 1019 /* 1020 The EAP-Message and Message-Authenticator attributes specified in 1021 this document MUST NOT be present in an Accounting-Request. 1022 */ 1023 case RADIUS_ATTR_ORIGINATING_LINE_INFO: 1024 CONV2DIAM_STR( Originating_Line_Info ); 1025 break; 1026 1027 /* Default */ 1028 default: /* unknown attribute */ 1029 /* We just keep the attribute in the RADIUS message */ 1030 rad_req->attr_pos[nattr_used++] = rad_req->attr_pos[idx]; 1031 } 1032 } 1033 1034 /* Update the radius message to remove all handled attributes */ 1035 rad_req->attr_used = nattr_used; 1036 1037 /* Store useful information in the session */ 1038 { 1039 struct sess_state * st; 1040 CHECK_PARAMS(session); 1041 1042 CHECK_MALLOC( st = malloc(sizeof(struct sess_state)) ); 1043 memset(st, 0, sizeof(struct sess_state)); 1044 memcpy(&st->req_auth, &rad_req->hdr->authenticator[0], 16); 1045 st->send_str = send_str; 1046 st->term_cause = str_cause; 1047 CHECK_FCT( fd_sess_state_store( cs->sess_hdl, session, &st ) ); 1048 } 1049 1050 return 0; 156 1051 } 157 1052 158 1053 static int acct_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli ) 159 1054 { 1055 struct sess_state * st = NULL; 1056 struct avp *avp, *next; 1057 struct avp_hdr *ahdr, *sid, *oh, *or; 1058 160 1059 TRACE_ENTRY("%p %p %p %p %p", cs, session, diam_ans, rad_fw, cli); 161 1060 CHECK_PARAMS(cs); 162 163 return ENOTSUP; 1061 1062 if (session) { 1063 CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, session, &st ) ); 1064 } 1065 1066 if (!st) { 1067 TRACE_DEBUG(INFO, "Received an ACA without corresponding session information, cannot translate to RADIUS"); 1068 return EINVAL; 1069 } 1070 1071 /* Search these AVPs first */ 1072 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Session_Id, &avp) ); 1073 CHECK_FCT( fd_msg_avp_hdr ( avp, &sid ) ); 1074 1075 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Host, &avp) ); 1076 CHECK_FCT( fd_msg_avp_hdr ( avp, &oh ) ); 1077 1078 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Origin_Realm, &avp) ); 1079 CHECK_FCT( fd_msg_avp_hdr ( avp, &or ) ); 1080 1081 /* Check the Diameter error code */ 1082 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Result_Code, &avp) ); 1083 ASSERT( avp ); /* otherwise the message should have been discarded a lot earlier because of ABNF */ 1084 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); 1085 switch (ahdr->avp_value->u32) { 1086 case ER_DIAMETER_SUCCESS: 1087 case ER_DIAMETER_LIMITED_SUCCESS: 1088 (*rad_fw)->hdr->code = RADIUS_CODE_ACCOUNTING_RESPONSE; 1089 break; 1090 1091 default: 1092 fd_log_debug("[auth.rgwx] Received Diameter answer with error code '%d' from server '%.*s', session %.*s, not translating into Accounting-Response\n", 1093 ahdr->avp_value->u32, 1094 oh->avp_value->os.len, oh->avp_value->os.data, 1095 sid->avp_value->os.len, sid->avp_value->os.data); 1096 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Message, &avp) ); 1097 if (avp) { 1098 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); 1099 fd_log_debug("[auth.rgwx] Error-Message content: '%.*s'\n", 1100 ahdr->avp_value->os.len, ahdr->avp_value->os.data); 1101 } 1102 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Error_Reporting_Host, &avp) ); 1103 if (avp) { 1104 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); 1105 fd_log_debug("[auth.rgwx] Error-Reporting-Host: '%.*s'\n", 1106 ahdr->avp_value->os.len, ahdr->avp_value->os.data); 1107 } 1108 CHECK_FCT( fd_msg_search_avp (*diam_ans, cs->dict.Failed_AVP, &avp) ); 1109 if (avp) { 1110 fd_log_debug("[auth.rgwx] Failed-AVP was included in the message.\n"); 1111 /* Dump its content ? */ 1112 } 1113 return -1; 1114 } 1115 /* Remove this Result-Code avp */ 1116 CHECK_FCT( fd_msg_free( avp ) ); 1117 1118 /* If it was a response to a STOP record, we must send an STR for this session */ 1119 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."); 1121 } 1122 1123 1124 /* 1125 No attributes should be found in 1126 Accounting-Response packets except Proxy-State and possibly Vendor- 1127 Specific. 1128 */ 1129 1130 /* Now loop in the list of AVPs and convert those that we know how */ 1131 CHECK_FCT( fd_msg_browse(*diam_ans, MSG_BRW_FIRST_CHILD, &next, NULL) ); 1132 1133 while (next) { 1134 int handled = 1; 1135 avp = next; 1136 CHECK_FCT( fd_msg_browse(avp, MSG_BRW_NEXT, &next, NULL) ); 1137 1138 CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); 1139 1140 if (!(ahdr->avp_flags & AVP_FLAG_VENDOR)) { 1141 switch (ahdr->avp_code) { 1142 /* Based on RFC4005, sec 3.10 */ 1143 case DIAM_ATTR_SESSION_ID: 1144 case DIAM_ATTR_ORIGIN_HOST: 1145 case DIAM_ATTR_ORIGIN_REALM: 1146 case DIAM_ATTR_ACCOUNTING_RECORD_TYPE: 1147 case DIAM_ATTR_ACCOUNTING_RECORD_NUMBER: 1148 case DIAM_ATTR_ACCT_APPLICATION_ID: 1149 case DIAM_ATTR_VENDOR_SPECIFIC_APPLICATION_ID: 1150 case DIAM_ATTR_USER_NAME: 1151 case DIAM_ATTR_ACCOUNTING_SUB_SESSION_ID: 1152 case DIAM_ATTR_ACCT_SESSION_ID: 1153 case DIAM_ATTR_ACCT_MULTI_SESSION_ID: 1154 case DIAM_ATTR_EVENT_TIMESTAMP: 1155 case DIAM_ATTR_ORIGIN_AAA_PROTOCOL: 1156 case DIAM_ATTR_ORIGIN_STATE_ID: 1157 case DIAM_ATTR_NAS_IDENTIFIER: 1158 case DIAM_ATTR_NAS_IP_ADDRESS: 1159 case DIAM_ATTR_NAS_IPV6_ADDRESS: 1160 case DIAM_ATTR_NAS_PORT: 1161 case DIAM_ATTR_NAS_PORT_ID: 1162 case DIAM_ATTR_NAS_PORT_TYPE: 1163 case DIAM_ATTR_SERVICE_TYPE: 1164 case DIAM_ATTR_TERMINATION_CAUSE: 1165 case DIAM_ATTR_ACCOUNTING_REALTIME_REQUIRED: 1166 case DIAM_ATTR_ACCT_INTERIM_INTERVAL: 1167 case DIAM_ATTR_CLASS: 1168 /* We just remove these AVP, they are not expected in RADIUS client */ 1169 break; 1170 1171 default: 1172 /* Leave the AVP in the message for further treatment */ 1173 handled = 0; 1174 } 1175 } else { 1176 /* Vendor-specific AVPs */ 1177 switch (ahdr->avp_vendor) { 1178 1179 default: /* unknown vendor */ 1180 handled = 0; 1181 } 1182 } 1183 1184 if (handled) { 1185 CHECK_FCT( fd_msg_free( avp ) ); 1186 } 1187 } 1188 1189 /* 1190 The Authenticator field in an Accounting-Response packet is called 1191 the Response Authenticator, and contains a one-way MD5 hash 1192 calculated over a stream of octets consisting of the Accounting- 1193 Response Code, Identifier, Length, the Request Authenticator field 1194 from the Accounting-Request packet being replied to, and the 1195 response attributes if any, followed by the shared secret. The 1196 resulting 16 octet MD5 hash value is stored in the Authenticator 1197 field of the Accounting-Response packet. 1198 1199 -- done in radius_msg_finish_srv 1200 */ 1201 1202 return 0; 164 1203 } 165 1204 -
extensions/app_radgw/rgwx_auth.c
r264 r271 47 47 #define CC_AA 265 /* AAR */ 48 48 #define CC_DIAMETER_EAP 268 /* DER */ 49 #define CC_DIAMETER_EAP 268 /* DER */50 49 #define ACV_ART_AUTHORIZE_AUTHENTICATE 3 /* AUTHORIZE_AUTHENTICATE */ 51 50 #define ACV_OAP_RADIUS 1 /* RADIUS */ … … 56 55 /* The state we keep for this plugin */ 57 56 struct rgwp_config { 58 struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */59 57 struct { 60 58 struct dict_object * ARAP_Password; /* ARAP-Password */ … … 120 118 121 119 } dict; /* cache of the dictionary objects we use */ 120 struct session_handler * sess_hdl; /* We store RADIUS request authenticator information in the session */ 122 121 char * confstr; 123 122 }; … … 768 767 if (tag > 0x1F) tag = 0; \ 769 768 if (avp_tun[tag] == NULL) { \ 770 CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) ); 769 CHECK_FCT( fd_msg_avp_new ( cs->dict.Tunneling, 0, &avp_tun[tag] ) ); \ 771 770 CHECK_FCT( fd_msg_avp_add (*diam_fw, MSG_BRW_LAST_CHILD, avp_tun[tag]));\ 772 771 } \ … … 774 773 775 774 /* Convert an attribute to an OctetString AVP and add inside the Tunneling AVP corresponding to the tag */ 776 #define CONV2DIAM_TUN_STR( _dictobj_ ) { 775 #define CONV2DIAM_TUN_STR( _dictobj_ ) { \ 777 776 uint8_t tag; \ 778 777 CHECK_PARAMS( attr->length >= 3); \ … … 786 785 787 786 /* Convert an attribute to a scalar AVP and add inside the Tunneling AVP corresponding to the tag */ 788 #define CONV2DIAM_TUN_24B( _dictobj_ ) { 787 #define CONV2DIAM_TUN_24B( _dictobj_ ) { \ 789 788 uint8_t tag; \ 790 789 CHECK_PARAMS( attr->length == 6); \ … … 916 915 static int auth_diam_ans( struct rgwp_config * cs, struct session * session, struct msg ** diam_ans, struct radius_msg ** rad_fw, struct rgw_client * cli ) 917 916 { 918 struct msg_hdr *mhdr;919 917 struct avp *avp, *next, *avp_x, *avp_y, *asid, *aoh; 920 918 struct avp_hdr *ahdr, *sid, *oh; … … 931 929 CHECK_FCT( fd_sess_state_retrieve( cs->sess_hdl, session, &req_auth ) ); 932 930 } 933 934 CHECK_FCT( fd_msg_hdr( *diam_ans, &mhdr ) );935 931 936 932 /* … … 1466 1462 break; 1467 1463 1468 case DIAM_ATTR_TUNNEL_ASSIGN EMENT_ID:1469 CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_ASSIGN EMENT_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1);1464 case DIAM_ATTR_TUNNEL_ASSIGNMENT_ID: 1465 CONV2RAD_TUN_STR(RADIUS_ATTR_TUNNEL_ASSIGNMENT_ID, ahdr->avp_value->os.data, ahdr->avp_value->os.len, 1); 1470 1466 break; 1471 1467
Note: See TracChangeset
for help on using the changeset viewer.