2006-12-21 06:30:28 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Sofia-SIP package
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005 Nokia Corporation.
|
|
|
|
*
|
|
|
|
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@CFILE auth_client.c Authenticators for SIP client
|
|
|
|
*
|
|
|
|
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
|
|
*
|
|
|
|
* @date Created: Wed Feb 14 18:32:58 2001 ppessi
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
#define SOFIA_EXTEND_AUTH_CLIENT 1
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
#include <sofia-sip/su.h>
|
|
|
|
#include <sofia-sip/su_md5.h>
|
|
|
|
|
|
|
|
#include "sofia-sip/auth_common.h"
|
|
|
|
#include "sofia-sip/auth_client.h"
|
|
|
|
#include "sofia-sip/auth_client_plugin.h"
|
|
|
|
|
|
|
|
#include <sofia-sip/msg_types.h>
|
|
|
|
#include <sofia-sip/msg_header.h>
|
|
|
|
|
|
|
|
#include <sofia-sip/auth_digest.h>
|
|
|
|
|
|
|
|
#include <sofia-sip/base64.h>
|
2009-07-10 00:49:35 +00:00
|
|
|
#include <sofia-sip/bnf.h>
|
2006-12-21 06:30:28 +00:00
|
|
|
#include <sofia-sip/su_uniqueid.h>
|
2009-02-11 16:47:44 +00:00
|
|
|
#include <sofia-sip/su_string.h>
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
#include <sofia-sip/su_debug.h>
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static auth_client_t *ca_create(su_home_t *home,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *scheme,
|
|
|
|
char const *realm);
|
|
|
|
|
|
|
|
static void ca_destroy(su_home_t *home, auth_client_t *ca);
|
|
|
|
|
|
|
|
static int ca_challenge(auth_client_t *ca,
|
2008-12-16 18:05:22 +00:00
|
|
|
msg_auth_t const *auth,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_hclass_t *credential_class,
|
|
|
|
char const *scheme,
|
|
|
|
char const *realm);
|
|
|
|
|
|
|
|
static int ca_info(auth_client_t *ca,
|
|
|
|
msg_auth_info_t const *ai,
|
|
|
|
msg_hclass_t *credential_class);
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static int ca_credentials(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *scheme,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *realm,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *user,
|
|
|
|
char const *pass);
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
static int ca_clear_credentials(auth_client_t *ca);
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2009-02-11 16:53:49 +00:00
|
|
|
static int ca_has_authorization(auth_client_t const *ca);
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
/** Initialize authenticators.
|
|
|
|
*
|
|
|
|
* The function auc_challenge() merges the challenge @a ch to the list of
|
2008-12-16 18:05:22 +00:00
|
|
|
* authenticators @a auc_list.
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @param[in,out] auc_list list of authenticators to be updated
|
|
|
|
* @param[in,out] home memory home used for allocating authenticators
|
|
|
|
* @param[in] ch challenge to be processed
|
|
|
|
* @param[in] crcl credential class
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2009-02-11 16:21:43 +00:00
|
|
|
* @retval 1 when at least one challenge was updated
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval 0 when there was no new challenges
|
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
|
|
|
int auc_challenge(auth_client_t **auc_list,
|
2008-12-16 18:05:22 +00:00
|
|
|
su_home_t *home,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_auth_t const *ch,
|
|
|
|
msg_hclass_t *crcl)
|
|
|
|
{
|
|
|
|
auth_client_t **cca;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
/* Go through each challenge in Authenticate or Proxy-Authenticate headers */
|
|
|
|
for (; ch; ch = ch->au_next) {
|
|
|
|
char const *scheme = ch->au_scheme;
|
|
|
|
char const *realm = msg_header_find_param(ch->au_common, "realm=");
|
|
|
|
int matched = 0, updated;
|
|
|
|
|
|
|
|
if (!scheme || !realm)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Update matching authenticator */
|
|
|
|
for (cca = auc_list; (*cca); cca = &(*cca)->ca_next) {
|
|
|
|
updated = ca_challenge((*cca), ch, crcl, scheme, realm);
|
|
|
|
if (updated < 0)
|
|
|
|
return -1;
|
|
|
|
if (updated == 0)
|
|
|
|
continue; /* No match, next */
|
|
|
|
matched = 1;
|
|
|
|
if (updated > 1)
|
|
|
|
retval = 1; /* Updated authenticator */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!matched) {
|
|
|
|
/* There was no matching authenticator, create a new one */
|
|
|
|
*cca = ca_create(home, scheme, realm);
|
2009-02-11 16:18:36 +00:00
|
|
|
|
|
|
|
if (*cca == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (ca_challenge((*cca), ch, crcl, scheme, realm) < 0) {
|
2006-12-21 06:30:28 +00:00
|
|
|
ca_destroy(home, *cca), *cca = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
2009-02-11 16:18:36 +00:00
|
|
|
/* XXX - case w/ unknown authentication scheme */
|
|
|
|
else
|
|
|
|
retval = 1; /* Updated authenticator */
|
2006-12-21 06:30:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
/** Update authentication client.
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @retval -1 upon an error
|
|
|
|
* @retval 0 when challenge did not match
|
|
|
|
* @retval 1 when challenge did match but was not updated
|
|
|
|
* @retval 2 when challenge did match and updated client
|
|
|
|
*/
|
|
|
|
static
|
2008-12-16 18:05:22 +00:00
|
|
|
int ca_challenge(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_auth_t const *ch,
|
|
|
|
msg_hclass_t *credential_class,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *scheme,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *realm)
|
|
|
|
{
|
|
|
|
int stale = 0;
|
|
|
|
|
|
|
|
assert(ca); assert(ch);
|
|
|
|
|
|
|
|
if (!ca || !ch)
|
|
|
|
return -1;
|
|
|
|
|
2009-02-11 16:47:44 +00:00
|
|
|
if (!su_casematch(ca->ca_scheme, scheme))
|
2006-12-21 06:30:28 +00:00
|
|
|
return 0;
|
2009-02-11 16:47:44 +00:00
|
|
|
if (!su_strmatch(ca->ca_realm, realm))
|
2006-12-21 06:30:28 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
if (ca->ca_credential_class &&
|
2006-12-21 06:30:28 +00:00
|
|
|
ca->ca_credential_class != credential_class)
|
|
|
|
return 0;
|
|
|
|
|
2009-02-11 16:53:49 +00:00
|
|
|
if (!ca->ca_auc) {
|
|
|
|
ca->ca_credential_class = credential_class;
|
2006-12-21 06:30:28 +00:00
|
|
|
return 1;
|
2009-02-11 16:53:49 +00:00
|
|
|
}
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
if (ca->ca_auc->auc_challenge)
|
|
|
|
stale = ca->ca_auc->auc_challenge(ca, ch);
|
2014-04-04 18:42:05 +00:00
|
|
|
|
|
|
|
if (AUTH_CLIENT_IS_EXTENDED(ca))
|
|
|
|
ca->ca_clear = 0;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
if (stale < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!ca->ca_credential_class)
|
2007-04-15 02:03:41 +00:00
|
|
|
stale = 2, ca->ca_credential_class = credential_class;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
return stale > 1 ? 2 : 1;
|
2006-12-21 06:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Store authentication info to authenticators.
|
|
|
|
*
|
2007-04-15 02:03:41 +00:00
|
|
|
* The function auc_info() feeds the authentication data from the @b
|
|
|
|
* Authentication-Info header @a info to the list of authenticators @a
|
|
|
|
* auc_list.
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @param[in,out] auc_list list of authenticators to be updated
|
2007-04-15 02:03:41 +00:00
|
|
|
* @param[in] info info header to be processed
|
|
|
|
* @param[in] credential_class corresponding credential class
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
2007-04-15 02:03:41 +00:00
|
|
|
* The authentication info can be in either @AuthenticationInfo or in
|
|
|
|
* @ProxyAuthenticationInfo headers. If the header is @AuthenticationInfo,
|
|
|
|
* the @a credential_class should be #sip_authorization_class or
|
|
|
|
* #http_authorization_class. Likewise, If the header is
|
|
|
|
* @ProxyAuthenticationInfo, the @a credential_class should be
|
|
|
|
* #sip_proxy_authorization_class or #http_proxy_authorization_class.
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
* The authentication into header usually contains next nonce or mutual
|
|
|
|
* authentication information. Currently, only the nextnonce parameter is
|
|
|
|
* processed.
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @bug
|
2008-12-16 18:05:22 +00:00
|
|
|
* In principle, SIP allows more than one challenge for a single request.
|
Sync to current darcs tree:
Mon Sep 17 14:50:04 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/sip_util.h: updated documentation
Mon Sep 17 14:50:18 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/tport_tag.h: updated documentation
Mon Sep 17 14:50:28 EDT 2007 Pekka.Pessi@nokia.com
* soa_tag.c: updated documentation
Wed Sep 19 12:50:01 EDT 2007 Pekka.Pessi@nokia.com
* msg: updated documentation
Wed Sep 19 13:29:50 EDT 2007 Pekka.Pessi@nokia.com
* url: updated documentation
Wed Sep 19 13:32:14 EDT 2007 Pekka.Pessi@nokia.com
* nth: updated documentation
Wed Sep 19 13:32:27 EDT 2007 Pekka.Pessi@nokia.com
* nea: updated documentation
Wed Sep 19 13:33:36 EDT 2007 Pekka.Pessi@nokia.com
* http: updated documentation
Wed Sep 19 13:36:58 EDT 2007 Pekka.Pessi@nokia.com
* bnf: updated documentation
Wed Sep 19 13:38:58 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated nua_stack_init_handle() prototype
Wed Sep 19 18:45:56 EDT 2007 Pekka.Pessi@nokia.com
* sip: added sip_name_addr_xtra(), sip_name_addr_dup()
Wed Sep 19 19:00:19 EDT 2007 Pekka.Pessi@nokia.com
* sip_basic.c: cleaned old crud
Thu Sep 20 13:34:04 EDT 2007 Pekka.Pessi@nokia.com
* iptsec: updated documentation
Thu Sep 20 13:36:22 EDT 2007 Pekka.Pessi@nokia.com
* tport: updated documentation
Thu Sep 20 13:36:56 EDT 2007 Pekka.Pessi@nokia.com
* su: updated documentation
Removed internal files from doxygen-generated documentation.
Thu Sep 20 13:38:29 EDT 2007 Pekka.Pessi@nokia.com
* soa: fixed documentation
Thu Sep 20 13:39:56 EDT 2007 Pekka.Pessi@nokia.com
* sdp: updated documentation
Thu Sep 20 13:40:16 EDT 2007 Pekka.Pessi@nokia.com
* ipt: updated documentation
Thu Sep 20 14:24:20 EDT 2007 Pekka.Pessi@nokia.com
* nta: updated documentation
Thu Sep 20 14:41:04 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated documentation
Updated tag documentation.
Moved doxygen doc entries from sofia-sip/nua_tag.h to nua_tag.c.
Removed internal datatypes and files from the generated documents.
Wed Sep 19 13:34:20 EDT 2007 Pekka.Pessi@nokia.com
* docs: updated the generation of documentation. Updated links to header files.
Thu Sep 20 08:45:32 EDT 2007 Pekka.Pessi@nokia.com
* sip/Makefile.am: added tags to <sofia-sip/sip_extra.h>
Added check for extra tags in torture_sip.c.
Thu Sep 20 14:45:22 EDT 2007 Pekka.Pessi@nokia.com
* stun: updated documentation
Wed Jul 4 18:55:20 EDT 2007 Pekka.Pessi@nokia.com
* torture_heap.c: added tests for ##sort() and su_smoothsort()
Wed Jul 4 18:56:59 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am: added smoothsort.c
Fri Jul 13 12:38:44 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: heap_remove() now set()s index to 0 on removed item
Mon Jul 23 11:14:22 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: fixed bug in heap##remove()
If left kid was in heap but right was not, left kid was ignored.
Wed Jul 4 18:51:08 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Jul 4 18:51:34 EDT 2007 Pekka.Pessi@nokia.com
* heap.h: using su_smoothsort()
Fri Jul 6 10:20:27 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Sep 19 17:40:30 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: generate two parser tables, default and extended
Wed Sep 19 18:39:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: just generate list of extra headers
Allocate extended parser dynamically.
Wed Sep 19 18:59:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: added Remote-Party-ID, P-Asserted-Identity, P-Preferred-Identity
Added functions sip_update_default_mclass() and sip_extend_mclass()
for handling the extended parser. Note that Reply-To and Alert-Info are only
available with the extended parser.
Wed Sep 19 19:05:44 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Thu Sep 20 13:38:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: updated documentation
Thu Sep 20 14:17:28 EDT 2007 Pekka.Pessi@nokia.com
* docs/conformance.docs: updated
Mon Oct 1 10:11:14 EDT 2007 Pekka.Pessi@nokia.com
* tport_tag.c: re-enabled tptag_trusted
Thu Oct 4 09:21:07 EDT 2007 Pekka.Pessi@nokia.com
* su_osx_runloop.c: moved virtual function table after struct definition
Preparing for su_port_vtable_t refactoring.
Thu Oct 4 10:22:03 EDT 2007 Pekka.Pessi@nokia.com
* su_source.c: refactored initialization/deinitialization
Fri Oct 5 04:58:18 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* sip_extra.c: fixed prototypes with isize_t
Fri Oct 5 04:58:45 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nta_api.c: removed warnings about signedness
Fri Oct 5 04:59:02 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nua_params.c: removed warnings about constness
Fri Oct 5 07:20:26 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h, su_root.c: cleaned argument checking
The su_root_*() and su_port_*() functions now check their arguments once
and do not assert() with NULL arguments. The sur_task->sut_port should
always be valid while su_root_t is alive.
Fri Oct 5 07:22:09 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su: added su_root_obtain(), su_root_release() and su_root_has_thread()
When root is created with su_root_create() or cloned with su_clone_start(),
the resulting root is obtained by the calling or created thread,
respectively.
The root can be released with su_root_release() and another thread can
obtain it.
The function su_root_has_thread() can be used to check if a thread has
obtained or released the root.
Implementation upgraded the su_port_own_thread() method as su_port_thread().
Fri Oct 5 07:28:10 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h: removed su_port_threadsafe() and su_port_yield() methods
su_port_wait_events() replaces su_port_yield().
Fri Oct 5 13:26:04 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* msg_parser.awk: not extending header structure unless needed.
Removed gawk-ish /* comments */.
Fri Oct 5 14:32:25 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* run_test_su: removed GNUisms
Fri Oct 5 14:32:47 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* Makefile.am: removed implicit check target test_urlmap
Fri Oct 5 14:22:32 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* torture_sresolv.c: use CLOCK_REALTIME if no CLOCK_PROCESS_CPUTIME_ID available
Casting timespec tv_sec to unsigned long.
Fri Oct * nua_s added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 08:15:23 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated.
Mon Oct 8 09:30:36 EDT 2007 Pekka.Pessi@nokia.com
* nua_stack: added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 10:26:31 EDT 2007 Pekka.Pessi@nokia.com
* nua: added test for nua_prack() (sf.net bug #1804248)
Avoid sending nua_i_state after nua_prack() if no SDP O/A is happening, too.
Mon Oct 8 10:32:04 EDT 2007 Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
* su_source.c: don t leak the wait arrays
Mon Oct 8 10:37:11 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Wed Oct 10 11:55:21 EDT 2007 Pekka.Pessi@nokia.com
* sip_parser.c: silenced warning about extra const in sip_extend_mclass()
Wed Oct 10 11:57:08 EDT 2007 Pekka.Pessi@nokia.com
* nta_tag.c: updated tag documentation
Wed Oct 10 13:16:40 EDT 2007 Pekka.Pessi@nokia.com
* nua: fix logging crash if outbound used with application contact
Silenced warnings.
Wed Oct 10 13:30:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: removed extra "const"
Wed Oct 10 13:31:45 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am's: fixed distclean of documentation
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5840 d0543943-73ff-0310-b7d9-9358b9ac24b2
2007-10-11 14:16:59 +00:00
|
|
|
* For example, there can be multiple proxies that each challenge the
|
|
|
|
* client. The result of storing authentication info can be quite unexpected
|
|
|
|
* if there are more than one authenticator with the given type (specified
|
|
|
|
* by @a credential_class).
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @retval number of challenges to updated
|
|
|
|
* @retval 0 when there was no challenge to update
|
|
|
|
* @retval -1 upon an error
|
2007-04-15 02:03:41 +00:00
|
|
|
*
|
Sync to current darcs tree:
Mon Sep 17 14:50:04 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/sip_util.h: updated documentation
Mon Sep 17 14:50:18 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/tport_tag.h: updated documentation
Mon Sep 17 14:50:28 EDT 2007 Pekka.Pessi@nokia.com
* soa_tag.c: updated documentation
Wed Sep 19 12:50:01 EDT 2007 Pekka.Pessi@nokia.com
* msg: updated documentation
Wed Sep 19 13:29:50 EDT 2007 Pekka.Pessi@nokia.com
* url: updated documentation
Wed Sep 19 13:32:14 EDT 2007 Pekka.Pessi@nokia.com
* nth: updated documentation
Wed Sep 19 13:32:27 EDT 2007 Pekka.Pessi@nokia.com
* nea: updated documentation
Wed Sep 19 13:33:36 EDT 2007 Pekka.Pessi@nokia.com
* http: updated documentation
Wed Sep 19 13:36:58 EDT 2007 Pekka.Pessi@nokia.com
* bnf: updated documentation
Wed Sep 19 13:38:58 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated nua_stack_init_handle() prototype
Wed Sep 19 18:45:56 EDT 2007 Pekka.Pessi@nokia.com
* sip: added sip_name_addr_xtra(), sip_name_addr_dup()
Wed Sep 19 19:00:19 EDT 2007 Pekka.Pessi@nokia.com
* sip_basic.c: cleaned old crud
Thu Sep 20 13:34:04 EDT 2007 Pekka.Pessi@nokia.com
* iptsec: updated documentation
Thu Sep 20 13:36:22 EDT 2007 Pekka.Pessi@nokia.com
* tport: updated documentation
Thu Sep 20 13:36:56 EDT 2007 Pekka.Pessi@nokia.com
* su: updated documentation
Removed internal files from doxygen-generated documentation.
Thu Sep 20 13:38:29 EDT 2007 Pekka.Pessi@nokia.com
* soa: fixed documentation
Thu Sep 20 13:39:56 EDT 2007 Pekka.Pessi@nokia.com
* sdp: updated documentation
Thu Sep 20 13:40:16 EDT 2007 Pekka.Pessi@nokia.com
* ipt: updated documentation
Thu Sep 20 14:24:20 EDT 2007 Pekka.Pessi@nokia.com
* nta: updated documentation
Thu Sep 20 14:41:04 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated documentation
Updated tag documentation.
Moved doxygen doc entries from sofia-sip/nua_tag.h to nua_tag.c.
Removed internal datatypes and files from the generated documents.
Wed Sep 19 13:34:20 EDT 2007 Pekka.Pessi@nokia.com
* docs: updated the generation of documentation. Updated links to header files.
Thu Sep 20 08:45:32 EDT 2007 Pekka.Pessi@nokia.com
* sip/Makefile.am: added tags to <sofia-sip/sip_extra.h>
Added check for extra tags in torture_sip.c.
Thu Sep 20 14:45:22 EDT 2007 Pekka.Pessi@nokia.com
* stun: updated documentation
Wed Jul 4 18:55:20 EDT 2007 Pekka.Pessi@nokia.com
* torture_heap.c: added tests for ##sort() and su_smoothsort()
Wed Jul 4 18:56:59 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am: added smoothsort.c
Fri Jul 13 12:38:44 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: heap_remove() now set()s index to 0 on removed item
Mon Jul 23 11:14:22 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: fixed bug in heap##remove()
If left kid was in heap but right was not, left kid was ignored.
Wed Jul 4 18:51:08 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Jul 4 18:51:34 EDT 2007 Pekka.Pessi@nokia.com
* heap.h: using su_smoothsort()
Fri Jul 6 10:20:27 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Sep 19 17:40:30 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: generate two parser tables, default and extended
Wed Sep 19 18:39:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: just generate list of extra headers
Allocate extended parser dynamically.
Wed Sep 19 18:59:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: added Remote-Party-ID, P-Asserted-Identity, P-Preferred-Identity
Added functions sip_update_default_mclass() and sip_extend_mclass()
for handling the extended parser. Note that Reply-To and Alert-Info are only
available with the extended parser.
Wed Sep 19 19:05:44 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Thu Sep 20 13:38:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: updated documentation
Thu Sep 20 14:17:28 EDT 2007 Pekka.Pessi@nokia.com
* docs/conformance.docs: updated
Mon Oct 1 10:11:14 EDT 2007 Pekka.Pessi@nokia.com
* tport_tag.c: re-enabled tptag_trusted
Thu Oct 4 09:21:07 EDT 2007 Pekka.Pessi@nokia.com
* su_osx_runloop.c: moved virtual function table after struct definition
Preparing for su_port_vtable_t refactoring.
Thu Oct 4 10:22:03 EDT 2007 Pekka.Pessi@nokia.com
* su_source.c: refactored initialization/deinitialization
Fri Oct 5 04:58:18 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* sip_extra.c: fixed prototypes with isize_t
Fri Oct 5 04:58:45 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nta_api.c: removed warnings about signedness
Fri Oct 5 04:59:02 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nua_params.c: removed warnings about constness
Fri Oct 5 07:20:26 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h, su_root.c: cleaned argument checking
The su_root_*() and su_port_*() functions now check their arguments once
and do not assert() with NULL arguments. The sur_task->sut_port should
always be valid while su_root_t is alive.
Fri Oct 5 07:22:09 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su: added su_root_obtain(), su_root_release() and su_root_has_thread()
When root is created with su_root_create() or cloned with su_clone_start(),
the resulting root is obtained by the calling or created thread,
respectively.
The root can be released with su_root_release() and another thread can
obtain it.
The function su_root_has_thread() can be used to check if a thread has
obtained or released the root.
Implementation upgraded the su_port_own_thread() method as su_port_thread().
Fri Oct 5 07:28:10 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h: removed su_port_threadsafe() and su_port_yield() methods
su_port_wait_events() replaces su_port_yield().
Fri Oct 5 13:26:04 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* msg_parser.awk: not extending header structure unless needed.
Removed gawk-ish /* comments */.
Fri Oct 5 14:32:25 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* run_test_su: removed GNUisms
Fri Oct 5 14:32:47 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* Makefile.am: removed implicit check target test_urlmap
Fri Oct 5 14:22:32 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* torture_sresolv.c: use CLOCK_REALTIME if no CLOCK_PROCESS_CPUTIME_ID available
Casting timespec tv_sec to unsigned long.
Fri Oct * nua_s added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 08:15:23 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated.
Mon Oct 8 09:30:36 EDT 2007 Pekka.Pessi@nokia.com
* nua_stack: added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 10:26:31 EDT 2007 Pekka.Pessi@nokia.com
* nua: added test for nua_prack() (sf.net bug #1804248)
Avoid sending nua_i_state after nua_prack() if no SDP O/A is happening, too.
Mon Oct 8 10:32:04 EDT 2007 Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
* su_source.c: don t leak the wait arrays
Mon Oct 8 10:37:11 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Wed Oct 10 11:55:21 EDT 2007 Pekka.Pessi@nokia.com
* sip_parser.c: silenced warning about extra const in sip_extend_mclass()
Wed Oct 10 11:57:08 EDT 2007 Pekka.Pessi@nokia.com
* nta_tag.c: updated tag documentation
Wed Oct 10 13:16:40 EDT 2007 Pekka.Pessi@nokia.com
* nua: fix logging crash if outbound used with application contact
Silenced warnings.
Wed Oct 10 13:30:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: removed extra "const"
Wed Oct 10 13:31:45 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am's: fixed distclean of documentation
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5840 d0543943-73ff-0310-b7d9-9358b9ac24b2
2007-10-11 14:16:59 +00:00
|
|
|
* @NEW_1_12_5.
|
2006-12-21 06:30:28 +00:00
|
|
|
*/
|
|
|
|
int auc_info(auth_client_t **auc_list,
|
2007-04-15 02:03:41 +00:00
|
|
|
msg_auth_info_t const *info,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_hclass_t *credential_class)
|
|
|
|
{
|
|
|
|
auth_client_t *ca;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
/* Go through each challenge in Authenticate or Proxy-Authenticate headers */
|
|
|
|
|
|
|
|
/* Update matching authenticator */
|
|
|
|
for (ca = *auc_list; ca; ca = ca->ca_next) {
|
2007-04-15 02:03:41 +00:00
|
|
|
int updated = ca_info(ca, info, credential_class);
|
2006-12-21 06:30:28 +00:00
|
|
|
if (updated < 0)
|
|
|
|
return -1;
|
|
|
|
if (updated >= 1)
|
|
|
|
retval = 1; /* Updated authenticator */
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
/** Update authentication client with authentication info.
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* @retval -1 upon an error
|
|
|
|
* @retval 0 when challenge did not match
|
|
|
|
* @retval 1 when challenge did match but was not updated
|
|
|
|
* @retval 2 when challenge did match and updated client
|
|
|
|
*/
|
|
|
|
static
|
2008-12-16 18:05:22 +00:00
|
|
|
int ca_info(auth_client_t *ca,
|
2007-04-15 02:03:41 +00:00
|
|
|
msg_auth_info_t const *info,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_hclass_t *credential_class)
|
|
|
|
{
|
2007-04-15 02:03:41 +00:00
|
|
|
assert(ca); assert(info);
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (!ca || !info)
|
2006-12-21 06:30:28 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!ca->ca_credential_class)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ca->ca_credential_class != credential_class)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!ca->ca_auc
|
2008-12-16 18:05:22 +00:00
|
|
|
|| (size_t)ca->ca_auc->auc_plugin_size <=
|
2006-12-21 06:30:28 +00:00
|
|
|
offsetof(auth_client_plugin_t, auc_info)
|
|
|
|
|| !ca->ca_auc->auc_info)
|
|
|
|
return 0;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
return ca->ca_auc->auc_info(ca, info);
|
2006-12-21 06:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**Feed authentication data to the authenticator.
|
|
|
|
*
|
|
|
|
* The function auc_credentials() is used to provide the authenticators in
|
|
|
|
* with authentication data (user name, secret). The authentication data
|
|
|
|
* has format as follows:
|
|
|
|
*
|
|
|
|
* scheme:"realm":user:pass
|
|
|
|
*
|
|
|
|
* For instance, @c Basic:"nokia-proxy":ppessi:verysecret
|
|
|
|
*
|
|
|
|
* @todo The authentication data format sucks.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in,out] auc_list list of authenticators
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in,out] home memory home used for allocations
|
2009-02-11 16:21:43 +00:00
|
|
|
* @param[in] data colon-separated authentication data
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2009-02-11 16:21:43 +00:00
|
|
|
* @retval >0 when successful
|
|
|
|
* @retval 0 if not authenticator matched with @a data
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_credentials(auth_client_t **auc_list, su_home_t *home,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *data)
|
|
|
|
{
|
|
|
|
int retval = 0, match;
|
|
|
|
char *s0, *s;
|
|
|
|
char *scheme = NULL, *user = NULL, *pass = NULL, *realm = NULL;
|
|
|
|
|
|
|
|
s0 = s = su_strdup(NULL, data);
|
|
|
|
|
|
|
|
/* Parse authentication data */
|
2009-07-10 00:49:35 +00:00
|
|
|
/* Data is string like "Basic:\"agni\":user1:secret"
|
|
|
|
or "Basic:\"[fe80::204:23ff:fea7:d60a]\":user1:secret" (IPv6)
|
|
|
|
or "Basic:\"Use \\\"interesting\\\" username and password here:\":user1:secret"
|
|
|
|
*/
|
2006-12-21 06:30:28 +00:00
|
|
|
if (s && (s = strchr(scheme = s, ':')))
|
|
|
|
*s++ = 0;
|
2009-07-10 00:49:35 +00:00
|
|
|
if (s) {
|
|
|
|
if (*s == '"') {
|
|
|
|
realm = s;
|
|
|
|
s += span_quoted(s);
|
|
|
|
if (*s == ':')
|
|
|
|
*s++ = 0;
|
|
|
|
else
|
|
|
|
realm = NULL, s = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
s = NULL;
|
|
|
|
}
|
2006-12-21 06:30:28 +00:00
|
|
|
if (s && (s = strchr(user = s, ':')))
|
|
|
|
*s++ = 0;
|
|
|
|
if (s && (s = strchr(pass = s, ':')))
|
|
|
|
*s++ = 0;
|
|
|
|
|
|
|
|
if (scheme && realm && user && pass) {
|
|
|
|
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
|
|
|
|
match = ca_credentials(*auc_list, scheme, realm, user, pass);
|
|
|
|
if (match < 0) {
|
|
|
|
retval = -1;
|
|
|
|
break;
|
|
|
|
}
|
2008-12-16 18:05:22 +00:00
|
|
|
if (match)
|
2006-12-21 06:30:28 +00:00
|
|
|
retval++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
su_free(NULL, s0);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**Feed authentication data to the authenticator.
|
|
|
|
*
|
|
|
|
* The function auc_credentials() is used to provide the authenticators in
|
2008-12-16 18:05:22 +00:00
|
|
|
* with authentication tuple (scheme, realm, user name, secret).
|
2006-12-21 06:30:28 +00:00
|
|
|
*
|
|
|
|
* scheme:"realm":user:pass
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in,out] auc_list list of authenticators
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in] scheme scheme to use (NULL, if any)
|
|
|
|
* @param[in] realm realm to use (NULL, if any)
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in] user username
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in] pass password
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2009-02-11 16:21:43 +00:00
|
|
|
* @retval >0 or number of updated clients when successful
|
2007-04-15 02:03:41 +00:00
|
|
|
* @retval 0 when no client was updated
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_all_credentials(auth_client_t **auc_list,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *scheme,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *realm,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *user,
|
|
|
|
char const *pass)
|
|
|
|
{
|
|
|
|
int retval = 0, match;
|
|
|
|
|
|
|
|
#if HAVE_SC_CRED_H
|
|
|
|
/* XXX: add */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (user && pass) {
|
|
|
|
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
|
|
|
|
match = ca_credentials(*auc_list, scheme, realm, user, pass);
|
|
|
|
if (match < 0)
|
|
|
|
return -1;
|
2008-12-16 18:05:22 +00:00
|
|
|
if (match)
|
2006-12-21 06:30:28 +00:00
|
|
|
retval++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
int ca_credentials(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *scheme,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *realm,
|
2006-12-21 06:30:28 +00:00
|
|
|
char const *user,
|
|
|
|
char const *pass)
|
|
|
|
{
|
2007-04-15 02:03:41 +00:00
|
|
|
char *new_user, *new_pass;
|
|
|
|
char *old_user, *old_pass;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
assert(ca);
|
|
|
|
|
|
|
|
if (!ca || !ca->ca_scheme || !ca->ca_realm)
|
|
|
|
return -1;
|
|
|
|
|
2009-02-11 16:47:44 +00:00
|
|
|
if ((scheme != NULL && !su_casematch(scheme, ca->ca_scheme)) ||
|
|
|
|
(realm != NULL && !su_strmatch(realm, ca->ca_realm)))
|
2007-11-19 18:09:15 +00:00
|
|
|
return 0;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
old_user = ca->ca_user, old_pass = ca->ca_pass;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2009-02-11 16:47:44 +00:00
|
|
|
if (su_strmatch(user, old_user) && su_strmatch(pass, old_pass))
|
2007-04-15 02:03:41 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
new_user = su_strdup(ca->ca_home, user);
|
|
|
|
new_pass = su_strdup(ca->ca_home, pass);
|
|
|
|
|
|
|
|
if (!new_user || !new_pass)
|
2006-12-21 06:30:28 +00:00
|
|
|
return -1;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
ca->ca_user = new_user, ca->ca_pass = new_pass;
|
|
|
|
if (AUTH_CLIENT_IS_EXTENDED(ca))
|
|
|
|
ca->ca_clear = 0;
|
|
|
|
|
|
|
|
su_free(ca->ca_home, old_user);
|
|
|
|
su_free(ca->ca_home, old_pass);
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Copy authentication data from @a src to @a dst.
|
|
|
|
*
|
|
|
|
* @retval >0 if credentials were copied
|
|
|
|
* @retval 0 if there was no credentials to copy
|
|
|
|
* @retval <0 if an error occurred.
|
|
|
|
*/
|
|
|
|
int auc_copy_credentials(auth_client_t **dst,
|
|
|
|
auth_client_t const *src)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
if (!dst)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (;*dst; dst = &(*dst)->ca_next) {
|
|
|
|
auth_client_t *d = *dst;
|
|
|
|
auth_client_t const *ca;
|
|
|
|
|
|
|
|
for (ca = src; ca; ca = ca->ca_next) {
|
|
|
|
char *u, *p;
|
|
|
|
if (!ca->ca_user || !ca->ca_pass)
|
|
|
|
continue;
|
2007-04-15 02:03:41 +00:00
|
|
|
if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
|
|
|
|
continue;
|
2009-02-11 16:47:44 +00:00
|
|
|
if (!ca->ca_scheme[0] || !su_casematch(ca->ca_scheme, d->ca_scheme))
|
2006-12-21 06:30:28 +00:00
|
|
|
continue;
|
2009-02-11 16:47:44 +00:00
|
|
|
if (!ca->ca_realm || !su_strmatch(ca->ca_realm, d->ca_realm))
|
2006-12-21 06:30:28 +00:00
|
|
|
continue;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (!(AUTH_CLIENT_IS_EXTENDED(d) && d->ca_clear) &&
|
2009-02-11 16:47:44 +00:00
|
|
|
su_strmatch(d->ca_user, ca->ca_user) &&
|
|
|
|
su_strmatch(d->ca_pass, ca->ca_pass)) {
|
2006-12-21 06:30:28 +00:00
|
|
|
retval++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
u = su_strdup(d->ca_home, ca->ca_user);
|
|
|
|
p = su_strdup(d->ca_home, ca->ca_pass);
|
|
|
|
if (!u || !p)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (d->ca_user) su_free(d->ca_home, (void *)d->ca_user);
|
|
|
|
if (d->ca_pass) su_free(d->ca_home, (void *)d->ca_pass);
|
|
|
|
d->ca_user = u, d->ca_pass = p;
|
2007-04-15 02:03:41 +00:00
|
|
|
if (AUTH_CLIENT_IS_EXTENDED(d))
|
|
|
|
d->ca_clear = 0;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
retval++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
2008-12-16 18:05:22 +00:00
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
/**Clear authentication data from the authenticator.
|
|
|
|
*
|
|
|
|
* The function auc_clear_credentials() is used to remove the credentials
|
|
|
|
* from the authenticators.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in,out] auc_list list of authenticators
|
|
|
|
* @param[in] scheme scheme (if non-null, remove only matching credentials)
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in] realm realm (if non-null, remove only matching credentials)
|
|
|
|
*
|
|
|
|
* @retval 0 when successful
|
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_clear_credentials(auth_client_t **auc_list,
|
2007-04-15 02:03:41 +00:00
|
|
|
char const *scheme,
|
|
|
|
char const *realm)
|
2006-12-21 06:30:28 +00:00
|
|
|
{
|
|
|
|
int retval = 0;
|
2007-04-15 02:03:41 +00:00
|
|
|
int match;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
|
2007-04-15 02:03:41 +00:00
|
|
|
auth_client_t *ca = *auc_list;
|
|
|
|
|
|
|
|
if (!AUTH_CLIENT_IS_EXTENDED(ca))
|
|
|
|
continue;
|
|
|
|
|
2009-02-11 16:47:44 +00:00
|
|
|
if ((scheme != NULL && !su_casematch(scheme, ca->ca_scheme)) ||
|
|
|
|
(realm != NULL && !su_strmatch(realm, ca->ca_realm)))
|
2007-04-15 02:03:41 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
match = ca->ca_auc->auc_clear(*auc_list);
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
if (match < 0) {
|
|
|
|
retval = -1;
|
|
|
|
break;
|
|
|
|
}
|
2008-12-16 18:05:22 +00:00
|
|
|
if (match)
|
2006-12-21 06:30:28 +00:00
|
|
|
retval++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
2007-04-15 02:03:41 +00:00
|
|
|
int ca_clear_credentials(auth_client_t *ca)
|
2006-12-21 06:30:28 +00:00
|
|
|
{
|
2007-04-15 02:03:41 +00:00
|
|
|
assert(ca); assert(ca->ca_home->suh_size >= (int)(sizeof *ca));
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (!ca)
|
2006-12-21 06:30:28 +00:00
|
|
|
return -1;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
ca->ca_clear = 1;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-02-11 16:21:43 +00:00
|
|
|
/** Check if there are credentials for all challenges.
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval 1 when authorization can proceed
|
|
|
|
* @retval 0 when there is not enough credentials
|
2007-04-15 02:03:41 +00:00
|
|
|
*
|
Sync to current darcs tree:
Mon Sep 17 14:50:04 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/sip_util.h: updated documentation
Mon Sep 17 14:50:18 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/tport_tag.h: updated documentation
Mon Sep 17 14:50:28 EDT 2007 Pekka.Pessi@nokia.com
* soa_tag.c: updated documentation
Wed Sep 19 12:50:01 EDT 2007 Pekka.Pessi@nokia.com
* msg: updated documentation
Wed Sep 19 13:29:50 EDT 2007 Pekka.Pessi@nokia.com
* url: updated documentation
Wed Sep 19 13:32:14 EDT 2007 Pekka.Pessi@nokia.com
* nth: updated documentation
Wed Sep 19 13:32:27 EDT 2007 Pekka.Pessi@nokia.com
* nea: updated documentation
Wed Sep 19 13:33:36 EDT 2007 Pekka.Pessi@nokia.com
* http: updated documentation
Wed Sep 19 13:36:58 EDT 2007 Pekka.Pessi@nokia.com
* bnf: updated documentation
Wed Sep 19 13:38:58 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated nua_stack_init_handle() prototype
Wed Sep 19 18:45:56 EDT 2007 Pekka.Pessi@nokia.com
* sip: added sip_name_addr_xtra(), sip_name_addr_dup()
Wed Sep 19 19:00:19 EDT 2007 Pekka.Pessi@nokia.com
* sip_basic.c: cleaned old crud
Thu Sep 20 13:34:04 EDT 2007 Pekka.Pessi@nokia.com
* iptsec: updated documentation
Thu Sep 20 13:36:22 EDT 2007 Pekka.Pessi@nokia.com
* tport: updated documentation
Thu Sep 20 13:36:56 EDT 2007 Pekka.Pessi@nokia.com
* su: updated documentation
Removed internal files from doxygen-generated documentation.
Thu Sep 20 13:38:29 EDT 2007 Pekka.Pessi@nokia.com
* soa: fixed documentation
Thu Sep 20 13:39:56 EDT 2007 Pekka.Pessi@nokia.com
* sdp: updated documentation
Thu Sep 20 13:40:16 EDT 2007 Pekka.Pessi@nokia.com
* ipt: updated documentation
Thu Sep 20 14:24:20 EDT 2007 Pekka.Pessi@nokia.com
* nta: updated documentation
Thu Sep 20 14:41:04 EDT 2007 Pekka.Pessi@nokia.com
* nua: updated documentation
Updated tag documentation.
Moved doxygen doc entries from sofia-sip/nua_tag.h to nua_tag.c.
Removed internal datatypes and files from the generated documents.
Wed Sep 19 13:34:20 EDT 2007 Pekka.Pessi@nokia.com
* docs: updated the generation of documentation. Updated links to header files.
Thu Sep 20 08:45:32 EDT 2007 Pekka.Pessi@nokia.com
* sip/Makefile.am: added tags to <sofia-sip/sip_extra.h>
Added check for extra tags in torture_sip.c.
Thu Sep 20 14:45:22 EDT 2007 Pekka.Pessi@nokia.com
* stun: updated documentation
Wed Jul 4 18:55:20 EDT 2007 Pekka.Pessi@nokia.com
* torture_heap.c: added tests for ##sort() and su_smoothsort()
Wed Jul 4 18:56:59 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am: added smoothsort.c
Fri Jul 13 12:38:44 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: heap_remove() now set()s index to 0 on removed item
Mon Jul 23 11:14:22 EDT 2007 Pekka.Pessi@nokia.com
* sofia-sip/heap.h: fixed bug in heap##remove()
If left kid was in heap but right was not, left kid was ignored.
Wed Jul 4 18:51:08 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Jul 4 18:51:34 EDT 2007 Pekka.Pessi@nokia.com
* heap.h: using su_smoothsort()
Fri Jul 6 10:20:27 EDT 2007 Pekka.Pessi@nokia.com
* smoothsort.c: added
Wed Sep 19 17:40:30 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: generate two parser tables, default and extended
Wed Sep 19 18:39:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: just generate list of extra headers
Allocate extended parser dynamically.
Wed Sep 19 18:59:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: added Remote-Party-ID, P-Asserted-Identity, P-Preferred-Identity
Added functions sip_update_default_mclass() and sip_extend_mclass()
for handling the extended parser. Note that Reply-To and Alert-Info are only
available with the extended parser.
Wed Sep 19 19:05:44 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Thu Sep 20 13:38:59 EDT 2007 Pekka.Pessi@nokia.com
* sip: updated documentation
Thu Sep 20 14:17:28 EDT 2007 Pekka.Pessi@nokia.com
* docs/conformance.docs: updated
Mon Oct 1 10:11:14 EDT 2007 Pekka.Pessi@nokia.com
* tport_tag.c: re-enabled tptag_trusted
Thu Oct 4 09:21:07 EDT 2007 Pekka.Pessi@nokia.com
* su_osx_runloop.c: moved virtual function table after struct definition
Preparing for su_port_vtable_t refactoring.
Thu Oct 4 10:22:03 EDT 2007 Pekka.Pessi@nokia.com
* su_source.c: refactored initialization/deinitialization
Fri Oct 5 04:58:18 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* sip_extra.c: fixed prototypes with isize_t
Fri Oct 5 04:58:45 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nta_api.c: removed warnings about signedness
Fri Oct 5 04:59:02 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* test_nua_params.c: removed warnings about constness
Fri Oct 5 07:20:26 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h, su_root.c: cleaned argument checking
The su_root_*() and su_port_*() functions now check their arguments once
and do not assert() with NULL arguments. The sur_task->sut_port should
always be valid while su_root_t is alive.
Fri Oct 5 07:22:09 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su: added su_root_obtain(), su_root_release() and su_root_has_thread()
When root is created with su_root_create() or cloned with su_clone_start(),
the resulting root is obtained by the calling or created thread,
respectively.
The root can be released with su_root_release() and another thread can
obtain it.
The function su_root_has_thread() can be used to check if a thread has
obtained or released the root.
Implementation upgraded the su_port_own_thread() method as su_port_thread().
Fri Oct 5 07:28:10 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* su_port.h: removed su_port_threadsafe() and su_port_yield() methods
su_port_wait_events() replaces su_port_yield().
Fri Oct 5 13:26:04 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* msg_parser.awk: not extending header structure unless needed.
Removed gawk-ish /* comments */.
Fri Oct 5 14:32:25 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* run_test_su: removed GNUisms
Fri Oct 5 14:32:47 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com>
* Makefile.am: removed implicit check target test_urlmap
Fri Oct 5 14:22:32 EDT 2007 Pekka Pessi <first.lastname@nokia.com>
* torture_sresolv.c: use CLOCK_REALTIME if no CLOCK_PROCESS_CPUTIME_ID available
Casting timespec tv_sec to unsigned long.
Fri Oct * nua_s added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 08:15:23 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated.
Mon Oct 8 09:30:36 EDT 2007 Pekka.Pessi@nokia.com
* nua_stack: added handling nua_prack()
Thanks to Fabio Margarido for the patch.
Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com
* test_nua: added test for sf.net bug #1803686
Mon Oct 8 10:26:31 EDT 2007 Pekka.Pessi@nokia.com
* nua: added test for nua_prack() (sf.net bug #1804248)
Avoid sending nua_i_state after nua_prack() if no SDP O/A is happening, too.
Mon Oct 8 10:32:04 EDT 2007 Mikhail Zabaluev <mikhail.zabaluev@nokia.com>
* su_source.c: don t leak the wait arrays
Mon Oct 8 10:37:11 EDT 2007 Pekka.Pessi@nokia.com
* RELEASE: updated
Wed Oct 10 11:55:21 EDT 2007 Pekka.Pessi@nokia.com
* sip_parser.c: silenced warning about extra const in sip_extend_mclass()
Wed Oct 10 11:57:08 EDT 2007 Pekka.Pessi@nokia.com
* nta_tag.c: updated tag documentation
Wed Oct 10 13:16:40 EDT 2007 Pekka.Pessi@nokia.com
* nua: fix logging crash if outbound used with application contact
Silenced warnings.
Wed Oct 10 13:30:45 EDT 2007 Pekka.Pessi@nokia.com
* msg_parser.awk: removed extra "const"
Wed Oct 10 13:31:45 EDT 2007 Pekka.Pessi@nokia.com
* Makefile.am's: fixed distclean of documentation
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5840 d0543943-73ff-0310-b7d9-9358b9ac24b2
2007-10-11 14:16:59 +00:00
|
|
|
* @NEW_1_12_5.
|
2006-12-21 06:30:28 +00:00
|
|
|
*/
|
|
|
|
int auc_has_authorization(auth_client_t **auc_list)
|
|
|
|
{
|
2009-02-11 16:53:49 +00:00
|
|
|
auth_client_t const *ca, *other;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
if (auc_list == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (ca = *auc_list; ca; ca = ca->ca_next) {
|
2009-02-11 16:53:49 +00:00
|
|
|
if (!ca_has_authorization(ca)) {
|
|
|
|
/*
|
|
|
|
* Check if we have another challenge with same realm but different
|
|
|
|
* scheme
|
|
|
|
*/
|
2010-03-26 17:38:00 +00:00
|
|
|
for (other = *auc_list; other; other = other->ca_next) {
|
|
|
|
if (ca == other) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-02-11 16:53:49 +00:00
|
|
|
if (ca->ca_credential_class == other->ca_credential_class &&
|
|
|
|
su_strcmp(ca->ca_realm, other->ca_realm) == 0 &&
|
|
|
|
ca_has_authorization(other))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!other)
|
|
|
|
return 0;
|
|
|
|
}
|
2006-12-21 06:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-02-11 16:53:49 +00:00
|
|
|
static int
|
|
|
|
ca_has_authorization(auth_client_t const *ca)
|
|
|
|
{
|
|
|
|
return ca->ca_credential_class &&
|
|
|
|
ca->ca_auc &&
|
|
|
|
ca->ca_user && ca->ca_pass &&
|
|
|
|
!(AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear);
|
|
|
|
}
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
/**Authorize a request.
|
|
|
|
*
|
|
|
|
* The function auc_authorization() is used to add correct authentication
|
|
|
|
* headers to a request. The authentication headers will contain the
|
|
|
|
* credentials generated by the list of authenticators.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in,out] auc_list list of authenticators
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[out] msg message to be authenticated
|
|
|
|
* @param[out] pub headers of the message
|
|
|
|
* @param[in] method request method
|
|
|
|
* @param[in] url request URI
|
|
|
|
* @param[in] body message body (NULL if empty)
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval 1 when successful
|
|
|
|
* @retval 0 when there is not enough credentials
|
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
|
|
|
int auc_authorization(auth_client_t **auc_list, msg_t *msg, msg_pub_t *pub,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body)
|
|
|
|
{
|
|
|
|
auth_client_t *ca;
|
|
|
|
msg_mclass_t const *mc = msg_mclass(msg);
|
|
|
|
|
|
|
|
if (auc_list == NULL || msg == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!auc_has_authorization(auc_list))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pub == NULL)
|
|
|
|
pub = msg_object(msg);
|
|
|
|
|
2009-02-11 16:21:43 +00:00
|
|
|
/* Remove existing credential headers */
|
2006-12-21 06:30:28 +00:00
|
|
|
for (ca = *auc_list; ca; ca = ca->ca_next) {
|
|
|
|
msg_header_t **hh = msg_hclass_offset(mc, pub, ca->ca_credential_class);
|
|
|
|
|
|
|
|
while (hh && *hh)
|
|
|
|
msg_header_remove(msg, pub, *hh);
|
|
|
|
}
|
|
|
|
|
2009-02-11 16:21:43 +00:00
|
|
|
/* Insert new credential headers */
|
2006-12-21 06:30:28 +00:00
|
|
|
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
|
|
|
|
su_home_t *home = msg_home(msg);
|
|
|
|
msg_header_t *h = NULL;
|
|
|
|
|
|
|
|
ca = *auc_list;
|
|
|
|
|
|
|
|
if (!ca->ca_auc)
|
|
|
|
continue;
|
2009-02-11 16:53:49 +00:00
|
|
|
if (!ca_has_authorization(ca))
|
|
|
|
continue;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0)
|
|
|
|
return -1;
|
|
|
|
if (h == NULL)
|
|
|
|
continue;
|
|
|
|
if (msg_header_insert(msg, pub, h) < 0)
|
2006-12-21 06:30:28 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**Generate headers authorizing a request.
|
|
|
|
*
|
|
|
|
* The function auc_authorization_headers() is used to generate
|
|
|
|
* authentication headers for a request. The list of authentication headers
|
|
|
|
* will contain the credentials generated by the list of authenticators.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in] auc_list list of authenticators
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in] home memory home used to allocate headers
|
|
|
|
* @param[in] method request method
|
|
|
|
* @param[in] url request URI
|
|
|
|
* @param[in] body message body (NULL if empty)
|
|
|
|
* @param[out] return_headers authorization headers return value
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval 1 when successful
|
|
|
|
* @retval 0 when there is not enough credentials
|
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_authorization_headers(auth_client_t **auc_list,
|
2006-12-21 06:30:28 +00:00
|
|
|
su_home_t *home,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body,
|
|
|
|
msg_header_t **return_headers)
|
|
|
|
{
|
|
|
|
auth_client_t *ca;
|
|
|
|
|
|
|
|
/* Make sure every challenge has credentials */
|
|
|
|
if (!auc_has_authorization(auc_list))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Create new credential headers */
|
|
|
|
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
|
|
|
|
msg_header_t *h = NULL;
|
|
|
|
|
|
|
|
ca = *auc_list;
|
|
|
|
|
|
|
|
if (!ca->ca_auc)
|
|
|
|
continue;
|
2009-02-11 16:53:49 +00:00
|
|
|
if (!ca_has_authorization(ca))
|
|
|
|
continue;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*return_headers = h;
|
|
|
|
|
|
|
|
while (*return_headers)
|
|
|
|
return_headers = &(*return_headers)->sh_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Basic scheme */
|
|
|
|
|
|
|
|
static int auc_basic_authorization(auth_client_t *ca,
|
|
|
|
su_home_t *h,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body,
|
|
|
|
msg_header_t **);
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static const auth_client_plugin_t ca_basic_plugin =
|
|
|
|
{
|
2006-12-21 06:30:28 +00:00
|
|
|
/* auc_plugin_size: */ sizeof ca_basic_plugin,
|
|
|
|
/* auc_size: */ sizeof (auth_client_t),
|
|
|
|
/* auc_name: */ "Basic",
|
|
|
|
/* auc_challenge: */ NULL,
|
|
|
|
/* auc_authorize: */ auc_basic_authorization,
|
2007-04-15 02:03:41 +00:00
|
|
|
/* auc_info: */ NULL,
|
|
|
|
/* auc_clear: */ ca_clear_credentials
|
2006-12-21 06:30:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**Create a basic authorization header.
|
|
|
|
*
|
|
|
|
* The function auc_basic_authorization() creates a basic authorization
|
|
|
|
* header from username @a user and password @a pass. The authorization
|
|
|
|
* header type is determined by @a hc - it can be sip_authorization_class,
|
|
|
|
* sip_proxy_authorization_class, http_authorization_class, or
|
|
|
|
* http_proxy_authorization_class, for instance.
|
|
|
|
*
|
|
|
|
* @param home memory home used to allocate memory for the new header
|
|
|
|
* @param hc header class for the header to be created
|
|
|
|
* @param user user name
|
|
|
|
* @param pass password
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2006-12-21 06:30:28 +00:00
|
|
|
* @return
|
2008-12-16 18:05:22 +00:00
|
|
|
* The function auc_basic_authorization() returns a pointer to newly created
|
2006-12-21 06:30:28 +00:00
|
|
|
* authorization header, or NULL upon an error.
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_basic_authorization(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
su_home_t *home,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body,
|
|
|
|
msg_header_t **return_headers)
|
|
|
|
{
|
|
|
|
msg_hclass_t *hc = ca->ca_credential_class;
|
|
|
|
char const *user = ca->ca_user;
|
|
|
|
char const *pass = ca->ca_pass;
|
|
|
|
size_t ulen, plen, uplen, b64len, basiclen;
|
|
|
|
char *basic, *base64, *userpass;
|
|
|
|
char buffer[71];
|
|
|
|
|
|
|
|
if (user == NULL || pass == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
|
|
|
|
return 0;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
ulen = strlen(user), plen = strlen(pass), uplen = ulen + 1 + plen;
|
|
|
|
b64len = BASE64_SIZE(uplen);
|
|
|
|
basiclen = strlen("Basic ") + b64len;
|
|
|
|
|
|
|
|
if (sizeof(buffer) > basiclen + 1)
|
|
|
|
basic = buffer;
|
|
|
|
else
|
|
|
|
basic = malloc(basiclen + 1);
|
|
|
|
|
2008-05-25 15:22:45 +00:00
|
|
|
if (basic == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
/*
|
|
|
|
* Basic authentication consists of username and password separated by
|
|
|
|
* colon and then base64 encoded.
|
|
|
|
*/
|
|
|
|
strcpy(basic, "Basic ");
|
|
|
|
base64 = basic + strlen("Basic ");
|
|
|
|
userpass = base64 + b64len - uplen;
|
|
|
|
memcpy(userpass, user, ulen);
|
|
|
|
userpass[ulen] = ':';
|
|
|
|
memcpy(userpass + ulen + 1, pass, plen);
|
|
|
|
userpass[uplen] = '\0';
|
2008-12-16 18:05:22 +00:00
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
base64_e(base64, b64len + 1, userpass, uplen);
|
|
|
|
|
|
|
|
base64[b64len] = '\0';
|
|
|
|
|
|
|
|
*return_headers = msg_header_make(home, hc, basic);
|
|
|
|
|
|
|
|
if (buffer != basic)
|
|
|
|
free(basic);
|
|
|
|
|
|
|
|
return *return_headers ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Digest scheme */
|
|
|
|
|
|
|
|
typedef struct auth_digest_client_s
|
|
|
|
{
|
|
|
|
auth_client_t cda_client;
|
|
|
|
|
|
|
|
int cda_ncount;
|
|
|
|
char const *cda_cnonce;
|
|
|
|
auth_challenge_t cda_ac[1];
|
|
|
|
} auth_digest_client_t;
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static int auc_digest_challenge(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_auth_t const *ch);
|
2008-12-16 18:05:22 +00:00
|
|
|
static int auc_digest_authorization(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
su_home_t *h,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body,
|
|
|
|
msg_header_t **);
|
2008-12-16 18:05:22 +00:00
|
|
|
static int auc_digest_info(auth_client_t *ca,
|
2007-04-15 02:03:41 +00:00
|
|
|
msg_auth_info_t const *info);
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static const auth_client_plugin_t ca_digest_plugin =
|
|
|
|
{
|
2006-12-21 06:30:28 +00:00
|
|
|
/* auc_plugin_size: */ sizeof ca_digest_plugin,
|
|
|
|
/* auc_size: */ sizeof (auth_digest_client_t),
|
2008-12-16 18:05:22 +00:00
|
|
|
/* auc_name: */ "Digest",
|
2006-12-21 06:30:28 +00:00
|
|
|
/* auc_challenge: */ auc_digest_challenge,
|
|
|
|
/* auc_authorize: */ auc_digest_authorization,
|
2007-04-15 02:03:41 +00:00
|
|
|
/* auc_info: */ auc_digest_info,
|
|
|
|
/* auc_clear: */ ca_clear_credentials
|
2006-12-21 06:30:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Store a digest authorization challenge.
|
2007-04-15 02:03:41 +00:00
|
|
|
*
|
|
|
|
* @retval 2 if credentials need to be (re)sent
|
|
|
|
* @retval 1 if challenge was updated
|
|
|
|
* @retval -1 upon an error
|
2006-12-21 06:30:28 +00:00
|
|
|
*/
|
|
|
|
static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch)
|
|
|
|
{
|
|
|
|
su_home_t *home = ca->ca_home;
|
|
|
|
auth_digest_client_t *cda = (auth_digest_client_t *)ca;
|
|
|
|
auth_challenge_t ac[1] = {{ sizeof ac }};
|
|
|
|
int stale;
|
|
|
|
|
|
|
|
if (auth_digest_challenge_get(home, ac, ch->au_params) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* Check that we can handle the challenge */
|
|
|
|
if (!ac->ac_md5 && !ac->ac_md5sess)
|
|
|
|
goto error;
|
|
|
|
if (ac->ac_qop && !ac->ac_auth && !ac->ac_auth_int)
|
|
|
|
goto error;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
stale = ac->ac_stale || cda->cda_ac->ac_nonce == NULL;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
2014-04-04 18:42:05 +00:00
|
|
|
if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale || ca->ca_clear )) {
|
2006-12-21 06:30:28 +00:00
|
|
|
su_guid_t guid[1];
|
|
|
|
char *cnonce;
|
2007-04-15 02:03:41 +00:00
|
|
|
size_t b64len = BASE64_MINSIZE(sizeof(guid)) + 1;
|
2006-12-21 06:30:28 +00:00
|
|
|
if (cda->cda_cnonce != NULL)
|
|
|
|
/* Free the old one if we are updating after stale=true */
|
|
|
|
su_free(home, (void *)cda->cda_cnonce);
|
|
|
|
su_guid_generate(guid);
|
2007-04-15 02:03:41 +00:00
|
|
|
cda->cda_cnonce = cnonce = su_alloc(home, b64len);
|
|
|
|
base64_e(cnonce, b64len, guid, sizeof(guid));
|
2006-12-21 06:30:28 +00:00
|
|
|
cda->cda_ncount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auth_digest_challenge_free_params(home, cda->cda_ac);
|
|
|
|
|
|
|
|
*cda->cda_ac = *ac;
|
|
|
|
|
|
|
|
return stale ? 2 : 1;
|
|
|
|
|
|
|
|
error:
|
|
|
|
auth_digest_challenge_free_params(home, ac);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int auc_digest_info(auth_client_t *ca,
|
2007-04-15 02:03:41 +00:00
|
|
|
msg_auth_info_t const *info)
|
2006-12-21 06:30:28 +00:00
|
|
|
{
|
|
|
|
auth_digest_client_t *cda = (auth_digest_client_t *)ca;
|
|
|
|
su_home_t *home = ca->ca_home;
|
|
|
|
char const *nextnonce = NULL;
|
|
|
|
issize_t n;
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
n = auth_get_params(home, info->ai_params,
|
2006-12-21 06:30:28 +00:00
|
|
|
"nextnonce=", &nextnonce,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (n <= 0)
|
|
|
|
return n;
|
|
|
|
|
|
|
|
cda->cda_ac->ac_nonce = nextnonce;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**Create a digest authorization header.
|
|
|
|
*
|
|
|
|
* Creates a digest authorization header from username @a user and password
|
|
|
|
* @a pass, client nonce @a cnonce, client nonce count @a nc, request method
|
|
|
|
* @a method, request URI @a uri and message body @a data. The authorization
|
|
|
|
* header type is determined by @a hc - it can be either
|
|
|
|
* sip_authorization_class or sip_proxy_authorization_class, as well as
|
|
|
|
* http_authorization_class or http_proxy_authorization_class.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @retval 1 when authorization headers has been created
|
2007-04-15 02:03:41 +00:00
|
|
|
* @retval 0 when there is no credentials
|
|
|
|
* @retval -1 upon an error
|
2006-12-21 06:30:28 +00:00
|
|
|
*/
|
|
|
|
static
|
2008-12-16 18:05:22 +00:00
|
|
|
int auc_digest_authorization(auth_client_t *ca,
|
2006-12-21 06:30:28 +00:00
|
|
|
su_home_t *home,
|
2008-12-16 18:05:22 +00:00
|
|
|
char const *method,
|
|
|
|
url_t const *url,
|
2006-12-21 06:30:28 +00:00
|
|
|
msg_payload_t const *body,
|
|
|
|
msg_header_t **return_headers)
|
|
|
|
{
|
|
|
|
auth_digest_client_t *cda = (auth_digest_client_t *)ca;
|
|
|
|
msg_hclass_t *hc = ca->ca_credential_class;
|
|
|
|
char const *user = ca->ca_user;
|
|
|
|
char const *pass = ca->ca_pass;
|
|
|
|
auth_challenge_t const *ac = cda->cda_ac;
|
|
|
|
char const *cnonce = cda->cda_cnonce;
|
|
|
|
unsigned nc = ++cda->cda_ncount;
|
|
|
|
void const *data = body ? body->pl_data : "";
|
|
|
|
usize_t dlen = body ? body->pl_len : 0;
|
2009-05-15 16:05:59 +00:00
|
|
|
char *uri;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
msg_header_t *h;
|
|
|
|
auth_hexmd5_t sessionkey, response;
|
|
|
|
auth_response_t ar[1] = {{ 0 }};
|
|
|
|
char ncount[17];
|
|
|
|
|
2007-04-15 02:03:41 +00:00
|
|
|
if (!user || !pass || (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear))
|
|
|
|
return 0;
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
ar->ar_size = sizeof(ar);
|
|
|
|
ar->ar_username = user;
|
|
|
|
ar->ar_realm = ac->ac_realm;
|
|
|
|
ar->ar_nonce = ac->ac_nonce;
|
|
|
|
ar->ar_algorithm = NULL;
|
|
|
|
ar->ar_md5 = ac->ac_md5;
|
|
|
|
ar->ar_md5sess = ac->ac_md5sess;
|
|
|
|
ar->ar_opaque = ac->ac_opaque;
|
|
|
|
ar->ar_qop = NULL;
|
|
|
|
ar->ar_auth = ac->ac_auth;
|
|
|
|
ar->ar_auth_int = ac->ac_auth_int;
|
2009-05-15 16:05:59 +00:00
|
|
|
ar->ar_uri = uri = url_as_string(home, url);
|
|
|
|
|
|
|
|
if (ar->ar_uri == NULL)
|
|
|
|
return -1;
|
2006-12-21 06:30:28 +00:00
|
|
|
|
|
|
|
/* If there is no qop, we MUST NOT include cnonce or nc */
|
|
|
|
if (!ar->ar_auth && !ar->ar_auth_int)
|
|
|
|
cnonce = NULL;
|
|
|
|
|
|
|
|
if (cnonce) {
|
|
|
|
snprintf(ncount, sizeof(ncount), "%08x", nc);
|
|
|
|
ar->ar_cnonce = cnonce;
|
|
|
|
ar->ar_nc = ncount;
|
|
|
|
}
|
|
|
|
|
|
|
|
auth_digest_sessionkey(ar, sessionkey, pass);
|
|
|
|
auth_digest_response(ar, response, sessionkey, method, data, dlen);
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
h = msg_header_format(home, hc,
|
2006-12-21 06:30:28 +00:00
|
|
|
"Digest "
|
|
|
|
"username=\"%s\", "
|
|
|
|
"realm=\"%s\", "
|
|
|
|
"nonce=\"%s"
|
|
|
|
"%s%s"
|
|
|
|
"%s%s"
|
|
|
|
"%s%s, "
|
|
|
|
"uri=\"%s\", "
|
|
|
|
"response=\"%s\""
|
|
|
|
"%s%s"
|
|
|
|
"%s%s",
|
2008-12-16 18:05:22 +00:00
|
|
|
ar->ar_username,
|
2006-12-21 06:30:28 +00:00
|
|
|
ar->ar_realm,
|
|
|
|
ar->ar_nonce,
|
2008-12-16 18:05:22 +00:00
|
|
|
cnonce ? "\", cnonce=\"" : "",
|
2006-12-21 06:30:28 +00:00
|
|
|
cnonce ? cnonce : "",
|
2008-12-16 18:05:22 +00:00
|
|
|
ar->ar_opaque ? "\", opaque=\"" : "",
|
2006-12-21 06:30:28 +00:00
|
|
|
ar->ar_opaque ? ar->ar_opaque : "",
|
|
|
|
ar->ar_algorithm ? "\", algorithm=" : "",
|
|
|
|
ar->ar_algorithm ? ar->ar_algorithm : "",
|
|
|
|
ar->ar_uri,
|
|
|
|
response,
|
2008-12-16 18:05:22 +00:00
|
|
|
ar->ar_auth || ar->ar_auth_int ? ", qop=" : "",
|
|
|
|
ar->ar_auth_int ? "auth-int" :
|
2006-12-21 06:30:28 +00:00
|
|
|
(ar->ar_auth ? "auth" : ""),
|
2008-12-16 18:05:22 +00:00
|
|
|
cnonce ? ", nc=" : "",
|
2006-12-21 06:30:28 +00:00
|
|
|
cnonce ? ncount : "");
|
|
|
|
|
|
|
|
su_free(home, uri);
|
|
|
|
|
|
|
|
if (!h)
|
|
|
|
return -1;
|
|
|
|
*return_headers = h;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#define MAX_AUC 20
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
static auth_client_plugin_t const *ca_plugins[MAX_AUC] =
|
2006-12-21 06:30:28 +00:00
|
|
|
{
|
|
|
|
&ca_digest_plugin, &ca_basic_plugin, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Register an authentication client plugin */
|
|
|
|
int auc_register_plugin(auth_client_plugin_t const *plugin)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (plugin == NULL ||
|
|
|
|
plugin->auc_name == NULL ||
|
|
|
|
plugin->auc_authorize == NULL)
|
|
|
|
return errno = EFAULT, -1;
|
|
|
|
|
|
|
|
if (plugin->auc_size < (int) sizeof (auth_client_t))
|
|
|
|
return errno = EINVAL, -1;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUC; i++) {
|
2008-12-16 18:05:22 +00:00
|
|
|
if (ca_plugins[i] == NULL ||
|
2009-02-11 16:47:44 +00:00
|
|
|
su_strmatch(plugin->auc_name, ca_plugins[i]->auc_name) == 0) {
|
2006-12-21 06:30:28 +00:00
|
|
|
ca_plugins[i] = plugin;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return errno = ENOMEM, -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Allocate an (possibly extended) auth_client_t structure. */
|
|
|
|
static
|
|
|
|
auth_client_t *ca_create(su_home_t *home,
|
|
|
|
char const *scheme,
|
|
|
|
char const *realm)
|
|
|
|
{
|
|
|
|
auth_client_plugin_t const *auc = NULL;
|
|
|
|
auth_client_t *ca;
|
|
|
|
size_t aucsize = (sizeof *ca), realmlen, size;
|
|
|
|
char *s;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (scheme == NULL || realm == NULL)
|
|
|
|
return (void)(errno = EFAULT), NULL;
|
|
|
|
|
|
|
|
realmlen = strlen(realm) + 1;
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_AUC; i++) {
|
|
|
|
auc = ca_plugins[i];
|
2009-02-11 16:47:44 +00:00
|
|
|
if (!auc || su_casematch(auc->auc_name, scheme))
|
2006-12-21 06:30:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-09-19 16:24:40 +00:00
|
|
|
/* XXX - should report error if the auth scheme is not known? */
|
|
|
|
|
2006-12-21 06:30:28 +00:00
|
|
|
aucsize = auc ? (size_t)auc->auc_size : (sizeof *ca);
|
|
|
|
size = aucsize + realmlen;
|
|
|
|
if (!auc)
|
|
|
|
size += strlen(scheme) + 1;
|
|
|
|
|
|
|
|
ca = su_home_clone(home, (isize_t)size);
|
|
|
|
if (!ca)
|
|
|
|
return ca;
|
|
|
|
|
|
|
|
s = (char *)ca + aucsize;
|
|
|
|
ca->ca_auc = auc;
|
|
|
|
ca->ca_realm = strcpy(s, realm);
|
|
|
|
ca->ca_scheme = auc ? auc->auc_name : strcpy(s + realmlen, scheme);
|
|
|
|
|
|
|
|
return ca;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ca_destroy(su_home_t *home, auth_client_t *ca)
|
|
|
|
{
|
|
|
|
su_free(home, ca);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_SOFIA_SIP
|
|
|
|
#include <sofia-sip/sip.h>
|
|
|
|
|
|
|
|
/**Authorize a SIP request.
|
|
|
|
*
|
|
|
|
* The function auc_authorize() is used to add correct authentication
|
|
|
|
* headers to a SIP request. The authentication headers will contain the
|
|
|
|
* credentials generated by the list of authenticators.
|
|
|
|
*
|
2008-12-16 18:05:22 +00:00
|
|
|
* @param[in,out] auc_list list of authenticators
|
2006-12-21 06:30:28 +00:00
|
|
|
* @param[in,out] msg message to be authenticated
|
|
|
|
* @param[in,out] sip sip headers of the message
|
2008-12-16 18:05:22 +00:00
|
|
|
*
|
2006-12-21 06:30:28 +00:00
|
|
|
* @retval 1 when successful
|
|
|
|
* @retval 0 when there is not enough credentials
|
|
|
|
* @retval -1 upon an error
|
|
|
|
*/
|
|
|
|
int auc_authorize(auth_client_t **auc_list, msg_t *msg, sip_t *sip)
|
|
|
|
{
|
|
|
|
sip_request_t *rq = sip ? sip->sip_request : NULL;
|
|
|
|
|
|
|
|
if (!rq)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-16 18:05:22 +00:00
|
|
|
return auc_authorization(auc_list, msg, (msg_pub_t *)sip,
|
|
|
|
rq->rq_method_name,
|
2006-12-21 06:30:28 +00:00
|
|
|
/*
|
|
|
|
RFC 3261 defines the protection domain based
|
|
|
|
only on realm, so we do not bother get a
|
|
|
|
correct URI to auth module.
|
|
|
|
*/
|
2008-12-16 18:05:22 +00:00
|
|
|
rq->rq_url,
|
2006-12-21 06:30:28 +00:00
|
|
|
sip->sip_payload);
|
|
|
|
}
|
|
|
|
#endif
|