[Devel] patch uac_auth cseq - however still problems ...

G.Jacobsen g_jacobsen at yahoo.co.uk
Mon Jun 5 18:03:54 CEST 2006


Bogdan,

thanks a lot for your comments regarding the cseq, UAC_authentication
problem.

Since I couldnt find any way to increment the CSeq Value via script language
I have patched textops.c of Openser 1.0.1 and introduced a new function
inc_cseq_val() in the textops module with no parameters. The Textops module
might not be the most suitable place for this function but appeared to me
the best place not to mess things up - given my coding skills and lack of
insight
into openser internals. If someone could have a look over this patch I would
be most grateful.

You wrote:

> maybe a simpler solution will be to increase the cseq on UAS side, allow
> the transaction to be completed (as you are transaction stateful,
> keeping cseq consistency is not difficult). AFter that, either send an
> re-INVITE or NOTIFY within the dialog only on UAC side to increase its
> CSEQ also and to get rid of dialog synchronization.

Unfortunately I did not understand you correctly here. As far
as I understand, the transaction (INVITE) is only completed when the remote
party has picked up the call. So any 100 or 180 ringing messages from the
UAS would have to be relayed to the UAC with the "wrong" CSeq number - or be
manipulated down again. Any cancel message of the UAC would fail with the
UAS due to the wrong CSeq number. Or did you mean I should issue a RE-INVITE
to the UAS after the UAC gives me back the first 100 trying or ringing 180
after the successful authentication ?

Secondly, I do not understand how OS can generate a RE-INVITE or NOTIFY by
itself by script language ?

I thought that there is an other way for me: I need to authenticate all UAC
against my OS anyway on each INVITE (Causing a CSeq number of minimum 2
after
authentication (if UAS are RFC compliant). So in the second INVITE from the
UAC  (which passed with the credentials for OS) I could theoretically
DEcrease the CSeq value when relaying it on the
downstream leg to the UAS, and INcrease again the CSeq when answering the
407 challenge from the downstream UAC. After that both CSeq legs would be in
sync again.

However as I had to discover a problem with this approach - openser sends
the ACK to the UAS challenge with NOT decreased CSeq number (although the
UAS challenge comes back with the decreased CSeq number). I suppose OS is
"too clever" here and caches the the old CSeq value and ignores the CSeq
number of the UAS challenge. Also other wierd things were happening in later
messages. I guess the module gets utterly confused by a decreased CSeq.


I would be most grateful if you could clarify what you meant.

TIA

Gerry


patch attached

----- Original Message ----- 
From: "Bogdan-Andrei Iancu" <bogdan at voice-system.ro>
To: "G.Jacobsen" <g_jacobsen at yahoo.co.uk>
Cc: <users at openser.org>
Sent: Wednesday, May 31, 2006 12:40 PM
Subject: [Bulk] Re: [Users] Can this work?: re. uac_auth cseq problem


> Hi Gerry,
>
> there are couple of problems with this approach:
>
> 1) you presume that the UAC phone supports authentication, but uac
> module is intended to be used also in front of devices that are not able
> to do auth.
>
> 2) there is no standard recipe that guarantee that the UAC phone will
> actually resend and INVITE to a fake authentication challenge - even if
> you mangle the user and domain in challenge, some phones do not try
> again if already failed with same credentials.
>
> 3) the dialog may be brake - you close the dialog with the UAC for the
> original INVITE, force it to generate a new one (via challenge), but on
> the UAS side there is only one dialog matching the first on UAC side -
> so when the UAS sends 200 OK (based on first dialog), it may to match
> the second dialog (on UAC side) - there is no guarantee that both
> dialogs will have same ftag or even that the callid is preserved.
>
> maybe a simpler solution will be to increase the cseq on UAS side, allow
> the transaction to be completed (as you are transaction stateful,
> keeping cseq consistency is not difficult). AFter that, either send an
> re-INVITE or NOTIFY within the dialog only on UAC side to increase its
> CSEQ also and to get rid of dialog synchronization.
> but, that should work in theory...practice is a different thing ;)
>
> regards,
> bogdan
>
> G.Jacobsen wrote:
>
> > I am still digging in this cseq uac problem which I need desperately
> > to solve.
> >
> > The problem is that the uac_auth function can create credentials for
> > the downstream proxy after being challenged with a 401 or 407 message
> > - but the downstream proxy (UAS) refuses this proxy_auth message since
> > openser does not increase the cseq number. Increasing the cseq number
> > only downstream wouldnt solve the problem since any replies of the
> > downstream proxy back to the originating UAC would have cseq numbers
> > which are out of sync.
> >
> > I propose: In order to keep the cseq numbers in sync upstream and
> > downstream one must generate challenges and proxy-auth responses on
> > both legs of the route - and not only respond downstream as currently.
> >
> > So whenever openser receives from the downstream proxy a challenge it
> > must forward this challenge the originating UAC (if necessary
> > modify the message in such a way that the UAC is
> > guaranteed to respond). This upstream challenge causes the
> > originating UAC to increase the cseq. Naturally openser must also
> > increase the cseq number downstream  when generating its own
> > proxy_auth repsonse to the downstream proxy. Whatever credentials UAC
> > produces are discarted by openser.
> >
> > The scheme:
> >
> > 1. UAC issues invite which is routed by OS to the downstream proxy
> > (UAS) - as usual.
> > 2. UAS issues challenge 401 or 407 - as usual
> > 3. OS captures challenge on_failure route - as envisaged by UAC module
> > 4. this is new:
> > a) OS relays the challenge upstream to UAC (would it be necessary to
> > modify it before doing so ?)
> > b) OS constructs with uac_auth function correct proxy_auth
> > credentials for UAS, increases the cseq with some text manipulation
> > function and replies to UAS.
> > 5. UAC responds with (wrong) proxy_auth credentials via OS to UAS
> > 6. OS discards the credential message it received from the UAC - to
> > avoid that the message reaches UAS.
> > 7. Invite successful or failure : UAS responds with further messages
> > which are routed to UAC.
> >
> > Can this scheme work - or am I overlooking something here ?
> >
> > TIA
> >
> > Gerry
> >
> >
> >------------------------------------------------------------------------
> >
> >_______________________________________________
> >Users mailing list
> >Users at openser.org
> >http://openser.org/cgi-bin/mailman/listinfo/users
> >
> >
>



