/* Generate AVPs from Radius reply items */ static void generate_avps(struct attr *attrs, VALUE_PAIR* received) { int_str name, val; unsigned short flags; VALUE_PAIR *vp; vp = received; for( ; (vp=rc_avpair_get(vp,attrs[SA_SIP_AVP].v,0)) ; vp=vp->next) { flags = 0; if (extract_avp( vp, &flags, &name, &val)!=0 ) continue; if (add_avp( flags, name, val) < 0) { LM_ERR("unable to create a new AVP\n"); } else { LM_DBG("AVP '%.*s'/%d='%.*s'/%d has been added\n", (flags&AVP_NAME_STR)?name.s.len:4, (flags&AVP_NAME_STR)?name.s.s:"null", (flags&AVP_NAME_STR)?0:name.n, (flags&AVP_VAL_STR)?val.s.len:4, (flags&AVP_VAL_STR)?val.s.s:"null", (flags&AVP_VAL_STR)?0:val.n ); } } return; }
/* * Generate AVPs from the database result */ static int generate_avps(VALUE_PAIR* received) { int_str name, val; unsigned short flags; VALUE_PAIR *vp; LM_DBG("getting AVPs from RADIUS Reply\n"); vp = received; if ( ! ar_radius_avps_mode ) vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0); for( ; vp; vp=((ar_radius_avps_mode)?vp->next:rc_avpair_get(vp->next,attrs[A_SIP_AVP].v,0)) ) { flags = 0; if (!extract_avp( vp, &flags, &name, &val)){ LM_ERR("error while extracting AVP '%.*s'\n",(int)strlen(vp->name),vp->name); continue; } if (add_avp( flags, name, val) < 0) { LM_ERR("unable to create a new AVP\n"); } else { LM_DBG("AVP '%.*s'/%d='%.*s'/%d has been added\n", (flags&AVP_NAME_STR)?name.s.len:4, (flags&AVP_NAME_STR)?name.s.s:"null", (flags&AVP_NAME_STR)?0:name.n, (flags&AVP_VAL_STR)?val.s.len:4, (flags&AVP_VAL_STR)?val.s.s:"null", (flags&AVP_VAL_STR)?0:val.n ); } } return 0; }
int send_auth_func(struct sip_msg* msg, str* s1, str* s2) { int i, res; int index1 = -1, index2 = -1; map_list *mp; pv_value_t pvt; char mess[1024]; VALUE_PAIR *send = NULL, *recv = NULL, *vp = NULL; if (!rh) { if (init_radius_handle()) { LM_ERR("invalid radius handle\n"); return -1; } } for (i = 0; i < set_size; i++) { if (sets[i]->set_name.len == s1->len && !strncmp(sets[i]->set_name.s, s1->s, s1->len)) index1 = i; if (sets[i]->set_name.len == s2->len && !strncmp(sets[i]->set_name.s, s2->s, s2->len)) index2 = i; } if (index1 == -1) { LM_ERR("the first set was not found\n"); return -1; } if (index2 == -1) { LM_ERR("the second set was not found\n"); return -1; } if (make_send_message(msg, index1, &send) < 0) { LM_ERR("make message failed\n"); return -1; } res = rc_auth(rh, SIP_PORT, send, &recv, mess); if (res!=OK_RC && res!=BADRESP_RC) { LM_ERR("radius authentication message failed with %s\n", (res==TIMEOUT_RC)?"TIMEOUT":"ERROR"); }else{ LM_DBG("radius authentication message sent\n"); } for ( mp=sets[index2]->parsed; mp ; mp = mp->next) { vp = recv; while ( (vp=rc_avpair_get(vp, ATTRID(mp->value), VENDOR(mp->value)))!=NULL ) { memset(&pvt, 0, sizeof(pv_value_t)); if (vp->type == PW_TYPE_INTEGER) { pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.ri = vp->lvalue; } else if (vp->type == PW_TYPE_STRING) { pvt.flags = PV_VAL_STR; pvt.rs.s = vp->strvalue; pvt.rs.len = vp->lvalue; } if (pv_set_value(msg, mp->pv, (int)EQ_T, &pvt) < 0) { LM_ERR("setting avp failed....skipping\n"); } vp = fetch_all_values ? vp->next : NULL; } } vp = recv; if (attr) for(; (vp = rc_avpair_get(vp, attr->value, 0)); vp = vp->next) extract_avp(vp); if ( res!=OK_RC && res!=BADRESP_RC) goto error; if (send) rc_avpair_free(send); if (recv) rc_avpair_free(recv); return (res==OK_RC)?1:-2; error: if (send) rc_avpair_free(send); if (recv) rc_avpair_free(recv); return -1; }
static int load_avp_user(struct sip_msg* msg, str* prefix, load_avp_param_t type) { static char rad_msg[4096]; str user_domain, buffer; str* user, *domain, *uri; struct hdr_field* h; dig_cred_t* cred = 0; int_str name, val; unsigned short flags; VALUE_PAIR* send, *received, *vp; UINT4 service; struct sip_uri puri; send = received = 0; user_domain.s = 0; switch(type) { case LOAD_CALLER: /* Use From header field */ if (parse_from_header(msg) < 0) { LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while " "parsing From header field\n"); return -1; } uri = &get_from(msg)->uri; if (parse_uri(uri->s, uri->len, &puri) == -1) { LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while " "parsing From URI\n"); return -1; } user = &puri.user; domain = &puri.host; service = vals[V_SIP_CALLER_AVPS].v; break; case LOAD_CALLEE: /* Use the Request-URI */ if (parse_sip_msg_uri(msg) < 0) { LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while " "parsing Request-URI\n"); return -1; } if (msg->parsed_uri.user.len == 0) { LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Request-URI user " "is missing\n"); return -1; } user = &msg->parsed_uri.user; domain = &msg->parsed_uri.host; service = vals[V_SIP_CALLEE_AVPS].v; break; case LOAD_DIGEST: /* Use digest credentials */ get_authorized_cred(msg->proxy_auth, &h); if (!h) { LOG(L_ERR, "ERROR:avp_radius:load_avp_user: No authoried " "credentials\n"); return -1; } cred = &((auth_body_t*)(h->parsed))->digest; user = &cred->username.user; domain = &cred->realm; service = vals[V_SIP_CALLER_AVPS].v; break; default: LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Unknown user type\n"); return -1; } user_domain.len = user->len + 1 + domain->len; user_domain.s = (char*)pkg_malloc(user_domain.len); if (!user_domain.s) { LOG(L_ERR, "ERROR:avp_radius:avp_load_user: No pkg memory left\n"); return -1; } memcpy(user_domain.s, user->s, user->len); user_domain.s[user->len] = '@'; memcpy(user_domain.s + user->len + 1, domain->s, domain->len); if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_domain.s, user_domain.len, 0)) { LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Error adding " "PW_USER_NAME\n"); goto error; } if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Error adding " "PW_SERVICE_TYPE\n"); goto error; } if (rc_auth(rh, 0, send, &received, rad_msg) == OK_RC) { DBG("DEBUG:avp_radius:avp_load_user: rc_auth Success\n"); rc_avpair_free(send); pkg_free(user_domain.s); vp = received; for( ; (vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0)) ; vp=vp->next) { flags = 0; if (extract_avp( vp, &flags, &name, &val)!=0 ) continue; /* append prefix only if AVP has name */ if (flags&AVP_NAME_STR) { buffer.len = prefix->len + name.s->len; buffer.s = (char*)pkg_malloc(buffer.len); if (!buffer.s) { LOG(L_ERR, "ERROR:avp_radius:avp_load_user: "******"No pkg memory left\n"); return -1; } memcpy(buffer.s, prefix->s, prefix->len); memcpy(buffer.s + prefix->len, name.s->s, name.s->len); name.s = &buffer; } else { buffer.s = 0; } if (add_avp( flags, name, val) < 0) { LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Unable to create " "a new AVP\n"); } else { DBG("DEBUG:avp_radius:generate_avps: " "AVP '%.*s'/%d='%.*s'/%d has been added\n", (flags&AVP_NAME_STR)?name.s->len:4, (flags&AVP_NAME_STR)?name.s->s:"null", (flags&AVP_NAME_STR)?0:name.n, (flags&AVP_VAL_STR)?val.s->len:4, (flags&AVP_VAL_STR)?val.s->s:"null", (flags&AVP_VAL_STR)?0:val.n ); } if (buffer.s) pkg_free(buffer.s); } rc_avpair_free(received); return 1; } else { LOG(L_ERR,"ERROR:avp_radius:avp_load_user: rc_auth failed\n"); } error: if (send) rc_avpair_free(send); if (received) rc_avpair_free(received); if (user_domain.s) pkg_free(user_domain.s); return -1; }
/* Radius implementation for the send_message callback */ int rad_send_message(aaa_conn* rh, aaa_message* request, aaa_message** reply) { char msg[4096]; VALUE_PAIR *vp; DICT_ATTR *attr; int result; if (!rh) { LM_ERR("invalid aaa connection argument\n"); return -1; } if (!request) { LM_ERR("invalid argument\n"); return -1; } if (request->type == AAA_AUTH) { *reply = (aaa_message*) pkg_malloc (sizeof(aaa_message)); if (!(*reply)) { LM_ERR("no pkg memory left \n"); return -1; } (*reply)->type = AAA_RECV; (*reply)->avpair = NULL; (*reply)->last_found = NULL; result = rc_auth(rh, SIP_PORT, (VALUE_PAIR*) request->avpair, (VALUE_PAIR**)(void*)&(*reply)->avpair, msg); if (result == OK_RC) { attr = rc_dict_findattr(rh, "SIP-AVP"); if (attr) { vp = (*reply)->avpair; for(; (vp = rc_avpair_get(vp, attr->value, 0)); vp = vp->next) if (extract_avp(vp)) { LM_ERR("extract_avp failed\n"); return -1; } return 0; } else { LM_ERR("SIP-AVP was not found in the radius dictionary\n"); return -1; } } else if (result == REJECT_RC) { LM_DBG("rc_auth function succeded with result REJECT_RC\n"); return result; } else { LM_ERR("rc_auth function failed\n"); return -1; } } if (request->type == AAA_ACCT) { return rc_acct(rh, SIP_PORT, (VALUE_PAIR*) request->avpair); } LM_ERR("send message failure\n"); return -1; }
/* TODO * when timeout mechanism will be available * rc_auth_function shall be called to try another * destination if the current one has timed out * */ int resume_send_auth(int fd, struct sip_msg *msg, void *param) { int res; map_list *mp; pv_value_t pvt; struct rad_ctx *rctx; VALUE_PAIR *recv = NULL, *vp = NULL; rctx = (struct rad_ctx *)param; if (rctx == NULL) { LM_ERR("no context given\n"); return -1; } res = rc_auth_resume(&rctx->ctx, &recv); if (res == OK_RC || res == REJECT_RC) { async_status = ASYNC_DONE; } else if (res == READBLOCK_RC) { async_status = ASYNC_CONTINUE; return 1; } else { LM_ERR("radius authentication message failed with %s\n", ((res==BADRESP_RC)?"BAD REPLY":"ERROR")); goto error; } for ( mp=sets[rctx->index2]->parsed; mp ; mp = mp->next) { vp = recv; while ( (vp=rc_avpair_get(vp, ATTRID(mp->value), VENDOR(mp->value)))!=NULL ) { memset(&pvt, 0, sizeof(pv_value_t)); if (vp->type == PW_TYPE_INTEGER) { pvt.flags = PV_VAL_INT|PV_TYPE_INT; pvt.ri = vp->lvalue; } else if (vp->type == PW_TYPE_STRING) { pvt.flags = PV_VAL_STR; pvt.rs.s = vp->strvalue; pvt.rs.len = vp->lvalue; } if (pv_set_value(msg, mp->pv, (int)EQ_T, &pvt) < 0) { LM_ERR("setting avp failed....skipping\n"); } vp = fetch_all_values ? vp->next : NULL; } } vp = recv; if (attr) for(; (vp = rc_avpair_get(vp, attr->value, 0)); vp = vp->next) extract_avp(vp); if ( res!=OK_RC && res!=REJECT_RC) goto error; if (rctx->send) rc_avpair_free(rctx->send); if (recv) rc_avpair_free(recv); pkg_free(rctx); return (res==OK_RC)?1:-2; error: pkg_free(rctx); if (rctx->send) rc_avpair_free(rctx->send); if (recv) rc_avpair_free(recv); return -1; }