Procházet zdrojové kódy

- 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 před 19 roky
rodič
revize
3ed13e7767

+ 1 - 1
Makefile.defs

@@ -67,7 +67,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev52-tm_fixes
+EXTRAVERSION = -dev53-tm_fixes
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 			$(SUBLEVEL) )

+ 9 - 1
NEWS

@@ -24,7 +24,15 @@ modules:
                 hashing after an uri (to, from or request uri)
               - improved uri hashing (password is ignored, port is used only
                 if != 5060 or 5061)
- - tm        - on 6xx immediately cancel all the branches for which a 
+ - tm        - aggregate challenges (WWW/Proxy-Authenticate) from all the
+               401 & 407 if the final reply is a 401/407. To turn this off
+               and fall back to the old behaviour set tm aggregate_challenges
+               parameter to 0.
+             - if a relayed 503 is the final reply, replace it by a 500
+             - if a 503 reply is received try the dns based failover
+               (forward to another ip if the original destination uri 
+                resolved to several SRV, A or AAAA records)
+             - on 6xx immediately cancel all the branches for which a 
                provisional response was received and wait for all the 
                branches to finish (either timeout, the 487 from the CANCEL
                or a final response still on the wire in the moment the

+ 26 - 0
modules/tm/doc/params.xml

@@ -177,4 +177,30 @@ modparam("tm", "unix_tx_timeout", 250)
 	    </programlisting>
 	</example>
 	</section>
+
+    <section id="aggregate_challenges">
+	<title><varname>aggregate_challenges</varname> (integer)</title>
+	<para>
+		If set (default), the final reply is a 401 or a 407 and more then
+		one branch received a 401 or 407, then all the WWW-Authenticate and 
+		Proxy-Authenticate headers from all the 401 and 407 replies will 
+		be aggregated in a new final reply. If only one branch received the
+		 winning 401 or 407 then this reply will be forwarded (no new one
+		 will be built).
+		If 0 only the first 401, or if no 401 was received the first 407,  will
+		be forwarded (no header aggregation).
+	</para>
+	<para>
+	    Default value is 1 (required by rfc3261).
+	</para>
+	<example>
+	    <title>Set <varname>aggregate_challenges</varname> parameter</title>
+	    <programlisting>
+...
+modparam("tm", "aggregate_challenges", 0)
+...
+	    </programlisting>
+	</example>
+    </section>
+
 </section>

+ 6 - 1
modules/tm/sip_msg.c

@@ -47,6 +47,7 @@
  *  2003-11-11  updated cloning of lump_rpl (bogdan)
  *  2004-03-31  alias shortcuts are also translated (andrei)
  *  2006-04-20  via->comp is also translated (andrei)
+ *  2006-10-16  HDR_{PROXY,WWW}_AUTHENTICATE_T cloned (andrei)
  */
 
 #include "defs.h"
@@ -387,7 +388,9 @@ struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg, int *sip_msg_len )
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
-/* we ignore them for now even if they have something parsed*/
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
+			/* we ignore them for now even if they have something parsed*/
 			break;
 		}/*switch*/
 	}/*for all headers*/
