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

Reply via email to