int make_send_message(struct sip_msg* msg, int index, VALUE_PAIR **send) { pv_value_t pt; map_list *mp = sets[index]->parsed; for (; mp; mp = mp->next) { pv_get_spec_value(msg, mp->pv, &pt); if (pt.flags & PV_VAL_INT) { //LM_DBG("%.*s---->%d---->%d---->%d\n",mp->name.len, mp->name.s, // pt.ri, mp->value, pt.flags); if (!rc_avpair_add(rh, send, ATTRID(mp->value), &pt.ri, -1, VENDOR(mp->value))) return -1; } else if (pt.flags & PV_VAL_STR) { //LM_DBG("%.*s----->%.*s---->%d---->%d---->%d\n",mp->name.len, // mp->name.s, pt.rs.len, pt.rs.s, mp->value, pt.flags, pt.rs.len); if (rc_dict_getattr(rh,mp->value)->type == PW_TYPE_IPADDR) { uint32_t ipaddr=rc_get_ipaddr(pt.rs.s); if (!rc_avpair_add(rh, send, ATTRID(mp->value), &ipaddr, -1, VENDOR(mp->value))) return -1; } else { if (!rc_avpair_add(rh, send, ATTRID(mp->value), pt.rs.s, pt.rs.len, VENDOR(mp->value))) return -1; } } } return 0; }
/** Find the first attribute value-pair (which matches the given attribute) from the specified value-pair list * * @param vp a pointer to a #VALUE_PAIR structure. * @param attrid The attribute of the pair to find (e.g., %PW_USER_NAME). * @param vendorpec The vendor ID in case of a vendor specific value - 0 otherwise. * @return the value pair found. */ VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, int attrid, int vendorpec) { for (; vp != NULL && !(ATTRID(vp->attribute) == ATTRID(attrid) && VENDOR(vp->attribute) == vendorpec); vp = vp->next) { continue; } return vp; }
static int load_user_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp) { static char rad_msg[4096]; str uid; UINT4 service; VALUE_PAIR* send, *received; send = NULL; received = NULL; if (get_str_fparam(&uid, msg, (fparam_t*)fp) < 0) { ERR("Unable to get UID\n"); return -1; } service = vals[V_GET_USER_ATTRS].v; if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), uid.s, uid.len, VENDOR(attrs[A_USER_NAME].v))) { ERR("Error while adding A_USER_NAME\n"); goto error; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), &vals[V_GET_USER_ATTRS].v, -1, VENDOR(attrs[A_SER_SERVICE_TYPE].v))) { ERR("Error adding A_SERVICE_TYPE\n"); goto error; } if (rc_auth(rh, 0, send, &received, rad_msg) != OK_RC) { DBG("load_user_attrs: Failure\n"); goto error; } DBG("load_user_attrs: Success\n"); rc_avpair_free(send); if (generate_avps(flags, received) < 0) { rc_avpair_free(received); goto error; } rc_avpair_free(received); return 1; error: if (send) rc_avpair_free(send); if (received) rc_avpair_free(send); return -1; }
static int add_cisco_vsa(VALUE_PAIR** send, struct sip_msg* msg) { str callid; if (!msg->callid && parse_headers(msg, HDR_CALLID_F, 0) == -1) { LOG(L_ERR, "add_cisco_vsa: Cannot parse Call-ID header field\n"); return -1; } if (!msg->callid) { LOG(L_ERR, "add_cisco_vsa: Call-ID header field not found\n"); return -1; } callid.len = msg->callid->body.len + 8; callid.s = pkg_malloc(callid.len); if (callid.s == NULL) { LOG(L_ERR, "add_cisco_vsa: No memory left\n"); return -1; } memcpy(callid.s, "call-id=", 8); memcpy(callid.s + 8, msg->callid->body.s, msg->callid->body.len); if (rc_avpair_add(rh, send, ATTRID(attrs[A_CISCO_AVPAIR].v), callid.s, callid.len, VENDOR(attrs[A_CISCO_AVPAIR].v)) == 0) { LOG(L_ERR, "add_cisco_vsa: Unable to add Cisco-AVPair attribute\n"); pkg_free(callid.s); return -1; } pkg_free(callid.s); return 0; }
/* skip leading text and begin with first item's * separator ", " which will be overwritten by the * leading text later * */ static int log_request(struct sip_msg* rq, str* ouri, struct hdr_field* to, unsigned int code, time_t req_time) { VALUE_PAIR *send; UINT4 av_type; send = NULL; if (skip_cancel(rq)) return 1; if (fmt2rad(log_fmt, rq, ouri, to, code, &send, req_time) < 0) goto error; /* Add Acct-Status-Type attribute */ av_type = rad_status(rq, code); if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_ACCT_STATUS_TYPE].v), &av_type, -1, VENDOR(attrs[A_ACCT_STATUS_TYPE].v))) { ERR("Add Status-Type\n"); goto error; } /* Add Service-Type attribute */ av_type = (service_type != -1) ? service_type : vals[V_SIP_SESSION].v; if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SERVICE_TYPE].v), &av_type, -1, VENDOR(attrs[A_SERVICE_TYPE].v))) { ERR("add STATUS_TYPE\n"); goto error; } /* Add User-Name attribute */ if (add_user_name(rq, rh, &send) < 0) goto error; /* Send the request out */ if (rc_acct(rh, SIP_PORT, send) != OK_RC) { ERR("RADIUS accounting request failed\n"); goto error; } rc_avpair_free(send); return 1; error: rc_avpair_free(send); return -1; }
/* * Generate AVPs from the database result */ static int generate_avps(VALUE_PAIR* received) { int_str name, val; VALUE_PAIR *vp; vp = rc_avpair_get(received, ATTRID(attrs[A_SER_UID].v), VENDOR(attrs[A_SER_UID].v)); if (vp == NULL) { WARN("RADIUS server did not send SER-UID attribute in digest authentication reply\n"); return -1; } val.s.len = vp->lvalue; val.s.s = vp->strvalue; name.s.s = "uid"; name.s.len = 3; if (add_avp(AVP_TRACK_FROM | AVP_CLASS_USER | AVP_NAME_STR | AVP_VAL_STR, name, val) < 0) { ERR("Unable to create UID attribute\n"); return -1; } vp = received; while ((vp = rc_avpair_get(vp, ATTRID(attrs[A_SER_ATTR].v), VENDOR(attrs[A_SER_ATTR].v)))) { attr_name_value(&name.s, &val.s, vp); if (name.s.len == 0) { ERR("Missing attribute name\n"); return -1; } if (add_avp(AVP_TRACK_FROM | AVP_CLASS_USER | AVP_NAME_STR | AVP_VAL_STR, name, val) < 0) { LOG(L_ERR, "generate_avps: Unable to create a new AVP\n"); return -1; } else { DBG("generate_avps: AVP '%.*s'='%.*s' has been added\n", name.s.len, ZSW(name.s.s), val.s.len, ZSW(val.s.s)); } vp = vp->next; } return 0; }
/* * Add User-Name attribute */ static inline int add_user_name(struct sip_msg* rq, void* rh, VALUE_PAIR** send) { struct sip_uri puri; str* user, *realm; str user_name; struct to_body* from; user = cred_user(rq); /* try to take it from credentials */ realm = cred_realm(rq); if (!user || !realm) { if (rq->from && (from = get_from(rq)) && from->uri.len) { if (parse_uri(from->uri.s, from->uri.len, &puri) < 0 ) { LOG(L_ERR, "ERROR:acc:add_user_name: Bad From URI\n"); return -1; } user = &puri.user; realm = &puri.host; } else { DBG("acc:add_user_name: Neither digest nor From found, mandatory attribute User-Name not added\n"); return -1; } } user_name.len = user->len + 1 + realm->len; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "ERROR:acc:add_user_name: no memory\n"); return -1; } memcpy(user_name.s, user->s, user->len); user_name.s[user->len] = '@'; memcpy(user_name.s + user->len + 1, realm->s, realm->len); if (!rc_avpair_add(rh, send, ATTRID(attrs[A_USER_NAME].v), user_name.s, user_name.len, VENDOR(attrs[A_USER_NAME].v))) { LOG(L_ERR, "ERROR:acc:add_user_name: Failed to add User-Name attribute\n"); pkg_free(user_name.s); return -1; } pkg_free(user_name.s); return 0; }
/* * Generate AVPs from the database result */ static int generate_avps(unsigned int flags, VALUE_PAIR* received) { int_str name, val; VALUE_PAIR *vp; vp = received; while ((vp = rc_avpair_get(vp, ATTRID(attrs[A_SER_ATTR].v), VENDOR(attrs[A_SER_ATTR].v)))) { attr_name_value(&name.s, &val.s, vp); if (name.s.len == 0) { ERR("Missing attribute name\n"); return -1; } if (add_avp(flags | AVP_NAME_STR | AVP_VAL_STR, name, val) < 0) { ERR("Unable to create a new SER attribute\n"); return -1; } vp = vp->next; } 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_uri_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp) { static char rad_msg[4096]; struct sip_uri puri; str uri, did, scheme; UINT4 service; VALUE_PAIR* send, *received; send = NULL; received = NULL; if (get_str_fparam(&uri, msg, (fparam_t*)fp) != 0) { ERR("Unable to get URI\n"); return -1; } if (parse_uri(uri.s, uri.len, &puri) < 0) { ERR("Error while parsing URI '%.*s'\n", uri.len, uri.s); return -1; } if (puri.host.len) { /* domain name is present */ if (dm_get_did(&did, &puri.host) < 0) { DBG("Cannot lookup DID for domain %.*s, using default value\n", puri.host.len, ZSW(puri.host.s)); did.s = DEFAULT_DID; did.len = sizeof(DEFAULT_DID) - 1; } } else { /* domain name is missing -- can be caused by tel: URI */ DBG("There is no domain name, using default value\n"); did.s = DEFAULT_DID; did.len = sizeof(DEFAULT_DID) - 1; } uri_type_to_str(puri.type, &scheme); service = vals[V_GET_URI_ATTRS].v; if (scheme.len) { if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_SCHEME].v), scheme.s, scheme.len, VENDOR(attrs[A_SER_URI_SCHEME].v))) { ERR("Error while adding A_SER_URI_SCHEME\n"); goto error; } } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), puri.user.s, puri.user.len, VENDOR(attrs[A_USER_NAME].v))) { ERR("Error while adding A_USER_NAME\n"); goto error; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_DID].v), did.s, did.len, VENDOR(attrs[A_SER_DID].v))) { ERR("Error while adding A_SER_DID\n"); goto error; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), &vals[V_GET_URI_ATTRS].v, -1, VENDOR(attrs[A_SER_SERVICE_TYPE].v))) { ERR("Error adding A_SERVICE_TYPE\n"); goto error; } if (rc_auth(rh, 0, send, &received, rad_msg) != OK_RC) { DBG("load_uri_attrs: Failure\n"); goto error; } DBG("load_uri_attrs: Success\n"); rc_avpair_free(send); if (generate_avps(flags, received) < 0) { rc_avpair_free(received); goto error; } rc_avpair_free(received); return 1; error: if (send) rc_avpair_free(send); if (received) rc_avpair_free(send); return -1; }
/* * This function creates and submits radius authentication request as per * draft-sterman-aaa-sip-00.txt. In addition, _user parameter is included * in the request as value of a SER specific attribute type SIP-URI-User, * which can be be used as a check item in the request. Service type of * the request is Authenticate-Only. */ int radius_authorize_sterman(VALUE_PAIR** received, struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user) { static char msg[4096]; VALUE_PAIR *send; UINT4 service, ser_service_type; str method, user, user_name; str *ruri; int i; send = 0; if (!(_cred && _method && _user)) { LOG(L_ERR, "radius_authorize_sterman(): Invalid parameter value\n"); return -1; } method = *_method; user = *_user; /* * Add all the user digest parameters according to the qop defined. * Most devices tested only offer support for the simplest digest. */ if (_cred->username.domain.len) { if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), _cred->username.whole.s, _cred->username.whole.len, VENDOR(attrs[A_USER_NAME].v))) { LOG(L_ERR, "radius_authorize_sterman(): Unable to add User-Name attribute\n"); goto err; } } else { user_name.len = _cred->username.user.len + _cred->realm.len + 1; user_name.s = pkg_malloc(user_name.len); if (!user_name.s) { LOG(L_ERR, "radius_authorize_sterman(): No memory left\n"); return -3; } memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len); user_name.s[_cred->username.whole.len] = '@'; memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s, _cred->realm.len); if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), user_name.s, user_name.len, VENDOR(attrs[A_USER_NAME].v))) { LOG(L_ERR, "sterman(): Unable to add User-Name attribute\n"); pkg_free(user_name.s); goto err; } pkg_free(user_name.s); } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_USER_NAME].v), _cred->username.whole.s, _cred->username.whole.len, VENDOR(attrs[A_DIGEST_USER_NAME].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-User-Name attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_REALM].v), _cred->realm.s, _cred->realm.len, VENDOR(attrs[A_DIGEST_REALM].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Realm attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE].v), _cred->nonce.s, _cred->nonce.len, VENDOR(attrs[A_DIGEST_NONCE].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Nonce attribute\n"); goto err; } if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) { ruri = &_cred->uri; } else { ruri = GET_RURI(_msg); } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_URI].v), ruri->s, ruri->len, VENDOR(attrs[A_DIGEST_URI].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-URI attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_METHOD].v), method.s, method.len, VENDOR(attrs[A_DIGEST_METHOD].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Method attribute\n"); goto err; } /* * Add the additional authentication fields according to the QOP. */ if (_cred->qop.qop_parsed == QOP_AUTH) { if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth", 4, VENDOR(attrs[A_DIGEST_QOP].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v), _cred->nc.s, _cred->nc.len, VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce-Count attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v), _cred->cnonce.s, _cred->cnonce.len, VENDOR(attrs[A_DIGEST_CNONCE].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n"); goto err; } } else if (_cred->qop.qop_parsed == QOP_AUTHINT) { if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_QOP].v), "auth-int", 8, VENDOR(attrs[A_DIGEST_QOP].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_NONCE_COUNT].v), _cred->nc.s, _cred->nc.len, VENDOR(attrs[A_DIGEST_NONCE_COUNT].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Nonce-Count attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_CNONCE].v), _cred->cnonce.s, _cred->cnonce.len, VENDOR(attrs[A_DIGEST_CNONCE].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_BODY_DIGEST].v), _cred->opaque.s, _cred->opaque.len, VENDOR(attrs[A_DIGEST_BODY_DIGEST].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Body-Digest attribute\n"); goto err; } } else { /* send nothing for qop == "" */ } /* Add the response... What to calculate against... */ if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_DIGEST_RESPONSE].v), _cred->response.s, _cred->response.len, VENDOR(attrs[A_DIGEST_RESPONSE].v))) { LOG(L_ERR, "sterman(): Unable to add Digest-Response attribute\n"); goto err; } /* Indicate the service type, Authenticate only in our case */ service = vals[V_SIP_SESSION].v; if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SERVICE_TYPE].v), &service, -1, VENDOR(attrs[A_SERVICE_TYPE].v))) { LOG(L_ERR, "sterman(): Unable to add Service-Type attribute\n"); goto err; } /* Indicate the service type, Authenticate only in our case */ ser_service_type = vals[V_DIGEST_AUTHENTICATION].v; if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), &ser_service_type, -1, VENDOR(attrs[A_SER_SERVICE_TYPE].v))) { LOG(L_ERR, "sterman(): Unable to add SER-Service-Type attribute\n"); goto err; } /* Add SIP URI as a check item */ if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_USER].v), user.s, user.len, VENDOR(attrs[A_SER_URI_USER].v))) { LOG(L_ERR, "sterman(): Unable to add Sip-URI-User attribute\n"); goto err; } if (attrs[A_CISCO_AVPAIR].n != NULL) { if (add_cisco_vsa(&send, _msg)) { goto err; } } /* Send request */ if ((i = rc_auth(rh, SIP_PORT, send, received, msg)) == OK_RC) { DBG("radius_authorize_sterman(): Success\n"); rc_avpair_free(send); send = 0; return 1; } else { DBG("radius_authorize_sterman(): Failure\n"); goto err; } err: if (send) rc_avpair_free(send); return -1; }
/* create an array of str's for accounting using a formatting string; * this is the heart of the accounting module -- it prints whatever * requested in a way, that can be used for syslog, radius, * sql, whatsoever * tm sip_msg_clones does not clone (shmmem-zed) parsed fields, other then Via1,2. Such fields clone now or use from rq_rp */ static int fmt2rad(char *fmt, struct sip_msg *rq, str* ouri, struct hdr_field *to, unsigned int code, VALUE_PAIR** send, time_t req_time) /* Timestamp of the request */ { static unsigned int cseq_num, src_port, src_ip; static time_t rq_time, rs_time; int cnt; struct to_body* from, *pto; str val, *cr, *at; struct cseq_body *cseq; struct attr* attr; int dir; cnt = 0; dir = -2; /* we don't care about parsing here; either the function * was called from script, in which case the wrapping function * is supposed to parse, or from reply processing in which case * TM should have preparsed from REQUEST_IN callback. */ while(*fmt) { if (cnt == ALL_LOG_FMT_LEN) { LOG(L_ERR, "ERROR:acc:fmt2rad: Formatting string is too long\n"); return 0; } attr = 0; switch(*fmt) { case 'a': /* attr */ at = print_attrs(avps, avps_n, 0); if (at) { attr = &attrs[A_SER_ATTR]; val = *at; } break; case 'c': /* sip_callid */ if (rq->callid && rq->callid->body.len) { attr = &attrs[A_ACCT_SESSION_ID]; val = rq->callid->body; } break; case 'd': /* to_tag */ if (swap_dir && dir == -2) dir = get_direction(rq); if (dir <= 0) { if (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) { attr = &attrs[A_SIP_TO_TAG]; val = pto->tag_value; } } else { if (rq->from && (from = get_from(rq)) && from->tag_value.len) { attr = &attrs[A_SIP_TO_TAG]; val = from->tag_value; } } break; case 'f': /* sip_from */ if (rq->from && rq->from->body.len) { attr = &attrs[A_SER_FROM]; val = rq->from->body; } break; case 'g': /* flags */ attr = &attrs[A_SER_FLAGS]; val.s = (char*)&rq->flags; val.len = sizeof(unsigned int); break; case 'i': /* inbound_ruri */ attr = &attrs[A_SER_ORIGINAL_REQUEST_ID]; val = rq->first_line.u.request.uri; break; case 'm': /* sip_method */ attr = &attrs[A_SIP_METHOD]; val = rq->first_line.u.request.method; break; case 'n': /* sip_cseq */ if (rq->cseq && (cseq = get_cseq(rq)) && cseq->number.len) { attr = &attrs[A_SIP_CSEQ]; str2int(&cseq->number, &cseq_num); val.s = (char*)&cseq_num; val.len = sizeof(unsigned int); } break; case 'o': /* outbound_ruri */ attr = &attrs[A_SIP_TRANSLATED_REQUEST_ID]; val = *ouri; break; case 'p': /* Source IP address */ attr = &attrs[A_SIP_SOURCE_IP_ADDRESS]; src_ip = ntohl(rq->rcv.src_ip.u.addr32[0]); val.s = (char*)&src_ip; val.len = sizeof(src_ip); break; case 'r': /* from_tag */ if (swap_dir && dir == -2) dir = get_direction(rq); if (dir <= 0) { if (rq->from && (from = get_from(rq)) && from->tag_value.len) { attr = &attrs[A_SIP_FROM_TAG]; val = from->tag_value; } } else { if (to && (pto = (struct to_body*)(to->parsed)) && pto->tag_value.len) { attr = &attrs[A_SIP_FROM_TAG]; val = pto->tag_value; } } break; case 's': /* server_id */ attr = &attrs[A_SER_SERVER_ID]; val.s = (char*)&server_id; val.len = sizeof(int); break; case 't': /* sip_to */ if (to && to->body.len) { attr = &attrs[A_SER_TO]; val = to->body; } break; case 'u': /* digest_username */ cr = cred_user(rq); if (cr) { attr = &attrs[A_SER_DIGEST_USERNAME]; val = *cr; } break; case 'x': /* request_timestamp */ attr = &attrs[A_SER_REQUEST_TIMESTAMP]; rq_time = req_time; val.s = (char*)&rq_time; val.len = sizeof(time_t); break; case 'D': /* to_did */ break; case 'F': /* from_uri */ if (swap_dir && dir == -2) dir = get_direction(rq); if (dir <= 0) { if (rq->from && (from = get_from(rq)) && from->uri.len) { attr = &attrs[A_CALLING_STATION_ID]; val = from->uri; } } else { if (rq->to && (pto = get_to(rq)) && pto->uri.len) { attr = &attrs[A_CALLING_STATION_ID]; val = pto->uri; } } break; case 'I': /* from_uid */ if (get_from_uid(&val, rq) < 0) { attr = &attrs[A_SER_FROM_UID]; } break; case 'M': /* from_did */ break; case 'P': /* Source port */ attr = &attrs[A_SIP_SOURCE_PORT]; src_port = rq->rcv.src_port; val.s = (char*)&src_port; val.len = sizeof(unsigned int); break; case 'R': /* digest_realm */ cr = cred_realm(rq); if (cr) { attr = &attrs[A_SER_DIGEST_REALM]; val = *cr; } break; case 'S': /* sip_status */ attr = &attrs[A_SIP_RESPONSE_CODE]; val.s = (char*)&code; val.len = sizeof(unsigned int); break; case 'T': /* to_uri */ if (swap_dir && dir == -2) dir = get_direction(rq); if (dir <= 0) { if (rq->to && (pto = get_to(rq)) && pto->uri.len) { attr = &attrs[A_CALLED_STATION_ID]; val = pto->uri; } } else { if (rq->from && (from = get_from(rq)) && from->uri.len) { attr = &attrs[A_CALLED_STATION_ID]; val = from->uri; } } break; case 'U': /* to_uid */ if (get_from_uid(&val, rq) < 0) { attr = &attrs[A_SER_TO_UID]; } break; case 'X': /* response_timestamp */ attr = &attrs[A_SER_RESPONSE_TIMESTAMP]; rs_time = time(0); val.s = (char*)&rs_time; val.len = sizeof(time_t); break; default: LOG(L_CRIT, "BUG:acc:fmt2rad: unknown char: %c\n", *fmt); return -1; } /* switch (*fmt) */ if (attr) { if (!rc_avpair_add(rh, send, ATTRID(attr->v), val.s, val.len, VENDOR(attr->v))) { LOG(L_ERR, "ERROR:acc:fmt2rad: Failed to add attribute %s\n", attr->n); return -1; } } fmt++; cnt++; } /* while (*fmt) */ return 0; }
/* 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; }