--- textops.c.old 2005-10-19 22:12:12.000000000 +0300
+++ textops.c 2006-06-05 08:29:21.000000000 +0300
@@ -63,6 +63,8 @@
 #include "../../parser/parse_uri.h"
 #include "../../parser/parse_hname2.h"
 #include "../../parser/parse_methods.h"
+#include "../../trim.h"
+#include "../../ut.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -98,6 +100,7 @@
 static int append_urihf(struct sip_msg* msg, char* str1, char* str2);
 static int append_time_f(struct sip_msg* msg, char* , char *);
 static int is_method_f(struct sip_msg* msg, char* , char *);
+static int inc_cseq_val_f(struct sip_msg* msg, char* , char *);

 static int fixup_regex(void**, int);
 static int fixup_substre(void**, int);
@@ -137,6 +140,8 @@
   REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
  {"is_method",        is_method_f,       1, fixup_method,
    REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
+ {"inc_cseq_val",        inc_cseq_val_f,   0, 0,
+   REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
  {0,0,0,0,0}
 };

@@ -165,8 +170,6 @@
  return msg->buf+msg->first_line.len;
 }

-
-
 static int search_f(struct sip_msg* msg, char* key, char* str2)
 {
  /*we registered only 1 param, so we ignore str2*/
@@ -176,8 +179,6 @@
  return 1;
 }

-
-
 static int search_append_f(struct sip_msg* msg, char* key, char* str)
 {
  struct lump* l;
@@ -214,8 +215,6 @@

 static int replace_all_f(struct sip_msg* msg, char* key, char* str)
 {
-
-
  struct lump* l;
  regmatch_t pmatch;
  char* s;
@@ -429,6 +428,7 @@
  act.p1_type = STRING_ST;
  act.p1.string = result->s;
  rval = do_action(&act, msg);
+
  pkg_free(result);
  return rval;
 }
@@ -536,7 +536,6 @@
 static int append_time_f(struct sip_msg* msg, char* p1, char *p2)
 {

-
  size_t len;
  char time_str[MAX_TIME];
  time_t now;
@@ -662,6 +661,106 @@
     m->len)==0))?1:-1;
 }

