Commit 22abd065 authored by Pekka Pessi's avatar Pekka Pessi

sofia-sip/auth_client_plugin.h: added plugin method for auc_clear_credentials()

Now auc_all_credentials() returns 0 if the username and password has not
been changed. Now authentication client can avoid looping if application
insists in giving it bad username/password again.

Plugin method auc_clear() is available only when SOFIA_EXTEND_AUTH_CLIENT
has been defined to non-zero before #include
<sofia-sip/auth_client_plugin.h>.

darcs-hash:20070411155509-65a35-dfd16db949bf8795b14c4bc9033a3a433c4606ad.gz
parent 5a15741f
......@@ -19,3 +19,6 @@ TAGFILES += ../docs/nta.doxytags=../nta
GENERATE_TAGFILE = ../docs/iptsec.doxytags
ALIASES +=
PREDEFINED += SOFIA_EXTEND_AUTH_CLIENT=1
......@@ -31,6 +31,8 @@
#include "config.h"
#define SOFIA_EXTEND_AUTH_CLIENT 1
#include <sofia-sip/su.h>
#include <sofia-sip/su_md5.h>
......@@ -77,9 +79,7 @@ static int ca_credentials(auth_client_t *ca,
char const *user,
char const *pass);
static int ca_clear_credentials(auth_client_t *ca,
char const *scheme,
char const *realm);
static int ca_clear_credentials(auth_client_t *ca);
/** Initialize authenticators.
......@@ -340,8 +340,8 @@ int auc_credentials(auth_client_t **auc_list, su_home_t *home,
* @param[in] user username
* @param[in] pass password
*
* @retval number of matching clients
* @retval 0 when no matching client was found
* @retval number of updated clients
* @retval 0 when no client was updated
* @retval -1 upon an error
*/
int auc_all_credentials(auth_client_t **auc_list,
......@@ -375,6 +375,9 @@ int ca_credentials(auth_client_t *ca,
char const *user,
char const *pass)
{
char *new_user, *new_pass;
char *old_user, *old_pass;
assert(ca);
if (!ca || !ca->ca_scheme || !ca->ca_realm)
......@@ -384,12 +387,24 @@ int ca_credentials(auth_client_t *ca,
(realm != NULL && strcmp(realm, ca->ca_realm)))
return -1;
ca->ca_user = su_strdup(ca->ca_home, user);
ca->ca_pass = su_strdup(ca->ca_home, pass);
old_user = ca->ca_user, old_pass = ca->ca_pass;
if (str0cmp(user, old_user) == 0 && str0cmp(pass, old_pass) == 0)
return 0;
new_user = su_strdup(ca->ca_home, user);
new_pass = su_strdup(ca->ca_home, pass);
if (!ca->ca_user || !ca->ca_pass)
if (!new_user || !new_pass)
return -1;
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);
return 1;
}
......@@ -416,12 +431,15 @@ int auc_copy_credentials(auth_client_t **dst,
char *u, *p;
if (!ca->ca_user || !ca->ca_pass)
continue;
if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
continue;
if (!ca->ca_scheme[0] || strcmp(ca->ca_scheme, d->ca_scheme))
continue;
if (!ca->ca_realm[0] || strcmp(ca->ca_realm, d->ca_realm))
continue;
if (d->ca_user && strcmp(d->ca_user, ca->ca_user) == 0 &&
if (!(AUTH_CLIENT_IS_EXTENDED(d) && d->ca_clear) &&
d->ca_user && strcmp(d->ca_user, ca->ca_user) == 0 &&
d->ca_pass && strcmp(d->ca_pass, ca->ca_pass) == 0) {
retval++;
break;
......@@ -435,6 +453,9 @@ int auc_copy_credentials(auth_client_t **dst,
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;
if (AUTH_CLIENT_IS_EXTENDED(d))
d->ca_clear = 0;
retval++;
break;
}
......@@ -457,13 +478,24 @@ int auc_copy_credentials(auth_client_t **dst,
* @retval -1 upon an error
*/
int auc_clear_credentials(auth_client_t **auc_list,
char const *scheme,
char const *realm)
char const *scheme,
char const *realm)
{
int retval = 0;
int match;
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
int match = ca_clear_credentials(*auc_list, scheme, realm);
auth_client_t *ca = *auc_list;
if (!AUTH_CLIENT_IS_EXTENDED(ca))
continue;
if ((scheme != NULL && strcasecmp(scheme, ca->ca_scheme)) ||
(realm != NULL && strcmp(realm, ca->ca_realm)))
continue;
match = ca->ca_auc->auc_clear(*auc_list);
if (match < 0) {
retval = -1;
break;
......@@ -476,21 +508,14 @@ int auc_clear_credentials(auth_client_t **auc_list,
}
static
int ca_clear_credentials(auth_client_t *ca,
char const *scheme,
char const *realm)
int ca_clear_credentials(auth_client_t *ca)
{
assert(ca);
if (!ca || !ca->ca_scheme || !ca->ca_realm)
return -1;
assert(ca); assert(ca->ca_home->suh_size >= (int)(sizeof *ca));
if ((scheme != NULL && strcasecmp(scheme, ca->ca_scheme)) ||
(realm != NULL && strcmp(realm, ca->ca_realm)))
if (!ca)
return -1;
su_free(ca->ca_home, (void *)ca->ca_user), ca->ca_user = NULL;
su_free(ca->ca_home, (void *)ca->ca_pass), ca->ca_pass = NULL;
ca->ca_clear = 1;
return 1;
}
......@@ -513,6 +538,8 @@ int auc_has_authorization(auth_client_t **auc_list)
for (ca = *auc_list; ca; ca = ca->ca_next) {
if (!ca->ca_user || !ca->ca_pass || !ca->ca_credential_class)
return 0;
if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
return 0;
}
return 1;
......@@ -570,8 +597,11 @@ int auc_authorization(auth_client_t **auc_list, msg_t *msg, msg_pub_t *pub,
if (!ca->ca_auc)
continue;
if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0
|| msg_header_insert(msg, pub, h) < 0)
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)
return -1;
}
......@@ -639,14 +669,15 @@ static int auc_basic_authorization(auth_client_t *ca,
msg_payload_t const *body,
msg_header_t **);
const auth_client_plugin_t ca_basic_plugin =
static const auth_client_plugin_t ca_basic_plugin =
{
/* 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
/* auc_info: */ NULL,
/* auc_clear: */ ca_clear_credentials
};
/**Create a basic authorization header.
......@@ -683,6 +714,9 @@ int auc_basic_authorization(auth_client_t *ca,
if (user == NULL || pass == NULL)
return -1;
if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
return 0;
ulen = strlen(user), plen = strlen(pass), uplen = ulen + 1 + plen;
b64len = BASE64_SIZE(uplen);
basiclen = strlen("Basic ") + b64len;
......@@ -746,7 +780,8 @@ static const auth_client_plugin_t ca_digest_plugin =
/* auc_name: */ "Digest",
/* auc_challenge: */ auc_digest_challenge,
/* auc_authorize: */ auc_digest_authorization,
/* auc_info: */ auc_digest_info
/* auc_info: */ auc_digest_info,
/* auc_clear: */ ca_clear_credentials
};
/** Store a digest authorization challenge.
......@@ -826,9 +861,9 @@ static int auc_digest_info(auth_client_t *ca,
* sip_authorization_class or sip_proxy_authorization_class, as well as
* http_authorization_class or http_proxy_authorization_class.
*
* @return
* Returns a pointer to newly created authorization header, or NULL upon an
* error.
* @retval 1 when authorization headers has been created
* @retval 0 when there is no credentials
* @retval -1 upon an error
*/
static
int auc_digest_authorization(auth_client_t *ca,
......@@ -854,6 +889,9 @@ int auc_digest_authorization(auth_client_t *ca,
auth_response_t ar[1] = {{ 0 }};
char ncount[17];
if (!user || !pass || (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear))
return 0;
ar->ar_size = sizeof(ar);
ar->ar_username = user;
ar->ar_realm = ac->ac_realm;
......
......@@ -29,6 +29,9 @@
/**@file sofia-sip/auth_client_plugin.h
* @brief Client-side plugin interface for authentication
*
* @note For extensions in 1.12.6 or later,
* you have to #define SOFIA_EXTEND_AUTH_CLIENT to 1.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
*
* @date Created: Fri May 19 16:18:21 EEST 2006
......@@ -58,6 +61,10 @@ struct auth_client_s {
char *ca_pass;
msg_hclass_t *ca_credential_class;
#if SOFIA_EXTEND_AUTH_CLIENT
int ca_clear;
#endif
};
struct auth_client_plugin
......@@ -81,8 +88,19 @@ struct auth_client_plugin
/** Store nextnonce from Authentication-Info or Proxy-Authentication-Info. */
int (*auc_info)(auth_client_t *ca, msg_auth_info_t const *ai);
#if SOFIA_EXTEND_AUTH_CLIENT
/** Clear credentials (user/pass). @NEW_1_12_6 */
int (*auc_clear)(auth_client_t *ca);
#endif
};
/** Check if authentication client has been extended. @NEW_1_12_6 */
#define AUTH_CLIENT_IS_EXTENDED(ca) \
((ca)->ca_auc->auc_plugin_size > \
offsetof(auth_client_plugin_t, auc_clear) \
&& (ca)->ca_auc->auc_clear != NULL)
SOFIA_END_DECLS
#endif /* !defined AUTH_CLIENT_PLUGIN_H */
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