Module: sip-router Branch: master Commit: b89c747bc717c0f9053e53c53a74f9744c1b8606 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b89c747b...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com 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; }