Browse Source

- 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 19 years ago
parent
commit
3ed13e7767
15 changed files with 270 additions and 41 deletions
  1. 1 1
      Makefile.defs
  2. 9 1
      NEWS
  3. 26 0
      modules/tm/doc/params.xml
  4. 6 1
      modules/tm/sip_msg.c
  5. 16 3
      modules/tm/t_lookup.c
  6. 138 12
      modules/tm/t_reply.c
  7. 1 0
      modules/tm/t_reply.h
  8. 5 2
      modules/tm/tm.c
  9. 30 2
      parser/case_prox.h
  10. 1 1
      parser/case_www.h
  11. 2 0
      parser/hf.c
  12. 22 17
      parser/hf.h
  13. 4 0
      parser/keys.h
  14. 5 1
      parser/msg_parser.c
  15. 4 0
      parser/parse_hname2.c

+ 1 - 1
Makefile.defs

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

+ 9 - 1
NEWS

@@ -24,7 +24,15 @@ modules:
                 hashing after an uri (to, from or request uri)
                 hashing after an uri (to, from or request uri)
               - improved uri hashing (password is ignored, port is used only
               - improved uri hashing (password is ignored, port is used only
                 if != 5060 or 5061)
                 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 
                provisional response was received and wait for all the 
                branches to finish (either timeout, the 487 from the CANCEL
                branches to finish (either timeout, the 487 from the CANCEL
                or a final response still on the wire in the moment the
                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>
 	    </programlisting>
 	</example>
 	</example>
 	</section>
 	</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>
 </section>

+ 6 - 1
modules/tm/sip_msg.c

@@ -47,6 +47,7 @@
  *  2003-11-11  updated cloning of lump_rpl (bogdan)
  *  2003-11-11  updated cloning of lump_rpl (bogdan)
  *  2004-03-31  alias shortcuts are also translated (andrei)
  *  2004-03-31  alias shortcuts are also translated (andrei)
  *  2006-04-20  via->comp is 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"
 #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_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_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;
 			break;
 		}/*switch*/
 		}/*switch*/
 	}/*for all headers*/
 	}/*for all headers*/
