From e6bd4b2f5530905a6c12a1e48c9f2224db6426c4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 28 Oct 2009 16:55:29 +0000 Subject: [PATCH] use nonce count with registration git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15260 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 7 +-- src/mod/endpoints/mod_sofia/sofia_reg.c | 67 ++++++++++++++++++++---- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 69f0fb072f..9bb68bee3d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -37,7 +37,7 @@ /*Defines etc..*/ /*************************************************************************************************************************************************************/ #define MANUAL_BYE - +#define DEFAULT_NONCE_TTL 60 #define IREG_SECONDS 30 #define GATEWAY_SECONDS 1 #define SOFIA_QUEUE_SIZE 50000 diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 97d34e9e2a..926ee9cd9f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3685,7 +3685,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile) " nonce VARCHAR(255),\n" " expires INTEGER," " profile_name VARCHAR(255),\n" - " hostname VARCHAR(255)\n" + " hostname VARCHAR(255),\n" + " last_nc INTEGER\n" ");\n"; /* should we move this glue to sofia_sla or keep it here where all db init happens? XXX MTK */ @@ -3799,7 +3800,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile) } free(test_sql); - test_sql = switch_mprintf("delete from sip_authentication where hostname='%q'", mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' and last_nc >= 0", mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_authentication", NULL); @@ -3857,7 +3858,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile) switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_presence", pres_sql); free(test_sql); - test_sql = switch_mprintf("delete from sip_authentication where hostname='%q'", mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' and last_nc >= 0", mod_sofia_globals.hostname); switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_authentication", auth_sql); free(test_sql); diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 33c81fbe3b..4935ef7361 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -681,8 +681,10 @@ void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_uuid_get(&uuid); switch_uuid_format(uuid_str, &uuid); - sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname) " - "values('%q', %ld, '%q', '%q')", uuid_str, switch_epoch_time_now(NULL) + profile->nonce_ttl, profile->name, mod_sofia_globals.hostname); + sql = switch_mprintf("insert into sip_authentication (nonce,expires,profile_name,hostname, last_nc) " + "values('%q', %ld, '%q', '%q', 0)", uuid_str, + switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL), + profile->name, mod_sofia_globals.hostname); switch_assert(sql != NULL); sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); switch_safe_free(sql); @@ -1567,6 +1569,25 @@ void sofia_reg_handle_sip_r_challenge(int status, } +static unsigned long get_nc(const char *nc, sip_t const *sip) +{ + unsigned long x; + const char *ua = NULL; + + if (sip->sip_user_agent) { + ua = sip->sip_user_agent->g_string; + } + + /* sigh, polycom sends nc in base-10 rather than spec which says base-16*/ + if (ua && switch_stristr("polycom", ua)) { + x = strtoul(nc, 0, 10); + } else { + x = strtoul(nc, 0, 16); + } + + return x; +} + auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, sip_t const *sip, @@ -1658,7 +1679,15 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, if (zstr(np)) { first = 1; - sql = switch_mprintf("select nonce from sip_authentication where nonce='%q'", nonce); + if (nc) { + unsigned long x; + + x = get_nc(nc, sip); + sql = switch_mprintf("select nonce from sip_authentication where nonce='%q' and last_nc + 1 >= %lu", nonce, x); + } else { + sql = switch_mprintf("select nonce from sip_authentication where nonce='%q'", nonce); + } + switch_assert(sql != NULL); if (!sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, np, nplen)) { free(sql); @@ -1885,15 +1914,15 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, input2 = switch_mprintf("%s:%s:%s", a1_hash, nonce, uridigest); } - switch_assert(input2); + if (input2) { + memset(&ctx, 0, sizeof(ctx)); + su_md5_init(&ctx); + su_md5_strupdate(&ctx, input2); + su_md5_hexdigest(&ctx, bigdigest); + su_md5_deinit(&ctx); + } - memset(&ctx, 0, sizeof(ctx)); - su_md5_init(&ctx); - su_md5_strupdate(&ctx, input2); - su_md5_hexdigest(&ctx, bigdigest); - su_md5_deinit(&ctx); - - if (!strcasecmp(bigdigest, response)) { + if (input2 && !strcasecmp(bigdigest, response)) { ret = AUTH_OK; } else { if ((profile->ndlb & PFLAG_NDLB_BROKEN_AUTH_HASH) && strcasecmp(regstr, "REGISTER") && strcasecmp(regstr, "INVITE")) { @@ -2047,6 +2076,22 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, } end: + + if (nc && cnonce && qop) { + unsigned long x; + char *sql; + + x = get_nc(nc, sip); + input2 = switch_mprintf("%s:%s:%s:%s:%s:%s", a1_hash, nonce, nc, cnonce, qop, uridigest); + + sql = switch_mprintf("update sip_authentication set expires='%ld',last_nc=%lu where nonce='%s'", + switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : exptime + 10), x, nonce); + + switch_assert(sql != NULL); + sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + switch_safe_free(sql); + } + switch_event_destroy(¶ms); if (xml) {