static inline int auth_get_ha1(struct sip_msg *msg, struct username* _username, str* _domain, char* _ha1) { pv_value_t sval; /* get username from PV */ memset(&sval, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &user_spec, &sval)==0) { if(sval.flags==PV_VAL_NONE || (sval.flags&PV_VAL_NULL) || (sval.flags&PV_VAL_EMPTY) || (!(sval.flags&PV_VAL_STR))) { pv_value_destroy(&sval); return 1; } if(sval.rs.len!= _username->whole.len || strncasecmp(sval.rs.s, _username->whole.s, sval.rs.len)) { LM_DBG("username mismatch [%.*s] [%.*s]\n", _username->whole.len, _username->whole.s, sval.rs.len, sval.rs.s); pv_value_destroy(&sval); return 1; } } else { return 1; } /* get password from PV */ memset(&sval, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &passwd_spec, &sval)==0) { if(sval.flags==PV_VAL_NONE || (sval.flags&PV_VAL_NULL) || (sval.flags&PV_VAL_EMPTY) || (!(sval.flags&PV_VAL_STR))) { pv_value_destroy(&sval); return 1; } } else { return 1; } if (auth_calc_ha1) { /* Only plaintext passwords are stored in database, * we have to calculate HA1 */ calc_HA1(HA_MD5, &_username->whole, _domain, &sval.rs, 0, 0, _ha1); LM_DBG("HA1 string calculated: %s\n", _ha1); } else { memcpy(_ha1, sval.rs.s, sval.rs.len); _ha1[sval.rs.len] = '\0'; } return 0; }
/** * @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; }
static inline int get_ha1(struct username* _username, str* _domain, char* _table, char* _ha1, db_res_t** res) { struct aaa_avp *cred; db_key_t keys[2]; db_val_t vals[2]; db_key_t *col; str result; int n, nc; col = pkg_malloc(sizeof(*col) * (credentials_n + 1)); if (col == NULL) { LOG(L_ERR, "get_ha1(): Error while allocating memory\n"); return -1; } keys[0] = user_column.s; keys[1] = domain_column.s; col[0] = (_username->domain.len && !calc_ha1) ? (pass_column_2.s) : (pass_column.s); for (n = 0, cred=credentials; cred ; n++, cred=cred->next) { col[1 + n] = cred->attr_name.s; } VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR; VAL_NULL(vals) = VAL_NULL(vals + 1) = 0; VAL_STR(vals).s = _username->user.s; VAL_STR(vals).len = _username->user.len; if (_username->domain.len) { VAL_STR(vals + 1) = _username->domain; } else { VAL_STR(vals + 1) = *_domain; } n = (use_domain ? 2 : 1); nc = 1 + credentials_n; if (auth_dbf.use_table(auth_db_handle, _table) < 0) { LOG(L_ERR, "get_ha1(): Error in use_table\n"); pkg_free(col); return -1; } if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, res) < 0) { LOG(L_ERR, "get_ha1(): Error while querying database\n"); pkg_free(col); return -1; } pkg_free(col); if (RES_ROW_N(*res) == 0) { DBG("get_ha1(): no result for user \'%.*s@%.*s\'\n", _username->user.len, ZSW(_username->user.s), (use_domain ? (_domain->len) : 0), ZSW(_domain->s)); return 1; } result.s = (char*)ROW_VALUES(RES_ROWS(*res))[0].val.string_val; result.len = strlen(result.s); if (calc_ha1) { /* Only plaintext passwords are stored in database, * we have to calculate HA1 */ calc_HA1(HA_MD5, &_username->whole, _domain, &result, 0, 0, _ha1); DBG("HA1 string calculated: %s\n", _ha1); } else { memcpy(_ha1, result.s, result.len); _ha1[result.len] = '\0'; } return 0; }
/** * @brief do WWW-Digest authentication with password taken from cfg var */ int pv_authenticate(struct sip_msg *msg, str *realm, str *passwd, int flags, int hftype, str *method) { 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; switch(pre_auth(msg, realm, hftype, &h, NULL)) { case NONCE_REUSED: LM_DBG("nonce reused"); ret = AUTH_NONCE_REUSED; goto end; case STALE_NONCE: LM_DBG("stale nonce\n"); ret = AUTH_STALE_NONCE; goto end; case NO_CREDENTIALS: LM_DBG("no credentials\n"); ret = AUTH_NO_CREDENTIALS; goto end; 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), 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); } } return ret; }
/*** void CPocketSMDlg::OnButtonDeleteContact() { // TODO: Add your control notification handler code here int nIndex = m_ctlComboTo.GetCurSel(); if(nIndex == CB_ERR) { AfxMessageBox(_T("No contact selected from the list.")); return; } if(m_ctlComboTo.DeleteString(nIndex) == CB_ERR) { AfxMessageBox(_T("The contact could not be deleted.")); return; } m_ctlComboTo.SetCurSel(0); } ***/ int CPocketSMDlg::computeAuthHeader( CString sipRepl ) { CString wwwAuth; CString authHdr; CString newSipReq; int h,t,l,n; int quote; CString s; CString strTmp; CString par; CString cnonce = "SAIDF3W2R8FAETR329FAHSDF34"; /* header params */ CString param[]={"realm","nonce","opaque","algorithm","qop","stale"}; CString vals[]={"","","","","",""}; CString strURI = "sip:"; int quoted[]={1,1,1,0,1,0}; HASHHEX hashHex1; HASHHEX hashHex2; str strMethod = {"REGISTER", 8}; char userBuf[30], passwdBuf[30], nonceBuf[50], cnonceBuf[50], uriBuf[50], realmBuf[50]; str sUser = {userBuf, 30}, sPasswd = {passwdBuf, 30}, sRealm = {realmBuf, 50}, sNonce = {nonceBuf, 50}, sCnonce = {cnonceBuf, 50}, sURI = {uriBuf, 50}; m_strAuthHdr = ""; strURI += m_strSrvPart; //AddInfoMessage(sipRepl); //UpdateDisplayedMessage(); /* get the www-auth header from reply */ h = sipRepl.Find(_T("WWW-Authenticate")); if (h==-1) return -1; strTmp = sipRepl.Right(sipRepl.GetLength()-h); t = strTmp.Find('\n'); if(strTmp.GetAt(t-1) == '\r') t--; wwwAuth = sipRepl.Mid(h,t); /* parse the www_auth header */ s = wwwAuth; h = s.Find(_T("Digest")); if (h==-1) return -2; h += 6; /* comput the length of useful part */ l = s.GetLength(); while (s.GetAt(l-1)=='\n' || s.GetAt(l-1)=='\r') l--; /* look for all the params */ while(h<l) { /* search the begining of the next param */ while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') ) h++; if (h==l) return -3; /* get the param name */ t = h; while( t<l && s.GetAt(t)!=' ' && s.GetAt(t)!='=') t++; if (t==l || t==h) return -4; par = s.Mid(h,t-h); h=t; /* are we looking for this parameter? */ for(n=0; n<6; n++) if(!param[n].CompareNoCase(par)) break; if(n==6) n = -1; /* eat spaces */ while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') ) h++; /* do we have a "="? */ if (h==l || s.GetAt(h)!='=' || ++h==l) return -5; /* eat spaces */ while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') ) h++; /* param's value */ if ( n!=-1 && ( (quoted[n]==1 && s.GetAt(h)!='"') || (quoted[n]==0 && s.GetAt(h)=='"')) ) return -6; if(n!=-1 && quoted[n]==1) h++; quote=(n==-1&&s.GetAt(h)=='"')||(n!=-1&"ed[n]==1)?1:0; /* look for the end of value */ t = h; while( t<l && (quote && s.GetAt(t)!='"' || !quote && s.GetAt(t)!=' ' && s.GetAt(t)!=',') ) t++; if (t==h) return -7; if (n!=-1) { vals[n] = s.Mid(h,t-h); } h = t + (quote?1:0); /* eat spaces */ while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') ) h++; if (h==l) break; /* here must be a ',' */ if (s.GetAt(h)!=',' || ++h==l) return -8; } /* some checkings */ if (vals[0]=="") return -9; if (vals[1]=="") return -10; /* comput the authentication */ translateToStr(m_strUserPart, &sUser); translateToStr(m_strPassword, &sPasswd); translateToStr(vals[0], &sRealm); translateToStr(vals[1], &sNonce); translateToStr(cnonce, &sCnonce); translateToStr(strURI, &sURI); calc_HA1(HA_MD5, &sUser, &sRealm, &sPasswd, &sNonce, &sCnonce, hashHex1); calc_response(hashHex1, &sNonce, NULL, &sCnonce, NULL, 0, &strMethod, &sURI, NULL, hashHex2); /* build authorization header */ m_strAuthHdr = "Authorization: Digest"; /* add username */ m_strAuthHdr += " username=\""+m_strUserPart+"\""; /* add realm */ m_strAuthHdr += ", realm=\""+vals[0]+"\""; /* add uri */ m_strAuthHdr += ", uri=\""; m_strAuthHdr += strURI; m_strAuthHdr += "\""; /* add algorithm */ if(vals[3].GetLength() > 0) m_strAuthHdr += ", algorithm=\""+vals[3]+"\""; else m_strAuthHdr += ", algorithm=\"md5\""; /* add nonce */ m_strAuthHdr += ", nonce=\""+vals[1]+"\""; /* add opaque, if needed */ if (vals[2]!="") m_strAuthHdr += ", opaque=\""+vals[2]+"\""; /* add qop, if needed */ if (vals[4]!="") { m_strAuthHdr += ", qop=\""+vals[4]+"\""; m_strAuthHdr += ", cnonce=\""+cnonce+"\""; } /* add response */ m_strAuthHdr += ", response=\""; m_strAuthHdr += hashHex2; m_strAuthHdr += "\""; return 0; }