Browse code

- tm: aggregate challenges (WWW/Proxy-Authenticate) from all the 401 & 407 if the final reply is a 401/407 (required by rfc3261). To turn this off and fall back to the old behaviour set tm aggregate_challenges parameter to 0 (see tm docs for more details) - core: header parse support for WWW-Authenticate and Proxy-Authenticate

Andrei Pelinescu-Onciul authored on 16/10/2006 18:44:01
Showing 15 changed files
... ...
@@ -67,7 +67,7 @@ MAIN_NAME=ser
67 67
 VERSION = 0
68 68
 PATCHLEVEL = 10
69 69
 SUBLEVEL =   99
70
-EXTRAVERSION = -dev52-tm_fixes
70
+EXTRAVERSION = -dev53-tm_fixes
71 71
 
72 72
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
73 73
 			$(SUBLEVEL) )
... ...
@@ -24,7 +24,15 @@ modules:
24 24
                 hashing after an uri (to, from or request uri)
25 25
               - improved uri hashing (password is ignored, port is used only
26 26
                 if != 5060 or 5061)
27
- - tm        - on 6xx immediately cancel all the branches for which a 
27
+ - tm        - aggregate challenges (WWW/Proxy-Authenticate) from all the
28
+               401 & 407 if the final reply is a 401/407. To turn this off
29
+               and fall back to the old behaviour set tm aggregate_challenges
30
+               parameter to 0.
31
+             - if a relayed 503 is the final reply, replace it by a 500
32
+             - if a 503 reply is received try the dns based failover
33
+               (forward to another ip if the original destination uri 
34
+                resolved to several SRV, A or AAAA records)
35
+             - on 6xx immediately cancel all the branches for which a 
28 36
                provisional response was received and wait for all the 
29 37
                branches to finish (either timeout, the 487 from the CANCEL
30 38
                or a final response still on the wire in the moment the
... ...
@@ -177,4 +177,30 @@ modparam("tm", "unix_tx_timeout", 250)
177 177
 	    </programlisting>
178 178
 	</example>
179 179
 	</section>
180
+
181
+    <section id="aggregate_challenges">
182
+	<title><varname>aggregate_challenges</varname> (integer)</title>
183
+	<para>
184
+		If set (default), the final reply is a 401 or a 407 and more then
185
+		one branch received a 401 or 407, then all the WWW-Authenticate and 
186
+		Proxy-Authenticate headers from all the 401 and 407 replies will 
187
+		be aggregated in a new final reply. If only one branch received the
188
+		 winning 401 or 407 then this reply will be forwarded (no new one
189
+		 will be built).
190
+		If 0 only the first 401, or if no 401 was received the first 407,  will
191
+		be forwarded (no header aggregation).
192
+	</para>
193
+	<para>
194
+	    Default value is 1 (required by rfc3261).
195
+	</para>
196
+	<example>
197
+	    <title>Set <varname>aggregate_challenges</varname> parameter</title>
198
+	    <programlisting>
199
+...
200
+modparam("tm", "aggregate_challenges", 0)
201
+...
202
+	    </programlisting>
203
+	</example>
204
+    </section>
205
+
180 206
 </section>
... ...
@@ -47,6 +47,7 @@
47 47
  *  2003-11-11  updated cloning of lump_rpl (bogdan)
48 48
  *  2004-03-31  alias shortcuts are also translated (andrei)
49 49
  *  2006-04-20  via->comp is also translated (andrei)
50
+ *  2006-10-16  HDR_{PROXY,WWW}_AUTHENTICATE_T cloned (andrei)
50 51
  */
51 52
 
52 53
 #include "defs.h"
... ...
@@ -387,7 +388,9 @@ struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg, int *sip_msg_len )
387 387
 		case HDR_REFERREDBY_T:
388 388
 		case HDR_REJECTCONTACT_T:
389 389
 		case HDR_REQUESTDISPOSITION_T:
