int rc_acct_proxy(VALUE_PAIR *send) { SEND_DATA data; int result; char msg[4096]; int i; SERVER *acctserver = rc_conf_srv("authserver"); int timeout = rc_conf_int("radius_timeout"); int retries = rc_conf_int("radius_retries"); data.send_pairs = send; data.receive_pairs = NULL; result = ERROR_RC; for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC) ; i++) { if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i], acctserver->port[i], timeout, retries); result = rc_send_server (&data, msg, NULL); } rc_avpair_free(data.receive_pairs); return result; }
int rc_acct_using_server(SERVER *acctserver, UINT4 client_port, VALUE_PAIR *send) { SEND_DATA data; VALUE_PAIR *adt_vp; int result; time_t start_time, dtime; char msg[4096]; int i; int timeout = rc_conf_int("radius_timeout"); int retries = rc_conf_int("radius_retries"); data.send_pairs = send; data.receive_pairs = NULL; /* * Fill in NAS-IP-Address or NAS-Identifier */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) return (ERROR_RC); /* * Fill in NAS-Port */ if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL) return (ERROR_RC); /* * Fill in Acct-Delay-Time */ dtime = 0; if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL) return (ERROR_RC); start_time = time(NULL); result = ERROR_RC; for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC) ; i++) { if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i], acctserver->port[i], timeout, retries); dtime = time(NULL) - start_time; rc_avpair_assign(adt_vp, &dtime, 0); result = rc_send_server (&data, msg, NULL); } rc_avpair_free(data.receive_pairs); return result; }
int send_acct_func_async(struct sip_msg* msg, async_resume_module **resume_f, void **resume_param, str *s) { int i, index = -1, res; VALUE_PAIR *send = NULL; SEND_CONTEXT *ctx = 0; struct rad_ctx *rctx; 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 == s->len && !strncmp(sets[i]->set_name.s, s->s, s->len)) index = i; } if (index == -1) { LM_ERR("set not found\n"); return -1; } if (make_send_message(msg, index, &send) < 0) { LM_ERR("make message failed\n"); return -1; } res = rc_acct_async(rh, SIP_PORT, send, &ctx); if (res == OK_RC) { LM_DBG("radius accounting message sent\n"); rctx = pkg_malloc(sizeof(struct rad_ctx)); if (rctx == NULL) { LM_ERR("no pkg mem\n"); if (send) rc_avpair_free(send); return -1; } rctx->send = send; rctx->ctx = ctx; *resume_param = rctx; *resume_f = resume_send_acct; async_status = ctx->sockfd; return 1; } if (send) rc_avpair_free(send); return -1; }
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; }
void free_radius_auth_value_pair(VALUE_PAIR *send, VALUE_PAIR *received, rc_handle *rh) { if (send) rc_avpair_free(send); if (received) rc_avpair_free(received); if (rh) rc_destroy(rh); rh = NULL; }
int process(void *rh, VALUE_PAIR * send, int acct, int nas_port) { VALUE_PAIR *received; char msg[PW_MAX_MSG_SIZE]; char buf[BUF_LEN]; int i, fd; fd = rc_tls_fd(rh); if (fd >= 0) { dup(fd); close(fd); } received = NULL; if (acct == 0) { i = rc_auth(rh, nas_port, send, &received, msg); if (i != OK_RC) { fprintf(stderr, "tls-restart: error sending 1 (ok)\n"); } i = rc_auth(rh, nas_port, send, &received, msg); if (i != OK_RC) { fprintf(stderr, "tls-restart: error sending 2\n"); exit(2); } if (received != NULL) { printf("%s", rc_avpair_log(rh, received, buf, BUF_LEN)); rc_avpair_free(received); } } else { i = rc_acct(rh, nas_port, send); } return (i == OK_RC) ? 0 : 1; }
static void radius_log(struct ast_event *event) { int result = ERROR_RC; VALUE_PAIR *send = NULL; struct ast_cel_event_record record = { .version = AST_CEL_EVENT_RECORD_VERSION, }; if (ast_cel_fill_record(event, &record)) { return; } if (build_radius_record(&send, &record)) { ast_debug(1, "Unable to create RADIUS record. CEL not recorded!\n"); goto return_cleanup; } result = rc_acct(rh, 0, send); if (result != OK_RC) { ast_log(LOG_ERROR, "Failed to record Radius CEL record!\n"); } return_cleanup: if (send) { rc_avpair_free(send); } }
int rc_check(char *host, unsigned short port, char *msg) { SEND_DATA data; int result; UINT4 service_type; int timeout = rc_conf_int("radius_timeout"); int retries = rc_conf_int("radius_retries"); data.send_pairs = data.receive_pairs = NULL; /* * Fill in NAS-IP-Address or NAS-Identifier, * although it isn't neccessary */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) return (ERROR_RC); /* * Fill in Service-Type */ service_type = PW_ADMINISTRATIVE; rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE); rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries); result = rc_send_server (&data, msg, NULL); rc_avpair_free(data.receive_pairs); return result; }
/** Asks the server hostname on the specified port for a status message * * @param rh a handle to parsed configuration. * @param host the name of the server. * @param secret the secret used by the server. * @param port the server's port number. * @param msg must be an array of PW_MAX_MSG_SIZE or NULL; will contain the concatenation of any * PW_REPLY_MESSAGE received. * @return OK_RC (0) on success, negative on failure as return value. */ int rc_check(rc_handle *rh, char *host, char *secret, unsigned short port, char *msg) { SEND_DATA data; int result; uint32_t service_type; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); rc_type type; data.send_pairs = data.receive_pairs = NULL; if (rh->so_type == RC_SOCKET_TLS || rh->so_type == RC_SOCKET_DTLS) type = AUTH; else type = ACCT; /* * Fill in Service-Type */ service_type = PW_ADMINISTRATIVE; rc_avpair_add(rh, &(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, 0); rc_buildreq(rh, &data, PW_STATUS_SERVER, host, port, secret, timeout, retries); result = rc_send_server (rh, &data, msg, type); rc_avpair_free(data.receive_pairs); return result; }
/* 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_acct(int fd, struct sip_msg *msg, void *param) { int res, retval; struct rad_ctx *rctx; rctx = (struct rad_ctx *)param; if (rctx == NULL) { LM_ERR("no context given\n"); return -1; } res = rc_acct_resume(&rctx->ctx); if (res == OK_RC || res == REJECT_RC) { async_status = ASYNC_DONE; retval = 1; } else if (res == READBLOCK_RC) { async_status = ASYNC_CONTINUE; retval = 1; goto exit; } else { LM_ERR("radius authentication message failed with %s\n", ((res==BADRESP_RC)?"BAD REPLY":"ERROR")); retval = -1; } if (rctx->send) rc_avpair_free(rctx->send); pkg_free(rctx); exit: return retval; }
int process(void *rh, VALUE_PAIR *send, int acct, int nas_port, int send_info) { VALUE_PAIR *received = NULL; char buf[BUF_LEN]; RC_AAA_CTX *ctx = NULL; const unsigned char *p; int i, j; received = NULL; if (acct == 0) { i = rc_aaa_ctx(rh, &ctx, nas_port, send, &received, NULL, 1, PW_ACCESS_REQUEST); if (received != NULL) { printf("%s", rc_avpair_log(rh, received, buf, BUF_LEN)); rc_avpair_free(received); } if (ctx) { if (send_info) { printf("Request-Info-Secret = %s\n", rc_aaa_ctx_get_secret(ctx)); printf("Request-Info-Vector = "); p = rc_aaa_ctx_get_vector(ctx); for (j=0; j<AUTH_VECTOR_LEN; j++) { printf("%.2x", (unsigned)p[j]); } printf("\n"); } rc_aaa_ctx_free(ctx); } } else { i = rc_acct(rh, nas_port, send); } return (i == OK_RC) ? 0 : 1; }
switch_status_t mod_xml_radius_accounting_end(switch_core_session_t *session){ VALUE_PAIR *send = NULL; uint32_t service = PW_STATUS_STOP; rc_handle *new_handle = NULL; switch_xml_t fields = NULL, conditions = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); if (GLOBAL_DEBUG ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting stop\n"); switch_core_session_execute_application(session, "info", NULL); } /* If there are conditions defined, and none of them pass, then skip this accounting */ if ((conditions = switch_xml_child(globals.acct_start_configs, "conditions")) != NULL && mod_xml_radius_check_conditions(channel, conditions) != SWITCH_STATUS_SUCCESS ) { goto end; } if ( mod_xml_radius_new_handle(&new_handle, globals.acct_end_configs) != SWITCH_STATUS_SUCCESS || new_handle == NULL ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new accounting_end handle for call: %s\n", switch_channel_get_variable(channel, "uuid")); goto end; } if ((fields = switch_xml_child(globals.acct_end_configs, "fields")) == NULL ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n"); goto end; } if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n"); goto end; } if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n"); goto end; } if (rc_acct(new_handle, 0, send) == OK_RC) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius: Accounting Stop success\n"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: Accounting Stop failed\n"); } end: if ( send ) { rc_avpair_free(send); send = NULL; } if ( new_handle) { rc_destroy(new_handle); new_handle = NULL; } return SWITCH_STATUS_SUCCESS; }
/* 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; }
/* Radius implementation for the destroy_aaa_message callback */ int rad_destroy_message(aaa_conn* rh, aaa_message* message) { if (!rh || ! message) { LM_ERR("invalid arguments\n"); return -1; } rc_avpair_free((VALUE_PAIR*) message->avpair); pkg_free(message); return 0; }
/* * Check from Radius if request URI belongs to a local user. * User-Name is user@host of request Uri and Service-Type is Call-Check. */ int radius_does_uri_exist(struct sip_msg* _m, char* _s1, char* _s2) { static char msg[4096]; VALUE_PAIR *send, *received; UINT4 service; char* at, *uri; send = received = 0; if (parse_sip_msg_uri(_m) < 0) { LM_ERR("parsing URI failed\n"); return -1; } uri = (char*)pkg_malloc(_m->parsed_uri.user.len + _m->parsed_uri.host.len + 2); if (!uri) { LM_ERR("no more pkg memory\n"); return -2; } at = uri; memcpy(at, _m->parsed_uri.user.s, _m->parsed_uri.user.len); at += _m->parsed_uri.user.len; *at = '@'; at++; memcpy(at , _m->parsed_uri.host.s, _m->parsed_uri.host.len); at += _m->parsed_uri.host.len; *at = '\0'; if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, uri, -1, 0)) { LM_ERR("adding User-Name failed\n"); rc_avpair_free(send); pkg_free(uri); return -3; } service = vals[V_CALL_CHECK].v; if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("adding service type failed\n"); rc_avpair_free(send); pkg_free(uri); return -4; } if (rc_auth(rh, 0, send, &received, msg) == OK_RC) { LM_DBG("success\n"); rc_avpair_free(send); generate_avps(received); rc_avpair_free(received); pkg_free(uri); return 1; } else { LM_DBG("failure\n"); rc_avpair_free(send); rc_avpair_free(received); pkg_free(uri); return -5; } }
int send_acct_func(struct sip_msg* msg, str *s) { int i, index = -1; VALUE_PAIR *send = 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 == s->len && !strncmp(sets[i]->set_name.s, s->s, s->len)) index = i; } if (index == -1) { LM_ERR("set not found\n"); return -1; } if (make_send_message(msg, index, &send) < 0) { LM_ERR("make message failed\n"); return -1; } if (rc_acct(rh, SIP_PORT, send) != OK_RC){ if (send) rc_avpair_free(send); LM_ERR("radius accounting message failed to send\n"); return -1; } if (send) rc_avpair_free(send); return 1; }
int rc_auth_using_server(SERVER *authserver, UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, REQUEST_INFO *info) { SEND_DATA data; int result; int i; int timeout = rc_conf_int("radius_timeout"); int retries = rc_conf_int("radius_retries"); data.send_pairs = send; data.receive_pairs = NULL; /* * Fill in NAS-IP-Address or NAS-Identifier */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) return (ERROR_RC); /* * Fill in NAS-Port */ if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL) return (ERROR_RC); result = ERROR_RC; for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC) ; i++) { if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i], authserver->port[i], timeout, retries); result = rc_send_server (&data, msg, info); } *received = data.receive_pairs; return result; }
/** * Perform authenticate request. * @param[in] radh Radius handle. * @param[out] reply_attr Reply attributes. * @param[in,out] reply_msg Reply message. * @return One of ZRAD_* codes. */ static zrad_status_t zrad_auth_request(rc_handle *radh, const zrad_auth_req_t *req, VALUE_PAIR **reply_attrs, char *reply_msg) { zrad_status_t ret = ZRAD_OTHER; VALUE_PAIR *request_attrs = NULL; int success = rc_avpair_add(radh, &request_attrs, PW_USER_NAME, req->username, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_USER_PASSWORD, req->password, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_NAS_IDENTIFIER, req->nas_id, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_CALLING_STATION_ID, req->calling_station_id, -1, 0); if (likely(success)) { ret = (zrad_status_t) rc_auth(radh, 0, request_attrs, reply_attrs, reply_msg); } if (likely(request_attrs)) { rc_avpair_free(request_attrs); } return ret; }
static int radius_log(struct ast_cdr *cdr) { int result = ERROR_RC; VALUE_PAIR *tosend = NULL; if (build_radius_record(&tosend, cdr)) { ast_debug(1, "Unable to create RADIUS record. CDR not recorded!\n"); goto return_cleanup; } result = rc_acct(rh, 0, tosend); if (result != OK_RC) { ast_log(LOG_ERROR, "Failed to record Radius CDR record!\n"); } return_cleanup: if (tosend) { rc_avpair_free(tosend); } return result; }
static void radius_log(struct ast_event *event) { int result = ERROR_RC; VALUE_PAIR *send = NULL; int ret = 0; char cdr_full_path[256]; struct ast_cel_event_record record = { .version = AST_CEL_EVENT_RECORD_VERSION, }; if (ast_cel_fill_record(event, &record)) { return; } if (build_radius_record(&send, &record)) { ast_debug(1, "Unable to create RADIUS record. CEL not recorded!\n"); goto return_cleanup; } result = rc_acct(rh, 0, send); if (result != OK_RC) { ast_log(LOG_ERROR, "Failed to record Radius CEL record! unique_id=%s\n", record.unique_id); /* file name */ if(record.unique_id && (!ast_strlen_zero(record.unique_id))){ snprintf(cdr_full_path,sizeof(cdr_full_path),"%s/%s",cdr_dir_tmp,record.unique_id); /* write cdr to file if rc_acct failed */ ret = save_avp_to_file(cdr_full_path,record.unique_id,send); if(!ret){ ast_log(LOG_ERROR,"Failed to write cdr to file! unique_id=%s\n", record.unique_id); } } goto return_cleanup; } return_cleanup: if (send) { rc_avpair_free(send); } }
/** * Authenticate and set client info. * @param[in] session Client session. * @return Zero on success. */ zrad_status_t zradius_session_auth(zscope_t *scope, zsession_t *session) { zrad_status_t ret; VALUE_PAIR *reply_attrs = NULL; char reply_msg[PW_MAX_MSG_SIZE] = {0}; zclient_rules_t rules; zclient_rules_init(&rules); zrad_auth_req_t req; zrad_auth_prepare(scope, session, &req); ret = zrad_auth_request(scope->radh, &req, &reply_attrs, reply_msg); if (unlikely(ZRAD_OK != ret)) { str_rtrim(reply_msg); ZLOG(LOG_ERR, "%s: Session authentication failed for %s (code: %s, msg: %s)", scope->cfg->name, session->ip_str, zrad_decode_state(ret), reply_msg); goto end; } zrad_auth_parse(session, reply_attrs, &rules); if (unlikely(!rules.have.user_id || !rules.have.login)) { ZLOG(LOG_ERR, "%s: Session authentication failed for %s (login or user_id not found)", scope->cfg->name, session->ip_str); ret = ZRAD_OTHER; goto end; } zscope_session_rules_apply(scope, session, &rules); zrad_auth_log(scope, session, reply_attrs); end: zclient_rules_destroy(&rules); if (likely(reply_attrs)) rc_avpair_free(reply_attrs); return ret; }
/** Get a sequence of attribute value pairs from the file input and make them into a list of value_pairs * * @param rh a handle to parsed configuration. * @param input a %FILE handle. * @return the array of value pairs. */ VALUE_PAIR *rc_avpair_readin(rc_handle const *rh, FILE *input) { VALUE_PAIR *vp = NULL; char buffer[1024], *q; while (fgets(buffer, sizeof(buffer), input) != NULL) { q = buffer; while(*q && isspace(*q)) q++; if ((*q == '\n') || (*q == '#') || (*q == '\0')) continue; if (rc_avpair_parse(rh, q, &vp) < 0) { rc_log(LOG_ERR, "rc_avpair_readin: malformed attribute: %s", buffer); rc_avpair_free(vp); return NULL; } } return vp; }
/** * @param[in] session Session * @param[in] status Accounting status (PW_STATUS_START, PW_STATUS_STOP, PW_STATUS_ALIVE) * @param[in] cause Accounting termination cause (used only in case of PW_STATUS_STOP) * @param[in] req Accounting request data. */ static zrad_status_t zrad_acct_request(rc_handle *radh, const zrad_acct_req_t *req) { zrad_status_t ret; VALUE_PAIR *request_attrs = NULL; int success = rc_avpair_add(radh, &request_attrs, PW_CALLING_STATION_ID, req->calling_station_id, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_AUTHENTIC, &req->authentic, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_FRAMED_IP_ADDRESS, &req->framed_ip_addr, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_USER_NAME, req->username, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_SESSION_ID, req->session_id, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_NAS_IDENTIFIER, req->nas_id, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_INPUT_OCTETS, &req->octets_down, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_INPUT_PACKETS, &req->packets_down, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_OUTPUT_OCTETS, &req->octets_up, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_OUTPUT_PACKETS, &req->packets_down, -1, 0) && (!req->gigawords_down || rc_avpair_add(radh, &request_attrs, PW_ACCT_OUTPUT_GIGAWORDS, &req->gigawords_up, -1, 0)) && (!req->gigawords_down || rc_avpair_add(radh, &request_attrs, PW_ACCT_INPUT_GIGAWORDS, &req->gigawords_down, -1, 0)) && rc_avpair_add(radh, &request_attrs, PW_ACCT_STATUS_TYPE, &req->status, -1, 0); if (success && PW_STATUS_STOP == req->status) { success = success && rc_avpair_add(radh, &request_attrs, PW_ACCT_SESSION_TIME, &req->session_time, -1, 0) && rc_avpair_add(radh, &request_attrs, PW_ACCT_TERMINATE_CAUSE, &req->term_cause, -1, 0); } if (likely(success)) { ret = (zrad_status_t) rc_acct(radh, 0, request_attrs); } else { ret = ZRAD_OTHER; } if (likely(request_attrs)) rc_avpair_free(request_attrs); return ret; }
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; }
/* * 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(struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user, str* _rpid) { static char msg[4096]; VALUE_PAIR *send, *received, *vp; UINT4 service; str method, user, user_name, callid; int i; send = received = 0; if (!(_cred && _method && _user && _rpid)) { 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, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) { LOG(L_ERR, "sterman(): Unable to add User-Name attribute\n"); rc_avpair_free(send); return -2; } } 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, attrs[A_USER_NAME].v, user_name.s, user_name.len, 0)) { LOG(L_ERR, "sterman(): Unable to add User-Name attribute\n"); pkg_free(user_name.s); rc_avpair_free(send); return -4; } pkg_free(user_name.s); } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-User-Name attribute\n"); rc_avpair_free(send); return -5; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_REALM].v, _cred->realm.s, _cred->realm.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Realm attribute\n"); rc_avpair_free(send); return -6; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE].v, _cred->nonce.s, _cred->nonce.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Nonce attribute\n"); rc_avpair_free(send); return -7; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_URI].v, _cred->uri.s, _cred->uri.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-URI attribute\n"); rc_avpair_free(send); return -8; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_METHOD].v, method.s, method.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Method attribute\n"); rc_avpair_free(send); return -9; } /* * Add the additional authentication fields according to the QOP. */ if (_cred->qop.qop_parsed == QOP_AUTH) { if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth", 4, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n"); rc_avpair_free(send); return -10; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, _cred->nc.s, _cred->nc.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce-Count attribute\n"); rc_avpair_free(send); return -11; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, _cred->cnonce.s, _cred->cnonce.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n"); rc_avpair_free(send); return -12; } } else if (_cred->qop.qop_parsed == QOP_AUTHINT) { if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth-int", 8, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-QOP attribute\n"); rc_avpair_free(send); return -13; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, _cred->nc.s, _cred->nc.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Nonce-Count attribute\n"); rc_avpair_free(send); return -14; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, _cred->cnonce.s, _cred->cnonce.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-CNonce attribute\n"); rc_avpair_free(send); return -15; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_BODY_DIGEST].v, _cred->opaque.s, _cred->opaque.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Body-Digest attribute\n"); rc_avpair_free(send); return -16; } } else { /* send nothing for qop == "" */ } /* Add the response... What to calculate against... */ if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_RESPONSE].v, _cred->response.s, _cred->response.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Digest-Response attribute\n"); rc_avpair_free(send); return -17; } /* Indicate the service type, Authenticate only in our case */ service = vals[V_SIP_SESSION].v; if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LOG(L_ERR, "sterman(): Unable to add Service-Type attribute\n"); rc_avpair_free(send); return -18; } /* Add SIP URI as a check item */ if (!rc_avpair_add(rh, &send, attrs[A_SIP_URI_USER].v, user.s, user.len, 0)) { LOG(L_ERR, "sterman(): Unable to add Sip-URI-User attribute\n"); rc_avpair_free(send); return -19; } if (attrs[A_CISCO_AVPAIR].n != NULL) { /* Add SIP Call-ID as a Cisco VSA, like IOS does */ if (_msg->callid == NULL || _msg->callid->body.s == NULL) { LOG(L_ERR, "sterman(): Call-ID is missed\n"); rc_avpair_free(send); return -20; } callid.len = _msg->callid->body.len + 8; callid.s = alloca(callid.len); if (callid.s == NULL) { LOG(L_ERR, "sterman(): No memory left\n"); rc_avpair_free(send); return -21; } memcpy(callid.s, "call-id=", 8); memcpy(callid.s + 8, _msg->callid->body.s, _msg->callid->body.len); if (rc_avpair_add(rh, &send, attrs[A_CISCO_AVPAIR].v, callid.s, callid.len, VENDOR(attrs[A_CISCO_AVPAIR].v)) == 0) { LOG(L_ERR, "sterman(): Unable to add Cisco-AVPair attribute\n"); rc_avpair_free(send); return -22; } } /* Send request */ if ((i = rc_auth(rh, SIP_PORT, send, &received, msg)) == OK_RC) { DBG("radius_authorize_sterman(): Success\n"); rc_avpair_free(send); /* Make a copy of rpid if available */ if ((vp = rc_avpair_get(received, attrs[A_SIP_RPID].v, 0))) { if (MAX_RPID_LEN < vp->lvalue) { LOG(L_ERR, "radius_authorize_sterman(): rpid buffer too small\n"); return -23; } memcpy(_rpid->s, vp->strvalue, vp->lvalue); _rpid->len = vp->lvalue; } rc_avpair_free(received); return 1; } else { DBG("res: %d\n", i); DBG("radius_authorize_sterman(): Failure\n"); rc_avpair_free(send); rc_avpair_free(received); return -24; } }
/** * Authenticate and set client info. * @param[in] sess Client session. * @return Zero on success (or one of *_RC). */ static int session_authenticate(struct zsession *sess) { int ret = OTHER_RC; VALUE_PAIR *request_attrs = NULL, *response_attrs = NULL, *attrs = NULL; char msg[8192]; // WARNING: libfreeradius-client has unsafe working with this buffer. rc_handle *rh = zinst()->radh; struct in_addr ip_addr; char ip_str[INET_ADDRSTRLEN]; struct zcrules rules; crules_init(&rules); ip_addr.s_addr = htonl(sess->ip); if (unlikely(NULL == inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_USER_NAME, ip_str, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_USER_PASSWORD, "", -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_NAS_IDENTIFIER, zcfg()->radius_nas_identifier, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_CALLING_STATION_ID, ip_str, -1, 0))) { goto end; } ret = rc_auth(rh, 0, request_attrs, &response_attrs, msg); if (OK_RC != ret) { ZERO_LOG(LOG_ERR, "Session authentication failed for %s (code:%d)", ip_str, ret); goto end; } attrs = response_attrs; while (likely(NULL != attrs)) { switch (attrs->attribute) { case PW_FILTER_ID: crules_parse(&rules, attrs->strvalue); break; case PW_SESSION_TIMEOUT: atomic_store_explicit(&sess->max_duration, SEC2USEC(attrs->lvalue), memory_order_release); break; case PW_ACCT_INTERIM_INTERVAL: atomic_store_explicit(&sess->acct_interval, SEC2USEC(attrs->lvalue), memory_order_release); break; } attrs = attrs->next; } if (likely(rules.have.user_id && rules.have.login)) { struct zclient *client = sess->client; client_db_find_or_set_id(zinst()->client_db, rules.user_id, &client); if (client != sess->client) { // found pthread_rwlock_wrlock(&sess->lock_client); atomic_fetch_add_explicit(&client->refcnt, 1, memory_order_relaxed); client_release(sess->client); sess->client = client; client_session_add(sess->client, sess); pthread_rwlock_unlock(&sess->lock_client); } else { client_apply_rules(sess->client, &rules); } atomic_fetch_sub_explicit(&zinst()->unauth_sessions_cnt, 1, memory_order_release); // log successful authentication { UT_string rules_str; utstring_init(&rules_str); utstring_reserve(&rules_str, 1024); attrs = response_attrs; while (likely(NULL != attrs)) { switch (attrs->attribute) { case PW_FILTER_ID: utstring_printf(&rules_str, " %s", attrs->strvalue); break; default: break; } attrs = attrs->next; } zero_syslog(LOG_INFO, "Authenticated session %s (rules:%s)", ip_str, utstring_body(&rules_str)); utstring_done(&rules_str); } } else { ret = OTHER_RC; ZERO_LOG(LOG_ERR, "Session authentication failed for %s (code:%d)", ip_str, ret); } end: crules_free(&rules); if (request_attrs) rc_avpair_free(request_attrs); if (response_attrs) rc_avpair_free(response_attrs); return ret; }
/** * Send radius accounting packet. * @param[in] sess Session * @param[in] status Accounting status (PW_STATUS_START, PW_STATUS_STOP, PW_STATUS_ALIVE) * @param[in] cause Accounting termination cause (used only in case of PW_STATUS_STOP) * @return Zero on success (one of *_RC codes). */ static int session_accounting(struct zsession *sess, uint32_t status, uint32_t term_cause) { int ret = OTHER_RC; VALUE_PAIR *request_attrs = NULL; rc_handle *rh = zinst()->radh; struct in_addr ip_addr; char ip_str[INET_ADDRSTRLEN]; uint64_t traff_down = atomic_load_explicit(&sess->traff_down, memory_order_acquire); uint64_t traff_up = atomic_load_explicit(&sess->traff_up, memory_order_acquire); uint32_t octets_down = (uint32_t) (traff_down % UINT32_MAX); uint32_t octets_up = (uint32_t) (traff_up % UINT32_MAX); uint32_t packets_down = atomic_load_explicit(&sess->packets_down, memory_order_acquire) % UINT32_MAX; uint32_t packets_up = atomic_load_explicit(&sess->packets_up, memory_order_acquire) % UINT32_MAX; uint32_t gigawords_down = 0; uint32_t gigawords_up = 0; char session_id[255]; snprintf(session_id, sizeof(session_id), "%s-%" PRIu32, sess->client->login, sess->ip); ip_addr.s_addr = htonl(sess->ip); if (unlikely(NULL == inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_CALLING_STATION_ID, ip_str, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_FRAMED_IP_ADDRESS, &sess->ip, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_USER_NAME, sess->client->login, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_SESSION_ID, session_id, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_NAS_IDENTIFIER, zcfg()->radius_nas_identifier, -1, 0))) { goto end; } if (PW_STATUS_STOP == status) { if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_TERMINATE_CAUSE, &term_cause, -1, 0))) { goto end; } } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_STATUS_TYPE, &status, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_INPUT_OCTETS, &octets_down, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_INPUT_PACKETS, &packets_down, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_OUTPUT_OCTETS, &octets_up, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_OUTPUT_PACKETS, &packets_down, -1, 0))) { goto end; } if (unlikely(UINT32_MAX < traff_down)) { gigawords_down = (uint32_t) (traff_down / UINT32_MAX); if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_INPUT_GIGAWORDS, &gigawords_down, -1, 0))) { goto end; } } if (unlikely(UINT32_MAX < traff_up)) { gigawords_up = (uint32_t) (traff_up / UINT32_MAX); if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_ACCT_OUTPUT_GIGAWORDS, &gigawords_up, -1, 0))) { goto end; } } ret = rc_acct(rh, 0, request_attrs); if (unlikely(OK_RC != ret)) { ZERO_LOG(LOG_ERR, "radius accounting failed %s (code:%d)", ip_str, ret); goto end; } atomic_fetch_sub_explicit(&sess->traff_down, traff_down, memory_order_release); atomic_fetch_sub_explicit(&sess->traff_up, traff_up, memory_order_release); atomic_fetch_sub_explicit(&sess->packets_down, packets_down, memory_order_release); atomic_fetch_sub_explicit(&sess->packets_up, packets_up, memory_order_release); end: if (request_attrs) { rc_avpair_free(request_attrs); } return ret; }
/* * Check from Radius if URI user given as argument belongs to a local user. * If so, loads AVPs based on reply items returned from Radius. */ int radius_does_uri_user_exist(struct sip_msg* _m, str user) { static char msg[4096]; VALUE_PAIR *send, *received; uint32_t service; int res, extra_cnt, offset, i; send = received = 0; if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v, user.s, user.len, 0)) { LM_ERR("in adding SA_USER_NAME\n"); return -1; } service = uri_vals[UV_CALL_CHECK].v; if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service); goto error; } /* Add extra attributes */ extra_cnt = extra2strar(uri_extra, _m, val_arr); if (extra_cnt == -1) { LM_ERR("in getting values of group extra attributes\n"); goto error; } offset = SA_STATIC_MAX; for (i = 0; i < extra_cnt; i++) { if (val_arr[i].len == -1) { /* Add integer attribute */ ADD_EXTRA_AVPAIR(uri_attrs, offset+i, &(val_arr[i].s), val_arr[i].len ); } else { /* Add string attribute */ ADD_EXTRA_AVPAIR(uri_attrs, offset+i, val_arr[i].s, val_arr[i].len ); } } if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) { LM_DBG("success\n"); rc_avpair_free(send); generate_avps(uri_attrs, received); rc_avpair_free(received); return 1; } else { rc_avpair_free(send); rc_avpair_free(received); #ifdef REJECT_RC if (res == REJECT_RC) { LM_DBG("rejected\n"); return -1; } else { LM_ERR("failure\n"); return -2; } #else LM_DBG("failure\n"); return -1; #endif } error: rc_avpair_free(send); return -1; }
/* * Check from Radius if URI, whose user and host parts are given as * arguments, exists. If so, loads AVPs based on reply items returned * from Radius. If use_sip_uri_host module parameter has non-zero value, * user is send in SA_USER_NAME attribute and host in SA_SIP_URI_HOST * attribute. If is has zero value, user@host is send in SA_USER_NAME * attribute. */ int radius_does_uri_user_host_exist(struct sip_msg* _m, str user, str host) { char* at, *user_host; VALUE_PAIR *send, *received; uint32_t service; static char msg[4096]; int extra_cnt, offset, i, res; send = received = 0; user_host = 0; if (!use_sip_uri_host) { /* Send user@host in SA_USER_NAME attr */ user_host = (char*)pkg_malloc(user.len + host.len + 2); if (!user_host) { LM_ERR("no more pkg memory\n"); return -1; } at = user_host; memcpy(at, user.s, user.len); at += user.len; *at = '@'; at++; memcpy(at , host.s, host.len); at += host.len; *at = '\0'; if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v, user_host, -1, 0)) { LM_ERR("in adding SA_USER_NAME\n"); pkg_free(user_host); return -1; } } else { /* Send user in SA_USER_NAME attribute and host in SA_SIP_URI_HOST attribute */ if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v, user.s, user.len, 0)) { LM_ERR("adding User-Name failed\n"); return -1; } if (!rc_avpair_add(rh, &send, uri_attrs[SA_SIP_URI_HOST].v, host.s, host.len, 0)) { LM_ERR("adding SIP-URI-Host failed\n"); goto error; } } service = uri_vals[UV_CALL_CHECK].v; if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service); goto error; } /* Add extra attributes */ extra_cnt = extra2strar(uri_extra, _m, val_arr); if (extra_cnt == -1) { LM_ERR("in getting values of group extra attributes\n"); goto error; } offset = SA_STATIC_MAX; for (i = 0; i < extra_cnt; i++) { if (val_arr[i].len == -1) { /* Add integer attribute */ ADD_EXTRA_AVPAIR(uri_attrs, offset+i, &(val_arr[i].s), val_arr[i].len ); } else { /* Add string attribute */ ADD_EXTRA_AVPAIR(uri_attrs, offset+i, val_arr[i].s, val_arr[i].len ); } } if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) { LM_DBG("success\n"); if (user_host) pkg_free(user_host); rc_avpair_free(send); generate_avps(uri_attrs, received); rc_avpair_free(received); return 1; } else { if (user_host) pkg_free(user_host); rc_avpair_free(send); rc_avpair_free(received); #ifdef REJECT_RC if (res == REJECT_RC) { LM_DBG("rejected\n"); return -1; } else { LM_ERR("failure\n"); return -2; } #else LM_DBG("failure\n"); return -1; #endif } error: rc_avpair_free(send); if (user_host) pkg_free(user_host); return -1; }
/* * Check from Radius if a user belongs to a group. User-Name is given in * first string argment that may contain pseudo variables. SIP-Group is * given in second string variable that may not contain pseudo variables. * Service-Type is Group-Check. */ int radius_is_user_in(struct sip_msg* _m, char* _user, char* _group) { str user, *group; VALUE_PAIR *send, *received; uint32_t service; static char msg[4096]; int extra_cnt, offset, i, res; send = received = 0; if ((_user == NULL) || (fixup_get_svalue(_m, (gparam_p)_user, &user) != 0)) { LM_ERR("invalid user parameter"); return -1; } if (!rc_avpair_add(rh, &send, group_attrs[SA_USER_NAME].v, user.s, user.len, 0)) { LM_ERR("in adding SA_USER_NAME\n"); return -1; } group = (str*)_group; if ((group == NULL) || (group->len == 0)) { LM_ERR("invalid group parameter"); goto error; } if (!rc_avpair_add(rh, &send, group_attrs[SA_SIP_GROUP].v, group->s, group->len, 0)) { LM_ERR("in adding SA_SIP_GROUP\n"); goto error; } service = group_vals[GV_GROUP_CHECK].v; if (!rc_avpair_add(rh, &send, group_attrs[SA_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service); goto error; } /* Add extra attributes */ extra_cnt = extra2strar(group_extra, _m, val_arr); if (extra_cnt == -1) { LM_ERR("in getting values of group extra attributes\n"); goto error; } offset = SA_STATIC_MAX; for (i = 0; i < extra_cnt; i++) { if (val_arr[i].len == -1) { /* Add integer attribute */ ADD_EXTRA_AVPAIR(group_attrs, offset+i, &(val_arr[i].s), val_arr[i].len ); } else { /* Add string attribute */ ADD_EXTRA_AVPAIR(group_attrs, offset+i, val_arr[i].s, val_arr[i].len ); } } if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) { LM_DBG("success\n"); rc_avpair_free(send); generate_avps(group_attrs, received); rc_avpair_free(received); return 1; } else { rc_avpair_free(send); rc_avpair_free(received); #ifdef REJECT_RC if (res == REJECT_RC) { LM_DBG("rejected\n"); return -1; } else { LM_ERR("failure\n"); return -2; } #else LM_DBG("failure\n"); return -1; #endif } error: rc_avpair_free(send); return -1; }