from.c

Go to the documentation of this file.
00001 /*
00002  * $Id: from.c 5500 2009-01-23 11:35:02Z carstenbock $
00003  *
00004  * Copyright (C) 2005 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * UAC Kamailio-module is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * UAC Kamailio-module is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021  *
00022  *
00023  * History:
00024  * ---------
00025  *  2005-01-31  first version (ramona)
00026  *  2005-08-12  encoded old FROM URI stored in RR hdr and not in FROM anymore;
00027  *              some TM callbacks replaced with RR callback - more efficient;
00028  *              XOR used to mix together old and new URI
00029  *              (bogdan)
00030  *  2006-03-03  new display name is added even if there is no previous one
00031  *              (bogdan)
00032  *  2006-03-03  the RR parameter is encrypted via XOR with a password
00033  *              (bogdan)
00034  */
00035 
00036 
00037 #include <ctype.h>
00038 
00039 #include "../../parser/parse_from.h"
00040 #include "../../mem/mem.h"
00041 #include "../../data_lump.h"
00042 #include "../tm/h_table.h"
00043 #include "../tm/tm_load.h"
00044 #include "../rr/api.h"
00045 
00046 #include "from.h"
00047 
00048 extern str rr_param;
00049 extern str uac_passwd;
00050 extern int from_restore_mode;
00051 extern struct tm_binds uac_tmb;
00052 extern struct rr_binds uac_rrb;
00053 
00054 static char enc_table64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00055       "abcdefghijklmnopqrstuvwxyz0123456789+/";
00056 
00057 static int dec_table64[256];
00058 
00059 static void restore_from_reply(struct cell* t, int type, struct tmcb_params *p);
00060 static void restore_to_reply(struct cell* t, int type, struct tmcb_params *p);
00061 
00062 #define text3B64_len(_l)   ( ( ((_l)+2)/3 ) << 2 )
00063 
00064 /* The reply, were the From-Line was replaced. */
00065 static int msg_id = 0;
00066 
00067 void init_from_replacer(void)
00068 {
00069    int i;
00070 
00071    for( i=0 ; i<256 ; i++)
00072       dec_table64[i] = -1;
00073    for ( i=0 ; i<64; i++)
00074       dec_table64[(unsigned char)enc_table64[i]] = i;
00075    }
00076 
00077 
00078 static inline int encode_from( str *src, str *dst )
00079 {
00080    static char buf[text3B64_len(MAX_URI_SIZE)];
00081    int  idx;
00082    int  left;
00083    int  block;
00084    int  i,r;
00085    char *p;
00086 
00087    dst->len = text3B64_len( src->len );
00088    dst->s = buf;
00089    if (dst->len>text3B64_len(MAX_URI_SIZE))
00090    {
00091       LM_ERR("uri too long\n");
00092       return -1;
00093    }
00094 
00095    for ( idx=0, p=buf ; idx<src->len ; idx+=3)
00096    {
00097       left = src->len - idx -1 ;
00098       left = (left>1? 2 : left);
00099 
00100       /* Collect 1 to 3 bytes to encode */
00101       block = 0;
00102       for ( i=0,r= 16 ; i<=left ; i++,r-=8 )
00103       {
00104          block += ((unsigned char)src->s[idx+i]) << r;
00105       }
00106 
00107       /* Encode into 2-4 chars appending '=' if not enough data left.*/
00108       *(p++) = enc_table64[(block >> 18) & 0x3f];
00109       *(p++) = enc_table64[(block >> 12) & 0x3f];
00110       *(p++) = left > 0 ? enc_table64[(block >> 6) & 0x3f] : '-';
00111       *(p++) = left > 1 ? enc_table64[block & 0x3f] : '-';
00112    }
00113 
00114    return 0;
00115 }
00116 
00117 
00118 static inline int decode_from( str *src , str *dst)
00119 {
00120    static char buf[MAX_URI_SIZE];
00121    int block;
00122    int n;
00123    int idx;
00124    int end;
00125    int i,j;
00126    char c;
00127 
00128    /* Count '-' at end and disregard them */
00129    for( n=0,i=src->len-1; src->s[i]=='-'; i--)
00130       n++;
00131 
00132    dst->len = ((src->len * 6) >> 3) - n;
00133    dst->s = buf;
00134    if (dst->len>MAX_URI_SIZE)
00135    {
00136       LM_ERR("uri too long\n");
00137       return -1;
00138    }
00139 
00140    end = src->len - n;
00141    for ( i=0,idx=0 ; i<end ; idx+=3 )
00142    {
00143       /* Assemble three bytes into an int from four "valid" characters */
00144       block = 0;
00145       for ( j=0; j<4 && i<end ; j++)
00146       {
00147          c = dec_table64[(unsigned char)src->s[i++]];
00148          if ( c<0 )
00149          {
00150             LM_ERR("invalid base64 string\"%.*s\"\n",src->len,src->s);
00151             return -1;
00152          }
00153          block += c << (18 - 6*j);
00154       }
00155 
00156       /* Add the bytes */
00157       for ( j=0,n=16 ; j<3 && idx+j< dst->len; j++,n-=8 )
00158          buf[idx+j] = (char) ((block >> n) & 0xff);
00159    }
00160 
00161    return 0;
00162 }
00163 
00164 
00165 static inline struct lump* get_fdisplay_anchor(struct sip_msg *msg,
00166                                     struct to_body *from, str *dsp)
00167 {
00168    struct lump* l;
00169    char *p1;
00170    char *p2;
00171 
00172    /* is URI quoted or not? */
00173    p1 = msg->from->name.s + msg->from->name.len;
00174    for( p2=from->uri.s-1 ; p2>=p1 && *p2!='<' ; p2--);
00175 
00176    if (*p2=='<') {
00177       /* is quoted */
00178       l = anchor_lump( msg, p2 - msg->buf, 0, 0);
00179       if (l==0) {
00180          LM_ERR("unable to build lump anchor\n");
00181          return 0;
00182       }
00183       dsp->s[dsp->len++] = ' ';
00184       return l;
00185    }
00186 
00187    /* not quoted - more complicated....must place the closing bracket */
00188    l = anchor_lump( msg, (from->uri.s+from->uri.len) - msg->buf, 0, 0);
00189    if (l==0) {
00190       LM_ERR("unable to build lump anchor\n");
00191       return 0;
00192    }
00193    p1 = (char*)pkg_malloc(1);
00194    if (p1==0) {
00195       LM_ERR("no more pkg mem \n");
00196       return 0;
00197    }
00198    *p1 = '>';
00199    if (insert_new_lump_after( l, p1, 1, 0)==0) {
00200       LM_ERR("insert lump failed\n");
00201       pkg_free(p1);
00202       return 0;
00203    }
00204    /* build anchor for display */
00205    l = anchor_lump( msg, from->uri.s - msg->buf, 0, 0);
00206    if (l==0) {
00207       LM_ERR("unable to build lump anchor\n");
00208       return 0;
00209    }
00210    dsp->s[dsp->len++] = ' ';
00211    dsp->s[dsp->len++] = '<';
00212    return l;
00213 }
00214 
00215 
00216 /*
00217  * relace from uri and/or from display name
00218  */
00219 int replace_from( struct sip_msg *msg, str *from_dsp, str *from_uri)
00220 {
00221    static char buf_s[MAX_URI_SIZE];
00222    struct to_body *from;
00223    struct lump* l;
00224    str replace;
00225    char *p;
00226    str param;
00227    str buf;
00228    int i;
00229 
00230    /* consistency check! in AUTO mode, do NOT allow FROM changing
00231     * in sequential request */
00232    if (from_restore_mode==FROM_AUTO_RESTORE && from_uri && from_uri->len) {
00233       if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
00234          LM_ERR("failed to parse TO hdr\n");
00235          goto error;
00236       }
00237       if (get_to(msg)->tag_value.len!=0) {
00238          LM_ERR("decline FROM replacing in sequential request in auto mode (has TO tag)\n");
00239          goto error;
00240       }
00241    }
00242 
00243    /* parse original from hdr */
00244    if (parse_from_header(msg)<0 )
00245    {
00246       LM_ERR("failed to find/parse FROM hdr\n");
00247       goto error;
00248    }
00249    from = (struct to_body*)msg->from->parsed;
00250    /* some validity checks */
00251    if (from->param_lst==0)
00252    {
00253       LM_ERR("broken FROM hdr; no tag param\n");
00254       goto error;
00255    }
00256 
00257    /* first deal with display name */
00258    if (from_dsp)
00259    {
00260       /* must be replaced/ removed */
00261       l = 0;
00262       /* first remove the existing display */
00263       if ( from->display.len)
00264       {
00265          LM_DBG("removing display [%.*s]\n",from->display.len,from->display.s);
00266          /* build del lump */
00267          l = del_lump( msg, from->display.s-msg->buf, from->display.len, 0);
00268          if (l==0)
00269          {
00270             LM_ERR("display del lump failed\n");
00271             goto error;
00272          }
00273       }
00274       /* some new display to set? */
00275       if (from_dsp->len)
00276       {
00277          /* add the new display exactly over the deleted one */
00278          buf.s = pkg_malloc( from_dsp->len + 2 );
00279          if (buf.s==0)
00280          {
00281             LM_ERR("no more pkg mem\n");
00282             goto error;
00283          }
00284          memcpy( buf.s, from_dsp->s, from_dsp->len);
00285          buf.len =  from_dsp->len;
00286          if (l==0 && (l=get_fdisplay_anchor(msg,from,&buf))==0)
00287          {
00288             LM_ERR("failed to insert anchor\n");
00289             goto error;
00290          }
00291          if (insert_new_lump_after( l, buf.s, buf.len, 0)==0)
00292          {
00293             LM_ERR("insert new display lump failed\n");
00294             pkg_free(buf.s);
00295             goto error;
00296          }
00297       }
00298    }
00299 
00300    /* now handle the URI */
00301    if (from_uri==0 || from_uri->len==0 )
00302       /* do not touch URI part */
00303       return 0;
00304 
00305    LM_DBG("uri to replace [%.*s]\n",from->uri.len, from->uri.s);
00306    LM_DBG("replacement uri is [%.*s]\n",from_uri->len, from_uri->s);
00307 
00308    /* build del/add lumps */
00309    if ((l=del_lump( msg, from->uri.s-msg->buf, from->uri.len, 0))==0)
00310    {
00311       LM_ERR("del lump failed\n");
00312       goto error;
00313    }
00314    p = pkg_malloc( from_uri->len);
00315    if (p==0)
00316    {
00317       LM_ERR("no more pkg mem\n");
00318       goto error;
00319    }
00320    memcpy( p, from_uri->s, from_uri->len); 
00321    if (insert_new_lump_after( l, p, from_uri->len, 0)==0)
00322    {
00323       LM_ERR("insert new lump failed\n");
00324       pkg_free(p);
00325       goto error;
00326    }
00327 
00328    if (from_restore_mode==FROM_NO_RESTORE)
00329       return 0;
00330 
00331    /* build RR parameter */
00332    buf.s = buf_s;
00333    if ( from->uri.len>from_uri->len ) {
00334       if (from->uri.len>MAX_URI_SIZE) {
00335          LM_ERR("old from uri to long\n");
00336          goto error;
00337       }
00338       memcpy( buf.s, from->uri.s, from->uri.len);
00339       for( i=0 ; i<from_uri->len ; i++ )
00340          buf.s[i] ^=from_uri->s[i];
00341       buf.len = from->uri.len;
00342    } else {
00343       if (from_uri->len>MAX_URI_SIZE) {
00344          LM_ERR("new from uri to long\n");
00345          goto error;
00346       }
00347       memcpy( buf.s, from_uri->s, from_uri->len);
00348       for( i=0 ; i<from->uri.len ; i++ )
00349          buf.s[i] ^=from->uri.s[i];
00350       buf.len = from_uri->len;
00351    }
00352 
00353    /* encrypt parameter ;) */
00354    if (uac_passwd.len)
00355       for( i=0 ; i<buf.len ; i++)
00356          buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
00357 
00358    /* encode the param */
00359    if (encode_from( &buf , &replace)<0 )
00360    {
00361       LM_ERR("failed to encode uris\n");
00362       goto error;
00363    }
00364    LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
00365 
00366    /* add RR parameter */
00367    param.len = 1+rr_param.len+1+replace.len;
00368    param.s = (char*)pkg_malloc(param.len);
00369    if (param.s==0)
00370    {
00371       LM_ERR("no more pkg mem\n");
00372       goto error;
00373    }
00374    p = param.s;
00375    *(p++) = ';';
00376    memcpy( p, rr_param.s, rr_param.len);
00377    p += rr_param.len;
00378    *(p++) = '=';
00379    memcpy( p, replace.s, replace.len);
00380    p += replace.len;
00381 
00382    if (uac_rrb.add_rr_param( msg, &param)!=0)
00383    {
00384       LM_ERR("add_RR_param failed\n");
00385       goto error1;
00386    }
00387    msg->msg_flags |= FL_USE_UAC_FROM;
00388 
00389    /* add TM callback to restore the FROM hdr in reply */
00390    if (uac_tmb.register_tmcb(msg,0,TMCB_RESPONSE_IN,restore_from_reply,0,0)!=1)
00391    {
00392       LM_ERR("failed to install TM callback\n");
00393       goto error1;
00394    }
00395 
00396    pkg_free(param.s);
00397    return 0;
00398 error1:
00399    pkg_free(param.s);
00400 error:
00401    return -1;
00402 }
00403 
00404 
00405 /*
00406  * return  0 - restored
00407  *        -1 - not restored or error
00408  */
00409 int restore_from( struct sip_msg *msg, int *is_from )
00410 {
00411    struct lump* l;
00412    str param_val;
00413    str old_uri;
00414    str new_uri;
00415    char *p;
00416    int i;
00417    int flag;
00418 
00419    /* we should process only sequntial request, but since we are looking
00420     * for Route param, the test is not really required -bogdan */
00421 
00422    LM_DBG("getting '%.*s' Route param\n",
00423       rr_param.len,rr_param.s);
00424    /* is there something to restore ? */
00425    if (uac_rrb.get_route_param( msg, &rr_param, &param_val)!=0) {
00426       LM_DBG("route param '%.*s' not found\n",
00427          rr_param.len,rr_param.s);
00428       goto failed;
00429    }
00430    LM_DBG("route param is '%.*s' (len=%d)\n",
00431       param_val.len,param_val.s,param_val.len);
00432 
00433    /* decode the parameter val to a URI */
00434    if (decode_from( &param_val, &new_uri)<0 ) {
00435       LM_ERR("failed to decode uri\n");
00436       goto failed;
00437    }
00438 
00439    /* dencrypt parameter ;) */
00440    if (uac_passwd.len)
00441       for( i=0 ; i<new_uri.len ; i++)
00442          new_uri.s[i] ^= uac_passwd.s[i%uac_passwd.len];
00443 
00444    /* check the request direction */
00445    if (uac_rrb.is_direction( msg, RR_FLOW_UPSTREAM)==0) {
00446       /* replace the TO URI */
00447       if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
00448          LM_ERR("failed to parse TO hdr\n");
00449          goto failed;
00450       }
00451       old_uri = ((struct to_body*)msg->to->parsed)->uri;
00452       flag = FL_USE_UAC_TO;
00453       if (is_from) *is_from = 0;
00454    } else {
00455       /* replace the FROM URI */
00456       if ( parse_from_header(msg)<0 ) {
00457          LM_ERR("failed to find/parse FROM hdr\n");
00458          goto failed;
00459       }
00460       old_uri = ((struct to_body*)msg->from->parsed)->uri;
00461       flag = FL_USE_UAC_FROM;
00462       if (is_from) *is_from = 1;
00463    }
00464 
00465    /* get new uri */
00466    if ( new_uri.len<old_uri.len ) {
00467       LM_ERR("new URI shorter than old URI\n");
00468       goto failed;
00469    }
00470    for( i=0 ; i<old_uri.len ; i++ )
00471       new_uri.s[i] ^= old_uri.s[i];
00472    if (new_uri.len==old_uri.len) {
00473       for( ; new_uri.len && (new_uri.s[new_uri.len-1]==0) ; new_uri.len-- );
00474       if (new_uri.len==0) {
00475          LM_ERR("new URI got 0 len\n");
00476          goto failed;
00477       }
00478    }
00479 
00480    LM_DBG("decoded uris are: new=[%.*s] old=[%.*s]\n",
00481       new_uri.len, new_uri.s, old_uri.len, old_uri.s);
00482 
00483    /* duplicate the decoded value */
00484    p = pkg_malloc( new_uri.len);
00485    if (p==0) {
00486       LM_ERR("no more pkg mem\n");
00487       goto failed;
00488    }
00489    memcpy( p, new_uri.s, new_uri.len);
00490    new_uri.s = p;
00491 
00492    /* build del/add lumps */
00493    l = del_lump( msg, old_uri.s-msg->buf, old_uri.len, 0);
00494    if (l==0) {
00495       LM_ERR("del lump failed\n");
00496       goto failed1;
00497    }
00498 
00499    if (insert_new_lump_after( l, new_uri.s, new_uri.len, 0)==0) {
00500       LM_ERR("insert new lump failed\n");
00501       goto failed1;
00502    }
00503 
00504    msg->msg_flags |= flag;
00505 
00506    return 0;
00507 failed1:
00508    pkg_free(new_uri.s);
00509 failed:
00510    return -1;
00511 }
00512 
00513 
00514 
00515 /************************** RRCB functions ******************************/
00516 
00517 void rr_checker(struct sip_msg *msg, str *r_param, void *cb_param)
00518 {
00519    int is_from;
00520 
00521    is_from = 0;
00522    /* check if the request contains the route param */
00523    if ( restore_from( msg, &is_from)==0 ) {
00524       /* restore in req performed -> replace in reply */
00525       /* in callback we need TO/FROM to be parsed- it's already done 
00526        * by restore_from() function */
00527       if ( uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
00528       is_from?restore_from_reply:restore_to_reply, 0, 0)!=1 ) {
00529          LM_ERR("failed to install TM callback\n");
00530             return;
00531       }
00532    }
00533 }
00534 
00535 
00536 /************************** TMCB functions ******************************/
00537 
00538 /* replace the entire from HDR with the original FROM request */
00539 void restore_from_reply(struct cell* t, int type, struct tmcb_params *p)
00540 {
00541    struct lump* l;
00542    struct sip_msg *req;
00543    struct sip_msg *rpl;
00544    str new_val;
00545 
00546    if ( !t || !t->uas.request || !p->rpl )
00547       return;
00548 
00549    req = t->uas.request;
00550    rpl = p->rpl;
00551 
00552    /* parse FROM in reply */
00553    if (parse_from_header( p->rpl )<0 ) {
00554       LM_ERR("failed to find/parse FROM hdr\n");
00555       return;
00556    }
00557 
00558    LM_DBG("rpl->id = %d, code %d (current id %d)\n", rpl->id, p->code, msg_id);
00559    if (msg_id == rpl->id) {
00560       LM_DBG("No change, already done!\n");
00561       return;
00562    }
00563    msg_id = rpl->id;    
00564    
00565    /* duplicate the new from value */
00566    new_val.s = pkg_malloc( req->from->len );
00567    if (p==0) {
00568       LM_ERR("no more pkg mem\n");
00569       return;
00570    }
00571    memcpy( new_val.s, req->from->name.s, req->from->len);
00572    new_val.len = req->from->len;
00573 
00574 
00575    LM_DBG("removing <%.*s>\n",
00576          rpl->from->len,rpl->from->name.s);
00577    l = del_lump( rpl, rpl->from->name.s-rpl->buf, rpl->from->len, 0);
00578    if (l==0) {
00579       LM_ERR("del lump failed\n");
00580       return;
00581    }
00582 
00583    LM_DBG("inserting <%.*s>\n",
00584          new_val.len,new_val.s);
00585    if (insert_new_lump_after( l, new_val.s, new_val.len, 0)==0) {
00586       LM_ERR("insert new lump failed\n");
00587       return;
00588    }
00589 }
00590 
00591 
00592 
00593 /* replace the entire from TO with the original TO request */
00594 void restore_to_reply(struct cell* t, int type, struct tmcb_params *p)
00595 {
00596    struct lump* l;
00597    struct sip_msg *req;
00598    struct sip_msg *rpl;
00599    str new_val;
00600 
00601    if ( !t || !t->uas.request || !p->rpl )
00602       return;
00603 
00604    req = t->uas.request;
00605    rpl = p->rpl;
00606 
00607    /* parse TO in reply */
00608    if ( rpl->to==0 && (parse_headers(rpl,HDR_TO_F,0)!=0 || rpl->to==0) ) {
00609       LM_ERR("failed to parse TO hdr\n");
00610       return;
00611    }
00612 
00613    /* duplicate the new from value */
00614    new_val.s = pkg_malloc( req->to->len );
00615    if (p==0) {
00616       LM_ERR("no more pkg mem\n");
00617       return;
00618    }
00619    memcpy( new_val.s, req->to->name.s, req->to->len);
00620    new_val.len = req->to->len;
00621 
00622    LM_DBG("removing <%.*s>\n",
00623          rpl->to->len,rpl->to->name.s);
00624    l = del_lump( rpl, rpl->to->name.s-rpl->buf, rpl->to->len, 0);
00625    if (l==0) {
00626       LM_ERR("del lump failed\n");
00627       return;
00628    }
00629 
00630    LM_DBG("inserting <%.*s>\n",
00631       new_val.len, new_val.s);
00632    if (insert_new_lump_after( l, new_val.s, new_val.len, 0)==0) {
00633       LM_ERR("insert new lump failed\n");
00634       return;
00635    }
00636 }
00637 

Generated on Wed May 23 06:00:45 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6