Commit e64f669f authored by Kai Vehmanen's avatar Kai Vehmanen

Track operation authentication attempts in nua_glib.

darcs-hash:20060531131707-7659e-bcc201ddb4715a0876bb43950d15a18aa05faa9d.gz
parent db334b0c
...@@ -106,6 +106,8 @@ static GObjectClass *parent_class=NULL; ...@@ -106,6 +106,8 @@ static GObjectClass *parent_class=NULL;
static int sof_init(NuaGlibPrivate *priv, const char *contact); static int sof_init(NuaGlibPrivate *priv, const char *contact);
static void priv_submit_authlist(NuaGlibOp *op); static void priv_submit_authlist(NuaGlibOp *op);
static void priv_oper_handle_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags);
static void priv_oper_check_response_for_auth(NuaGlib *self, NuaGlibOp *op, int status, sip_t const *sip, tagi_t *tags);
static GObject * static GObject *
nua_glib_constructor (GType type, nua_glib_constructor (GType type,
...@@ -1207,11 +1209,30 @@ oper_assign(NuaGlibOp *op, sip_method_t method, char const *name) ...@@ -1207,11 +1209,30 @@ oper_assign(NuaGlibOp *op, sip_method_t method, char const *name)
method == sip_method_publish; method == sip_method_publish;
} }
/**
* Helper function called from all response callback handler.
* Checks whether authentication is needed, and handles it if
* require. Marks succesful authentications as completed.
*/
static void priv_oper_check_response_for_auth(NuaGlib *self, NuaGlibOp *op, int status, sip_t const *sip, tagi_t *tags)
{
if (status == 401 || status == 407) {
priv_oper_handle_auth(self, op, sip, tags);
}
else if (status >= 200 && status <= 299){
if (op->op_authstate != opa_none &&
op->op_authstate != opa_auth_ok) {
op->op_authstate = opa_auth_ok;
SU_DEBUG_3(("%s: authorization of %s (%p) was succesful\n",
self->priv->name, op->op_method_name, op));
}
}
}
/** /**
* Handles authentication challenge for operation 'op'. * Handles authentication challenge for operation 'op'.
*/ */
static void static void priv_oper_handle_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags)
oper_set_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags)
{ {
sip_www_authenticate_t const *wa = sip->sip_www_authenticate; sip_www_authenticate_t const *wa = sip->sip_www_authenticate;
sip_proxy_authenticate_t const *pa = sip->sip_proxy_authenticate; sip_proxy_authenticate_t const *pa = sip->sip_proxy_authenticate;
...@@ -1225,31 +1246,41 @@ oper_set_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags) ...@@ -1225,31 +1246,41 @@ oper_set_auth (NuaGlib *self, NuaGlibOp *op, sip_t const *sip, tagi_t *tags)
SIPTAG_PROXY_AUTHENTICATE_REF(pa), SIPTAG_PROXY_AUTHENTICATE_REF(pa),
TAG_NULL()); TAG_NULL());
SU_DEBUG_3(("%s: %s was unauthorized\n", self->priv->name, op->op_method_name)); SU_DEBUG_3(("%s: %s (%p) was unauthorized\n", self->priv->name, op->op_method_name, op));
if (wa) { /* step: the initial challenge */
sl_header_print(stdout, "Server auth: %s\n", (sip_header_t *)wa); if (op->op_authstate == opa_none) {
realm = msg_params_find(wa->au_params, "realm="); if (wa) {
nua_glib_auth_add(self, op, wa->au_scheme, realm, sipfrom->a_url->url_user, self->priv->password); sl_header_print(stdout, "Server auth: %s\n", (sip_header_t *)wa);
realm = msg_params_find(wa->au_params, "realm=");
nua_glib_auth_add(self, op, wa->au_scheme, realm, sipfrom->a_url->url_user, self->priv->password);
}
if (pa) {
sl_header_print(stdout, "Proxy auth: %s\n", (sip_header_t *)pa);
realm = msg_params_find(pa->au_params, "realm=");
nua_glib_auth_add(self, op, pa->au_scheme, realm, sipfrom->a_url->url_user, self->priv->password);
}
op->op_authstate = opa_try_derived;
priv_submit_authlist(op);
} }
if (pa) { /* step: a new challenge and local credentials updated since last attempt */
sl_header_print(stdout, "Proxy auth: %s\n", (sip_header_t *)pa); else if (op->op_authstate == opa_retry) {
realm = msg_params_find(pa->au_params, "realm="); priv_submit_authlist(op);
nua_glib_auth_add(self, op, pa->au_scheme, realm, sipfrom->a_url->url_user, self->priv->password);
} }
/* step: a new challenge, ask for matching credentials */
if (op->op_tried_auth) else if (op->op_authstate == opa_try_derived) {
{ g_message("Requesting for additional authentication credentials %s(%s)",
self->priv->name, op->op_method_name);
op->op_authstate = opa_auth_req;
g_signal_emit(self, signals[NGSIG_AUTH_REQUIRED], 0, op, op->op_method_name, realm);
}
/* step: a new challenge, ask for matching credentials */
else if (op->op_authstate == opa_auth_req) {
g_message("Failed auth for %s by %s", g_message("Failed auth for %s by %s",
op->op_method_name, self->priv->name); op->op_method_name, self->priv->name);
op->op_tried_auth =0; op->op_authstate = opa_failed;
op->op_auth_failed =1;
return;
} }
priv_submit_authlist(op);
op->op_tried_auth =1;
} }
...@@ -1368,8 +1399,7 @@ sof_r_invite(int status, char const *phrase, ...@@ -1368,8 +1399,7 @@ sof_r_invite(int status, char const *phrase,
{ {
if (status >= 300) { if (status >= 300) {
op->op_callstate &= ~opc_sent; op->op_callstate &= ~opc_sent;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
g_signal_emit(self, signals[NGSIG_INVITE_ANSWERED],0, op, status, phrase); g_signal_emit(self, signals[NGSIG_INVITE_ANSWERED],0, op, status, phrase);
} }
...@@ -1682,9 +1712,7 @@ sof_r_options(int status, char const *phrase, ...@@ -1682,9 +1712,7 @@ sof_r_options(int status, char const *phrase,
{ {
g_signal_emit(self, signals[NGSIG_OPTIONS_ANSWERED], 0, op, status, phrase); g_signal_emit(self, signals[NGSIG_OPTIONS_ANSWERED], 0, op, status, phrase);
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
/** /**
...@@ -1722,9 +1750,7 @@ sof_r_message(int status, char const *phrase, ...@@ -1722,9 +1750,7 @@ sof_r_message(int status, char const *phrase,
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
static void static void
...@@ -1798,9 +1824,7 @@ sof_r_info(int status, char const *phrase, ...@@ -1798,9 +1824,7 @@ sof_r_info(int status, char const *phrase,
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
static void static void
...@@ -1873,9 +1897,7 @@ sof_r_refer (int status, char const *phrase, ...@@ -1873,9 +1897,7 @@ sof_r_refer (int status, char const *phrase,
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
/*---------------------------------------*/ /*---------------------------------------*/
...@@ -2024,9 +2046,8 @@ sof_r_subscribe (int status, char const *phrase, ...@@ -2024,9 +2046,8 @@ sof_r_subscribe (int status, char const *phrase,
return; return;
if (status >= 300) if (status >= 300)
op->op_persistent = 0; op->op_persistent = 0;
if (status == 401 || status == 407)
oper_set_auth(self, op, sip, tags);
priv_oper_check_response_for_auth(self, op, status, sip, tags);
} }
/** /**
* nua_glib_notify: * nua_glib_notify:
...@@ -2076,10 +2097,9 @@ sof_r_notify(int status, char const *phrase, ...@@ -2076,10 +2097,9 @@ sof_r_notify(int status, char const *phrase,
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
} }
/*---------------------------------------*/ /*---------------------------------------*/
/** /**
...@@ -2157,20 +2177,13 @@ sof_r_register (int status, char const *phrase, ...@@ -2157,20 +2177,13 @@ sof_r_register (int status, char const *phrase,
{ {
g_signal_emit(self, signals[NGSIG_REGISTER_ANSWERED], 0, op, status, phrase); g_signal_emit(self, signals[NGSIG_REGISTER_ANSWERED], 0, op, status, phrase);
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s: trace", G_STRFUNC);
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
else if (status >= 300) if (status >= 300 && status != 401 && status != 407)
nua_glib_op_destroy(self, op); nua_glib_op_destroy(self, op);
/*
else if (status == 200)
for (m = sip ? sip->sip_contact : NULL; m; m = m->m_next)
sl_header_print(stdout, "\tContact: %s\n", (sip_header_t *)m);
*/
} }
/** /**
...@@ -2232,11 +2245,10 @@ sof_r_unregister (int status, char const *phrase, ...@@ -2232,11 +2245,10 @@ sof_r_unregister (int status, char const *phrase,
for (m = sip ? sip->sip_contact : NULL; m; m = m->m_next) for (m = sip ? sip->sip_contact : NULL; m; m = m->m_next)
sl_header_print(stdout, "\tContact: %s\n", (sip_header_t *)m); sl_header_print(stdout, "\tContact: %s\n", (sip_header_t *)m);
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
else
nua_glib_op_destroy(self, op);
if (status >= 300 && status != 401 && status != 407)
nua_glib_op_destroy(self, op);
} }
/** /**
...@@ -2382,13 +2394,12 @@ sof_r_publish (int status, char const *phrase, ...@@ -2382,13 +2394,12 @@ sof_r_publish (int status, char const *phrase,
if (status < 200) if (status < 200)
return; return;
if (status == 401 || status == 407) priv_oper_check_response_for_auth(self, op, status, sip, tags);
oper_set_auth(self, op, sip, tags);
else if (status >= 300) if (status >= 300 && status != 401 && status != 407)
nua_glib_op_destroy(self, op); nua_glib_op_destroy(self, op);
else if (!sip->sip_expires || sip->sip_expires->ex_delta == 0) else if (!sip->sip_expires || sip->sip_expires->ex_delta == 0)
nua_glib_op_destroy(self, op); nua_glib_op_destroy(self, op);
} }
static void static void
...@@ -2442,8 +2453,7 @@ static void priv_submit_authlist(NuaGlibOp *op) ...@@ -2442,8 +2453,7 @@ static void priv_submit_authlist(NuaGlibOp *op)
GString *tmp = (GString*)i->data; GString *tmp = (GString*)i->data;
if (tmp && tmp->str) { if (tmp && tmp->str) {
g_assert(tmp->len > 0); g_assert(tmp->len > 0);
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, SU_DEBUG_3(("submitting authitem (op=%p): %s.\n", op, tmp->str));
"submitting authitem (op=%p): %s.\n", op, tmp->str);
nua_authenticate(op->op_handle, NUTAG_AUTH(tmp->str), TAG_END()); nua_authenticate(op->op_handle, NUTAG_AUTH(tmp->str), TAG_END());
} }
i = g_slist_next(i); i = g_slist_next(i);
...@@ -2477,7 +2487,7 @@ void nua_glib_auth_add(NuaGlib *self, NuaGlibOp *op, const char *method, const c ...@@ -2477,7 +2487,7 @@ void nua_glib_auth_add(NuaGlib *self, NuaGlibOp *op, const char *method, const c
method, realm, user, password); method, realm, user, password);
op->op_authlist = g_slist_append(op->op_authlist, tmp); op->op_authlist = g_slist_append(op->op_authlist, tmp);
op->op_tried_auth = 0; op->op_authstate = opa_retry;
priv_submit_authlist(op); priv_submit_authlist(op);
} }
...@@ -2501,5 +2511,5 @@ void nua_glib_auth_clear(NuaGlib *self, NuaGlibOp *op) ...@@ -2501,5 +2511,5 @@ void nua_glib_auth_clear(NuaGlib *self, NuaGlibOp *op)
} }
g_slist_free(op->op_authlist), op->op_authlist = NULL; g_slist_free(op->op_authlist), op->op_authlist = NULL;
op->op_tried_auth = 0; op->op_authstate = opa_none;
} }
...@@ -89,7 +89,7 @@ struct _NuaGlibOp { ...@@ -89,7 +89,7 @@ struct _NuaGlibOp {
* - opc_recv2 when re-INVITE has been received * - opc_recv2 when re-INVITE has been received
*/ */
enum { enum {
opc_none, opc_none = 0,
opc_sent = 1, opc_sent = 1,
opc_recv = 2, opc_recv = 2,
opc_complete = 3, opc_complete = 3,
...@@ -98,11 +98,25 @@ struct _NuaGlibOp { ...@@ -98,11 +98,25 @@ struct _NuaGlibOp {
opc_recv2 = 6 opc_recv2 = 6
} op_callstate; } op_callstate;
/** Authentication state.
*
* - opa_try_derived when using account password
* - opa_auth_req when requesting for additional credentials
* - opa_retry when additional credentials have been provided
* - opa_auth_ok if auth was succesful
* - opa_failed if auth failed
*/
enum {
opa_none = 0,
opa_try_derived,
opa_auth_req,
opa_retry,
opa_auth_ok,
opa_failed
} op_authstate;
int op_prev_state; /**< Previous call state */ int op_prev_state; /**< Previous call state */
unsigned op_tried_auth: 1; /**< we've tried to authenticate this op */
unsigned op_auth_failed: 1; /**< we tried to authenticate this op
and it failed */
unsigned op_persistent : 1; /**< Is this handle persistent? */ unsigned op_persistent : 1; /**< Is this handle persistent? */
unsigned op_referred : 1; unsigned op_referred : 1;
unsigned :0; unsigned :0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment