Module: sip-router
Branch: master
Commit: b89c747bc717c0f9053e53c53a74f9744c1b8606
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b89c747bc717c0f9053e53c53a74f9744c1b8606

Author: Daniel-Constantin Mierla <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date:   Tue Apr 23 11:52:13 2013 +0200

uac: added possibility to authenticate generated requests

- $uac_req(auser) - specify the authentication username
- $uac_req(apasswd) - specify the authentication password
- if both attributes above are set and the request is challenged with
  401/407, then the request is resent with auth header

---

 modules/uac/uac_send.c |  244 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 234 insertions(+), 10 deletions(-)

diff --git a/modules/uac/uac_send.c b/modules/uac/uac_send.c
index 47744cd..50bff25 100644
--- a/modules/uac/uac_send.c
+++ b/modules/uac/uac_send.c
@@ -21,9 +21,17 @@
  */
 
 #include "../../dprint.h"
+#include "../../trim.h"
 
 #include "../../modules/tm/tm_load.h"
 
+#include "../../parser/parse_uri.h"
+#include "../../parser/parse_from.h"
+#include "../../parser/parse_to.h"
+#include "../../parser/contact/parse_contact.h"
+
+#include "auth.h"
+#include "auth_hdr.h"
 #include "uac_send.h"
 
 #define MAX_UACH_SIZE 2048
@@ -32,7 +40,7 @@
 /** TM bind */
 struct tm_binds tmb;
 
-struct _uac_send_info {
+typedef struct _uac_send_info {
        unsigned int flags;
        char  b_method[32];
        str   s_method;
@@ -48,11 +56,38 @@ struct _uac_send_info {
        str   s_body;
        char  b_ouri[MAX_URI_SIZE];
        str   s_ouri;
+       char  b_auser[128];
+       str   s_auser;
+       char  b_apasswd[64];
+       str   s_apasswd;
        unsigned int onreply;
-};
+} uac_send_info_t;
 
 static struct _uac_send_info _uac_req;
 
+uac_send_info_t *uac_send_info_clone(uac_send_info_t *ur)
+{
+       uac_send_info_t *tp = NULL;
+       tp = (uac_send_info_t*)shm_malloc(sizeof(uac_send_info_t));
+       if(tp==NULL)
+       {
+               LM_ERR("no more shm memory\n");
+               return NULL;
+       }
+       memcpy(tp, ur, sizeof(uac_send_info_t));
+       tp->s_method.s  = tp->b_method;
+       tp->s_ruri.s    = tp->b_ruri;
+       tp->s_turi.s    = tp->b_turi;
+       tp->s_furi.s    = tp->b_furi;
+       tp->s_hdrs.s    = tp->b_hdrs;
+       tp->s_body.s    = tp->b_body;
+       tp->s_ouri.s    = tp->b_ouri;
+       tp->s_auser.s   = tp->b_auser;
+       tp->s_apasswd.s = tp->b_apasswd;
+
+       return tp;
+}
+
 int pv_get_uac_req(struct sip_msg *msg, pv_param_t *param,
                pv_value_t *res)
 {
@@ -91,6 +126,14 @@ int pv_get_uac_req(struct sip_msg *msg, pv_param_t *param,
                        if(_uac_req.s_method.len<=0)
                                return pv_get_null(msg, param, res);
                        return pv_get_strval(msg, param, res, 
&_uac_req.s_method);
+               case 9:
+                       if(_uac_req.s_auser.len<=0)
+                               return pv_get_null(msg, param, res);
+                       return pv_get_strval(msg, param, res, 
&_uac_req.s_auser);
+               case 10:
+                       if(_uac_req.s_apasswd.len<=0)
+                               return pv_get_null(msg, param, res);
+                       return pv_get_strval(msg, param, res, 
&_uac_req.s_apasswd);
                default:
                        return pv_get_uintval(msg, param, res, _uac_req.flags);
        }
@@ -277,6 +320,46 @@ int pv_set_uac_req(struct sip_msg* msg, pv_param_t *param,
                        }
                        _uac_req.onreply = val->ri;
                        break;
+               case 9:
+                       if(val==NULL)
+                       {
+                               _uac_req.s_auser.len = 0;
+                               return 0;
+                       }
+                       if(!(val->flags&PV_VAL_STR))
+                       {
+                               LM_ERR("Invalid auth user type\n");
+                               return -1;
+                       }
+                       if(val->rs.len>=128)
+                       {
+                               LM_ERR("Value size too big\n");
+                               return -1;
+                       }
+                       memcpy(_uac_req.s_auser.s, val->rs.s, val->rs.len);
+                       _uac_req.s_auser.s[val->rs.len] = '\0';
+                       _uac_req.s_auser.len = val->rs.len;
+                       break;
+               case 10:
+                       if(val==NULL)
+                       {
+                               _uac_req.s_apasswd.len = 0;
+                               return 0;
+                       }
+                       if(!(val->flags&PV_VAL_STR))
+                       {
+                               LM_ERR("Invalid auth password type\n");
+                               return -1;
+                       }
+                       if(val->rs.len>=64)
+                       {
+                               LM_ERR("Value size too big\n");
+                               return -1;
+                       }
+                       memcpy(_uac_req.s_apasswd.s, val->rs.s, val->rs.len);
+                       _uac_req.s_apasswd.s[val->rs.len] = '\0';
+                       _uac_req.s_apasswd.len = val->rs.len;
+                       break;
        }
        return 0;
 }
