Commit 995ac6d2 authored by Pekka Pessi's avatar Pekka Pessi

iptsec, msg, sip, http: using Authentication-Info on client side to update the nonce.

darcs-hash:20061207145605-65a35-d215f99a986123aa6d6b6bb5ab8a5b0780db4060.gz
parent 5bef9982
......@@ -109,8 +109,7 @@ typedef msg_accept_language_t http_accept_language_t;
typedef msg_list_t http_accept_ranges_t;
typedef msg_numeric_t http_age_t;
typedef msg_list_t http_allow_t;
typedef
struct http_authentication_info_s http_authentication_info_t;
typedef msg_auth_info_t http_authentication_info_t;
typedef msg_auth_t http_authorization_t;
typedef msg_list_t http_cache_control_t;
typedef msg_list_t http_connection_t;
......@@ -197,6 +196,8 @@ struct http_status_s {
/**@ingroup http_authentication_info
* @brief Structure for @b Authentication-Info header.
*
* @deprecated Use struct msg_auth_info_s instead.
*/
struct http_authentication_info_s
{
......
......@@ -34,9 +34,11 @@
#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>
......@@ -65,6 +67,10 @@ static int ca_challenge(auth_client_t *ca,
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);
static int ca_credentials(auth_client_t *ca,
char const *scheme,
char const *realm,
......@@ -177,6 +183,87 @@ int ca_challenge(auth_client_t *ca,
return stale ? 2 : 1;
}
/** Store authentication info to authenticators.
*
* The function auc_info() feeds the authentication data from the
* authentication info @a info to the list of authenticators @a auc_list.
*
* @param auc_list [in/out] list of authenticators to be updated
* @param info [in] info to be processed
* @param crcl [in] corresponding credential class
*
* The authentication info can be in either Authentication-Info or in
* Proxy-Authentication-Info headers.
* If the header is Authentication-Info, the @a crcl should be
* #sip_authorization_class or #http_authorization_class.
* Likewise, If the header is Proxy-Authentication-Info, the @a crcl should
* be #sip_proxy_authorization_class or #http_proxy_authorization_class.
* The authentication into usually contains next nonce or mutual
* authentication information. We handle only nextnonce parameter.
*
* @bug
* The result can be quite unexpected if there are more than one
* authenticator with the given type (specified by @a crcl). In principle,
* SIP allows more than one challenge for a single request.
*
* @retval number of challenges to updated
* @retval 0 when there was no challenge to update
* @retval -1 upon an error
*/
int auc_info(auth_client_t **auc_list,
msg_auth_info_t const *ai,
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) {
int updated = ca_info(ca, ai, credential_class);
if (updated < 0)
return -1;
if (updated >= 1)
retval = 1; /* Updated authenticator */
}
return retval;
}
/** Update authentication client with authentication info.
*
* @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
int ca_info(auth_client_t *ca,
msg_auth_info_t const *ai,
msg_hclass_t *credential_class)
{
assert(ca); assert(ai);
if (!ca || !ai)
return -1;
if (!ca->ca_credential_class)
return 0;
if (ca->ca_credential_class != credential_class)
return 0;
if (!ca->ca_auc
|| ca->ca_auc->auc_plugin_size <= offsetof(auth_client_plugin_t, auc_info)
|| !ca->ca_auc->auc_info)
return 0;
return ca->ca_auc->auc_info(ca, ai);
}
/**Feed authentication data to the authenticator.
*
* The function auc_credentials() is used to provide the authenticators in
......@@ -531,11 +618,12 @@ static int auc_basic_authorization(auth_client_t *ca,
const auth_client_plugin_t ca_basic_plugin =
{
sizeof ca_basic_plugin,
sizeof (auth_client_t),
"Basic",
NULL,
auc_basic_authorization
/* auc_plugin_size: */ sizeof ca_basic_plugin,
/* auc_size: */ sizeof (auth_client_t),
/* auc_name: */ "Basic",
/* auc_challenge: */ NULL,
/* auc_authorize: */ auc_basic_authorization,
/* auc_info: */ NULL
};
/**Create a basic authorization header.
......@@ -625,14 +713,17 @@ static int auc_digest_authorization(auth_client_t *ca,
url_t const *url,
msg_payload_t const *body,
msg_header_t **);
static int auc_digest_info(auth_client_t *ca,
msg_auth_info_t const *ai);
static const auth_client_plugin_t ca_digest_plugin =
{
sizeof ca_digest_plugin,
sizeof (auth_digest_client_t),
"Digest",
auc_digest_challenge,
auc_digest_authorization
/* auc_plugin_size: */ sizeof ca_digest_plugin,
/* auc_size: */ sizeof (auth_digest_client_t),
/* auc_name: */ "Digest",
/* auc_challenge: */ auc_digest_challenge,
/* auc_authorize: */ auc_digest_authorization,
/* auc_info: */ auc_digest_info
};
/** Store a digest authorization challenge.
......@@ -678,6 +769,25 @@ static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch)
return -1;
}
static int auc_digest_info(auth_client_t *ca,
msg_auth_info_t const *ai)
{
auth_digest_client_t *cda = (auth_digest_client_t *)ca;
su_home_t *home = ca->ca_home;
char const *nextnonce = NULL;
issize_t n;
n = auth_get_params(home, ai->ai_params,
"nextnonce=", &nextnonce,
NULL);
if (n <= 0)
return n;
cda->cda_ac->ac_nonce = nextnonce;
return 1;
}
/**Create a digest authorization header.
*
......
......@@ -56,6 +56,11 @@ int auc_challenge(auth_client_t **auc, su_home_t *home,
SOFIAPUBFUN
int auc_credentials(auth_client_t **auc, su_home_t *home, char const *data);
SOFIAPUBFUN
int auc_info(auth_client_t **auc_list,
msg_auth_info_t const *ai,
msg_hclass_t *credential_class);
SOFIAPUBFUN
int auc_all_credentials(auth_client_t **auc_list,
char const *scheme,
......
......@@ -62,8 +62,10 @@ struct auth_client_s {
struct auth_client_plugin
{
int auc_plugin_size, auc_size;
char const *auc_name;
int auc_plugin_size; /* Size of this structure */
int auc_size; /* Size of the client structure */
char const *auc_name; /* Name of the autentication scheme */
/** Store challenge */
int (*auc_challenge)(auth_client_t *ca,
......@@ -77,7 +79,8 @@ struct auth_client_plugin
msg_payload_t const *body,
msg_header_t **return_headers);
/** Store nextnonce from Authentication-Info or Proxy-Authentication-Info. */
int (*auc_info)(auth_client_t *ca, msg_auth_info_t const *ai);
};
SOFIA_END_DECLS
......
......@@ -765,6 +765,58 @@ int test_digest_client()
reinit_as(as); auth_mod_destroy(am); aucs = NULL;
/* Test nextnonce */
{
char const *nonce1, *nextnonce, *nonce2;
reinit_as(as); auth_mod_destroy(am); aucs = NULL;
TEST_1(am = auth_mod_create(NULL,
AUTHTAG_METHOD("Digest"),
AUTHTAG_REALM("ims3.so.noklab.net"),
AUTHTAG_DB(testpasswd),
AUTHTAG_ALGORITHM("MD5"),
AUTHTAG_QOP("auth-int"),
AUTHTAG_EXPIRES(90),
AUTHTAG_NEXT_EXPIRES(900),
TAG_END()));
reinit_as(as);
auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
sip_authorization_class), 1);
TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
"user1", "secret"), 1);
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
(url_t *)"sip:surf3@ims3.so.noklab.net",
sip->sip_payload), 1);
TEST_1(sip->sip_authorization);
TEST_1(nonce1 = msg_header_find_param(sip->sip_authorization->au_common, "nonce"));
reinit_as(as);
auth_mod_check_client(am, as, sip->sip_authorization, ach);
TEST(as->as_status, 0);
TEST_1(as->as_info);
TEST_1(nextnonce = msg_header_find_param(as->as_info->sh_common, "nextnonce"));
TEST(auc_info(&aucs, (msg_auth_info_t const *)as->as_info, sip_authorization_class), 1);
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
(url_t *)"sip:surf3@ims3.so.noklab.net",
sip->sip_payload), 1);
TEST_1(sip->sip_authorization);
TEST_1(nonce2 = msg_header_find_param(sip->sip_authorization->au_common, "nonce"));
TEST_1(strcmp(nonce1, nextnonce));
TEST_1(strcmp(nonce1, nonce2));
TEST_S(nonce2, nextnonce);
auth_mod_destroy(am); aucs = NULL;
}
TEST_1(am = auth_mod_create(NULL,
AUTHTAG_METHOD("Digest"),
AUTHTAG_REALM("ims3.so.noklab.net"),
......
......@@ -100,6 +100,7 @@ typedef struct msg_numeric_s msg_numeric_t;
typedef struct msg_generic_s msg_generic_t;
typedef struct msg_list_s msg_list_t;
typedef struct msg_auth_s msg_auth_t;
typedef struct msg_auth_info_s msg_auth_info_t;
#define MSG_HEADER_N 16377
......@@ -174,6 +175,17 @@ struct msg_auth_s {
msg_param_t const *au_params; /**< Comma-separated parameters */
};
/**Authentication-Info header
*
* An Authentication-Info header has comma-separated list of parameters as its value.
*/
struct msg_auth_info_s
{
msg_common_t ai_common[1]; /**< Common fragment info */
msg_error_t *ai_next; /**< Dummy link to next */
msg_param_t const *ai_params; /**< List of ainfo */
};
/** Unknown header. */
struct msg_unknown_s {
msg_common_t un_common[1]; /**< Common fragment info */
......
......@@ -350,11 +350,11 @@ issize_t sip_www_authenticate_e(char b[], isize_t bsiz, sip_header_t const *h, i
*
* The #sip_authentication_info_t is defined as follows:
* @code
* typedef struct msg_list_s
* typedef struct msg_auth_info_s
* {
* msg_common_t k_common[1]; // Common fragment info
* msg_list_t *k_next; // Dummy link to next header
* msg_param_t *k_items; // List of ainfo
* msg_common_t ai_common[1]; // Common fragment info
* msg_error_t *ai_next; // Dummy link to next header
* msg_param_t *ai_items; // List of ainfo
* } sip_authentication_info_t;
* @endcode
*/
......@@ -408,18 +408,18 @@ issize_t sip_authentication_info_e(char b[], isize_t bsiz, sip_header_t const *h
*/
/**@ingroup sip_proxy_authentication_info
* @typedef typedef struct sip_proxy_authentication_info_s sip_proxy_authentication_info_t;
* @typedef typedef struct msg_authentication_info_s sip_proxy_authentication_info_t;
*
* The structure #sip_proxy_authentication_info_t contains representation of SIP
* @ProxyAuthenticationInfo header.
*
* The #sip_proxy_authentication_info_t is defined as follows:
* @code
* typedef struct msg_list_s
* typedef struct msg_auth_info_s
* {
* msg_common_t k_common[1]; // Common fragment info
* msg_list_t *k_next; // Dummy link to next header
* msg_param_t *k_items; // List of ainfo
* msg_common_t ai_common[1]; // Common fragment info
* msg_error_t *ai_next; // Dummy link to next header
* msg_param_t *ai_items; // List of ainfo
* } sip_proxy_authentication_info_t;
* @endcode
*
......@@ -442,7 +442,7 @@ issize_t sip_proxy_authentication_info_d(su_home_t *home, sip_header_t *h,
issize_t sip_proxy_authentication_info_e(char b[], isize_t bsiz,
sip_header_t const *h, int f)
{
assert(sip_is_authentication_info(h));
assert(sip_is_proxy_authentication_info(h)); /* This is soo popular */
return msg_list_e(b, bsiz, h, f);
}
......
......@@ -140,8 +140,7 @@ typedef struct sip_accept_s sip_accept_t;
typedef msg_accept_any_t sip_accept_encoding_t;
typedef msg_accept_any_t sip_accept_language_t;
typedef msg_list_t sip_allow_t;
typedef struct sip_authentication_info_s
sip_authentication_info_t;
typedef struct msg_auth_info_s sip_authentication_info_t;
typedef struct msg_auth_s sip_authorization_t;
typedef struct sip_call_id_s sip_call_id_t;
typedef struct sip_call_info_s sip_call_info_t;
......@@ -166,8 +165,7 @@ typedef struct sip_min_se_s sip_min_se_t;
typedef struct msg_generic_s sip_organization_t;
typedef struct msg_generic_s sip_priority_t;
typedef struct msg_auth_s sip_proxy_authenticate_t;
typedef struct sip_authentication_info_s
sip_proxy_authentication_info_t;
typedef struct msg_auth_info_s sip_proxy_authentication_info_t;
typedef struct msg_auth_s sip_proxy_authorization_t;
typedef msg_list_t sip_proxy_require_t;
typedef struct sip_rack_s sip_rack_t;
......@@ -223,10 +221,10 @@ typedef struct sip_route_s sip_service_route_t;
/**SIP message object.
*
* This structure contains a parsed SIP message The struct is usually
* This structure contains a parsed SIP message. The struct is usually
* referred with typedef #sip_t. It is used to access the headers and
* payload within the SIP message. The generic transport aspects of the
* message, like network address, is accessed using a #msg_t object
* message, like network address, is accessed using the #msg_t object
* directly.
*/
struct sip_s {
......@@ -410,6 +408,8 @@ struct sip_accept_s
/**@ingroup sip_authentication_info
* @brief Structure for @AuthenticationInfo header.
*
* @deprecated Use struct msg_auth_info_s instead.
*/
struct sip_authentication_info_s
{
......
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