@@ -525,6 +528,8 @@ do { \
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 			break;
 
 		case HDR_VIA_T:

+ 16 - 3
modules/tm/t_lookup.c

@@ -82,6 +82,8 @@
  * 2005-12-09  added t_set_fr()  (andrei)
  * 2006-01-27  transaction lookup function will set up a cancel flag
  *             if the searched transaction was pre-canceled (andrei)
+ * 2006-10-16  401 & 407 replies are completely parsed if tm_aggregate_auth is
+ *              set (andrei)
  */
 
 #include "defs.h"
@@ -936,13 +938,24 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
 		} else {
 			/* we need Via for branch and Cseq method to distinguish
 			   replies with the same branch/cseqNr (CANCEL)
+			   and we need all the WWW/Proxy Authenticate headers for
+			   401 & 407 replies
 			*/
-			if ( parse_headers(p_msg, HDR_VIA1_F|HDR_CSEQ_F, 0 )==-1
-			|| !p_msg->via1 || !p_msg->cseq ) {
+			if (tm_aggregate_auth && 
+					(p_msg->REPLY_STATUS==401 || p_msg->REPLY_STATUS==407)){
+				if (parse_headers(p_msg, HDR_EOH_F,0)==-1){
+					LOG(L_WARN, "WARNING: the reply cannot be "
+								"completely parsed\n");
+					/* try to continue, via1 & cseq are checked below */
+				}
+			}else if ( parse_headers(p_msg, HDR_VIA1_F|HDR_CSEQ_F, 0 )==-1) {
 				LOG(L_ERR, "ERROR: reply cannot be parsed\n");
 				return -1;
 			}
-
+			if ((p_msg->via1==0) || (p_msg->cseq==0)){
+				LOG(L_ERR, "ERROR: reply doesn't have a via or cseq header\n");
+				return -1;
+			}
 			/* if that is an INVITE, we will also need to-tag
 			   for later ACK matching
 			*/

+ 138 - 12
modules/tm/t_reply.c

@@ -75,7 +75,9 @@
  *              if no 6xx reply => lowest class/code; if class==4xx =>
  *              prefer 401, 407, 415, 420 and 484   (andrei)
  * 2006-10-12  dns failover when a 503 is received
-*              replace a 503 final relayed reply by a 500 (andrei)
+ *              replace a 503 final relayed reply by a 500 (andrei)
+ * 2006-10-16  aggregate all the authorization headers/challenges when
+ *               the final response is 401 or 407 (andrei)
  *
  */
 
@@ -112,6 +114,9 @@
 
 /* restart fr timer on each provisional reply, default yes */
 int restart_fr_on_each_reply=1;
+/* if the final reponse is a 401 or a 407, aggregate all the 
+ * authorization headers (challenges) (rfc3261 requires this to be on) */
+int tm_aggregate_auth=1;
 
 /* are we processing original or shmemed request ? */
 enum route_mode rmode=MODE_REQUEST;
@@ -1133,6 +1138,87 @@ static int store_reply( struct cell *trans, int branch, struct sip_msg *rpl)
 		return 1;
 }
 
+
+
+/* returns the number of authenticate replies (401 and 407) received so far
+ *  (FAKED_REPLYes are excluded)
+ *  It must be called with the REPLY_LOCK held */
+inline static int auth_reply_count(struct cell *t, struct sip_msg* crt_reply)
+{
+	int count;
+	int r;
+
+	count=0;
+	if (crt_reply && (crt_reply!=FAKED_REPLY) && 
+			(crt_reply->REPLY_STATUS ==401 || crt_reply->REPLY_STATUS ==407))
+		count=1;
+	for (r=0; r<t->nr_of_outgoings; r++){
+		if (t->uac[r].reply && (t->uac[r].reply!=FAKED_REPLY) &&
+				(t->uac[r].last_received==401 || t->uac[r].last_received==407))
+			count++;
+	}
+	return count;
+}
+
+
+
+/* must be called with the REPY_LOCK held */
+inline static char* reply_aggregate_auth(int code, char* txt, str* new_tag, 
+									struct cell* t, unsigned int* res_len, 
+									struct bookmark* bm)
+{
+	int r;
+	struct hdr_field* hdr;
+	struct lump_rpl** first;
+	struct lump_rpl** crt;
+	struct lump_rpl* lst;
+	struct lump_rpl*  lst_end;
+	struct sip_msg* req;
+	char* buf;
+	
+	first=0;
+	lst_end=0;
+	req=t->uas.request;
+	
+	for (r=0; r<t->nr_of_outgoings; r++){
+		if (t->uac[r].reply && (t->uac[r].reply!=FAKED_REPLY) &&
+			(t->uac[r].last_received==401 || t->uac[r].last_received==407)){
+			for (hdr=t->uac[r].reply->headers; hdr; hdr=hdr->next){
+				if (hdr->type==HDR_WWW_AUTHENTICATE_T ||
+						hdr->type==HDR_PROXY_AUTHENTICATE_T){
+					crt=add_lump_rpl2(req, hdr->name.s, hdr->len,
+							LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
+					if (crt==0){
+						/* some kind of error, better stop */
+						LOG(L_ERR, "ERROR: tm:reply_aggregate_auth:"
+									" add_lump_rpl2 failed\n");
+						goto skip;
+					}
+					lst_end=*crt;
+					if (first==0) first=crt;
+				}
+			}
+		}
+	}
+skip:
+	buf=build_res_buf_from_sip_req(code, txt, new_tag, req, res_len, bm);
+	/* clean the added lumps */
+	if (first){
+		lst=*first;
+		*first=lst_end->next; /* "detach" the list of added rpl_lumps */
+		lst_end->next=0; /* terminate lst */
+		del_nonshm_lump_rpl(&lst);
+		if (lst){
+			LOG(L_CRIT, "BUG: tm: repply_aggregate_auth: rpl_lump list"
+					    "contains shm alloc'ed lumps\n");
+			abort();
+		}
+	}
+	return buf;
+}
+
+
+
 /* this is the code which decides what and when shall be relayed
    upstream; note well -- it assumes it is entered locked with
    REPLY_LOCK and it returns unlocked!
@@ -1147,11 +1233,13 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 	unsigned int res_len;
 	int relayed_code;
 	struct sip_msg *relayed_msg;
+	struct sip_msg *reply_bak;
 	struct bookmark bm;
 	int totag_retr;
 	enum rps reply_status;
 	/* retransmission structure of outbound reply and request */
 	struct retr_buf *uas_rb;
+	str* to_tag;
 
 	/* keep compiler warnings about use of uninit vars silent */
 	res_len=0;
@@ -1197,22 +1285,34 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 			tm_stats->replied_localy++;
 			relayed_code = branch==relay
 				? msg_status : t->uac[relay].last_received;
-
+			/* use to_tag from the original request, or if not present,
+			 * generate a new one */
 			if (relayed_code>=180 && t->uas.request->to
 					&& (get_to(t->uas.request)->tag_value.s==0
 			    		|| get_to(t->uas.request)->tag_value.len==0)) {
 				calc_crc_suffix( t->uas.request, tm_tag_suffix );
-				buf = build_res_buf_from_sip_req(
-						relayed_code,
-						error_text(relayed_code),
-						&tm_tag,
-						t->uas.request, &res_len, &bm );
+				to_tag=&tm_tag;
 			} else {
+				to_tag=0;
+			}
+			if (tm_aggregate_auth && 
+						(relayed_code==401 || relayed_code==407) &&
+						(auth_reply_count(t, p_msg)>1)){
+				/* aggregate 401 & 407 www & proxy authenticate headers in
+				 *  a "FAKE" reply*/
+				
+				/* temporarily "store" the current reply */
+				reply_bak=t->uac[branch].reply;
+				t->uac[branch].reply=p_msg;
+				buf=reply_aggregate_auth(relayed_code, 
+						error_text(relayed_code), to_tag, t, &res_len, &bm);
+				/* revert the temporary "store" reply above */
+				t->uac[branch].reply=reply_bak;
+			}else{
 				buf = build_res_buf_from_sip_req( relayed_code,
-					error_text(relayed_code), 0/* no to-tag */,
-					t->uas.request, &res_len, &bm );
+						error_text(relayed_code), to_tag,
+						t->uas.request, &res_len, &bm );
 			}
-
 		} else {
 			relayed_code=relayed_msg->REPLY_STATUS;
 			if (relayed_code==503){
@@ -1220,11 +1320,37 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 				 * generate a "FAKE" reply and a new to_tag (for easier
 				 *  debugging)*/
 				relayed_msg=FAKED_REPLY;
-				calc_crc_suffix( t->uas.request, tm_tag_suffix );
+				if ((get_to(t->uas.request)->tag_value.s==0 ||
+					 get_to(t->uas.request)->tag_value.len==0)) {
+					calc_crc_suffix( t->uas.request, tm_tag_suffix );
+					to_tag=&tm_tag;
+				} else {
+					to_tag=0;
+				}
 				/* don't relay a 503, replace it w/ 500 (rfc3261) */
 				buf=build_res_buf_from_sip_req(500, error_text(relayed_code),
-								&tm_tag, t->uas.request, &res_len, &bm);
+									to_tag, t->uas.request, &res_len, &bm);
 				relayed_code=500;
+			}else if (tm_aggregate_auth && 
+						(relayed_code==401 || relayed_code==407) &&
+						(auth_reply_count(t, p_msg)>1)){
+				/* aggregate 401 & 407 www & proxy authenticate headers in
+				 *  a "FAKE" reply*/
+				if ((get_to(t->uas.request)->tag_value.s==0 ||
+					 get_to(t->uas.request)->tag_value.len==0)) {
+					calc_crc_suffix( t->uas.request, tm_tag_suffix );
+					to_tag=&tm_tag;
+				} else {
+					to_tag=0;
+				}
+				/* temporarily "store" the current reply */
+				reply_bak=t->uac[branch].reply;
+				t->uac[branch].reply=p_msg;
+				buf=reply_aggregate_auth(relayed_code, 
+						error_text(relayed_code), to_tag, t, &res_len, &bm);
+				/* revert the temporary "store" reply above */
+				t->uac[branch].reply=reply_bak;;
+				relayed_msg=FAKED_REPLY; /* mark the relayed_msg as a "FAKE" */
 			}else{
 				buf = build_res_buf_from_sip_res( relayed_msg, &res_len );
 				/* if we build a message from shmem, we need to remove

+ 1 - 0
modules/tm/t_reply.h

@@ -38,6 +38,7 @@
 
 
 extern int restart_fr_on_each_reply;
+extern int tm_aggregate_auth; /* aggregate authorization header value */
 
 /* reply processing status */
 enum rps {

+ 5 - 2
modules/tm/tm.c

@@ -79,6 +79,7 @@
  *  2006-02-07  named routes support (andrei)
  *  2006-09-28  added t_branch_replied, t_branch_timeout, t_any_replied, 
  *               t_any_timeout, t_is_canceled (andrei)
+ *  2006-10-16  added a new param.: aggregate challenges (andrei)
  */
 
 
@@ -320,8 +321,10 @@ static param_export_t params[]={
 	{"restart_fr_on_each_reply", PARAM_INT, &restart_fr_on_each_reply        },
 	{"fr_timer_avp",        PARAM_STRING, &fr_timer_param                    },
 	{"fr_inv_timer_avp",    PARAM_STRING, &fr_inv_timer_param                },
-	{"tw_append",           PARAM_STRING|PARAM_USE_FUNC, (void*)parse_tw_append },
-        {"pass_provisional_replies", PARAM_INT, &pass_provisional_replies        },
+	{"tw_append",           PARAM_STRING|PARAM_USE_FUNC, 
+													(void*)parse_tw_append   },
+	{"pass_provisional_replies", PARAM_INT, &pass_provisional_replies        },
+	{"aggregate_challenges", PARAM_INT, &tm_aggregate_auth                   },
 	{"default_code",        PARAM_INT, &default_code                         },
 	{"default_reason",      PARAM_STR, &default_reason                       },
 	{0,0,0}

+ 30 - 2
parser/case_prox.h

@@ -62,13 +62,41 @@
         }
 
 
-#define THOR_CASE                  \
+#define TE_CASE                    \
+        switch(LOWER_DWORD(val)&0xffffff) { \
+        case _te1_:     /* "te:"*/            \
+	        hdr->type = HDR_PROXY_AUTHENTICATE_T; \
+	        hdr->name.len = 18;        \
+	        return (p + 3);            \
+        case _te2_: /* "te " */ \
+	        hdr->type = HDR_PROXY_AUTHENTICATE_T; \
+	        p+=3; \
+            goto dc_end;        \
+        }
+
+
+#define TICA_CASE                  \
+        switch(LOWER_DWORD(val)) { \
+        case _tica_:               \
+                p += 4;            \
+                val = READ3(p);    \
+                TE_CASE;           \
+                goto other;        \
+        }
+
+
+#define THOR_THEN_CASE             \
         switch(LOWER_DWORD(val)) { \
         case _thor_:               \
                 p += 4;            \
                 val = READ(p);     \
                 IZAT_CASE;         \
                 goto other;        \
+        case _then_:               \
+                p += 4;            \
+                val = READ(p);     \
+                TICA_CASE;         \
+                goto other;        \
         }
 
 
@@ -91,7 +119,7 @@
         case _y_au_:               \
                 p += 4;            \
                 val = READ(p);     \
-                THOR_CASE;         \
+                THOR_THEN_CASE;    \
                 goto other;        \
                                    \
         case _y_re_:               \

+ 1 - 1
parser/case_www.h

@@ -35,7 +35,7 @@
 #define CATE_CASE                        \
         switch(LOWER_DWORD(val)) {       \
         case _cate_:                     \
-                hdr->type = HDR_WWWAUTH_T; \
+                hdr->type = HDR_WWW_AUTHENTICATE_T; \
                 p += 4;                  \
 	        goto dc_end;             \
         }

+ 2 - 0
parser/hf.c

@@ -183,6 +183,8 @@ void clean_hdr_field(struct hdr_field* hf)
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 			break;
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",

+ 22 - 17
parser/hf.h

@@ -49,11 +49,12 @@
  *  - update clean_hdr_field (in hf.c)
  *  - update sip_msg_cloner (modules/tm/sip_msg.c)
  *  - update parse_headers (msg_parser.c)
+ *  - update get_hdr_field (msg_parser.c)
  */
 
 enum _hdr_types_t {
 	HDR_ERROR_T					= -1   /* Error while parsing */,
-	HDR_OTHER_T                                     =  0   /* Some other header field */,
+	HDR_OTHER_T					=  0   /* Some other header field */,
 	HDR_VIA_T					=  1   /* Via header field */,
 	HDR_VIA1_T					=  1   /* First Via header field */,
 	HDR_VIA2_T					=  2   /* only used as flag */,
@@ -71,7 +72,7 @@ enum _hdr_types_t {
 	HDR_EXPIRES_T				       /* Expires header field */,
 	HDR_PROXYAUTH_T				       /* Proxy-Authorization hdr field */,
 	HDR_SUPPORTED_T				       /* Supported  header field */,
-	HDR_REQUIRE_T					   /* Require header */,
+	HDR_REQUIRE_T				       /* Require header */,
 	HDR_PROXYREQUIRE_T			       /* Proxy-Require header field */,
 	HDR_UNSUPPORTED_T			       /* Unsupported header field */,
 	HDR_ALLOW_T					       /* Allow header field */,
@@ -87,18 +88,20 @@ enum _hdr_types_t {
 	HDR_DIVERSION_T				       /* Diversion header field */,
 	HDR_RPID_T					       /* Remote-Party-ID header field */,
 	HDR_REFER_TO_T				       /* Refer-To header fiels */,
-	HDR_SIPIFMATCH_T                   /* SIP-If-Match header field */,
-	HDR_SESSIONEXPIRES_T                           /* Session-Expires header */,
-	HDR_MIN_SE_T                                   /* Min-SE */,
-	HDR_SUBSCRIPTION_STATE_T                       /* Subscription-State */,
-	HDR_ACCEPTCONTACT_T                            /* Accept-Contact header */,
-	HDR_ALLOWEVENTS_T                              /* Allow-Events header */,
-	HDR_CONTENTENCODING_T                          /* Content-Encoding header */,
-	HDR_REFERREDBY_T                               /* Referred-By header */,
-	HDR_REJECTCONTACT_T                            /* Reject-Contact header */,
-	HDR_REQUESTDISPOSITION_T                       /* Request-Disposition header */,
-
-	HDR_EOH_T				       /* End of message header */
+	HDR_SIPIFMATCH_T			       /* SIP-If-Match header field */,
+	HDR_SESSIONEXPIRES_T		       /* Session-Expires header */,
+	HDR_MIN_SE_T				       /* Min-SE */,
+	HDR_SUBSCRIPTION_STATE_T	       /* Subscription-State */,
+	HDR_ACCEPTCONTACT_T			       /* Accept-Contact header */,
+	HDR_ALLOWEVENTS_T			       /* Allow-Events header */,
+	HDR_CONTENTENCODING_T		       /* Content-Encoding header */,
+	HDR_REFERREDBY_T			       /* Referred-By header */,
+	HDR_REJECTCONTACT_T			       /* Reject-Contact header */,
+	HDR_REQUESTDISPOSITION_T	       /* Request-Disposition header */,
+	HDR_WWW_AUTHENTICATE_T		       /* WWW-Authenticate header field */,
+	HDR_PROXY_AUTHENTICATE_T	       /* Proxy-Authenticate header field */,
+
+	HDR_EOH_T					       /* End of message header */
 };
 
 
@@ -149,15 +152,17 @@ typedef unsigned long long hdr_flags_t;
 #define HDR_RPID_F					HDR_F_DEF(RPID)
 #define HDR_REFER_TO_F				HDR_F_DEF(REFER_TO)
 #define HDR_SIPIFMATCH_F			HDR_F_DEF(SIPIFMATCH)
-#define HDR_SESSIONEXPIRES_F			HDR_F_DEF(SESSIONEXPIRES)
+#define HDR_SESSIONEXPIRES_F		HDR_F_DEF(SESSIONEXPIRES)
 #define HDR_MIN_SE_F				HDR_F_DEF(MIN_SE)
 #define HDR_SUBSCRIPTION_STATE_F	HDR_F_DEF(SUBSCRIPTION_STATE)
 #define HDR_ACCEPTCONTACT_F			HDR_F_DEF(HDR_ACCEPTCONTACT_T)
 #define HDR_ALLOWEVENTS_F			HDR_F_DEF(HDR_ALLOWEVENTS_T)
-#define HDR_CONTENTENCODING_F			HDR_F_DEF(HDR_CONTENTENCODING_T)
+#define HDR_CONTENTENCODING_F		HDR_F_DEF(HDR_CONTENTENCODING_T)
 #define HDR_REFERREDBY_F			HDR_F_DEF(HDR_REFERREDBY_T)
 #define HDR_REJECTCONTACT_F			HDR_F_DEF(HDR_REJECTCONTACT_T)
-#define HDR_REQUESTDISPOSITION_F		HDR_F_DEF(HDR_REQUESTDISPOSITION_T)
+#define HDR_REQUESTDISPOSITION_F	HDR_F_DEF(HDR_REQUESTDISPOSITION_T)
+#define HDR_WWW_AUTHENTICATE_F		HDR_F_DEF(HDR_WWW_AUTHENTICATE_T)
+#define HDR_PROXY_AUTHENTICATE_F	HDR_F_DEF(HDR_PROXY_AUTHENTICATE_T)
 
 #define HDR_OTHER_F					HDR_F_DEF(OTHER)
 

+ 4 - 0
parser/keys.h

@@ -74,6 +74,10 @@
 #define _izat_ 0x74617a69   /* "izat" */
 #define _ion2_ 0x206e6f69   /* "ion " */
 #define _ion1_ 0x3a6e6f69   /* "ion:" */
+#define _then_ 0x6e656874   /* "then" */
+#define _tica_ 0x61636974   /* "tica" */
+#define _te1_  0x003a6574   /* "te:" */
+#define _te2_  0x00206574   /* "te " */
 #define _y_re_ 0x65722d79   /* "y-re" */
 #define _quir_ 0x72697571   /* "quir" */
 #define _reco_ 0x6f636572   /* "reco" */

+ 5 - 1
parser/msg_parser.c

@@ -218,6 +218,8 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 		case HDR_OTHER_T:
 			/* just skip over it */
 			hdr->body.s=tmp;
@@ -300,7 +302,7 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
 		}
 		memset(hf,0, sizeof(struct hdr_field));
 		hf->type=HDR_ERROR_T;
-		rest=get_hdr_field(tmp, msg->buf+msg->len, hf);
+		rest=get_hdr_field(tmp, end, hf);
 		switch (hf->type){
 			case HDR_ERROR_T:
 				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)
 			case HDR_REFERREDBY_T:
 			case HDR_REJECTCONTACT_T:
 			case HDR_REQUESTDISPOSITION_T:
+			case HDR_WWW_AUTHENTICATE_T:
+			case HDR_PROXY_AUTHENTICATE_T:
 			case HDR_OTHER_T: /*do nothing*/
 				break;
 			case HDR_CALLID_T:

+ 4 - 0
parser/parse_hname2.c

@@ -91,11 +91,14 @@ static inline char* skip_ws(char* p, unsigned int size)
 #include "case_min.h"      /* Min-SE */
 #include "case_subs.h"     /* Subscription-State */
 #include "case_requ.h"     /* Require */
+#include "case_www.h"      /* WWW-Authenticate */
 
 
 #define READ(val) \
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
 
+#define READ3(val) \
+(*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16))
 
 #define FIRST_QUATERNIONS       \
         case _via1_: via1_CASE; \
@@ -129,6 +132,7 @@ static inline char* skip_ws(char* p, unsigned int size)
 	case _reje_: reje_CASE; \
 	case _min__: min_CASE;  \
 	case _requ_: requ_CASE;  \
+	case _www__: www_CASE; \