static int w_pv_auth_check(sip_msg_t *msg, char *realm, char *passwd, char *flags, char *checks) { int vflags = 0; int vchecks = 0; str srealm = {0, 0}; str spasswd = {0, 0}; if(msg==NULL) { LM_ERR("invalid msg parameter\n"); return AUTH_ERROR; } if ((msg->REQ_METHOD == METHOD_ACK) || (msg->REQ_METHOD == METHOD_CANCEL)) { return AUTH_OK; } if(realm==NULL || passwd==NULL || flags==NULL || checks==NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); return AUTH_ERROR; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); return AUTH_ERROR; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); return AUTH_ERROR; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); return AUTH_ERROR; } if (get_int_fparam(&vchecks, msg, (fparam_t*)checks) < 0) { LM_ERR("invalid checks value\n"); return AUTH_ERROR; } LM_DBG("realm [%.*s] flags [%d] checks [%d]\n", srealm.len, srealm.s, vflags, vchecks); return pv_auth_check(msg, &srealm, &spasswd, vflags, vchecks); }
/* set fr_inv_timeout & or fr_timeout; 0 means: use the default value */ static int t_set_fr_all(struct sip_msg* msg, char* p1, char* p2) { int fr, fr_inv; if (get_int_fparam(&fr_inv, msg, (fparam_t*)p1) < 0) return -1; if (p2) { if (get_int_fparam(&fr, msg, (fparam_t*)p2) < 0) return -1; } else { fr = 0; } return t_set_fr(msg, fr_inv, fr); }
/* returns error if no retry_after hdr field is present */ static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max) { #ifdef USE_DST_BLACKLIST int t_min, t_max, t; struct dest_info src; struct hdr_field* hf; if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){ if (unlikely(get_int_fparam(&t_min, msg, (fparam_t*)min)<0)) return -1; if (likely(max)){ if (unlikely(get_int_fparam(&t_max, msg, (fparam_t*)max)<0)) return -1; }else{ t_max=0; } init_dest_info(&src); src.send_sock=0; src.to=msg->rcv.src_su; src.id=msg->rcv.proto_reserved1; src.proto=msg->rcv.proto; t=-1; if ((parse_headers(msg, HDR_RETRY_AFTER_F, 0)==0) && (msg->parsed_flag & HDR_RETRY_AFTER_F)){ for (hf=msg->headers; hf; hf=hf->next) if (hf->type==HDR_RETRY_AFTER_T){ /* found */ t=(unsigned)(unsigned long)hf->parsed; break; } } if (t<0) return -1; t=MAX_unsigned(t, t_min); t=MIN_unsigned(t, t_max); if (likely(t)) dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg, S_TO_TICKS(t)); return 1; }else{ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support disabled\n"); } #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_add_retry_after:" " blacklist support not compiled-in - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
/** * @brief Small wrapper around sl_send_reply * * Warapper around sl_send_rply() which accepts parameters that include * config variables * */ static int w_sl_send_reply(struct sip_msg* msg, char* p1, char* p2) { int code, ret; str reason; char* r; if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } if(reason.s[reason.len-1]=='\0') { r = reason.s; } else { r = as_asciiz(&reason); if (r == NULL) r = default_reason.s; } ret = sl_send_reply(msg, code, r); if ((r!=reason.s) && (r!=default_reason.s)) pkg_free(r); return ret; }
static int auth_challenge(struct sip_msg *msg, char *p1, char *p2, int hftype) { int flags = 0; str realm = {0, 0}; int ret; str hf = {0, 0}; struct qp *qop = NULL; ret = -1; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(realm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_int_fparam(&flags, msg, (fparam_t*)p2) < 0) { LM_ERR("invalid flags value\n"); goto error; } if(flags&2) { qop = &auth_qauthint; } else if(flags&1) { qop = &auth_qauth; } if (get_challenge_hf(msg, 0, &realm, NULL, NULL, qop, hftype, &hf) < 0) { ERR("Error while creating challenge\n"); ret = -2; goto error; } ret = 1; switch(hftype) { case HDR_AUTHORIZATION_T: if(auth_send_reply(msg, 401, "Unauthorized", hf.s, hf.len) <0 ) ret = -3; break; case HDR_PROXYAUTH_T: if(auth_send_reply(msg, 407, "Proxy Authentication Required", hf.s, hf.len) <0 ) ret = -3; break; } if(hf.s) pkg_free(hf.s); return ret; error: if(hf.s) pkg_free(hf.s); if(!(flags&4)) { if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 ) ret = -4; } return ret; }
static int www_challenge(struct sip_msg *msg, char* realm, char *flags) { int vflags = 0; str srealm = {0, 0}; if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } return auth_challenge(msg, &srealm, vflags, HDR_AUTHORIZATION_T); error: if(!(vflags&4)) { if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 ) return -4; } return -1; }
static int blst_add_f(struct sip_msg* msg, char* to, char* foo) { #ifdef USE_DST_BLACKLIST int t; struct dest_info src; if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){ t=0; if (unlikely( to && (get_int_fparam(&t, msg, (fparam_t*)to)<0))) return -1; if (t==0) t=cfg_get(core, core_cfg, blst_timeout); init_dest_info(&src); src.send_sock=0; src.to=msg->rcv.src_su; src.id=msg->rcv.proto_reserved1; src.proto=msg->rcv.proto; dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg, S_TO_TICKS(t)); return 1; }else{ LOG(L_WARN, "WARNING: blst: blst_add: blacklist support disabled\n"); } #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_add: blacklist support not compiled-in" " - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
static int change_reply_status_f(struct sip_msg* msg, char* _code, char* _reason) { int code; str reason; struct lump *l; char *ch; if (get_int_fparam(&code, msg, (fparam_t*)_code) || get_str_fparam(&reason, msg, (fparam_t*)_reason) || (reason.len == 0) ) { LOG(L_ERR, "ERROR: textops: cannot get parameter\n"); return -1; } if ((code < 100) || (code > 699)) { LOG(L_ERR, "ERROR: textops: wrong status code: %d\n", code); return -1; } if (((code < 300) || (msg->REPLY_STATUS < 300)) && (code/100 != msg->REPLY_STATUS/100) ) { LOG(L_ERR, "ERROR: textops: the class of provisional or " "positive final replies cannot be changed\n"); return -1; } /* rewrite the status code directly in the message buffer */ msg->first_line.u.reply.statuscode = code; msg->first_line.u.reply.status.s[2] = code % 10 + '0'; code /= 10; msg->first_line.u.reply.status.s[1] = code % 10 + '0'; code /= 10; msg->first_line.u.reply.status.s[0] = code + '0'; l = del_lump(msg, msg->first_line.u.reply.reason.s - msg->buf, msg->first_line.u.reply.reason.len, 0); if (!l) { LOG(L_ERR, "ERROR: textops(): Failed to add del lump\n"); return -1; } /* clone the reason phrase, the lumps need to be pkg allocated */ ch = (char *)pkg_malloc(reason.len); if (!ch) { LOG(L_ERR, "ERROR: textops: Not enough memory\n"); return -1; } memcpy(ch, reason.s, reason.len); if (insert_new_lump_after(l, ch, reason.len, 0)==0){ LOG(L_ERR, "ERROR: textops: failed to add new lump: %.*s\n", reason.len, ch); pkg_free(ch); return -1; } return 1; }
/** * @brief config file function for replicating SIP message to all nodes (wraps t_replicate) */ int cfg_dmq_t_replicate(struct sip_msg* msg, char* s) { dmq_node_t* node; struct socket_info* sock; int i = 0; int first = 1; /* avoid loops - do not replicate if message has come from another node * (override if optional parameter is set) */ if ((!s || (get_int_fparam(&i, msg, (fparam_t*)s)==0 && !i)) && (is_from_remote_node(msg) > 0)) { LM_DBG("message is from another node - skipping replication\n"); return -1; } /* TODO - backup/restore original send socket */ sock = lookup_local_socket(&dmq_server_socket); if (sock) { set_force_socket(msg, sock); } lock_get(&node_list->lock); node = node_list->nodes; while(node) { /* we do not send the message to the following: * - ourself * - any inactive nodes */ if(node->local || node->status != DMQ_NODE_ACTIVE) { LM_DBG("skipping node %.*s\n", STR_FMT(&node->orig_uri)); node = node->next; continue; } if (!first) { if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, sock, 0, 0, 0, 0) == -1) { LM_ERR("failed to append a branch\n"); node = node->next; continue; } } else { first = 0; } if(tmb.t_replicate(msg, &node->orig_uri) < 0) { LM_ERR("error calling t_replicate\n"); goto error; } node = node->next; } lock_release(&node_list->lock); return 0; error: lock_release(&node_list->lock); return -1; }
static int w_rl_drop(struct sip_msg* msg, char *p1, char *p2) { int low, high; LOG(L_DBG, "w_rl_drop (%p, %p)\n", p1, p2); if (!p1 || get_int_fparam(&low, msg, (fparam_t *)p1) < 0) { LOG(L_DBG, "using default low retry interval\n"); low = 5; } if (!p2 || get_int_fparam(&high, msg, (fparam_t *)p2) < 0) { LOG(L_DBG, "using default high retry interval\n"); high = low; } return rl_drop(msg, low, high); }
/* these wrappers parse all what may be needed; they don't care about * the result -- accounting functions just display "unavailable" if there * is nothing meaningful */ static int acc_rad_missed1(struct sip_msg *rq, char* p1, char* p2) { int code; preparse_req(rq); if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) { code = 0; } return log_request(rq, GET_RURI(rq), rq->to, code, time(0)); }
/** * @brief config file function for replicating SIP message to all nodes (wraps t_replicate) */ int cfg_dmq_t_replicate(struct sip_msg *msg, char *s, char *p2) { int i = 0; if(s!=NULL && get_int_fparam(&i, msg, (fparam_t *)s) < 0) { LM_ERR("failed to get parameter value\n"); return -1; } return ki_dmq_t_replicate_mode(msg, i); }
/* these wrappers parse all what may be needed; they don't care about * the result -- accounting functions just display "unavailable" if there * is nothing meaningful */ static int acc_db_request1(struct sip_msg *rq, char* p1, char* p2) { int code; if (get_int_fparam(&code, rq, (fparam_t*)p1) < 0) { code = 0; } preparse_req(rq); return log_request(rq, GET_RURI(rq), rq->to, acc_table.s, code, time(0)); }
static int sca_call_info_update_1_f(sip_msg_t* msg, char* p1, char* p2) { int update_mask = SCA_CALL_INFO_SHARED_BOTH; if (get_int_fparam(&update_mask, msg, (fparam_t *) p1) < 0) { LM_ERR("sca_call_info_update: argument 1: bad value " "(integer expected)\n"); return (-1); } return sca_call_info_update(msg, update_mask, NULL, NULL); }
static int cnt_add_f(struct sip_msg* msg, char* handle, char* val) { counter_handle_t h; int v; h.id = (long)(void*)handle; if (unlikely(get_int_fparam(&v, msg, (fparam_t*)val) < 0)) { ERR("non integer parameter\n"); return -1; } counter_add(h, v); return 1; }
static int dbops_seek_func(struct sip_msg* m, char* handle, char* row_no) { int res, n; struct dbops_handle *a = (void *) handle; res = check_query_opened(a, "seek"); if (res < 0) return res; if (get_int_fparam(&n, m, (fparam_t*) row_no) < 0) { return -1; } res = do_seek(a->result, &a->cur_row_no, n); if (res < 0) return res; return 1; }
static int w_rl_check(struct sip_msg* msg, char *p1, char *p2) { int pipe; LOG(L_DBG, "w_rl_check (%p, %p)\n", p1, p2); if (!p1 || get_int_fparam(&pipe, msg, (fparam_t *)p1) < 0) { LOG(L_DBG, "using the pipe associated with the current req. method\n"); pipe = -1; } return rl_check(msg, pipe); }
static int w_auth_get_www_authenticate(sip_msg_t* msg, char* realm, char *flags, char *dst) { int vflags = 0; str srealm = {0}; str hf = {0}; pv_spec_t *pv; pv_value_t val; int ret; if(get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if(get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } pv = (pv_spec_t *)dst; ret = auth_challenge_helper(NULL, &srealm, vflags, HDR_AUTHORIZATION_T, &hf); if(ret<0) return ret; val.rs.s = pv_get_buffer(); val.rs.len = 0; if(hf.s!=NULL) { memcpy(val.rs.s, hf.s, hf.len); val.rs.len = hf.len; val.rs.s[val.rs.len] = '\0'; pkg_free(hf.s); } val.flags = PV_VAL_STR; pv->setf(msg, &pv->pvp, (int)EQ_T, &val); return ret; error: return -1; }
static int pv_www_authenticate2(struct sip_msg *msg, char* realm, char *passwd, char *flags, char *method) { int vflags = 0; str srealm = {0, 0}; str spasswd = {0, 0}; str smethod = {0, 0}; if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } if (get_str_fparam(&smethod, msg, (fparam_t*)method) < 0) { LM_ERR("failed to get method value from msg %p var %p\n", msg, method); goto error; } if(smethod.len==0) { LM_ERR("invalid method value - empty content\n"); goto error; } return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T, &smethod); error: return AUTH_ERROR; }
/** * @brief Small wrapper around send_reply */ static int w_send_reply(struct sip_msg* msg, char* p1, char* p2) { int code; str reason; if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } return send_reply(msg, code, &reason); }
inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2) { struct cell *t; int code, ret = -1; str reason; char* r; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } r = as_asciiz(&reason); if (r == NULL) r = default_reason.s; /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ if (rmode==MODE_ONFAILURE) { DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); ret = t_reply_unsafe(t, msg, code, r); } else if (rmode==MODE_REQUEST) { ret = t_reply( t, msg, code, r); } else { LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n"); ret = -1; } if (r) pkg_free(r); return ret; }
static int nat_uac_test_f(struct sip_msg* msg, char* str1, char* str2) { int tests; if (get_int_fparam(&tests, msg, (fparam_t*) str1) < 0) return -1; /* return true if any of the NAT-UAC tests holds */ /* test if the source port is different from the port in Via */ if ((tests & NAT_UAC_TEST_RPORT) && (msg->rcv.src_port != (msg->via1->port ? msg->via1->port : SIP_PORT))) { return 1; } /* * test if source address of signaling is different from * address advertised in Via */ if ((tests & NAT_UAC_TEST_RCVD) && received_test(msg)) return 1; /* * test for occurrences of RFC1918 addresses in Contact * header field */ if ((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg) > 0)) return 1; /* * test for occurrences of RFC1918 addresses in SDP body */ if ((tests & NAT_UAC_TEST_S_1918) && sdp_1918(msg)) return 1; /* * test for occurrences of RFC1918 addresses top Via */ if ((tests & NAT_UAC_TEST_V_1918) && via_1918(msg)) return 1; /* * test if source port of signaling is different from * port advertised in Contact */ if ((tests & NAT_UAC_TEST_C_PORT) && (contact_rport(msg) > 0)) return 1; /* no test succeeded */ return -1; }
static int sca_call_info_update_2_f(sip_msg_t* msg, char* p1, char* p2) { str uri_to = STR_NULL; int update_mask = SCA_CALL_INFO_SHARED_BOTH; if (get_int_fparam(&update_mask, msg, (fparam_t *) p1) < 0) { LM_ERR("sca_call_info_update: argument 1: bad value " "(integer expected)\n"); return (-1); } if(get_str_fparam(&uri_to, msg, (gparam_p)p2)!=0) { LM_ERR("unable to get value from param pvar_to\n"); return -1; } return sca_call_info_update(msg, update_mask, &uri_to, NULL); }
static int blst_rpl_clear_ignore_f(struct sip_msg* msg, char* flags, char* foo) { #ifdef USE_DST_BLACKLIST unsigned char blst_imask; int mask; if (unlikely(flags && (get_int_fparam(&mask, msg, (fparam_t*)flags)<0))) return -1; blst_imask=flags?mask:0xff; msg->rpl_send_flags.blst_imask&=~blst_imask; return 1; #else /* USE_DST_BLACKLIST */ LOG(L_WARN, "WARNING: blst: blst_ignore_req: blacklist support" " not compiled-in - no effect -\n"); #endif /* USE_DST_BLACKLIST */ return 1; }
static int set_iattr(struct sip_msg* msg, char* p1, char* p2) { avp_ident_t avpid; int_str value; if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) { return -1; } if (get_int_fparam(&value.n, msg, (fparam_t*)p2) < 0) { ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig); return -1; } if (add_avp(avpid.flags | AVP_NAME_STR, avpid.name, value) != 0) { ERR("add_avp failed\n"); return -1; } return 1; }
static int xlog(struct sip_msg* msg, char* lev, char* frm) { int log_len, level; if (get_int_fparam(&level, msg, (fparam_t *)lev)) { LOG(L_ERR, "XLOG:xlog: cannot get log level\n"); return -1; } if (level < L_ALERT) level = L_ALERT; else if (level > L_DBG) level = L_DBG; log_len = buf_size; if(xl_print_log(msg, (xl_elog_t*)frm, log_buf, &log_len)<0) return -1; /* log_buf[log_len] = '\0'; */ LOG_(level, "<script>: ", "%.*s", log_len, log_buf); return 1; }
static int pv_proxy_authenticate(struct sip_msg *msg, char* realm, char *passwd, char *flags) { int vflags = 0; str srealm = {0, 0}; str spasswd = {0, 0}; if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T, &msg->first_line.u.request.method); error: return AUTH_ERROR; }
static int w_auth_challenge(struct sip_msg *msg, char* realm, char *flags) { int vflags = 0; str srealm = {0, 0}; if((msg->REQ_METHOD == METHOD_ACK) || (msg->REQ_METHOD == METHOD_CANCEL)) { return 1; } if(get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if(get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } if(msg->REQ_METHOD==METHOD_REGISTER) return auth_challenge_hftype(msg, &srealm, vflags, HDR_AUTHORIZATION_T); else return auth_challenge_hftype(msg, &srealm, vflags, HDR_PROXYAUTH_T); error: if(!(vflags&4)) { if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 ) return -4; } return -1; }
static int pv_auth_check(sip_msg_t *msg, char *realm, char *passwd, char *flags, char *checks) { int vflags = 0; int vchecks = 0; str srealm = {0, 0}; str spasswd = {0, 0}; int ret; hdr_field_t *hdr; sip_uri_t *uri = NULL; sip_uri_t *turi = NULL; sip_uri_t *furi = NULL; if(msg==NULL) { LM_ERR("invalid msg parameter\n"); return AUTH_ERROR; } if ((msg->REQ_METHOD == METHOD_ACK) || (msg->REQ_METHOD == METHOD_CANCEL)) { return AUTH_OK; } if(realm==NULL || passwd==NULL || flags==NULL || checks==NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); return AUTH_ERROR; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); return AUTH_ERROR; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); return AUTH_ERROR; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); return AUTH_ERROR; } if (get_int_fparam(&vchecks, msg, (fparam_t*)checks) < 0) { LM_ERR("invalid checks value\n"); return AUTH_ERROR; } LM_DBG("realm [%.*s] flags [%d] checks [%d]\n", srealm.len, srealm.s, vflags, vchecks); if(msg->REQ_METHOD==METHOD_REGISTER) ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T, &msg->first_line.u.request.method); else ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T, &msg->first_line.u.request.method); if(ret==AUTH_OK && (vchecks&AUTH_CHECK_ID_F)) { hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth; srealm = ((auth_body_t*)(hdr->parsed))->digest.username.user; if((furi=parse_from_uri(msg))==NULL) return AUTH_ERROR; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { if((turi=parse_to_uri(msg))==NULL) return AUTH_ERROR; uri = turi; } else { uri = furi; } if(srealm.len!=uri->user.len || strncmp(srealm.s, uri->user.s, srealm.len)!=0) return AUTH_USER_MISMATCH; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { /* check from==to */ if(furi->user.len!=turi->user.len || strncmp(furi->user.s, turi->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=turi->host.len || strncmp(furi->host.s, turi->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; /* check r-uri==from for publish */ if(msg->REQ_METHOD==METHOD_PUBLISH) { if(parse_sip_msg_uri(msg)<0) return AUTH_ERROR; uri = &msg->parsed_uri; if(furi->user.len!=uri->user.len || strncmp(furi->user.s, uri->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=uri->host.len || strncmp(furi->host.s, uri->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; } } return AUTH_OK; } return ret; }
/** * @brief do WWW-Digest authentication with password taken from cfg var */ static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2, char *p3, int hftype) { int flags = 0; str realm = {0, 0}; str passwd = {0, 0}; struct hdr_field* h; auth_body_t* cred; int ret; str hf = {0, 0}; avp_value_t val; static char ha1[256]; struct qp *qop = NULL; cred = 0; ret = AUTH_ERROR; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(realm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&passwd, msg, (fparam_t*)p2) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(passwd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&flags, msg, (fparam_t*)p3) < 0) { LM_ERR("invalid flags value\n"); goto error; } switch(pre_auth(msg, &realm, hftype, &h, NULL)) { case ERROR: case BAD_CREDENTIALS: LM_DBG("error or bad credentials\n"); ret = AUTH_ERROR; goto end; case CREATE_CHALLENGE: LM_ERR("CREATE_CHALLENGE is not a valid state\n"); ret = AUTH_ERROR; goto end; case DO_RESYNCHRONIZATION: LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); ret = AUTH_ERROR; goto end; case NOT_AUTHENTICATED: LM_DBG("not authenticated\n"); ret = AUTH_ERROR; goto end; case DO_AUTHENTICATION: break; case AUTHENTICATED: ret = AUTH_OK; goto end; } cred = (auth_body_t*)h->parsed; /* compute HA1 if needed */ if ((flags&1)==0) { /* Plaintext password is stored in PV, calculate HA1 */ calc_HA1(HA_MD5, &cred->digest.username.whole, &realm, &passwd, 0, 0, ha1); LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, passwd.s, passwd.len); ha1[passwd.len] = '\0'; } /* Recalculate response, it must be same to authorize successfully */ ret = auth_check_response(&(cred->digest), &msg->first_line.u.request.method, ha1); if(ret==AUTHENTICATED) { ret = AUTH_OK; switch(post_auth(msg, h)) { case AUTHENTICATED: break; default: ret = AUTH_ERROR; break; } } else { if(ret==NOT_AUTHENTICATED) ret = AUTH_INVALID_PASSWORD; else ret = AUTH_ERROR; } end: if (ret < 0) { /* check if required to add challenge header as avp */ if(!(flags&14)) return ret; if(flags&8) { qop = &auth_qauthint; } else if(flags&4) { qop = &auth_qauth; } if (get_challenge_hf(msg, (cred ? cred->stale : 0), &realm, NULL, NULL, qop, hftype, &hf) < 0) { ERR("Error while creating challenge\n"); ret = AUTH_ERROR; } else { val.s = hf; if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val) < 0) { LM_ERR("Error while creating attribute with challenge\n"); ret = AUTH_ERROR; } pkg_free(hf.s); } } error: return ret; }