+/* inc_cseq_val function obtains CSeq value and CSeq method name
+with SER parsing methods; increments the CSeq value by 1;
+searches for string of CSeq value + whitespace + CSeq method name in header
text
+and replaces this string with a string of incremented CSeq value +
whitespace + Cseq method name */
+static int inc_cseq_val_f(struct sip_msg* msg, char* p1, char *p2)
+{
+ unsigned int cseq_val;
+ char* insert_str;
+ char* search_str;
+ int searchlen;
+ int insertlen;
+ str cseq_old_val_str;
+ str cseq_new_val_str;
+ int off;
+ str cseq_meth;
+ char* begin;
+ char* header;
+ struct lump* l;
+
+ if(parse_headers(msg, HDR_CSEQ_F, 0)!=0)
+ {
+  LOG(L_ERR, "textops:inc_cseq_val: ERROR - cannot parse cseq header\n");
+  return -1; /* should it be 0 ?!?! */
+ }
+
+ /* get cseq value as unsigned int */
+ cseq_old_val_str.s = get_cseq(msg)->number.s;
+ cseq_old_val_str.len = get_cseq(msg)->number.len;
+ trim_leading(&cseq_old_val_str);
+ if (str2int(&cseq_old_val_str, &cseq_val) < 0) {
+     LOG(L_ERR, "textops:inc_cseq_val(): Error while converting cseq
number\n");
+     return -1;
+ }
+
+ /* increment cseq value */
+ cseq_val++;
+ /* convert incremented cseq integer value back to string null terminated*/
+ cseq_new_val_str.s = int2str((unsigned long)cseq_val,
&cseq_new_val_str.len);
+ /* get cseq method */
+ cseq_meth.s=get_cseq(msg)->method.s;
+ cseq_meth.len=get_cseq(msg)->method.len;
+
+ /* allocate memory for insert string - not null terminated*/
+ insertlen = cseq_new_val_str.len + cseq_meth.len + 1;
+ insert_str = (char *)pkg_malloc(insertlen);
+ if (insert_str==0){
+  LOG(L_ERR, "ERROR: inc_cseq_val: mem. allocation failure insert
string\n");
+  return -1;
+ }
+
+ /* Construct the insert string - not null terminated*/
+ memcpy(insert_str, cseq_new_val_str.s, cseq_new_val_str.len);
+ memcpy(insert_str+cseq_new_val_str.len, " ", 1);
+ memcpy(insert_str+cseq_new_val_str.len+1 ,cseq_meth.s, cseq_meth.len);
+
+ /* allocate memory for search string null terminated*/
+ searchlen = cseq_old_val_str.len + cseq_meth.len + 2;
+ search_str= (char *)pkg_malloc(searchlen);
+ if (search_str==0){
+  pkg_free(insert_str);
+  LOG(L_ERR, "ERROR: inc_cseq_val: mem. allocation failure search
string\n");
+  return -1;
+ }
+
+ /* Construct the search string null terminated*/
+ memcpy(search_str, cseq_old_val_str.s, cseq_old_val_str.len);
+ memcpy(search_str+cseq_old_val_str.len, " ", 1);
+ memcpy(search_str+cseq_old_val_str.len+1 ,cseq_meth.s, cseq_meth.len);
+ search_str[searchlen-1]=0;
+
+ header=get_header(msg);
+ off= header - msg->buf;
+
+ /* find the search string */
+ begin = strstr(header, search_str);
+ pkg_free(search_str);
+
+ if (!(begin==NULL))
+ {
+  /* string found */
+  if ((l=del_lump(msg, begin - header + off, searchlen-1, 0))==0){
+   LOG(L_ERR, "ERROR: could not del_lump\n");
+   pkg_free(insert_str);
+   return -1;
+  }
+  if (insert_new_lump_after(l, insert_str,insertlen, 0)==0){
+   LOG(L_ERR, "ERROR: could not insert new lump\n");
+   pkg_free(insert_str);
+   return -1;
+  }
+  return 1;
+ } else {
+  /*string not found */
+  LOG(L_ERR, "textops:inc_cseq_val: search string NOT found\n");
+  pkg_free(insert_str);
+  return -1;
+ }
+}
+
+
 /*
  * Convert char* parameter to str* parameter
  */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: textops.c.patch
Type: application/octet-stream
Size: 5100 bytes
Desc: not available
Url : http://openser.org/pipermail/devel/attachments/20060605/b89a18e0/textops.c-0001.obj


More information about the Devel mailing list