int acc_log_request( struct sip_msg *rq) { static char log_msg[MAX_SYSLOG_SIZE]; static char *log_msg_end=log_msg+MAX_SYSLOG_SIZE-2; char *p; int n; int m; int i; /* get default values */ m = core2strar( rq, val_arr, int_arr, type_arr); /* get extra values */ m += extra2strar( log_extra, rq, val_arr+m, int_arr+m, type_arr+m); for ( i=0,p=log_msg ; i<m ; i++ ) { if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) { LM_WARN("acc message too long, truncating..\n"); p = log_msg_end; break; } *(p++) = A_SEPARATOR_CHR; memcpy(p, log_attrs[i].s, log_attrs[i].len); p += log_attrs[i].len; *(p++) = A_EQ_CHR; memcpy(p, val_arr[i].s, val_arr[i].len); p += val_arr[i].len; } /* get per leg attributes */ if ( leg_info ) { n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m, 1); do { for (i=m; i<m+n; i++) { if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) { LM_WARN("acc message too long, truncating..\n"); p = log_msg_end; break; } *(p++) = A_SEPARATOR_CHR; memcpy(p, log_attrs[i].s, log_attrs[i].len); p += log_attrs[i].len; *(p++) = A_EQ_CHR; memcpy(p, val_arr[i].s, val_arr[i].len); p += val_arr[i].len; } }while (p!=log_msg_end && (n=legs2strar(leg_info,rq,val_arr+m, int_arr+m,type_arr+m, 0))!=0); } /* terminating line */ *(p++) = '\n'; *(p++) = 0; LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu%s", acc_env.text.len, acc_env.text.s,(unsigned long) acc_env.ts, log_msg); return 1; }
/* gets extra values from dlg and stores them into val_arr array */ static int prebuild_extra_arr(struct dlg_cell *dlg, struct sip_msg *msg, str *buffer, str *type_str, struct acc_extra * extra, int start) { short extra_len; if (!start || !type_str || !buffer) { LM_ERR("invalid parameters\n"); return -1; } buffer->len = 0; buffer->s = 0; /* fetching extra string values */ if (dlg_api.fetch_dlg_value(dlg, type_str, buffer, 1) < 0) { LM_ERR("cannot fetch core string value\n"); return -1; } extra_len = GET_LEN(buffer->s); buffer->len = 2; complete_dlg_values(buffer, val_arr + start, extra_len); start += extra_len; /* populate the extra from bye */ return start + extra2strar(extra, msg, NULL, val_arr + start, 1); }
int acc_db_request( struct sip_msg *rq, struct sip_msg *rpl, query_list_t **ins_list) { static db_ps_t my_ps_ins = NULL; static db_ps_t my_ps = NULL; int m; int n; int i; /* formated database columns */ m = core2strar( rq, val_arr ); for(i = 0; i < m; i++) VAL_STR(db_vals+i) = val_arr[i]; /* time value */ VAL_TIME(db_vals+(m++)) = acc_env.ts; /* extra columns */ m += extra2strar( db_extra, rq, rpl, val_arr+m, 0); for( i++; i < m; i++) VAL_STR(db_vals+i) = val_arr[i]; acc_dbf.use_table(db_handle, &acc_env.text/*table*/); CON_PS_REFERENCE(db_handle) = ins_list? &my_ps_ins : &my_ps; /* multi-leg columns */ if ( !leg_info ) { if (con_set_inslist(&acc_dbf,db_handle,ins_list,db_keys,m) < 0 ) CON_RESET_INSLIST(db_handle); if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) { LM_ERR("failed to insert into database\n"); return -1; } } else { n = legs2strar(leg_info,rq,val_arr+m,1); do { for ( i = m; i < m + n; i++) VAL_STR(db_vals+i)=val_arr[i]; if (con_set_inslist(&acc_dbf,db_handle,ins_list,db_keys,m+n) < 0 ) CON_RESET_INSLIST(db_handle); if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) { LM_ERR("failed to insert into database\n"); return -1; } }while ( (n = legs2strar(leg_info,rq,val_arr+m,0))!=0 ); } return 1; }
/* builds extra values string */ static int build_extra_dlg_values(struct acc_extra *extra, struct dlg_cell *dlg,struct sip_msg *req, struct sip_msg *reply) { str val_arr[MAX_ACC_EXTRA]; int nr, i; cdr_buf.len = 2; nr = extra2strar(extra, req, reply, val_arr, 0); for (i=0; i<nr; i++) if (set_dlg_value(&val_arr[i]) < 0) return -1; SET_LEN(cdr_buf.s, nr); return nr; }
int acc_db_request( struct sip_msg *rq) { int m; int n; int i; /* formated database columns */ m = core2strar( rq, val_arr, int_arr, type_arr ); for(i=0; i<m; i++) VAL_STR(db_vals+i) = val_arr[i]; /* time value */ VAL_TIME(db_vals+(m++)) = acc_env.ts; /* extra columns */ m += extra2strar( db_extra, rq, val_arr+m, int_arr+m, type_arr+m); for( i++ ; i<m; i++) VAL_STR(db_vals+i) = val_arr[i]; if (acc_dbf.use_table(db_handle, &acc_env.text/*table*/) < 0) { LM_ERR("error in use_table\n"); return -1; } /* multi-leg columns */ if ( !leg_info ) { if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) { LM_ERR("failed to insert into database\n"); return -1; } } else { n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m,1); do { for (i=m; i<m+n; i++) VAL_STR(db_vals+i)=val_arr[i]; if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) { LM_ERR("failed to insert into database\n"); return -1; } }while ( (n=legs2strar(leg_info,rq,val_arr+m,int_arr+m, type_arr+m,0))!=0 ); } return 1; }
/* collect all crd data and write it to a syslog */ static int log_write_cdr( struct dlg_cell* dialog, struct sip_msg* message) { static char cdr_message[ MAX_SYSLOG_SIZE]; static char* const cdr_message_end = cdr_message + MAX_SYSLOG_SIZE - 2;// -2 because of the string ending '\n\0' char* message_position = NULL; int message_index = 0; int counter = 0; if(cdr_log_enable==0) return 0; /* get default values */ message_index = cdr_core2strar( dialog, cdr_value_array, cdr_int_array, cdr_type_array); /* get extra values */ message_index += extra2strar( cdr_extra, message, cdr_value_array + message_index, cdr_int_array + message_index, cdr_type_array + message_index); for( counter = 0, message_position = cdr_message; counter < message_index ; counter++ ) { const char* const next_message_end = message_position + 2 + // ', ' -> two letters cdr_attrs[ counter].len + 1 + // '=' -> one letter cdr_value_array[ counter].len; if( next_message_end >= cdr_message_end || next_message_end < message_position) { LM_WARN("cdr message too long, truncating..\n"); message_position = cdr_message_end; break; } if( counter > 0) { *(message_position++) = A_SEPARATOR_CHR; *(message_position++) = A_SEPARATOR_CHR_2; } memcpy( message_position, cdr_attrs[ counter].s, cdr_attrs[ counter].len); message_position += cdr_attrs[ counter].len; *( message_position++) = A_EQ_CHR; memcpy( message_position, cdr_value_array[ counter].s, cdr_value_array[ counter].len); message_position += cdr_value_array[ counter].len; } /* terminating line */ *(message_position++) = '\n'; *(message_position++) = '\0'; LM_GEN2( cdr_facility, log_level, "%s", cdr_message); return 0; }
/* collect all crd data and write it to a syslog */ static int db_write_cdr( struct dlg_cell* dialog, struct sip_msg* message) { int m = 0; int i; db_func_t *df=NULL; db1_con_t *dh=NULL; void *vf=NULL; void *vh=NULL; if(acc_cdrs_table.len<=0) return 0; if(acc_get_db_handlers(&vf, &vh)<0) { LM_ERR("cannot get db handlers\n"); return -1; } df = (db_func_t*)vf; dh = (db1_con_t*)vh; /* get default values */ m = cdr_core2strar( dialog, cdr_value_array, cdr_int_array, cdr_type_array); for(i=0; i<m; i++) { db_cdr_keys[i] = &cdr_attrs[i]; VAL_TYPE(db_cdr_vals+i)=DB1_STR; VAL_NULL(db_cdr_vals+i)=0; VAL_STR(db_cdr_vals+i) = cdr_value_array[i]; } /* get extra values */ m += extra2strar( cdr_extra, message, cdr_value_array + m, cdr_int_array + m, cdr_type_array + m); for( ; i<m; i++) { db_cdr_keys[i] = &cdr_attrs[i]; VAL_TYPE(db_cdr_vals+i)=DB1_STR; VAL_NULL(db_cdr_vals+i)=0; VAL_STR(db_cdr_vals+i) = cdr_value_array[i]; } if (df->use_table(dh, &acc_cdrs_table /*table*/) < 0) { LM_ERR("error in use_table\n"); return -1; } if(acc_db_insert_mode==1 && df->insert_delayed!=NULL) { if (df->insert_delayed(dh, db_cdr_keys, db_cdr_vals, m) < 0) { LM_ERR("failed to insert delayed into database\n"); return -1; } } else { if (df->insert(dh, db_cdr_keys, db_cdr_vals, m) < 0) { LM_ERR("failed to insert into database\n"); return -1; } } return 0; }
/* collect all crd data and write it to a syslog */ static int log_write_cdr( struct dlg_cell* dialog, struct sip_msg* message) { static char cdr_message[ MAX_SYSLOG_SIZE]; static char* const cdr_message_end = cdr_message + MAX_SYSLOG_SIZE - 2;// -2 because of the string ending '\n\0' char* message_position = NULL; int message_index = 0; int extra_index = 0; int counter = 0; if(cdr_log_enable==0) return 0; /* get default values */ message_index = cdr_core2strar( dialog, cdr_value_array, cdr_int_array, cdr_type_array); /* get extra values */ if (message) { extra_index += extra2strar( cdr_extra, message, cdr_value_array + message_index, cdr_int_array + message_index, cdr_type_array + message_index); } else if (cdr_expired_dlg_enable){ LM_DBG("fallback to dlg_only search because of message does not exist.\n"); message_index += extra2strar_dlg_only( cdr_extra, dialog, cdr_value_array + message_index, cdr_int_array + message_index, cdr_type_array + message_index, &dlgb); } message_index += extra_index; for( counter = 0, message_position = cdr_message; counter < message_index ; counter++ ) { const char* const next_message_end = message_position + 2 + // ', ' -> two letters cdr_attrs[ counter].len + 1 + // '=' -> one letter cdr_value_array[ counter].len; if( next_message_end >= cdr_message_end || next_message_end < message_position) { LM_WARN("cdr message too long, truncating..\n"); message_position = cdr_message_end; break; } if( counter > 0) { *(message_position++) = A_SEPARATOR_CHR; *(message_position++) = A_SEPARATOR_CHR_2; } memcpy( message_position, cdr_attrs[ counter].s, cdr_attrs[ counter].len); message_position += cdr_attrs[ counter].len; *( message_position++) = A_EQ_CHR; memcpy( message_position, cdr_value_array[ counter].s, cdr_value_array[ counter].len); message_position += cdr_value_array[ counter].len; } /* terminating line */ *(message_position++) = '\n'; *(message_position++) = '\0'; LM_GEN2( cdr_facility, log_level, "%s", cdr_message); /* free memory allocated by extra2strar, nothing is done in case no extra strings were found by extra2strar */ free_strar_mem( &(cdr_type_array[message_index-extra_index]), &(cdr_value_array[message_index-extra_index]), extra_index, message_index); return 0; }
/* collect all crd data and write it to a syslog */ static int db_write_cdr( struct dlg_cell* dialog, struct sip_msg* message) { int m = 0; int n = 0; int i; db_func_t *df=NULL; db1_con_t *dh=NULL; void *vf=NULL; void *vh=NULL; struct timeval timeval_val; long long_val; double double_val; char * end; if(acc_cdrs_table.len<=0) return 0; if(acc_get_db_handlers(&vf, &vh)<0) { LM_ERR("cannot get db handlers\n"); return -1; } df = (db_func_t*)vf; dh = (db1_con_t*)vh; /* get default values */ m = cdr_core2strar( dialog, cdr_value_array, cdr_int_array, cdr_type_array); for(i=0; i<m; i++) { db_cdr_keys[i] = &cdr_attrs[i]; /* reset errno, some strtoX don't reset it */ errno = 0; switch(cdr_type_array[i]) { case TYPE_NULL: VAL_NULL(db_cdr_vals+i)=1; break; case TYPE_INT: VAL_TYPE(db_cdr_vals+i)=DB1_INT; VAL_NULL(db_cdr_vals+i)=0; long_val = strtol(cdr_value_array[i].s, &end, 10); if(errno && (errno != EAGAIN)) { LM_ERR("failed to convert string to integer - %d.\n", errno); goto error; } VAL_INT(db_cdr_vals+i) = long_val; break; case TYPE_STR: VAL_TYPE(db_cdr_vals+i)=DB1_STR; VAL_NULL(db_cdr_vals+i)=0; VAL_STR(db_cdr_vals+i) = cdr_value_array[i]; break; case TYPE_DATE: VAL_TYPE(db_cdr_vals+i)=DB1_DATETIME; VAL_NULL(db_cdr_vals+i)=0; if(string2time(&cdr_value_array[i], &timeval_val) < 0) { LM_ERR("failed to convert string to timeval.\n"); goto error; } VAL_TIME(db_cdr_vals+i) = timeval_val.tv_sec; break; case TYPE_DOUBLE: VAL_TYPE(db_cdr_vals+i)=DB1_DOUBLE; VAL_NULL(db_cdr_vals+i)=0; double_val = strtod(cdr_value_array[i].s, &end); if(errno && (errno != EAGAIN)) { LM_ERR("failed to convert string to double - %d.\n", errno); goto error; } VAL_DOUBLE(db_cdr_vals+i) = double_val; break; } } /* get extra values */ if (message) { n += extra2strar( cdr_extra, message, cdr_value_array + m, cdr_int_array + m, cdr_type_array + m); m += n; } else if (cdr_expired_dlg_enable){ LM_WARN( "fallback to dlg_only search because of message doesn't exist.\n"); m += extra2strar_dlg_only( cdr_extra, dialog, cdr_value_array + m, cdr_int_array + m, cdr_type_array +m, &dlgb); } for( ; i<m; i++) { db_cdr_keys[i] = &cdr_attrs[i]; VAL_TYPE(db_cdr_vals+i)=DB1_STR; VAL_NULL(db_cdr_vals+i)=0; VAL_STR(db_cdr_vals+i) = cdr_value_array[i]; } if (df->use_table(dh, &acc_cdrs_table /*table*/) < 0) { LM_ERR("error in use_table\n"); goto error; } if(acc_db_insert_mode==1 && df->insert_delayed!=NULL) { if (df->insert_delayed(dh, db_cdr_keys, db_cdr_vals, m) < 0) { LM_ERR("failed to insert delayed into database\n"); goto error; } } else if(acc_db_insert_mode==2 && df->insert_async!=NULL) { if (df->insert_async(dh, db_cdr_keys, db_cdr_vals, m) < 0) { LM_ERR("failed to insert async into database\n"); goto error; } } else { if (df->insert(dh, db_cdr_keys, db_cdr_vals, m) < 0) { LM_ERR("failed to insert into database\n"); goto error; } } /* Free memory allocated by acc_extra.c/extra2strar */ free_strar_mem( &(cdr_type_array[m-n]), &(cdr_value_array[m-n]), n, m); return 0; error: /* Free memory allocated by acc_extra.c/extra2strar */ free_strar_mem( &(cdr_type_array[m-n]), &(cdr_value_array[m-n]), n, m); return -1; }
int acc_diam_request( struct sip_msg *req ) { int attr_cnt; int cnt; AAAMessage *send = NULL; AAA_AVP *avp; struct sip_uri puri; str *uri; int ret; int i; int status; char tmp[2]; unsigned int mid; attr_cnt = core2strar( req, val_arr, int_arr, type_arr ); /* last value is not used */ attr_cnt--; if ( (send=AAAInMessage(ACCOUNTING_REQUEST, AAA_APP_NASREQ))==NULL) { LM_ERR("failed to create new AAA request\n"); return -1; } /* AVP_ACCOUNTIG_RECORD_TYPE */ if( (status = diam_status(req, acc_env.code))<0) { LM_ERR("status unknown\n"); goto error; } tmp[0] = status+'0'; tmp[1] = 0; if( (avp=AAACreateAVP(AVP_Accounting_Record_Type, 0, 0, tmp, 1, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP_MSGID AVP */ mid = req->id; if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&mid), sizeof(mid), AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* SIP Service AVP */ if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_ACCOUNTING, SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* also the extra attributes */ attr_cnt += extra2strar( dia_extra, req, val_arr, int_arr, type_arr); /* add attributes */ for(i=0; i<attr_cnt; i++) { if((avp=AAACreateAVP(diam_attrs[i], 0,0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } /* and the leg attributes */ if ( leg_info ) { cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1); do { for (i=0; i<cnt; i++) { if((avp=AAACreateAVP(diam_attrs[attr_cnt+i], 0, 0, val_arr[i].s, val_arr[i].len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP: no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } } } while ( (cnt=legs2strar(leg_info,req,val_arr,int_arr, type_arr,0))!=0 ); } if (get_uri(req, &uri) < 0) { LM_ERR("failed to get uri, From/To URI not found\n"); goto error; } if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From/To URI\n"); goto error; } /* Destination-Realm AVP */ if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s, puri.host.len, AVP_DUPLICATE_DATA)) == 0) { LM_ERR("failed to create AVP:no more free memory!\n"); goto error; } if( AAAAddAVPToMessage(send, avp, 0)!= AAA_ERR_SUCCESS) { LM_ERR("avp not added \n"); AAAFreeAVP(&avp); goto error; } /* prepare the message to be sent over the network */ if(AAABuildMsgBuffer(send) != AAA_ERR_SUCCESS) { LM_ERR("message buffer not created\n"); goto error; } if(sockfd==AAA_NO_CONNECTION) { sockfd = init_mytcp(diameter_client_host, diameter_client_port); if(sockfd==AAA_NO_CONNECTION) { LM_ERR("failed to reconnect to Diameter client\n"); goto error; } } /* send the message to the DIAMETER client */ ret = tcp_send_recv(sockfd, send->buf.s, send->buf.len, rb, req->id); if(ret == AAA_CONN_CLOSED) { LM_NOTICE("connection to Diameter client closed.It will be " "reopened by the next request\n"); close(sockfd); sockfd = AAA_NO_CONNECTION; goto error; } if(ret != ACC_SUCCESS) { /* a transmission error occurred */ LM_ERR("message sending to the DIAMETER backend authorization " "server failed\n"); goto error; } AAAFreeMessage(&send); return 1; error: AAAFreeMessage(&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; }
int acc_log_request( struct sip_msg *rq) { static char log_msg[MAX_SYSLOG_SIZE]; static char *log_msg_end=log_msg+MAX_SYSLOG_SIZE-2; char *p; int n; int m; int i; struct tm *t; /* get default values */ m = core2strar( rq, val_arr, int_arr, type_arr); /* get extra values */ m += extra2strar( log_extra, rq, val_arr+m, int_arr+m, type_arr+m); for ( i=0,p=log_msg ; i<m ; i++ ) { if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) { LM_WARN("acc message too long, truncating..\n"); p = log_msg_end; break; } *(p++) = A_SEPARATOR_CHR; memcpy(p, log_attrs[i].s, log_attrs[i].len); p += log_attrs[i].len; *(p++) = A_EQ_CHR; if (val_arr[i].s != NULL) { memcpy(p, val_arr[i].s, val_arr[i].len); p += val_arr[i].len; } } /* get per leg attributes */ if ( leg_info ) { n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m, 1); do { for (i=m; i<m+n; i++) { if (p+1+log_attrs[i].len+1+val_arr[i].len >= log_msg_end) { LM_WARN("acc message too long, truncating..\n"); p = log_msg_end; break; } *(p++) = A_SEPARATOR_CHR; memcpy(p, log_attrs[i].s, log_attrs[i].len); p += log_attrs[i].len; *(p++) = A_EQ_CHR; if (val_arr[i].s != NULL) { memcpy(p, val_arr[i].s, val_arr[i].len); p += val_arr[i].len; } } } while (p!=log_msg_end && (n=legs2strar(leg_info,rq,val_arr+m, int_arr+m,type_arr+m, 0))!=0); } /* terminating line */ *(p++) = '\n'; *(p++) = 0; if(acc_time_mode==1) { LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%u%s", acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts, acc_time_exten.s, (unsigned int)acc_env.tv.tv_usec, log_msg); } else if(acc_time_mode==2) { LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%.3f%s", acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts, acc_time_attr.s, (((double)(acc_env.tv.tv_sec * 1000) + (acc_env.tv.tv_usec / 1000)) / 1000), log_msg); } else if(acc_time_mode==3 || acc_time_mode==4) { if(acc_time_mode==3) { t = localtime(&acc_env.ts); } else { t = gmtime(&acc_env.ts); } if(strftime(acc_time_format_buf, ACC_TIME_FORMAT_SIZE, acc_time_format, t)<=0) { acc_time_format_buf[0] = '\0'; } LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu;%s=%s%s", acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts, acc_time_attr.s, acc_time_format_buf, log_msg); } else { LM_GEN2(log_facility, log_level, "%.*stimestamp=%lu%s", acc_env.text.len, acc_env.text.s,(unsigned long)acc_env.ts, log_msg); } return 1; }
int acc_aaa_request( struct sip_msg *req, struct sip_msg *rpl) { int attr_cnt; aaa_message *send; int offset, i, av_type; aaa_map *r_stat; if ((send = proto.create_aaa_message(conn, AAA_ACCT)) == NULL) { LM_ERR("failed to create new aaa message for acct\n"); return -1; } attr_cnt = core2strar( req, val_arr); /* not interested in the last 2 values */ attr_cnt -= 2; r_stat = aaa_status( req, acc_env.code); /* AAA PROTOCOL status */ ADD_AAA_AVPAIR( RA_ACCT_STATUS_TYPE, &(r_stat->value), -1); av_type = rd_vals[RV_SIP_SESSION].value; /* session*/ ADD_AAA_AVPAIR( RA_SERVICE_TYPE, &av_type, -1); av_type = (uint32_t)acc_env.code; /* status=integer */ ADD_AAA_AVPAIR( RA_SIP_RESPONSE_CODE, &av_type, -1); av_type = req->REQ_METHOD; /* method */ ADD_AAA_AVPAIR( RA_SIP_METHOD, &av_type, -1); /* unix time */ av_type = (uint32_t)acc_env.ts; ADD_AAA_AVPAIR( RA_TIME_STAMP, &av_type, -1); /* add extra also */ attr_cnt += extra2strar( aaa_extra, req, rpl, val_arr+attr_cnt, 0); /* add the values for the vector - start from 1 instead of * 0 to skip the first value which is the METHOD as string */ offset = RA_STATIC_MAX-1; for (i = 1; i < attr_cnt; i++) ADD_AAA_AVPAIR( offset + i, val_arr[i].s, val_arr[i].len ); /* call-legs attributes also get inserted */ if (leg_info) { offset += attr_cnt; attr_cnt = legs2strar(leg_info,req,val_arr,1); do { for (i = 0; i < attr_cnt; i++) ADD_AAA_AVPAIR( offset+i, val_arr[i].s, val_arr[i].len ); } while ((attr_cnt = legs2strar(leg_info,req,val_arr,0)) != 0); } if (proto.send_aaa_request(conn, send, NULL)) { LM_ERR("Radius accounting request failed for status: '%s' " "Call-Id: '%.*s' \n",r_stat->name, req->callid->body.len, req->callid->body.s); goto error; } proto.destroy_aaa_message(conn, send); return 1; error: proto.destroy_aaa_message(conn, send); return -1; }
/* * Loads from Radius callee's AVPs based on pvar argument. * Returns 1 if Radius request succeeded and -1 otherwise. */ int radius_load_callee_avps(struct sip_msg* _m, char* _callee, char* _s2) { str user; VALUE_PAIR *send, *received; uint32_t service; static char msg[4096]; int extra_cnt, offset, i, res; send = received = 0; if ((_callee == NULL) || (fixup_get_svalue(_m, (gparam_p)_callee, &user) != 0)) { LM_ERR("invalid callee parameter"); return -1; } if (!rc_avpair_add(rh, &send, callee_attrs[SA_USER_NAME].v, user.s, user.len, 0)) { LM_ERR("in adding SA_USER_NAME\n"); return -1; } service = callee_vals[EV_SIP_CALLEE_AVPS].v; if (!rc_avpair_add(rh, &send, callee_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(callee_extra, _m, val_arr); if (extra_cnt == -1) { LM_ERR("in getting values of callee 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(callee_attrs, offset+i, &(val_arr[i].s), val_arr[i].len ); } else { /* Add string attribute */ ADD_EXTRA_AVPAIR(callee_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(callee_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; }
int acc_db_request( struct sip_msg *rq) { int m; int n; int i; struct tm *t; /* formated database columns */ m = core2strar( rq, val_arr, int_arr, type_arr ); for(i=0; i<m; i++) VAL_STR(db_vals+i) = val_arr[i]; /* time value */ VAL_TIME(db_vals+(m++)) = acc_env.ts; /* extra time value */ if(acc_time_mode==1) { VAL_INT(db_vals+(m++)) = (int)acc_env.tv.tv_sec; i++; VAL_INT(db_vals+(m++)) = (int)acc_env.tv.tv_usec; i++; } else if(acc_time_mode==2) { VAL_DOUBLE(db_vals+(m++)) = ((double)(acc_env.tv.tv_sec * 1000) + (acc_env.tv.tv_usec / 1000)) / 1000; i++; } else if(acc_time_mode==3 || acc_time_mode==4) { if(acc_time_mode==3) { t = localtime(&acc_env.ts); } else { t = gmtime(&acc_env.ts); } if(strftime(acc_time_format_buf, ACC_TIME_FORMAT_SIZE, acc_time_format, t)<=0) { acc_time_format_buf[0] = '\0'; } VAL_STRING(db_vals+(m++)) = acc_time_format_buf; i++; } /* extra columns */ m += extra2strar( db_extra, rq, val_arr+m, int_arr+m, type_arr+m); for( i++ ; i<m; i++) VAL_STR(db_vals+i) = val_arr[i]; if (acc_dbf.use_table(db_handle, &acc_env.text/*table*/) < 0) { LM_ERR("error in use_table\n"); return -1; } /* multi-leg columns */ if ( !leg_info ) { if(acc_db_insert_mode==1 && acc_dbf.insert_delayed!=NULL) { if (acc_dbf.insert_delayed(db_handle, db_keys, db_vals, m) < 0) { LM_ERR("failed to insert delayed into database\n"); return -1; } } else if(acc_db_insert_mode==2 && acc_dbf.insert_async!=NULL) { if (acc_dbf.insert_async(db_handle, db_keys, db_vals, m) < 0) { LM_ERR("failed to insert async into database\n"); return -1; } } else { if (acc_dbf.insert(db_handle, db_keys, db_vals, m) < 0) { LM_ERR("failed to insert into database\n"); return -1; } } } else { n = legs2strar(leg_info,rq,val_arr+m,int_arr+m,type_arr+m,1); do { for (i=m; i<m+n; i++) VAL_STR(db_vals+i)=val_arr[i]; if(acc_db_insert_mode==1 && acc_dbf.insert_delayed!=NULL) { if(acc_dbf.insert_delayed(db_handle,db_keys,db_vals,m+n)<0) { LM_ERR("failed to insert delayed into database\n"); return -1; } } else if(acc_db_insert_mode==2 && acc_dbf.insert_async!=NULL) { if(acc_dbf.insert_async(db_handle,db_keys,db_vals,m+n)<0) { LM_ERR("failed to insert async into database\n"); return -1; } } else { if (acc_dbf.insert(db_handle, db_keys, db_vals, m+n) < 0) { LM_ERR("failed to insert into database\n"); return -1; } } }while ( (n=legs2strar(leg_info,rq,val_arr+m,int_arr+m, type_arr+m,0))!=0 ); } 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; }
int acc_rad_request( struct sip_msg *req ) { int attr_cnt; VALUE_PAIR *send; UINT4 av_type; int offset; int i; send=NULL; attr_cnt = core2strar( req, val_arr, int_arr, type_arr ); /* not interested in the last 2 values */ attr_cnt -= 2; av_type = rad_status( req, acc_env.code); /* RADIUS status */ ADD_RAD_AVPAIR( RA_ACCT_STATUS_TYPE, &av_type, -1); av_type = rd_vals[RV_SIP_SESSION].v; /* session*/ ADD_RAD_AVPAIR( RA_SERVICE_TYPE, &av_type, -1); av_type = (UINT4)acc_env.code; /* status=integer */ ADD_RAD_AVPAIR( RA_SIP_RESPONSE_CODE, &av_type, -1); av_type = req->REQ_METHOD; /* method */ ADD_RAD_AVPAIR( RA_SIP_METHOD, &av_type, -1); /* unix time */ av_type = (UINT4)acc_env.ts; ADD_RAD_AVPAIR( RA_TIME_STAMP, &av_type, -1); /* add extra also */ attr_cnt += extra2strar(rad_extra, req, val_arr+attr_cnt, int_arr+attr_cnt, type_arr+attr_cnt); /* add the values for the vector - start from 1 instead of * 0 to skip the first value which is the METHOD as string */ offset = RA_STATIC_MAX-1; for( i=1; i<attr_cnt; i++) { switch (type_arr[i]) { case TYPE_STR: ADD_RAD_AVPAIR(offset+i, val_arr[i].s, val_arr[i].len); break; case TYPE_INT: ADD_RAD_AVPAIR(offset+i, &(int_arr[i]), -1); break; default: break; } } /* call-legs attributes also get inserted */ if ( leg_info ) { offset += attr_cnt; attr_cnt = legs2strar(leg_info,req,val_arr,int_arr,type_arr,1); do { for (i=0; i<attr_cnt; i++) ADD_RAD_AVPAIR( offset+i, val_arr[i].s, val_arr[i].len ); }while ( (attr_cnt=legs2strar(leg_info,req,val_arr,int_arr, type_arr, 0))!=0 ); } if (rc_acct(rh, SIP_PORT, send)!=OK_RC) { LM_ERR("radius-ing failed\n"); goto error; } rc_avpair_free(send); return 1; error: rc_avpair_free(send); return -1; }
/* * 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; }
/* * 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) { static char msg[4096]; VALUE_PAIR *send, *received; uint32_t service; str method, user, user_name; str *ruri; int extra_cnt, offset, i; send = received = 0; if (!(_cred && _method && _user)) { LM_ERR("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 || !append_realm_to_username) { if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) { LM_ERR("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) { LM_ERR("no pkg 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)) { LM_ERR("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, attrs[A_DIGEST_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) { LM_ERR("unable to add Digest-User-Name attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_REALM].v, _cred->realm.s, _cred->realm.len, 0)) { LM_ERR("unable to add Digest-Realm attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE].v, _cred->nonce.s, _cred->nonce.len, 0)) { LM_ERR("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, attrs[A_DIGEST_URI].v, ruri->s, ruri->len, 0)) { LM_ERR("unable to add Digest-URI attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_METHOD].v, method.s, method.len, 0)) { LM_ERR("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, attrs[A_DIGEST_QOP].v, "auth", 4, 0)) { LM_ERR("unable to add Digest-QOP attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, _cred->nc.s, _cred->nc.len, 0)) { LM_ERR("unable to add Digest-CNonce-Count attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, _cred->cnonce.s, _cred->cnonce.len, 0)) { LM_ERR("unable to add Digest-CNonce attribute\n"); goto err; } } else if (_cred->qop.qop_parsed == QOP_AUTHINT) { if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth-int", 8, 0)) { LM_ERR("unable to add Digest-QOP attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, _cred->nc.s, _cred->nc.len, 0)) { LM_ERR("unable to add Digest-Nonce-Count attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, _cred->cnonce.s, _cred->cnonce.len, 0)) { LM_ERR("unable to add Digest-CNonce attribute\n"); goto err; } if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_BODY_DIGEST].v, _cred->opaque.s, _cred->opaque.len, 0)) { LM_ERR("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, attrs[A_DIGEST_RESPONSE].v, _cred->response.s, _cred->response.len, 0)) { LM_ERR("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, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("unable to add Service-Type attribute\n"); goto err; } /* Add SIP URI as a check item */ if (!rc_avpair_add(rh,&send,attrs[A_SIP_URI_USER].v,user.s,user.len,0)) { LM_ERR("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; } } /* Add extra attributes */ extra_cnt = extra2strar(auth_extra, _msg, val_arr); if (extra_cnt == -1) { LM_ERR("in getting values of extra attributes\n"); goto err; } offset = A_MAX; for (i = 0; i < extra_cnt; i++) { if (val_arr[i].len == -1) { /* Add integer attribute */ ADD_EXTRA_AVPAIR(attrs, offset+i, &(val_arr[i].s), val_arr[i].len ); } else { /* Add string attribute */ ADD_EXTRA_AVPAIR(attrs, offset+i, val_arr[i].s, val_arr[i].len ); } } /* Send request */ if ((i = rc_auth(rh, SIP_PORT, send, &received, msg)) == OK_RC) { LM_DBG("Success\n"); rc_avpair_free(send); send = 0; generate_avps(received); rc_avpair_free(received); return 1; } else { #ifdef REJECT_RC if (i == REJECT_RC) { LM_DBG("Failure\n"); goto err; } #endif LM_ERR("authorization failed. RC auth returned %d\n", i); } err: if (send) rc_avpair_free(send); if (received) rc_avpair_free(received); return -1; }