Browse code

b/f: add authentication header to in-dialog requests

Stefan Sayer authored on 22/06/2011 12:55:13
Showing 3 changed files
... ...
@@ -44,6 +44,8 @@ using std::string;
44 44
 #define SIP_FLAGS_VERBATIM     1 // send request verbatim, 
45 45
                                  // i.e. modify as little as possible
46 46
 
47
+#define SIP_FLAGS_NOAUTH       1<<1 // don't add authentication header
48
+
47 49
 class AmSipTimeoutEvent;
48 50
 class AmSipDialogEventHandler;
49 51
 
... ...
@@ -149,10 +149,10 @@ bool UACAuth::onSipReply(const AmSipReply& reply, AmSipDialog::Status old_dlg_st
149 149
 	    getHeader(reply.hdrs, SIP_HDR_PROXY_AUTHENTICATE, true) : 
150 150
 	    getHeader(reply.hdrs, SIP_HDR_WWW_AUTHENTICATE, true);
151 151
 	  string result; 
152
-			
152
+
153 153
 	  string auth_uri; 
154 154
 	  auth_uri = dlg->remote_uri;
155
-				
155
+
156 156
 	  if (do_auth(reply.code, auth_hdr,  
157 157
 		      ri->second.method,
158 158
 		      auth_uri, ri->second.body, result)) {
... ...
@@ -191,7 +191,7 @@ bool UACAuth::onSipReply(const AmSipReply& reply, AmSipDialog::Status old_dlg_st
191 191
 	    if (dlg->sendRequest(ri->second.method,
192 192
 				 ri->second.content_type,
193 193
 				 ri->second.body, 
194
-				 hdrs, SIP_FLAGS_VERBATIM) == 0) {
194
+				 hdrs, SIP_FLAGS_VERBATIM | SIP_FLAGS_NOAUTH) == 0) {
195 195
 	      processed = true;
196 196
               DBG("authenticated request successfully sent.\n");
197 197
 	      // undo SIP dialog status change
... ...
@@ -217,6 +217,20 @@ bool UACAuth::onSendRequest(const string& method,
217 217
 			    int flags,
218 218
 			    unsigned int cseq)
219 219
 {
220
+  // add authentication header if nonce is already there
221
+  string result;
222
+  if (!(flags & SIP_FLAGS_NOAUTH) &&
223
+      !challenge.nonce.empty() &&
224
+      do_auth(challenge, challenge_code,
225
+	      method,
226
+	      dlg->remote_uri, body, result)) {
227
+    // add headers
228
+    if (hdrs == "\r\n" || hdrs == "\r" || hdrs == "\n")
229
+      hdrs = result;
230
+    else
231
+      hdrs += result;
232
+  }
233
+
220 234
   DBG("adding %d to list of sent requests.\n", cseq);
221 235
   sent_requests[cseq] = SIPRequestInfo(method, 
222 236
 				       content_type,
... ...
@@ -280,20 +294,30 @@ bool UACAuth::parse_header(const string& auth_hdr, UACAuthDigestChallenge& chall
280 294
 }
281 295
 
282 296
 bool UACAuth::do_auth(const unsigned int code, const string& auth_hdr,  
283
-		      const string& method, const string& uri, 
284
-		      const string& body, string& result) 
297
+		      const string& method, const string& uri,
298
+		      const string& body, string& result)
285 299
 {
286 300
   if (!auth_hdr.length()) {
287 301
     ERROR("empty auth header.\n");
288 302
     return false;
289 303
   }
290 304
 
291
-  UACAuthDigestChallenge challenge;
292 305
   if (!parse_header(auth_hdr, challenge)) {
293 306
     ERROR("error parsing auth header '%s'\n", auth_hdr.c_str());
294 307
     return false;
295 308
   }
296
-  
309
+
310
+  challenge_code = code;
311
+
312
+  return do_auth(challenge, code, method, uri, body, result);
313
+}
314
+
315
+
316
+bool UACAuth::do_auth(const UACAuthDigestChallenge& challenge,
317
+		      const unsigned int code,
318
+		      const string& method, const string& uri, 
319
+		      const string& body, string& result) 
320
+{
297 321
   if ((challenge.algorithm.length()) && (challenge.algorithm != "MD5")) {
298 322
     DBG("unsupported algorithm: '%s'\n", challenge.algorithm.c_str());
299 323
     return false;
... ...
@@ -405,7 +429,7 @@ static inline void cvt_hex(HASH bin, HASHHEX hex)
405 429
 /* 
406 430
  * calculate H(A1)
407 431
  */
408
-void UACAuth::uac_calc_HA1(UACAuthDigestChallenge& challenge,
432
+void UACAuth::uac_calc_HA1(const UACAuthDigestChallenge& challenge,
409 433
 			   string cnonce,
410 434
 			   HASHHEX sess_key)
411 435
 {
... ...
@@ -440,7 +464,7 @@ void UACAuth::uac_calc_HA1(UACAuthDigestChallenge& challenge,
440 464
  * calculate H(A2)
441 465
  */
442 466
 void UACAuth::uac_calc_HA2( const string& method, const string& uri,
443
-			    UACAuthDigestChallenge& challenge,
467
+			    const UACAuthDigestChallenge& challenge,
444 468
 			    HASHHEX hentity,
445 469
 			    HASHHEX HA2Hex )
446 470
 {
... ...
@@ -481,9 +505,9 @@ void UACAuth::uac_calc_hentity( const string& body, HASHHEX hentity )
481 505
 /* 
482 506
  * calculate request-digest/response-digest as per HTTP Digest spec 
483 507
  */
484
-void UACAuth::uac_calc_response( HASHHEX ha1, HASHHEX ha2,
485
-				 UACAuthDigestChallenge& challenge, const string& cnonce,
486
-				 const string& qop_value, HASHHEX response)
508
+void UACAuth::uac_calc_response(HASHHEX ha1, HASHHEX ha2,
509
+				const UACAuthDigestChallenge& challenge, const string& cnonce,
510
+				const string& qop_value, HASHHEX response)
487 511
 {
488 512
   unsigned char hc[1]; hc[0]=':';
489 513
   MD5_CTX Md5Ctx;
... ...
@@ -107,35 +107,47 @@ class UACAuth : public AmSessionEventHandler
107 107
   UACAuthCred* credential;
108 108
   AmSipDialog* dlg;
109 109
 
110
+  UACAuthDigestChallenge challenge;
111
+  unsigned int challenge_code;
112
+
110 113
   string nonce; // last nonce received from server
111 114
   unsigned int nonce_count;
112 115
 
113 116
   std::string find_attribute(const std::string& name, const std::string& header);
114 117
   bool parse_header(const std::string& auth_hdr, UACAuthDigestChallenge& challenge);
115 118
 
116
-  void uac_calc_HA1(UACAuthDigestChallenge& challenge,
119
+  void uac_calc_HA1(const UACAuthDigestChallenge& challenge,
117 120
 		    std::string cnonce,
118 121
 		    HASHHEX sess_key);
119 122
 
120 123
   void uac_calc_HA2( const std::string& method, const std::string& uri,
121
-		     UACAuthDigestChallenge& challenge,
124
+		     const UACAuthDigestChallenge& challenge,
122 125
 		     HASHHEX hentity,
123 126
 		     HASHHEX HA2Hex );
124 127
 
125 128
   void uac_calc_hentity( const std::string& body, HASHHEX hentity );
126 129
 	
127 130
   void uac_calc_response( HASHHEX ha1, HASHHEX ha2,
128
-			  UACAuthDigestChallenge& challenge,
131
+			  const UACAuthDigestChallenge& challenge,
129 132
 			  const std::string& cnonce, const string& qop_value, 
130 133
 			  HASHHEX response);
131 134
 	
132
-  /** 
133
-   *  do auth on cmd with nonce in auth_hdr if possible 
134
-   *  @return true if successful 
135
+  /**
136
+   *  do auth on cmd with nonce in auth_hdr if possible
137
+   *  @return true if successful
135 138
    */
136 139
   bool do_auth(const unsigned int code, const string& auth_hdr,  
137 140
 	       const string& method, const string& uri, 
138 141
 	       const string& body, string& result);
142
+
143
+  /**
144
+   *  do auth on cmd with saved challenge
145
+   *  @return true if successful
146
+   */
147
+  bool do_auth(const UACAuthDigestChallenge& challenge,
148
+	       const unsigned int code,
149
+	       const string& method, const string& uri,
150
+	       const string& body, string& result);
139 151
 	
140 152
  public:
141 153