Changeset 356:e203fc0c95e3 in freeDiameter for extensions/app_radgw/rgwx_auth.c
- Timestamp:
- Jul 1, 2010, 3:47:34 PM (13 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/app_radgw/rgwx_auth.c
r296 r356 71 71 struct dict_object * CHAP_Ident; /* CHAP-Ident */ 72 72 struct dict_object * CHAP_Response; /* CHAP-Response */ 73 struct dict_object * Destination_Host; /* Destination-Host */ 74 struct dict_object * Destination_Realm; /* Destination-Realm */ 73 75 struct dict_object * Connect_Info; /* Connect-Info */ 74 76 struct dict_object * EAP_Payload; /* EAP-Payload */ … … 154 156 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "CHAP-Response", &new->dict.CHAP_Response, ENOENT) ); 155 157 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Connect-Info", &new->dict.Connect_Info, ENOENT) ); 158 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &new->dict.Destination_Host, ENOENT) ); 159 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Realm", &new->dict.Destination_Realm, ENOENT) ); 156 160 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "EAP-Payload", &new->dict.EAP_Payload, ENOENT) ); 157 161 CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Message", &new->dict.Error_Message, ENOENT) ); … … 222 226 223 227 /* Handle an incoming RADIUS request */ 224 static int auth_rad_req( struct rgwp_config * cs, struct session * session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli )228 static int auth_rad_req( struct rgwp_config * cs, struct session ** session, struct radius_msg * rad_req, struct radius_msg ** rad_ans, struct msg ** diam_fw, struct rgw_client * cli ) 225 229 { 226 230 int idx; … … 230 234 int got_eap = 0; 231 235 int got_empty_eap = 0; 236 const char * prefix = "Diameter/"; 237 size_t pref_len; 238 char * dh = NULL; 239 size_t dh_len = 0; 240 char * dr = NULL; 241 size_t dr_len = 0; 242 char * si = NULL; 243 size_t si_len = 0; 244 char * un = NULL; 245 size_t un_len = 0; 232 246 uint32_t status_type; 233 247 size_t nattr_used = 0; … … 236 250 237 251 TRACE_ENTRY("%p %p %p %p %p %p", cs, session, rad_req, rad_ans, diam_fw, cli); 238 CHECK_PARAMS(rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCESS_REQUEST) && rad_ans && diam_fw && *diam_fw); 252 CHECK_PARAMS(cs && session && rad_req && (rad_req->hdr->code == RADIUS_CODE_ACCESS_REQUEST) && rad_ans && diam_fw && *diam_fw); 253 254 pref_len = strlen(prefix); 239 255 240 256 /* … … 269 285 and associated with the session state. 270 286 -> sub_echo_drop should handle the Proxy-State attribute (conf issue) 271 272 - If the RADIUS request contained a State attribute and the273 prefix of the data is "Diameter/", the data following the274 prefix contains the Diameter Origin-Host/Origin-Realm/Session-275 Id. If no such attributes are present and the RADIUS command276 is an Access-Request, a new Session-Id is created. The277 Session-Id is included in the Session-Id AVP.278 -> done in rgw_msg_create_base.279 287 280 288 - The Diameter Origin-Host and Origin-Realm AVPs MUST be created … … 305 313 */ 306 314 307 /* Check basic information is there */315 /* Check basic information is there, and also retrieve some attribute information */ 308 316 for (idx = 0; idx < rad_req->attr_used; idx++) { 309 317 struct radius_attr_hdr * attr = (struct radius_attr_hdr *)(rad_req->buf + rad_req->attr_pos[idx]); 318 char * attr_val = (char *)(attr + 1); 319 size_t attr_len = attr->length - sizeof(struct radius_attr_hdr); 320 310 321 switch (attr->type) { 311 322 case RADIUS_ATTR_NAS_IP_ADDRESS: … … 327 338 got_passwd += 1; 328 339 break; 340 341 /* Is there a State attribute with prefix "Diameter/" in the message? (in that case: Diameter/Destination-Host/Destination-Realm/Session-Id) */ 342 /* NOTE: RFC4005 says "Origin-Host" here, but it's not coherent with the rules for answers. Destination-Host makes more sense */ 343 case RADIUS_ATTR_STATE: 344 if ((attr_len > pref_len + 5 /* for the '/'s and non empty strings */ ) 345 && ! strncmp(attr_val, prefix, pref_len)) { /* should we make it strncasecmp? */ 346 int i, start; 347 348 TRACE_DEBUG(ANNOYING, "Found a State attribute with '%s' prefix (attr #%d).", prefix, idx); 349 350 /* Now parse the value and check its content is valid. Unfortunately we cannot use strchr here since strings are not \0-terminated */ 351 352 i = start = pref_len; 353 dh = attr_val + i; 354 for (; (i < attr_len - 2) && (attr_val[i] != '/'); i++) /* loop */; 355 if ( i >= attr_len - 2 ) continue; /* the attribute format is not good */ 356 dh_len = i - start; 357 358 start = ++i; 359 dr = attr_val + i; 360 for (; (i < attr_len - 1) && (attr_val[i] != '/'); i++) /* loop */; 361 if ( i >= attr_len - 1 ) continue; /* the attribute format is not good */ 362 dr_len = i - start; 363 364 i++; 365 si = attr_val + i; 366 si_len = attr_len - i; 367 368 TRACE_DEBUG(ANNOYING, "Attribute parsed successfully: DH:'%.*s' DR:'%.*s' SI:'%.*s'.", dh_len, dh, dr_len, dr, si_len, si); 369 /* Remove from the message */ 370 for (i = idx + 1; i < rad_req->attr_used; i++) 371 rad_req->attr_pos[i - 1] = rad_req->attr_pos[i]; 372 rad_req->attr_used -= 1; 373 } 374 break; 375 376 case RADIUS_ATTR_USER_NAME: 377 if (attr_len) { 378 TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", attr_len, attr_val); 379 un = attr_val; 380 un_len = attr_len; 381 } 382 break; 383 329 384 } 330 385 } … … 346 401 return EINVAL; 347 402 } 403 404 405 406 /* 407 - If the RADIUS request contained a State attribute and the 408 prefix of the data is "Diameter/", the data following the 409 prefix contains the Diameter Origin-Host/Origin-Realm/Session- 410 Id. If no such attributes are present and the RADIUS command 411 is an Access-Request, a new Session-Id is created. The 412 Session-Id is included in the Session-Id AVP. 413 */ 414 415 /* Add the Destination-Realm AVP */ 416 CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Realm, 0, &avp ) ); 417 if (dr) { 418 value.os.data = (unsigned char *)dr; 419 value.os.len = dr_len; 420 } else { 421 int i = 0; 422 if (un) { 423 /* Is there an '@' in the user name? We don't care for decorated NAI here */ 424 for (i = un_len - 2; i > 0; i--) { 425 if (un[i] == '@') { 426 i++; 427 break; 428 } 429 } 430 } 431 if (i == 0) { 432 /* Not found in the User-Name => we use the local domain of this gateway */ 433 value.os.data = fd_g_config->cnf_diamrlm; 434 value.os.len = fd_g_config->cnf_diamrlm_len; 435 } else { 436 value.os.data = un + i; 437 value.os.len = un_len - i; 438 } 439 } 440 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 441 CHECK_FCT( fd_msg_avp_add ( *diam_fw, *session ? MSG_BRW_LAST_CHILD : MSG_BRW_FIRST_CHILD, avp) ); 442 443 /* Add the Destination-Host if found */ 444 if (dh) { 445 CHECK_FCT( fd_msg_avp_new ( cs->dict.Destination_Host, 0, &avp ) ); 446 value.os.data = (unsigned char *)dh; 447 value.os.len = dh_len; 448 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 449 CHECK_FCT( fd_msg_avp_add ( *diam_fw, *session ? MSG_BRW_LAST_CHILD : MSG_BRW_FIRST_CHILD, avp) ); 450 } 451 452 /* Create the session if it is not already done */ 453 if (*session == NULL) { 454 char * sess_str = NULL; 455 456 if (si_len) { 457 /* We already have the Session-Id, just use it */ 458 CHECK_FCT( fd_sess_fromsid ( si, si_len, session, NULL) ); 459 } else { 460 /* Create a new Session-Id string */ 461 462 char * fqdn; 463 char * realm; 464 465 /* Get information on the RADIUS client */ 466 CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) ); 467 468 /* If we have a user name, create the new session with it */ 469 if (un) { 470 int len; 471 /* If not found, create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */ 472 CHECK_MALLOC( sess_str = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) ); 473 len = sprintf(sess_str, "%.*s;%s", un_len, un, fd_g_config->cnf_diamid); 474 CHECK_FCT( fd_sess_new(session, fqdn, sess_str, len) ); 475 free(sess_str); 476 } else { 477 /* We don't have enough information to create the Session-Id, the RADIUS message is probably invalid */ 478 TRACE_DEBUG(INFO, "RADIUS Access-Request does not contain a User-Name attribute, rejecting."); 479 return EINVAL; 480 } 481 } 482 483 /* Now, add the Session-Id AVP at beginning of Diameter message */ 484 CHECK_FCT( fd_sess_getsid(*session, &sess_str) ); 485 486 TRACE_DEBUG(FULL, "[auth.rgwx] Translating new message for session '%s'...", sess_str); 487 488 /* Add the Session-Id AVP as first AVP */ 489 CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) ); 490 value.os.data = (unsigned char *)sess_str; 491 value.os.len = strlen(sess_str); 492 CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 493 CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) ); 494 } 495 348 496 349 497 /* Add the appropriate command code & Auth-Application-Id */ … … 908 1056 memcpy(req_auth, &rad_req->hdr->authenticator[0], 16); 909 1057 910 CHECK_FCT( fd_sess_state_store( cs->sess_hdl, session, &req_auth ) );1058 CHECK_FCT( fd_sess_state_store( cs->sess_hdl, *session, &req_auth ) ); 911 1059 } 912 1060 … … 914 1062 } 915 1063 916 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 )1064 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, int * stateful ) 917 1065 { 918 1066 struct msg_hdr * hdr;
Note: See TracChangeset
for help on using the changeset viewer.