390
-/* we ignore them for now even if they have something parsed*/
390
+		case HDR_WWW_AUTHENTICATE_T:
391
+		case HDR_PROXY_AUTHENTICATE_T:
392
+			/* we ignore them for now even if they have something parsed*/
391 393
 			break;
392 394
 		}/*switch*/
393 395
 	}/*for all headers*/
... ...
@@ -525,6 +528,8 @@ do { \
525 525
 		case HDR_REFERREDBY_T:
526 526
 		case HDR_REJECTCONTACT_T:
527 527
 		case HDR_REQUESTDISPOSITION_T:
528
+		case HDR_WWW_AUTHENTICATE_T:
529
+		case HDR_PROXY_AUTHENTICATE_T:
528 530
 			break;
529 531
 
530 532
 		case HDR_VIA_T:
... ...
@@ -82,6 +82,8 @@
82 82
  * 2005-12-09  added t_set_fr()  (andrei)
83 83
  * 2006-01-27  transaction lookup function will set up a cancel flag
84 84
  *             if the searched transaction was pre-canceled (andrei)
85
+ * 2006-10-16  401 & 407 replies are completely parsed if tm_aggregate_auth is
86
+ *              set (andrei)
85 87
  */
86 88
 
87 89
 #include "defs.h"
... ...
@@ -936,13 +938,24 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
936 936
 		} else {
937 937
 			/* we need Via for branch and Cseq method to distinguish
938 938
 			   replies with the same branch/cseqNr (CANCEL)
939
+			   and we need all the WWW/Proxy Authenticate headers for
940
+			   401 & 407 replies
939 941
 			*/
940
-			if ( parse_headers(p_msg, HDR_VIA1_F|HDR_CSEQ_F, 0 )==-1
941
-			|| !p_msg->via1 || !p_msg->cseq ) {
942
+			if (tm_aggregate_auth && 
943
+					(p_msg->REPLY_STATUS==401 || p_msg->REPLY_STATUS==407)){
944
+				if (parse_headers(p_msg, HDR_EOH_F,0)==-1){
945
+					LOG(L_WARN, "WARNING: the reply cannot be "
946
+								"completely parsed\n");
947
+					/* try to continue, via1 & cseq are checked below */
948
+				}
949
+			}else if ( parse_headers(p_msg, HDR_VIA1_F|HDR_CSEQ_F, 0 )==-1) {
942 950
 				LOG(L_ERR, "ERROR: reply cannot be parsed\n");
943 951
 				return -1;
944 952
 			}
945
-
953
+			if ((p_msg->via1==0) || (p_msg->cseq==0)){
954
+				LOG(L_ERR, "ERROR: reply doesn't have a via or cseq header\n");
955
+				return -1;
956
+			}
946 957
 			/* if that is an INVITE, we will also need to-tag
947 958
 			   for later ACK matching
948 959
 			*/
... ...
@@ -75,7 +75,9 @@
75 75
  *              if no 6xx reply => lowest class/code; if class==4xx =>
76 76
  *              prefer 401, 407, 415, 420 and 484   (andrei)
77 77
  * 2006-10-12  dns failover when a 503 is received
78
-*              replace a 503 final relayed reply by a 500 (andrei)
78
+ *              replace a 503 final relayed reply by a 500 (andrei)
79
+ * 2006-10-16  aggregate all the authorization headers/challenges when
80
+ *               the final response is 401 or 407 (andrei)
79 81
  *
80 82
  */
81 83
 
... ...
@@ -112,6 +114,9 @@
112 112
 
113 113
 /* restart fr timer on each provisional reply, default yes */
114 114
 int restart_fr_on_each_reply=1;
115
+/* if the final reponse is a 401 or a 407, aggregate all the 
116
+ * authorization headers (challenges) (rfc3261 requires this to be on) */
117
+int tm_aggregate_auth=1;
115 118
 
116 119
 /* are we processing original or shmemed request ? */
117 120
 enum route_mode rmode=MODE_REQUEST;
... ...
@@ -1133,6 +1138,87 @@ static int store_reply( struct cell *trans, int branch, struct sip_msg *rpl)
1133 1133
 		return 1;
1134 1134
 }
1135 1135
 
1136
+
1137
+
1138
+/* returns the number of authenticate replies (401 and 407) received so far
1139
+ *  (FAKED_REPLYes are excluded)
1140
+ *  It must be called with the REPLY_LOCK held */
1141
+inline static int auth_reply_count(struct cell *t, struct sip_msg* crt_reply)
1142
+{
1143
+	int count;
1144
+	int r;
1145
+
1146
+	count=0;
1147
+	if (crt_reply && (crt_reply!=FAKED_REPLY) && 
1148
+			(crt_reply->REPLY_STATUS ==401 || crt_reply->REPLY_STATUS ==407))
1149
+		count=1;
1150
+	for (r=0; r<t->nr_of_outgoings; r++){
1151
+		if (t->uac[r].reply && (t->uac[r].reply!=FAKED_REPLY) &&
1152
+				(t->uac[r].last_received==401 || t->uac[r].last_received==407))
1153
+			count++;
1154
+	}
1155
+	return count;
1156
+}
1157
+
1158
+
1159
+
1160
+/* must be called with the REPY_LOCK held */
1161
+inline static char* reply_aggregate_auth(int code, char* txt, str* new_tag, 
1162
+									struct cell* t, unsigned int* res_len, 
1163
+									struct bookmark* bm)
1164
+{
1165
+	int r;
1166
+	struct hdr_field* hdr;
1167
+	struct lump_rpl** first;
1168
+	struct lump_rpl** crt;
1169
+	struct lump_rpl* lst;
1170
+	struct lump_rpl*  lst_end;
1171
+	struct sip_msg* req;
1172
+	char* buf;
1173
+	
1174
+	first=0;
1175
+	lst_end=0;
1176
+	req=t->uas.request;
1177
+	
1178
+	for (r=0; r<t->nr_of_outgoings; r++){
1179
+		if (t->uac[r].reply && (t->uac[r].reply!=FAKED_REPLY) &&
1180
+			(t->uac[r].last_received==401 || t->uac[r].last_received==407)){
1181
+			for (hdr=t->uac[r].reply->headers; hdr; hdr=hdr->next){
1182
+				if (hdr->type==HDR_WWW_AUTHENTICATE_T ||
1183
+						hdr->type==HDR_PROXY_AUTHENTICATE_T){
1184
+					crt=add_lump_rpl2(req, hdr->name.s, hdr->len,
1185
+							LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
1186
+					if (crt==0){
1187
+						/* some kind of error, better stop */
1188
+						LOG(L_ERR, "ERROR: tm:reply_aggregate_auth:"
1189
+									" add_lump_rpl2 failed\n");
1190
+						goto skip;
1191
+					}
1192
+					lst_end=*crt;
1193
+					if (first==0) first=crt;
1194
+				}
1195
+			}
1196
+		}
1197
+	}
1198
+skip:
1199
+	buf=build_res_buf_from_sip_req(code, txt, new_tag, req, res_len, bm);
1200
+	/* clean the added lumps */
1201
+	if (first){
1202
+		lst=*first;
1203
+		*first=lst_end->next; /* "detach" the list of added rpl_lumps */
1204
+		lst_end->next=0; /* terminate lst */
1205
+		del_nonshm_lump_rpl(&lst);
1206
+		if (lst){
1207
+			LOG(L_CRIT, "BUG: tm: repply_aggregate_auth: rpl_lump list"
1208
+					    "contains shm alloc'ed lumps\n");
1209
+			abort();
1210
+		}
1211
+	}
1212
+	return buf;
1213
+}
1214
+
1215
+
1216
+
1136 1217
 /* this is the code which decides what and when shall be relayed
1137 1218
    upstream; note well -- it assumes it is entered locked with
1138 1219
    REPLY_LOCK and it returns unlocked!
... ...
@@ -1147,11 +1233,13 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
1147 1147
 	unsigned int res_len;
1148 1148
 	int relayed_code;
1149 1149
 	struct sip_msg *relayed_msg;
1150
+	struct sip_msg *reply_bak;
1150 1151
 	struct bookmark bm;
1151 1152
 	int totag_retr;
1152 1153
 	enum rps reply_status;
1153 1154
 	/* retransmission structure of outbound reply and request */
1154 1155
 	struct retr_buf *uas_rb;
1156
+	str* to_tag;
1155 1157
 
1156 1158
 	/* keep compiler warnings about use of uninit vars silent */
1157 1159
 	res_len=0;
... ...
@@ -1197,22 +1285,34 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
1197 1197
 			tm_stats->replied_localy++;
1198 1198
 			relayed_code = branch==relay
1199 1199
 				? msg_status : t->uac[relay].last_received;
1200
-
1200
+			/* use to_tag from the original request, or if not present,
1201
+			 * generate a new one */
1201 1202
 			if (relayed_code>=180 && t->uas.request->to
1202 1203
 					&& (get_to(t->uas.request)->tag_value.s==0
1203 1204
 			    		|| get_to(t->uas.request)->tag_value.len==0)) {
1204 1205
 				calc_crc_suffix( t->uas.request, tm_tag_suffix );
1205
-				buf = build_res_buf_from_sip_req(
1206
-						relayed_code,
1207
-						error_text(relayed_code),
1208
-						&tm_tag,
1209
-						t->uas.request, &res_len, &bm );
1206
+				to_tag=&tm_tag;
1210 1207
 			} else {
1208
+				to_tag=0;
1209
+			}
1210
+			if (tm_aggregate_auth && 
1211
+						(relayed_code==401 || relayed_code==407) &&
1212
+						(auth_reply_count(t, p_msg)>1)){
1213
+				/* aggregate 401 & 407 www & proxy authenticate headers in
1214
+				 *  a "FAKE" reply*/
1215
+				
1216
+				/* temporarily "store" the current reply */
1217
+				reply_bak=t->uac[branch].reply;
1218
+				t->uac[branch].reply=p_msg;
1219
+				buf=reply_aggregate_auth(relayed_code, 
1220
+						error_text(relayed_code), to_tag, t, &res_len, &bm);
1221
+				/* revert the temporary "store" reply above */
1222
+				t->uac[branch].reply=reply_bak;
1223
+			}else{
1211 1224
 				buf = build_res_buf_from_sip_req( relayed_code,
1212
-					error_text(relayed_code), 0/* no to-tag */,
1213
-					t->uas.request, &res_len, &bm );
1225
+						error_text(relayed_code), to_tag,
1226
+						t->uas.request, &res_len, &bm );
1214 1227
 			}
1215
-
1216 1228
 		} else {
1217 1229
 			relayed_code=relayed_msg->REPLY_STATUS;
1218 1230
 			if (relayed_code==503){
... ...
@@ -1220,11 +1320,37 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
1220 1220
 				 * generate a "FAKE" reply and a new to_tag (for easier
1221 1221
 				 *  debugging)*/
1222 1222
 				relayed_msg=FAKED_REPLY;
1223
-				calc_crc_suffix( t->uas.request, tm_tag_suffix );
1223
+				if ((get_to(t->uas.request)->tag_value.s==0 ||
1224
+					 get_to(t->uas.request)->tag_value.len==0)) {
1225
+					calc_crc_suffix( t->uas.request, tm_tag_suffix );
1226
+					to_tag=&tm_tag;
1227
+				} else {
1228
+					to_tag=0;
1229
+				}
1224 1230
 				/* don't relay a 503, replace it w/ 500 (rfc3261) */
1225 1231
 				buf=build_res_buf_from_sip_req(500, error_text(relayed_code),
1226
-								&tm_tag, t->uas.request, &res_len, &bm);
1232
+									to_tag, t->uas.request, &res_len, &bm);
1227 1233
 				relayed_code=500;
1234
+			}else if (tm_aggregate_auth && 
1235
+						(relayed_code==401 || relayed_code==407) &&
1236
+						(auth_reply_count(t, p_msg)>1)){
1237
+				/* aggregate 401 & 407 www & proxy authenticate headers in
1238
+				 *  a "FAKE" reply*/
1239
+				if ((get_to(t->uas.request)->tag_value.s==0 ||
1240
+					 get_to(t->uas.request)->tag_value.len==0)) {
1241
+					calc_crc_suffix( t->uas.request, tm_tag_suffix );
1242
+					to_tag=&tm_tag;
1243
+				} else {
1244
+					to_tag=0;
1245
+				}
1246
+				/* temporarily "store" the current reply */
1247
+				reply_bak=t->uac[branch].reply;
1248
+				t->uac[branch].reply=p_msg;
1249
+				buf=reply_aggregate_auth(relayed_code, 
1250
+						error_text(relayed_code), to_tag, t, &res_len, &bm);
1251
+				/* revert the temporary "store" reply above */
1252
+				t->uac[branch].reply=reply_bak;;
1253
+				relayed_msg=FAKED_REPLY; /* mark the relayed_msg as a "FAKE" */
1228 1254
 			}else{
1229 1255
 				buf = build_res_buf_from_sip_res( relayed_msg, &res_len );
1230 1256
 				/* if we build a message from shmem, we need to remove
... ...
@@ -38,6 +38,7 @@
38 38
 
39 39
 
40 40
 extern int restart_fr_on_each_reply;
41
+extern int tm_aggregate_auth; /* aggregate authorization header value */
41 42
 
42 43
 /* reply processing status */
43 44
 enum rps {
... ...
@@ -79,6 +79,7 @@
79 79
  *  2006-02-07  named routes support (andrei)
80 80
  *  2006-09-28  added t_branch_replied, t_branch_timeout, t_any_replied, 
81 81
  *               t_any_timeout, t_is_canceled (andrei)
82
+ *  2006-10-16  added a new param.: aggregate challenges (andrei)
82 83
  */
83 84
 
84 85
 
... ...
@@ -320,8 +321,10 @@ static param_export_t params[]={
320 320
 	{"restart_fr_on_each_reply", PARAM_INT, &restart_fr_on_each_reply        },
321 321
 	{"fr_timer_avp",        PARAM_STRING, &fr_timer_param                    },
322 322
 	{"fr_inv_timer_avp",    PARAM_STRING, &fr_inv_timer_param                },
323
-	{"tw_append",           PARAM_STRING|PARAM_USE_FUNC, (void*)parse_tw_append },
324
-        {"pass_provisional_replies", PARAM_INT, &pass_provisional_replies        },
323
+	{"tw_append",           PARAM_STRING|PARAM_USE_FUNC, 
324
+													(void*)parse_tw_append   },
325
+	{"pass_provisional_replies", PARAM_INT, &pass_provisional_replies        },
326
+	{"aggregate_challenges", PARAM_INT, &tm_aggregate_auth                   },
325 327
 	{"default_code",        PARAM_INT, &default_code                         },
326 328
 	{"default_reason",      PARAM_STR, &default_reason                       },
327 329
 	{0,0,0}
... ...
@@ -62,13 +62,41 @@
62 62
         }
63 63
 
64 64
 
65
-#define THOR_CASE                  \
65
+#define TE_CASE                    \
66
+        switch(LOWER_DWORD(val)&0xffffff) { \
67
+        case _te1_:     /* "te:"*/            \
68
+	        hdr->type = HDR_PROXY_AUTHENTICATE_T; \
69
+	        hdr->name.len = 18;        \
70
+	        return (p + 3);            \
71
+        case _te2_: /* "te " */ \
72
+	        hdr->type = HDR_PROXY_AUTHENTICATE_T; \
73
+	        p+=3; \
74
+            goto dc_end;        \
75
+        }
76
+
77
+
78
+#define TICA_CASE                  \
79
+        switch(LOWER_DWORD(val)) { \
80
+        case _tica_:               \
81
+                p += 4;            \
82
+                val = READ3(p);    \
83
+                TE_CASE;           \
84
+                goto other;        \
85
+        }
86
+
87
+
88
+#define THOR_THEN_CASE             \
66 89
         switch(LOWER_DWORD(val)) { \
67 90
         case _thor_:               \
68 91
                 p += 4;            \
69 92
                 val = READ(p);     \
70 93
                 IZAT_CASE;         \
71 94
                 goto other;        \
95
+        case _then_:               \
96
+                p += 4;            \
97
+                val = READ(p);     \
98
+                TICA_CASE;         \
99
+                goto other;        \
72 100
         }
73 101
 
74 102
 
... ...
@@ -91,7 +119,7 @@
91 91
         case _y_au_:               \
92 92
                 p += 4;            \
93 93
                 val = READ(p);     \
94
-                THOR_CASE;         \
94
+                THOR_THEN_CASE;    \
95 95
                 goto other;        \
96 96
                                    \
97 97
         case _y_re_:               \
... ...
@@ -35,7 +35,7 @@
35 35
 #define CATE_CASE                        \
36 36
         switch(LOWER_DWORD(val)) {       \
37 37
         case _cate_:                     \
38
-                hdr->type = HDR_WWWAUTH_T; \
38
+                hdr->type = HDR_WWW_AUTHENTICATE_T; \
39 39
                 p += 4;                  \
40 40
 	        goto dc_end;             \
41 41
         }
... ...
@@ -183,6 +183,8 @@ void clean_hdr_field(struct hdr_field* hf)
183 183
 		case HDR_REFERREDBY_T:
184 184
 		case HDR_REJECTCONTACT_T:
185 185
 		case HDR_REQUESTDISPOSITION_T:
186
+		case HDR_WWW_AUTHENTICATE_T:
187
+		case HDR_PROXY_AUTHENTICATE_T:
186 188
 			break;
187 189
 		default:
188 190
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
... ...
@@ -49,11 +49,12 @@
49 49
  *  - update clean_hdr_field (in hf.c)
50 50
  *  - update sip_msg_cloner (modules/tm/sip_msg.c)
51 51
  *  - update parse_headers (msg_parser.c)
52
+ *  - update get_hdr_field (msg_parser.c)
52 53
  */
53 54
 
54 55
 enum _hdr_types_t {
55 56
 	HDR_ERROR_T					= -1   /* Error while parsing */,
56
-	HDR_OTHER_T                                     =  0   /* Some other header field */,
57
+	HDR_OTHER_T					=  0   /* Some other header field */,
57 58
 	HDR_VIA_T					=  1   /* Via header field */,
58 59
 	HDR_VIA1_T					=  1   /* First Via header field */,
59 60
 	HDR_VIA2_T					=  2   /* only used as flag */,
... ...
@@ -71,7 +72,7 @@ enum _hdr_types_t {
71 71
 	HDR_EXPIRES_T				       /* Expires header field */,
72 72
 	HDR_PROXYAUTH_T				       /* Proxy-Authorization hdr field */,
73 73
 	HDR_SUPPORTED_T				       /* Supported  header field */,
74
-	HDR_REQUIRE_T					   /* Require header */,
74
+	HDR_REQUIRE_T				       /* Require header */,
75 75
 	HDR_PROXYREQUIRE_T			       /* Proxy-Require header field */,
76 76
 	HDR_UNSUPPORTED_T			       /* Unsupported header field */,
77 77
 	HDR_ALLOW_T					       /* Allow header field */,
... ...
@@ -87,18 +88,20 @@ enum _hdr_types_t {
87 87
 	HDR_DIVERSION_T				       /* Diversion header field */,
88 88
 	HDR_RPID_T					       /* Remote-Party-ID header field */,
89 89
 	HDR_REFER_TO_T				       /* Refer-To header fiels */,
90
-	HDR_SIPIFMATCH_T                   /* SIP-If-Match header field */,
91
-	HDR_SESSIONEXPIRES_T                           /* Session-Expires header */,
92
-	HDR_MIN_SE_T                                   /* Min-SE */,
93
-	HDR_SUBSCRIPTION_STATE_T                       /* Subscription-State */,
94
-	HDR_ACCEPTCONTACT_T                            /* Accept-Contact header */,
95
-	HDR_ALLOWEVENTS_T                              /* Allow-Events header */,
96
-	HDR_CONTENTENCODING_T                          /* Content-Encoding header */,
97
-	HDR_REFERREDBY_T                               /* Referred-By header */,
98
-	HDR_REJECTCONTACT_T                            /* Reject-Contact header */,
99
-	HDR_REQUESTDISPOSITION_T                       /* Request-Disposition header */,
100
-
101
-	HDR_EOH_T				       /* End of message header */
90
+	HDR_SIPIFMATCH_T			       /* SIP-If-Match header field */,
91
+	HDR_SESSIONEXPIRES_T		       /* Session-Expires header */,
92
+	HDR_MIN_SE_T				       /* Min-SE */,
93
+	HDR_SUBSCRIPTION_STATE_T	       /* Subscription-State */,
94
+	HDR_ACCEPTCONTACT_T			       /* Accept-Contact header */,
95
+	HDR_ALLOWEVENTS_T			       /* Allow-Events header */,
96
+	HDR_CONTENTENCODING_T		       /* Content-Encoding header */,
97
+	HDR_REFERREDBY_T			       /* Referred-By header */,
98
+	HDR_REJECTCONTACT_T			       /* Reject-Contact header */,
99
+	HDR_REQUESTDISPOSITION_T	       /* Request-Disposition header */,
100
+	HDR_WWW_AUTHENTICATE_T		       /* WWW-Authenticate header field */,
101
+	HDR_PROXY_AUTHENTICATE_T	       /* Proxy-Authenticate header field */,
102
+
103
+	HDR_EOH_T					       /* End of message header */
102 104
 };
103 105
 
104 106
 
... ...
@@ -149,15 +152,17 @@ typedef unsigned long long hdr_flags_t;
149 149
 #define HDR_RPID_F					HDR_F_DEF(RPID)
150 150
 #define HDR_REFER_TO_F				HDR_F_DEF(REFER_TO)
151 151
 #define HDR_SIPIFMATCH_F			HDR_F_DEF(SIPIFMATCH)
152
-#define HDR_SESSIONEXPIRES_F			HDR_F_DEF(SESSIONEXPIRES)
152
+#define HDR_SESSIONEXPIRES_F		HDR_F_DEF(SESSIONEXPIRES)
153 153
 #define HDR_MIN_SE_F				HDR_F_DEF(MIN_SE)
154 154
 #define HDR_SUBSCRIPTION_STATE_F	HDR_F_DEF(SUBSCRIPTION_STATE)
155 155
 #define HDR_ACCEPTCONTACT_F			HDR_F_DEF(HDR_ACCEPTCONTACT_T)
156 156
 #define HDR_ALLOWEVENTS_F			HDR_F_DEF(HDR_ALLOWEVENTS_T)
157
-#define HDR_CONTENTENCODING_F			HDR_F_DEF(HDR_CONTENTENCODING_T)
157
+#define HDR_CONTENTENCODING_F		HDR_F_DEF(HDR_CONTENTENCODING_T)
158 158
 #define HDR_REFERREDBY_F			HDR_F_DEF(HDR_REFERREDBY_T)
159 159
 #define HDR_REJECTCONTACT_F			HDR_F_DEF(HDR_REJECTCONTACT_T)
160
-#define HDR_REQUESTDISPOSITION_F		HDR_F_DEF(HDR_REQUESTDISPOSITION_T)
160
+#define HDR_REQUESTDISPOSITION_F	HDR_F_DEF(HDR_REQUESTDISPOSITION_T)
161
+#define HDR_WWW_AUTHENTICATE_F		HDR_F_DEF(HDR_WWW_AUTHENTICATE_T)
162
+#define HDR_PROXY_AUTHENTICATE_F	HDR_F_DEF(HDR_PROXY_AUTHENTICATE_T)
161 163
 
162 164
 #define HDR_OTHER_F					HDR_F_DEF(OTHER)
163 165
 
... ...
@@ -74,6 +74,10 @@
74 74
 #define _izat_ 0x74617a69   /* "izat" */
75 75
 #define _ion2_ 0x206e6f69   /* "ion " */
76 76
 #define _ion1_ 0x3a6e6f69   /* "ion:" */
77
+#define _then_ 0x6e656874   /* "then" */
78
+#define _tica_ 0x61636974   /* "tica" */
79
+#define _te1_  0x003a6574   /* "te:" */
80
+#define _te2_  0x00206574   /* "te " */
77 81
 #define _y_re_ 0x65722d79   /* "y-re" */
78 82
 #define _quir_ 0x72697571   /* "quir" */
79 83
 #define _reco_ 0x6f636572   /* "reco" */
... ...
@@ -218,6 +218,8 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
218 218
 		case HDR_REFERREDBY_T:
219 219
 		case HDR_REJECTCONTACT_T:
220 220
 		case HDR_REQUESTDISPOSITION_T:
221
+		case HDR_WWW_AUTHENTICATE_T:
222
+		case HDR_PROXY_AUTHENTICATE_T:
221 223
 		case HDR_OTHER_T:
222 224
 			/* just skip over it */
223 225
 			hdr->body.s=tmp;
... ...
@@ -300,7 +302,7 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
300 300
 		}
301 301
 		memset(hf,0, sizeof(struct hdr_field));
302 302
 		hf->type=HDR_ERROR_T;
303
-		rest=get_hdr_field(tmp, msg->buf+msg->len, hf);
303
+		rest=get_hdr_field(tmp, end, hf);
304 304
 		switch (hf->type){
305 305
 			case HDR_ERROR_T:
306 306
 				LOG(L_INFO,"ERROR: bad header  field\n");
... ...
@@ -316,6 +318,8 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
316 316
 			case HDR_REFERREDBY_T:
317 317
 			case HDR_REJECTCONTACT_T:
318 318
 			case HDR_REQUESTDISPOSITION_T:
319
+			case HDR_WWW_AUTHENTICATE_T:
320
+			case HDR_PROXY_AUTHENTICATE_T:
319 321
 			case HDR_OTHER_T: /*do nothing*/
320 322
 				break;
321 323
 			case HDR_CALLID_T:
... ...
@@ -91,11 +91,14 @@ static inline char* skip_ws(char* p, unsigned int size)
91 91
 #include "case_min.h"      /* Min-SE */
92 92
 #include "case_subs.h"     /* Subscription-State */
93 93
 #include "case_requ.h"     /* Require */
94
+#include "case_www.h"      /* WWW-Authenticate */
94 95
 
95 96
 
96 97
 #define READ(val) \
97 98
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
98 99
 
100
+#define READ3(val) \
101
+(*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16))
99 102
 
100 103
 #define FIRST_QUATERNIONS       \
101 104
         case _via1_: via1_CASE; \
... ...
@@ -129,6 +132,7 @@ static inline char* skip_ws(char* p, unsigned int size)
129 129
 	case _reje_: reje_CASE; \
130 130
 	case _min__: min_CASE;  \
131 131
 	case _requ_: requ_CASE;  \
132
+	case _www__: www_CASE; \
132 133
 
133 134
 
134 135