static int parse_attr_params(void) { str tmp; tmp = reply_code_attr; trim(&tmp); if (!tmp.len || tmp.s[0] != '$') { ERR("Invalid attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } tmp.s++; tmp.len--; if (parse_avp_ident(&tmp, &avpid_code) < 0) { ERR("Error while parsing attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } tmp = reply_reason_attr; trim(&tmp); if (!tmp.len || tmp.s[0] != '$') { ERR("Invalid attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } tmp.s++; tmp.len--; if (parse_avp_ident(&tmp, &avpid_reason) < 0) { ERR("Error while parsing attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } tmp = contact_attr; trim(&tmp); if (!tmp.len || tmp.s[0] != '$') { ERR("Invalid attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } tmp.s++; tmp.len--; if (parse_avp_ident(&tmp, &avpid_contact) < 0) { ERR("Error while parsing attribute name '%.*s'\n", tmp.len, tmp.s); return -1; } return 0; }
static int select_attr_fixup(str* res, select_t* s, struct sip_msg* msg) { avp_ident_t *avp_ident; #define SEL_PARAM_IDX 1 if (! msg) { /* fixup call */ str attr_name; if (s->params[SEL_PARAM_IDX].type != SEL_PARAM_STR) { ERR("attribute name expected.\n"); return -1; } attr_name = s->params[SEL_PARAM_IDX].v.s; DEBUG("fix up for attribute '%.*s'\n", STR_FMT(&attr_name)); if (! (avp_ident = pkg_malloc(sizeof(avp_ident_t)))) { ERR("out of mem; requested: %d.\n", (int)sizeof(avp_ident_t)); return -1; } memset(avp_ident, 0, sizeof(avp_ident_t)); /* skip leading `$' */ if ((1 < attr_name.len) && (attr_name.s[0] == '$')) { attr_name.len --; attr_name.s ++; } if (parse_avp_ident(&attr_name, avp_ident) < 0) { ERR("failed to parse attribute name: `%.*s'.\n", STR_FMT(&attr_name)); pkg_free(avp_ident); } s->params[SEL_PARAM_IDX].v.p = avp_ident; s->params[SEL_PARAM_IDX].type = SEL_PARAM_PTR; } else { /* run time call */ avp_t *ret; avp_value_t val; #ifdef EXTRA_DEBUG assert(s->params[SEL_PARAM_IDX].type == SEL_PARAM_PTR); #endif avp_ident = s->params[SEL_PARAM_IDX].v.p; ret = search_first_avp(avp_ident->flags, avp_ident->name, &val, NULL); if (ret && ret->flags & AVP_VAL_STR) *res = val.s; } return 0; #undef SEL_PARAM_IDX }
static int get_avp_id(avp_ident_t* id, fparam_t* p, struct sip_msg* msg) { str str_id; avp_t* avp; avp_value_t val; int ret; switch(p->type) { case FPARAM_AVP: avp = search_avp(p->v.avp, &val, 0); if (!avp) { DBG("get_avp_id: AVP %s does not exist\n", p->orig); return -1; } if ((avp->flags & AVP_VAL_STR) == 0) { DBG("get_avp_id: Not a string AVP\n"); return -1; } str_id = val.s; break; case FPARAM_SELECT: ret = run_select(&str_id, p->v.select, msg); if (ret < 0 || ret > 0) return -1; break; case FPARAM_STR: str_id = p->v.str; break; default: ERR("Invalid parameter type in get_avp_id\n"); return -1; } return parse_avp_ident(&str_id, id); }
static int mod_init(void) { str attr; DBG("auth module - initializing\n"); /* If the parameter was not used */ if (sec_param == 0) { /* Generate secret using random generator */ if (generate_random_secret() < 0) { LOG(L_ERR, "auth:mod_init: Error while generating random secret\n"); return -3; } } else { /* Otherwise use the parameter's value */ secret1.s = sec_param; secret1.len = strlen(secret1.s); if (auth_checks_reg || auth_checks_ind || auth_checks_ood) { /* divide the secret in half: one half for secret1 and one half for * secret2 */ secret2.len = secret1.len/2; secret1.len -= secret2.len; secret2.s = secret1.s + secret1.len; if (secret2.len < 16) { WARN("auth: consider a longer secret when extra auth checks are" " enabled (the config secret is divided in 2!)\n"); } } } if ((!challenge_attr.s || challenge_attr.len == 0) || challenge_attr.s[0] != '$') { ERR("auth: Invalid value of challenge_attr module parameter\n"); return -1; } attr.s = challenge_attr.s + 1; attr.len = challenge_attr.len - 1; if (parse_avp_ident(&attr, &challenge_avpid) < 0) { ERR("auth: Error while parsing value of challenge_attr module parameter\n"); return -1; } parse_qop(&qop); switch(qop.qop_parsed){ case QOP_OTHER: ERR("auth: Unsupported qop parameter value\n"); return -1; case QOP_AUTH: case QOP_AUTHINT: if (nc_enabled){ #ifndef USE_NC WARN("auth: nounce count support enabled from config, but" " disabled at compile time (recompile with -DUSE_NC)\n"); nc_enabled=0; #else if (nid_crt==0) init_nonce_id(); if (init_nonce_count()!=0) return -1; #endif } #ifdef USE_NC else{ INFO("auth: qop set, but nonce-count (nc_enabled) support" " disabled\n"); } #endif break; default: if (nc_enabled){ WARN("auth: nonce-count support enabled, but qop not set\n"); nc_enabled=0; } break; } if (otn_enabled){ #ifdef USE_OT_NONCE if (nid_crt==0) init_nonce_id(); if (init_ot_nonce()!=0) return -1; #else WARN("auth: one-time-nonce support enabled from config, but " "disabled at compile time (recompile with -DUSE_OT_NONCE)\n"); otn_enabled=0; #endif /* USE_OT_NONCE */ } return 0; }
/** Generic parameter fixup function. * Creates a fparam_t structure. * @param type contains allowed parameter types * @param param is the parameter that will be fixed-up * * @return * 0 on success, * 1 if the param doesn't match the specified type * <0 on failure */ int fix_param(int type, void** param) { fparam_t* p; str name, s; int num; int err; p = (fparam_t*)pkg_malloc(sizeof(fparam_t)); if (!p) { LM_ERR("No memory left\n"); return E_OUT_OF_MEM; } memset(p, 0, sizeof(fparam_t)); p->orig = *param; switch(type) { case FPARAM_UNSPEC: LM_ERR("Invalid type value\n"); goto error; case FPARAM_STRING: p->v.asciiz = *param; /* no break */ case FPARAM_STR: p->v.str.s = (char*)*param; p->v.str.len = strlen(p->v.str.s); p->fixed = &p->v; break; case FPARAM_INT: s.s = (char*)*param; s.len = strlen(s.s); err = str2sint(&s, &num); if (err == 0) { p->v.i = (int)num; } else { /* Not a number */ pkg_free(p); return 1; } p->fixed = (void*)(long)num; break; case FPARAM_REGEX: if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) { LM_ERR("No memory left\n"); goto error; } if (regcomp(p->v.regex, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) { pkg_free(p->v.regex); p->v.regex=0; /* not a valid regex */ goto no_match; } p->fixed = p->v.regex; break; case FPARAM_AVP: name.s = (char*)*param; name.len = strlen(name.s); trim(&name); if (!name.len || name.s[0] != '$') { /* Not an AVP identifier */ goto no_match; } name.s++; name.len--; if (parse_avp_ident(&name, &p->v.avp) < 0) { /* invalid avp identifier (=> no match) */ goto no_match; } p->fixed = &p->v; break; case FPARAM_SELECT: name.s = (char*)*param; name.len = strlen(name.s); trim(&name); if (!name.len || name.s[0] != '@') { /* Not a select identifier */ goto no_match; } if (parse_select(&name.s, &p->v.select) < 0) { LM_ERR("Error while parsing select identifier\n"); goto error; } p->fixed = &p->v; break; case FPARAM_SUBST: s.s = *param; s.len = strlen(s.s); p->v.subst = subst_parser(&s); if (!p->v.subst) { LM_ERR("Error while parsing regex substitution\n"); goto error; } p->fixed = &p->v; break; case FPARAM_PVS: name.s = (char*)*param; name.len = strlen(name.s); trim(&name); if (!name.len || name.s[0] != '$'){ /* not a pvs identifier */ goto no_match; } p->v.pvs=pkg_malloc(sizeof(pv_spec_t)); if (p->v.pvs==0){ LM_ERR("out of memory while parsing pv_spec_t\n"); goto error; } if (pv_parse_spec2(&name, p->v.pvs, 1)==0){ /* not a valid pvs identifier (but it might be an avp) */ pkg_free(p->v.pvs); p->v.pvs=0; goto no_match; } p->fixed = p->v.pvs; break; case FPARAM_PVE: name.s = (char*)*param; name.len = strlen(name.s); if (pv_parse_format(&name, &p->v.pve)<0){ LM_ERR("bad PVE format: \"%.*s\"\n", name.len, name.s); goto error; } p->fixed = &p->v; break; } p->type = type; *param = (void*)p; return 0; no_match: pkg_free(p); return 1; error: pkg_free(p); return E_UNSPEC; }
static int mod_init(void) { str attr; DBG("auth module - initializing\n"); auth_realm_prefix.len = strlen(auth_realm_prefix.s); /* bind the SL API */ if (sl_load_api(&slb)!=0) { LM_ERR("cannot bind to SL API\n"); return -1; } /* If the parameter was not used */ if (sec_param == 0) { /* Generate secret using random generator */ if (generate_random_secret() < 0) { LM_ERR("Error while generating random secret\n"); return -3; } } else { /* Otherwise use the parameter's value */ secret1.s = sec_param; secret1.len = strlen(secret1.s); if (auth_checks_reg || auth_checks_ind || auth_checks_ood) { /* divide the secret in half: one half for secret1 and one half for * secret2 */ secret2.len = secret1.len/2; secret1.len -= secret2.len; secret2.s = secret1.s + secret1.len; if (secret2.len < 16) { LM_WARN("consider a longer secret when extra auth checks are" " enabled (the config secret is divided in 2!)\n"); } } } if ((!challenge_attr.s || challenge_attr.len == 0) || challenge_attr.s[0] != '$') { LM_ERR("Invalid value of challenge_attr module parameter\n"); return -1; } attr.s = challenge_attr.s + 1; attr.len = challenge_attr.len - 1; if (parse_avp_ident(&attr, &challenge_avpid) < 0) { LM_ERR("Error while parsing value of challenge_attr module" " parameter\n"); return -1; } parse_qop(&auth_qop); switch(auth_qop.qop_parsed){ case QOP_OTHER: LM_ERR("Unsupported qop parameter value\n"); return -1; case QOP_AUTH: case QOP_AUTHINT: if (nc_enabled){ #ifndef USE_NC LM_WARN("nounce count support enabled from config, but" " disabled at compile time (recompile with -DUSE_NC)\n"); nc_enabled=0; #else if (nid_crt==0) init_nonce_id(); if (init_nonce_count()!=0) return -1; #endif } #ifdef USE_NC else{ LM_INFO("qop set, but nonce-count (nc_enabled) support" " disabled\n"); } #endif break; default: if (nc_enabled){ LM_WARN("nonce-count support enabled, but qop not set\n"); nc_enabled=0; } break; } if (otn_enabled){ #ifdef USE_OT_NONCE if (nid_crt==0) init_nonce_id(); if (init_ot_nonce()!=0) return -1; #else LM_WARN("one-time-nonce support enabled from config, but " "disabled at compile time (recompile with -DUSE_OT_NONCE)\n"); otn_enabled=0; #endif /* USE_OT_NONCE */ } if (auth_algorithm.len == 0 || strcmp(auth_algorithm.s, "MD5") == 0) { hash_hex_len = HASHHEXLEN; calc_HA1 = calc_HA1_md5; calc_response = calc_response_md5; } else if (strcmp(auth_algorithm.s, "SHA-256") == 0) { hash_hex_len = HASHHEXLEN_SHA256; calc_HA1 = calc_HA1_sha256; calc_response = calc_response_sha256; } else { LM_ERR("Invalid algorithm provided." " Possible values are \"\", \"MD5\" or \"SHA-256\"\n"); return -1; } return 0; }