@@ -308,6 +391,11 @@ int pv_parse_uac_req_name(pv_spec_p sp, str *in)
                                sp->pvp.pvn.u.isname.name.n = 6;
                        else goto error;
                break;
+               case 5:
+                       if(strncmp(in->s, "auser", 5)==0)
+                               sp->pvp.pvn.u.isname.name.n = 9;
+                       else goto error;
+               break;
                case 6: 
                        if(strncmp(in->s, "method", 6)==0)
                                sp->pvp.pvn.u.isname.name.n = 7;
@@ -316,6 +404,8 @@ int pv_parse_uac_req_name(pv_spec_p sp, str *in)
                case 7: 
                        if(strncmp(in->s, "onreply", 7)==0)
                                sp->pvp.pvn.u.isname.name.n = 8;
+                       else if(strncmp(in->s, "apasswd", 7)==0)
+                               sp->pvp.pvn.u.isname.name.n = 10;
                        else goto error;
                break;
                default:
@@ -347,25 +437,148 @@ void uac_req_init(void)
        _uac_req.s_hdrs.s = _uac_req.b_hdrs;
        _uac_req.s_body.s = _uac_req.b_body;
        _uac_req.s_method.s = _uac_req.b_method;
+       _uac_req.s_auser.s  = _uac_req.b_auser;
+       _uac_req.s_apasswd.s  = _uac_req.b_apasswd;
        return;
 }
 
+int uac_send_tmdlg(dlg_t *tmdlg, sip_msg_t *rpl)
+{
+       if(tmdlg==NULL || rpl==NULL)
+               return -1;
+
+       if (parse_headers(rpl, HDR_EOH_F, 0) < 0) {
+               LM_ERR("error while parsing all headers in the reply\n");
+               return -1;
+       }
+       if(parse_to_header(rpl)<0 || parse_from_header(rpl)<0) {
+               LM_ERR("error while parsing From/To headers in the reply\n");
+               return -1;
+       }
+       memset(tmdlg, 0, sizeof(dlg_t));
+
+       str2int(&(get_cseq(rpl)->number), &tmdlg->loc_seq.value);
+       tmdlg->loc_seq.is_set = 1;
+
+       tmdlg->id.call_id = rpl->callid->body;
+       trim(&tmdlg->id.call_id);
+
+       if (get_from(rpl)->tag_value.len) {
+               tmdlg->id.loc_tag = get_from(rpl)->tag_value;
+       }
+#if 0
+       if (get_to(rpl)->tag_value.len) {
+               tmdlg->id.rem_tag = get_to(rpl)->tag_value;
+       }
+#endif
+       tmdlg->loc_uri = get_from(rpl)->uri;
+       tmdlg->rem_uri = get_to(rpl)->uri;
+       tmdlg->state= DLG_CONFIRMED;
+       return 0;
+}
+
+#define MAX_UACH_SIZE 2048
+
 /** 
  * TM callback function
  */