@@ -525,6 +528,8 @@ do { \
 		case HDR_REFERREDBY_T:
 		case HDR_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 			break;
 			break;
 
 
 		case HDR_VIA_T:
 		case HDR_VIA_T:

+ 16 - 3
modules/tm/t_lookup.c

@@ -82,6 +82,8 @@
  * 2005-12-09  added t_set_fr()  (andrei)
  * 2005-12-09  added t_set_fr()  (andrei)
  * 2006-01-27  transaction lookup function will set up a cancel flag
  * 2006-01-27  transaction lookup function will set up a cancel flag
  *             if the searched transaction was pre-canceled (andrei)
  *             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"
 #include "defs.h"
@@ -936,13 +938,24 @@ int t_check( struct sip_msg* p_msg , int *param_branch )
 		} else {
 		} else {
 			/* we need Via for branch and Cseq method to distinguish
 			/* we need Via for branch and Cseq method to distinguish
 			   replies with the same branch/cseqNr (CANCEL)
 			   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");
 				LOG(L_ERR, "ERROR: reply cannot be parsed\n");
 				return -1;
 				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
 			/* if that is an INVITE, we will also need to-tag
 			   for later ACK matching
 			   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 =>
  *              if no 6xx reply => lowest class/code; if class==4xx =>
  *              prefer 401, 407, 415, 420 and 484   (andrei)
  *              prefer 401, 407, 415, 420 and 484   (andrei)
  * 2006-10-12  dns failover when a 503 is received
  * 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 */
 /* restart fr timer on each provisional reply, default yes */
 int restart_fr_on_each_reply=1;
 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 ? */
 /* are we processing original or shmemed request ? */
 enum route_mode rmode=MODE_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;
 		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
 /* this is the code which decides what and when shall be relayed
    upstream; note well -- it assumes it is entered locked with
    upstream; note well -- it assumes it is entered locked with
    REPLY_LOCK and it returns unlocked!
    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;
 	unsigned int res_len;
 	int relayed_code;
 	int relayed_code;
 	struct sip_msg *relayed_msg;
 	struct sip_msg *relayed_msg;
+	struct sip_msg *reply_bak;
 	struct bookmark bm;
 	struct bookmark bm;
 	int totag_retr;
 	int totag_retr;
 	enum rps reply_status;
 	enum rps reply_status;
 	/* retransmission structure of outbound reply and request */
 	/* retransmission structure of outbound reply and request */
 	struct retr_buf *uas_rb;
 	struct retr_buf *uas_rb;
+	str* to_tag;
 
 
 	/* keep compiler warnings about use of uninit vars silent */
 	/* keep compiler warnings about use of uninit vars silent */
 	res_len=0;
 	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++;
 			tm_stats->replied_localy++;
 			relayed_code = branch==relay
 			relayed_code = branch==relay
 				? msg_status : t->uac[relay].last_received;
 				? 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
 			if (relayed_code>=180 && t->uas.request->to
 					&& (get_to(t->uas.request)->tag_value.s==0
 					&& (get_to(t->uas.request)->tag_value.s==0
 			    		|| get_to(t->uas.request)->tag_value.len==0)) {
 			    		|| get_to(t->uas.request)->tag_value.len==0)) {
 				calc_crc_suffix( t->uas.request, tm_tag_suffix );
 				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 {
 			} 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,
 				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 {
 		} else {
 			relayed_code=relayed_msg->REPLY_STATUS;
 			relayed_code=relayed_msg->REPLY_STATUS;
 			if (relayed_code==503){
 			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
 				 * generate a "FAKE" reply and a new to_tag (for easier
 				 *  debugging)*/
 				 *  debugging)*/
 				relayed_msg=FAKED_REPLY;
 				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) */
 				/* don't relay a 503, replace it w/ 500 (rfc3261) */
 				buf=build_res_buf_from_sip_req(500, error_text(relayed_code),
 				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;
 				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{
 			}else{
 				buf = build_res_buf_from_sip_res( relayed_msg, &res_len );
 				buf = build_res_buf_from_sip_res( relayed_msg, &res_len );
 				/* if we build a message from shmem, we need to remove
 				/* 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 restart_fr_on_each_reply;
+extern int tm_aggregate_auth; /* aggregate authorization header value */
 
 
 /* reply processing status */
 /* reply processing status */
 enum rps {
 enum rps {

+ 5 - 2
modules/tm/tm.c

@@ -79,6 +79,7 @@
  *  2006-02-07  named routes support (andrei)
  *  2006-02-07  named routes support (andrei)
  *  2006-09-28  added t_branch_replied, t_branch_timeout, t_any_replied, 
  *  2006-09-28  added t_branch_replied, t_branch_timeout, t_any_replied, 
  *               t_any_timeout, t_is_canceled (andrei)
  *               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        },
 	{"restart_fr_on_each_reply", PARAM_INT, &restart_fr_on_each_reply        },
 	{"fr_timer_avp",        PARAM_STRING, &fr_timer_param                    },
 	{"fr_timer_avp",        PARAM_STRING, &fr_timer_param                    },
 	{"fr_inv_timer_avp",    PARAM_STRING, &fr_inv_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_code",        PARAM_INT, &default_code                         },
 	{"default_reason",      PARAM_STR, &default_reason                       },
 	{"default_reason",      PARAM_STR, &default_reason                       },
 	{0,0,0}
 	{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)) { \
         switch(LOWER_DWORD(val)) { \
         case _thor_:               \
         case _thor_:               \
                 p += 4;            \
                 p += 4;            \
                 val = READ(p);     \
                 val = READ(p);     \
                 IZAT_CASE;         \
                 IZAT_CASE;         \
                 goto other;        \
                 goto other;        \
+        case _then_:               \
+                p += 4;            \
+                val = READ(p);     \
+                TICA_CASE;         \
+                goto other;        \
         }
         }
 
 
 
 
@@ -91,7 +119,7 @@
         case _y_au_:               \
         case _y_au_:               \
                 p += 4;            \
                 p += 4;            \
                 val = READ(p);     \
                 val = READ(p);     \
-                THOR_CASE;         \
+                THOR_THEN_CASE;    \
                 goto other;        \
                 goto other;        \
                                    \
                                    \
         case _y_re_:               \
         case _y_re_:               \

+ 1 - 1
parser/case_www.h

@@ -35,7 +35,7 @@
 #define CATE_CASE                        \
 #define CATE_CASE                        \
         switch(LOWER_DWORD(val)) {       \
         switch(LOWER_DWORD(val)) {       \
         case _cate_:                     \
         case _cate_:                     \
-                hdr->type = HDR_WWWAUTH_T; \
+                hdr->type = HDR_WWW_AUTHENTICATE_T; \
                 p += 4;                  \
                 p += 4;                  \
 	        goto dc_end;             \
 	        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_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 			break;
 			break;
 		default:
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			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 clean_hdr_field (in hf.c)
  *  - update sip_msg_cloner (modules/tm/sip_msg.c)
  *  - update sip_msg_cloner (modules/tm/sip_msg.c)
  *  - update parse_headers (msg_parser.c)
  *  - update parse_headers (msg_parser.c)
+ *  - update get_hdr_field (msg_parser.c)
  */
  */
 
 
 enum _hdr_types_t {
 enum _hdr_types_t {
 	HDR_ERROR_T					= -1   /* Error while parsing */,
 	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_VIA_T					=  1   /* Via header field */,
 	HDR_VIA1_T					=  1   /* First Via header field */,
 	HDR_VIA1_T					=  1   /* First Via header field */,
 	HDR_VIA2_T					=  2   /* only used as flag */,
 	HDR_VIA2_T					=  2   /* only used as flag */,
@@ -71,7 +72,7 @@ enum _hdr_types_t {
 	HDR_EXPIRES_T				       /* Expires header field */,
 	HDR_EXPIRES_T				       /* Expires header field */,
 	HDR_PROXYAUTH_T				       /* Proxy-Authorization hdr field */,
 	HDR_PROXYAUTH_T				       /* Proxy-Authorization hdr field */,
 	HDR_SUPPORTED_T				       /* Supported  header 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_PROXYREQUIRE_T			       /* Proxy-Require header field */,
 	HDR_UNSUPPORTED_T			       /* Unsupported header field */,
 	HDR_UNSUPPORTED_T			       /* Unsupported header field */,
 	HDR_ALLOW_T					       /* Allow header field */,
 	HDR_ALLOW_T					       /* Allow header field */,
@@ -87,18 +88,20 @@ enum _hdr_types_t {
 	HDR_DIVERSION_T				       /* Diversion header field */,
 	HDR_DIVERSION_T				       /* Diversion header field */,
 	HDR_RPID_T					       /* Remote-Party-ID header field */,
 	HDR_RPID_T					       /* Remote-Party-ID header field */,
 	HDR_REFER_TO_T				       /* Refer-To header fiels */,
 	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_RPID_F					HDR_F_DEF(RPID)
 #define HDR_REFER_TO_F				HDR_F_DEF(REFER_TO)
 #define HDR_REFER_TO_F				HDR_F_DEF(REFER_TO)
 #define HDR_SIPIFMATCH_F			HDR_F_DEF(SIPIFMATCH)
 #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_MIN_SE_F				HDR_F_DEF(MIN_SE)
 #define HDR_SUBSCRIPTION_STATE_F	HDR_F_DEF(SUBSCRIPTION_STATE)
 #define HDR_SUBSCRIPTION_STATE_F	HDR_F_DEF(SUBSCRIPTION_STATE)
 #define HDR_ACCEPTCONTACT_F			HDR_F_DEF(HDR_ACCEPTCONTACT_T)
 #define HDR_ACCEPTCONTACT_F			HDR_F_DEF(HDR_ACCEPTCONTACT_T)
 #define HDR_ALLOWEVENTS_F			HDR_F_DEF(HDR_ALLOWEVENTS_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_REFERREDBY_F			HDR_F_DEF(HDR_REFERREDBY_T)
 #define HDR_REJECTCONTACT_F			HDR_F_DEF(HDR_REJECTCONTACT_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)
 #define HDR_OTHER_F					HDR_F_DEF(OTHER)
 
 

+ 4 - 0
parser/keys.h

@@ -74,6 +74,10 @@
 #define _izat_ 0x74617a69   /* "izat" */
 #define _izat_ 0x74617a69   /* "izat" */
 #define _ion2_ 0x206e6f69   /* "ion " */
 #define _ion2_ 0x206e6f69   /* "ion " */
 #define _ion1_ 0x3a6e6f69   /* "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 _y_re_ 0x65722d79   /* "y-re" */
 #define _quir_ 0x72697571   /* "quir" */
 #define _quir_ 0x72697571   /* "quir" */
 #define _reco_ 0x6f636572   /* "reco" */
 #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_REFERREDBY_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REJECTCONTACT_T:
 		case HDR_REQUESTDISPOSITION_T:
 		case HDR_REQUESTDISPOSITION_T:
+		case HDR_WWW_AUTHENTICATE_T:
+		case HDR_PROXY_AUTHENTICATE_T:
 		case HDR_OTHER_T:
 		case HDR_OTHER_T:
 			/* just skip over it */
 			/* just skip over it */
 			hdr->body.s=tmp;
 			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));
 		memset(hf,0, sizeof(struct hdr_field));
 		hf->type=HDR_ERROR_T;
 		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){
 		switch (hf->type){
 			case HDR_ERROR_T:
 			case HDR_ERROR_T:
 				LOG(L_INFO,"ERROR: bad header  field\n");
 				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_REFERREDBY_T:
 			case HDR_REJECTCONTACT_T:
 			case HDR_REJECTCONTACT_T:
 			case HDR_REQUESTDISPOSITION_T:
 			case HDR_REQUESTDISPOSITION_T:
+			case HDR_WWW_AUTHENTICATE_T:
+			case HDR_PROXY_AUTHENTICATE_T:
 			case HDR_OTHER_T: /*do nothing*/
 			case HDR_OTHER_T: /*do nothing*/
 				break;
 				break;
 			case HDR_CALLID_T:
 			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_min.h"      /* Min-SE */
 #include "case_subs.h"     /* Subscription-State */
 #include "case_subs.h"     /* Subscription-State */
 #include "case_requ.h"     /* Require */
 #include "case_requ.h"     /* Require */
+#include "case_www.h"      /* WWW-Authenticate */
 
 
 
 
 #define READ(val) \
 #define READ(val) \
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
 (*(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       \
 #define FIRST_QUATERNIONS       \
         case _via1_: via1_CASE; \
         case _via1_: via1_CASE; \
@@ -129,6 +132,7 @@ static inline char* skip_ws(char* p, unsigned int size)
 	case _reje_: reje_CASE; \
 	case _reje_: reje_CASE; \
 	case _min__: min_CASE;  \
 	case _min__: min_CASE;  \
 	case _requ_: requ_CASE;  \
 	case _requ_: requ_CASE;  \
+	case _www__: www_CASE; \