Module: sems Branch: master Commit: db53a4ba9c535d8c936af274c4b028b7df857042 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=db53a4ba9c535d8c936af274c4b028b7df857042
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Wed May 4 15:52:39 2011 +0200 adds support for "qop" as described in rfc2617. Please note that MD5-sess is still not supported. --- core/plug-in/uac_auth/UACAuth.cpp | 106 +++++++++++++++++++++++++++--------- core/plug-in/uac_auth/UACAuth.h | 10 +++- 2 files changed, 87 insertions(+), 29 deletions(-) diff --git a/core/plug-in/uac_auth/UACAuth.cpp b/core/plug-in/uac_auth/UACAuth.cpp index c0e27b6..5804889 100644 --- a/core/plug-in/uac_auth/UACAuth.cpp +++ b/core/plug-in/uac_auth/UACAuth.cpp @@ -155,7 +155,7 @@ bool UACAuth::onSipReply(const AmSipReply& reply, int old_dlg_status, const stri if (do_auth(reply.code, auth_hdr, ri->second.method, - auth_uri, result)) { + auth_uri, ri->second.body, result)) { string hdrs = ri->second.hdrs; // TODO(?): strip headers // ((code==401) ? stripHeader(ri->second.hdrs, "Authorization") : @@ -274,11 +274,14 @@ bool UACAuth::parse_header(const string& auth_hdr, UACAuthDigestChallenge& chall challenge.opaque = find_attribute("opaque", auth_hdr); challenge.algorithm = find_attribute("algorithm", auth_hdr); challenge.qop = find_attribute("qop", auth_hdr); + return (challenge.realm.length() && challenge.nonce.length()); } bool UACAuth::do_auth(const unsigned int code, const string& auth_hdr, - const string& method, const string& uri, string& result) { + const string& method, const string& uri, + const string& body, string& result) +{ if (!auth_hdr.length()) { ERROR("empty auth header.\n"); return false; @@ -295,8 +298,10 @@ bool UACAuth::do_auth(const unsigned int code, const string& auth_hdr, return false; } - DBG("realm='%s', nonce='%s'\n", challenge.realm.c_str(), - challenge.nonce.c_str()); + DBG("realm='%s', nonce='%s', qop='%s'\n", + challenge.realm.c_str(), + challenge.nonce.c_str(), + challenge.qop.c_str()); if (credential->realm.length() && (credential->realm != challenge.realm)) { @@ -306,23 +311,60 @@ bool UACAuth::do_auth(const unsigned int code, const string& auth_hdr, HASHHEX ha1; HASHHEX ha2; + HASHHEX hentity; HASHHEX response; + bool qop_auth=false; + bool qop_auth_int=false; + string cnonce; + string qop_value; + + if(!challenge.qop.empty()){ + + qop_auth = key_in_list(challenge.qop,"auth"); + qop_auth_int = key_in_list(challenge.qop,"auth-int"); + + if(qop_auth || qop_auth_int) { + + cnonce = int2hex(get_random(),true); + + if(challenge.nonce == nonce) + nonce_count++; + else + nonce_count = 1; + + if(qop_auth_int){ + uac_calc_hentity(body,hentity); + qop_value = "auth-int"; + } + else + qop_value = "auth"; + } + } /* do authentication */ - uac_calc_HA1( challenge, ""/*cnonce*/, ha1); - uac_calc_HA2( method, uri, challenge, 0/*hentity*/, ha2); - uac_calc_response( ha1, ha2, challenge, ""/*nc*/, "" /*cnonce*/, response); + uac_calc_HA1( challenge, cnonce, ha1); + uac_calc_HA2( method, uri, challenge, qop_auth_int ? hentity : NULL, ha2); + uac_calc_response( ha1, ha2, challenge, cnonce, qop_value, response); DBG("calculated response = %s\n", response); // compile auth response - result = ((code==401) ? SIP_HDR_COLSP(SIP_HDR_AUTHORIZATION) "Digest username=\"" : - SIP_HDR_COLSP(SIP_HDR_PROXY_AUTHORIZATION) "Digest username=\"") - + credential->user + "\", realm=\"" + challenge.realm + "\", nonce=\""+challenge.nonce + - "\", uri=\""+uri+"\", "; + result = ((code==401) ? SIP_HDR_COLSP(SIP_HDR_AUTHORIZATION) : + SIP_HDR_COLSP(SIP_HDR_PROXY_AUTHORIZATION)); + + result += "Digest username=\"" + credential->user + "\", " + "realm=\"" + challenge.realm + "\", " + "nonce=\"" + challenge.nonce + "\", " + "uri=\"" + uri + "\", "; + if (challenge.opaque.length()) - result+="opaque=\""+challenge.opaque+"\", "; + result += "opaque=\"" + challenge.opaque + "\", "; - result+="response=\""+string((char*)response)+"\", algorithm=MD5\n"; + if (!qop_value.empty()) + result += "qop=\"" + qop_value + "\", " + "cnonce=\"" + cnonce + "\", " + "nc=\"" + int2hex(nonce_count,true) + "\", "; + + result += "response=\"" + string((char*)response) + "\", algorithm=MD5\n"; DBG("Auth req hdr: '%s'\n", result.c_str()); @@ -410,7 +452,7 @@ void UACAuth::uac_calc_HA2( const string& method, const string& uri, MD5Update(&Md5Ctx, hc, 1); w_MD5Update(&Md5Ctx, uri); - if ( challenge.qop == "auth-int" ) + if ( hentity != 0 ) { MD5Update(&Md5Ctx, hc, 1); MD5Update(&Md5Ctx, hentity, HASHHEXLEN); @@ -420,15 +462,27 @@ void UACAuth::uac_calc_HA2( const string& method, const string& uri, cvt_hex(HA2, HA2Hex); } +/* + * calculate H(body) + */ +void UACAuth::uac_calc_hentity( const string& body, HASHHEX hentity ) +{ + MD5_CTX Md5Ctx; + HASH h; + + MD5Init(&Md5Ctx); + w_MD5Update(&Md5Ctx, body); + MD5Final(h, &Md5Ctx); + cvt_hex(h,hentity); +} /* * calculate request-digest/response-digest as per HTTP Digest spec */ void UACAuth::uac_calc_response( HASHHEX ha1, HASHHEX ha2, - UACAuthDigestChallenge& challenge, - const string& nc, const string& cnonce, - HASHHEX response) + UACAuthDigestChallenge& challenge, const string& cnonce, + const string& qop_value, HASHHEX response) { unsigned char hc[1]; hc[0]=':'; MD5_CTX Md5Ctx; @@ -440,17 +494,15 @@ void UACAuth::uac_calc_response( HASHHEX ha1, HASHHEX ha2, w_MD5Update(&Md5Ctx, challenge.nonce); MD5Update(&Md5Ctx, hc, 1); - if (challenge.qop.length() - && challenge.qop == "auth_int") - { + if (!qop_value.empty()) { - w_MD5Update(&Md5Ctx, nc); - MD5Update(&Md5Ctx, hc, 1); - w_MD5Update(&Md5Ctx, cnonce); - MD5Update(&Md5Ctx, hc, 1); - w_MD5Update(&Md5Ctx, "" /*challenge.qop*/); - MD5Update(&Md5Ctx, hc, 1); - }; + w_MD5Update(&Md5Ctx, int2hex(nonce_count,true)); + MD5Update(&Md5Ctx, hc, 1); + w_MD5Update(&Md5Ctx, cnonce); + MD5Update(&Md5Ctx, hc, 1); + w_MD5Update(&Md5Ctx, qop_value); + MD5Update(&Md5Ctx, hc, 1); + }; MD5Update(&Md5Ctx, ha2, HASHHEXLEN); MD5Final(RespHash, &Md5Ctx); diff --git a/core/plug-in/uac_auth/UACAuth.h b/core/plug-in/uac_auth/UACAuth.h index fd7f98b..d585f40 100644 --- a/core/plug-in/uac_auth/UACAuth.h +++ b/core/plug-in/uac_auth/UACAuth.h @@ -105,6 +105,9 @@ class UACAuth : public AmSessionEventHandler UACAuthCred* credential; AmSipDialog* dlg; + string nonce; // last nonce received from server + unsigned int nonce_count; + std::string find_attribute(const std::string& name, const std::string& header); bool parse_header(const std::string& auth_hdr, UACAuthDigestChallenge& challenge); @@ -116,10 +119,12 @@ class UACAuth : public AmSessionEventHandler UACAuthDigestChallenge& challenge, HASHHEX hentity, HASHHEX HA2Hex ); + + void uac_calc_hentity( const std::string& body, HASHHEX hentity ); void uac_calc_response( HASHHEX ha1, HASHHEX ha2, UACAuthDigestChallenge& challenge, - const std::string& nc, const std::string& cnonce, + const std::string& cnonce, const string& qop_value, HASHHEX response); /** @@ -127,7 +132,8 @@ class UACAuth : public AmSessionEventHandler * @return true if successful */ bool do_auth(const unsigned int code, const string& auth_hdr, - const string& method, const string& uri, string& result); + const string& method, const string& uri, + const string& body, string& result); public: _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