-void uac_send_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
+void uac_send_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
 {
-       unsigned int onreply;
+       int ret;
+       struct hdr_field *hdr;
+       HASHHEX response;
+       str *new_auth_hdr = NULL;
+       static struct authenticate_body auth;
+       struct uac_credential cred;
+       char  b_hdrs[MAX_UACH_SIZE];
+       str   s_hdrs;
+       uac_req_t uac_r;
+       dlg_t tmdlg;
+       uac_send_info_t *tp = NULL;
+
        if(ps->param==NULL || *ps->param==0)
        {
                LM_DBG("message id not received\n");
                goto done;
        }
-       onreply = *((unsigned int*)ps->param);
-       LM_DBG("completed with status %d [onreply: %u]\n",
-               ps->code, onreply);
+       tp = (uac_send_info_t*)(*ps->param);
+       if(ps->code != 401 && ps->code != 407)
+       {
+               LM_DBG("completed with status %d\n", ps->code);
+               goto done;
+       }
+
+       LM_DBG("completed with status %d\n", ps->code);
+
+       hdr = get_autenticate_hdr(ps->rpl, ps->code);
+       if (hdr==0)
+       {
+               LM_ERR("failed to extract authenticate hdr\n");
+               goto error;
+       }
+
+       LM_DBG("auth header body [%.*s]\n",
+               hdr->body.len, hdr->body.s);
+
+       if (parse_authenticate_body(&hdr->body, &auth)<0)
+       {
+               LM_ERR("failed to parse auth hdr body\n");
+               goto error;
+       }
+
+       cred.realm  = auth.realm;
+       cred.user   = tp->s_auser;
+       cred.passwd = tp->s_apasswd;
+       cred.next   = NULL;
+
+       do_uac_auth(&tp->s_method, &tp->s_ruri, &cred, &auth, response);
+       new_auth_hdr=build_authorization_hdr(ps->code, &tp->s_ruri, &cred,
+                                               &auth, response);
+       if (new_auth_hdr==0)
+       {
+               LM_ERR("failed to build authorization hdr\n");
+               goto error;
+       }
+
+       if(tp->s_hdrs.len <= 0) {
+               snprintf(b_hdrs, MAX_UACH_SIZE,
+                               "%.*s",
+                               new_auth_hdr->len, new_auth_hdr->s);
+       } else {
+               snprintf(b_hdrs, MAX_UACH_SIZE,
+                               "%.*s%.*s",
+                               tp->s_hdrs.len, tp->s_hdrs.s,
+                               new_auth_hdr->len, new_auth_hdr->s);
+       }
+
+       s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
+       pkg_free(new_auth_hdr->s);
+
+       memset(&uac_r, 0, sizeof(uac_r));
+       if(uac_send_tmdlg(&tmdlg, ps->rpl)<0)
+       {
+               LM_ERR("failed to build tm dialog\n");
+               goto error;
+       }
+       tmdlg.rem_target = tp->s_ruri;
+       if(tp->s_ouri.len>0)
+               tmdlg.dst_uri = tp->s_ouri;
+       uac_r.method = &tp->s_method;
+       uac_r.headers = &s_hdrs;
+       uac_r.body = (tp->s_body.len <= 0) ? NULL : &tp->s_body;
+       uac_r.dialog = &tmdlg;
+       uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
+       ret = tmb.t_request_within(&uac_r);
+
+       if(ret<0) {
+               LM_ERR("failed to send request with authentication\n");
+               goto error;
+       }
 
 done:
+error:
+       if(tp!=NULL)
+               shm_free(tp);
        return;
 }
 
@@ -374,6 +587,7 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
 {
        int ret;
        uac_req_t uac_r;
+       uac_send_info_t *tp = NULL;
 
        if(_uac_req.s_ruri.len<=0 || _uac_req.s_method.len == 0
                        || tmb.t_request==NULL)
@@ -383,13 +597,20 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
        uac_r.method = &_uac_req.s_method;
        uac_r.headers = (_uac_req.s_hdrs.len <= 0) ? NULL : &_uac_req.s_hdrs;
        uac_r.body = (_uac_req.s_body.len <= 0) ? NULL : &_uac_req.s_body;
-       if(_uac_req.onreply > 0)
+       if(_uac_req.s_auser.len > 0 && _uac_req.s_apasswd.len>0)
        {
+               tp = uac_send_info_clone(&_uac_req);
+               if(tp==NULL)
+               {
+                       LM_ERR("cannot clone the uac structure\n");
+                       return -1;
+               }
+
                uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
                /* Callback function */
                uac_r.cb  = uac_send_tm_callback;
                /* Callback parameter */
-               uac_r.cbp = (void*)(long)_uac_req.onreply;
+               uac_r.cbp = (void*)tp;
        }
        ret = tmb.t_request(&uac_r,  /* UAC Req */
                                                &_uac_req.s_ruri,        /* 
Request-URI */
@@ -398,8 +619,11 @@ int uac_req_send(struct sip_msg *msg, char *s1, char *s2)
                                                
(_uac_req.s_ouri.len<=0)?NULL:&_uac_req.s_ouri /* outbound uri */
                );
 
-       if(ret<0)
+       if(ret<0) {
+               if(tp!=NULL)
+                       shm_free(tp);
                return -1;
+       }
        return 1;
 }
 


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to