Skip to content
Permalink
Browse files
Added direct support for hashed password to auxprop API
  • Loading branch information
Alexey Melnikov committed Mar 10, 2009
1 parent bde52d9 commit 62ce0768aa375cf0d16102570970b232dcb1cb28
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 25 deletions.
@@ -631,6 +631,14 @@ typedef int sasl_server_userdb_setpass_t(sasl_conn_t *conn,
#define SASL_CU_AUTHID 0x01
#define SASL_CU_AUTHZID 0x02

#define SASL_CU_OVERRIDE 0x08 /* mapped to SASL_AUXPROP_OVERRIDE */

/* The following CU flags are passed "as is" down to auxprop lookup */
#define SASL_CU_ASIS_MASK 0xFFF0
/* NOTE: Keep in sync with SASL_AUXPROP_<XXX> flags */
#define SASL_CU_VERIFY_AGAINST_HASH 0x10


typedef int sasl_canon_user_t(sasl_conn_t *conn,
void *context,
const char *in, unsigned inlen,
@@ -922,7 +922,11 @@ typedef struct sasl_auxprop_plug {
* we are looking up the authzid flags
* (no prefix) */

#define SASL_AUXPROP_PLUG_VERSION 5
/* NOTE: Keep in sync with SASL_CU_<XXX> flags */
#define SASL_AUXPROP_VERIFY_AGAINST_HASH 0x10


#define SASL_AUXPROP_PLUG_VERSION 8

/* default name for auxprop plug-in entry point is "sasl_auxprop_init"
* similar to sasl_server_plug_init model, except only returns one
@@ -1,6 +1,6 @@
/* canonusr.c - user canonicalization support
* Rob Siemborski
* $Id: canonusr.c,v 1.18 2008/10/30 14:21:30 mel Exp $
* $Id: canonusr.c,v 1.19 2009/03/10 14:10:52 mel Exp $
*/
/*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
@@ -128,7 +128,7 @@ int _sasl_canon_user(sasl_conn_t *conn,
}

if(!plugin_name) {
/* Use Defualt */
/* Use Default */
plugin_name = "INTERNAL";
}

@@ -186,9 +186,9 @@ int _sasl_canon_user(sasl_conn_t *conn,
}

/* Lookup all properties for authentication and/or authorization identity. */
int _sasl_auxprop_lookup_user_props (sasl_conn_t *conn,
unsigned flags,
sasl_out_params_t *oparams)
static int _sasl_auxprop_lookup_user_props (sasl_conn_t *conn,
unsigned flags,
sasl_out_params_t *oparams)
{
sasl_server_conn_t *sconn = NULL;
int result = SASL_OK;
@@ -202,16 +202,25 @@ int _sasl_auxprop_lookup_user_props (sasl_conn_t *conn,
/* do auxprop lookups (server only) */
if (sconn) {
int authz_result;
unsigned auxprop_lookup_flags = flags & SASL_CU_ASIS_MASK;

if(flags & SASL_CU_AUTHID) {
result = _sasl_auxprop_lookup(sconn->sparams, 0,
oparams->authid, oparams->alen);
if (flags & SASL_CU_OVERRIDE) {
auxprop_lookup_flags |= SASL_AUXPROP_OVERRIDE;
}

if (flags & SASL_CU_AUTHID) {
result = _sasl_auxprop_lookup(sconn->sparams,
auxprop_lookup_flags,
oparams->authid,
oparams->alen);
} else {
result = SASL_CONTINUE;
}
if(flags & SASL_CU_AUTHZID) {
authz_result = _sasl_auxprop_lookup(sconn->sparams, SASL_AUXPROP_AUTHZID,
oparams->user, oparams->ulen);
if (flags & SASL_CU_AUTHZID) {
authz_result = _sasl_auxprop_lookup(sconn->sparams,
auxprop_lookup_flags | SASL_AUXPROP_AUTHZID,
oparams->user,
oparams->ulen);

if (result == SASL_CONTINUE) {
/* Only SASL_CU_AUTHZID was requested.
@@ -1,7 +1,7 @@
/* SASL server API implementation
* Rob Siemborski
* Tim Martin
* $Id: checkpw.c,v 1.77 2008/10/29 15:01:30 mel Exp $
* $Id: checkpw.c,v 1.78 2009/03/10 14:10:52 mel Exp $
*/
/*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
@@ -135,8 +135,6 @@ static int auxprop_verify_password(sasl_conn_t *conn,
const char *user_realm __attribute__((unused)))
{
int ret = SASL_FAIL;
char *userid = NULL;
char *realm = NULL;
int result = SASL_OK;
sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn;
const char *password_request[] = { SASL_AUX_PASSWORD,
@@ -150,7 +148,7 @@ static int auxprop_verify_password(sasl_conn_t *conn,
/* We need to clear any previous results and re-canonify to
* ensure correctness */

prop_clear(sconn->sparams->propctx, 0);
prop_clear (sconn->sparams->propctx, 0);

/* ensure its requested */
result = prop_request(sconn->sparams->propctx, password_request);
@@ -229,9 +227,102 @@ static int auxprop_verify_password(sasl_conn_t *conn,
password_request[0]);

done:
if (userid) sasl_FREE(userid);
if (realm) sasl_FREE(realm);
/* We're not going to erase the property here because other people
* may want it */
return ret;
}

/* Verify user password using auxprop plugins. Allow verification against a hashed password,
* or non-retrievable password. Don't use cmusaslsecretPLAIN attribute.
*
* This function is similar to auxprop_verify_password().
*/
static int auxprop_verify_password_hashed(sasl_conn_t *conn,
const char *userstr,
const char *passwd,
const char *service __attribute__((unused)),
const char *user_realm __attribute__((unused)))
{
int ret = SASL_FAIL;
int result = SASL_OK;
sasl_server_conn_t *sconn = (sasl_server_conn_t *)conn;
const char *password_request[] = { SASL_AUX_PASSWORD,
NULL };
struct propval auxprop_values[2];
unsigned extra_cu_flags = 0;

if (!conn || !userstr)
return SASL_BADPARAM;

/* We need to clear any previous results and re-canonify to
* ensure correctness */

prop_clear(sconn->sparams->propctx, 0);

/* ensure its requested */
result = prop_request(sconn->sparams->propctx, password_request);

if (result != SASL_OK) return result;

/* We need to pass "password" down to the auxprop_lookup */
/* NB: We don't support binary passwords */
if (passwd != NULL) {
prop_set (sconn->sparams->propctx,
SASL_AUX_PASSWORD,
passwd,
-1);
extra_cu_flags = SASL_CU_VERIFY_AGAINST_HASH;
}

result = _sasl_canon_user_lookup (conn,
userstr,
0,
SASL_CU_AUTHID | SASL_CU_AUTHZID | extra_cu_flags,
&(conn->oparams));

if (result != SASL_OK) return result;

result = prop_getnames(sconn->sparams->propctx, password_request,
auxprop_values);
if (result < 0) {
return result;
}

/* Verify that the returned <name>s are correct.
But we defer checking for NULL values till after we verify
that a passwd is specified. */
if (!auxprop_values[0].name && !auxprop_values[1].name) {
return SASL_NOUSER;
}

/* It is possible for us to get useful information out of just
* the lookup, so we won't check that we have a password until now */
if (!passwd) {
ret = SASL_BADPARAM;
goto done;
}

if ((!auxprop_values[0].values || !auxprop_values[0].values[0])) {
return SASL_NOUSER;
}

/* At the point this has been called, the username has been canonified
* and we've done the auxprop lookup. This should be easy. */

/* NB: Note that if auxprop_lookup failed to verify the password,
then the userPassword property value would be NULL */
if (auxprop_values[0].name
&& auxprop_values[0].values
&& auxprop_values[0].values[0]
&& !strcmp(auxprop_values[0].values[0], passwd)) {
/* We have a plaintext version and it matched! */
return SASL_OK;
} else {
/* passwords do not match */
ret = SASL_BADAUTH;
}

done:
/* We're not going to erase the property here because other people
* may want it */
return ret;
@@ -988,6 +1079,7 @@ static int always_true(sasl_conn_t *conn,

struct sasl_verify_password_s _sasl_verify_password[] = {
{ "auxprop", &auxprop_verify_password },
{ "auxprop-hashed", &auxprop_verify_password_hashed },
#ifdef HAVE_PWCHECK
{ "pwcheck", &pwcheck_verify_password },
#endif
@@ -1,7 +1,7 @@
/* SASL server API implementation
* Rob Siemborski
* Tim Martin
* $Id: sasldb.c,v 1.14 2008/10/29 15:01:31 mel Exp $
* $Id: sasldb.c,v 1.15 2009/03/10 14:10:53 mel Exp $
*/
/*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
@@ -70,8 +70,9 @@ static int sasldb_auxprop_lookup(void *glob_context __attribute__((unused)),
char value[8192];
size_t value_len;
char *user_buf;

if (!sparams || !user) return SASL_BADPARAM;
int verify_against_hashed_password;

if (!sparams || !user) return SASL_BADPARAM;

user_buf = sparams->utils->malloc(ulen + 1);
if(!user_buf) {
@@ -98,6 +99,8 @@ static int sasldb_auxprop_lookup(void *glob_context __attribute__((unused)),
goto done;
}

verify_against_hashed_password = flags & SASL_AUXPROP_VERIFY_AGAINST_HASH;

/* Use a fake value to signal that we have no property to lookup */
ret = SASL_CONTINUE;
for(cur = to_fetch; cur->name; cur++) {
@@ -112,12 +115,17 @@ static int sasldb_auxprop_lookup(void *glob_context __attribute__((unused)),
}

/* If it's there already, we want to see if it needs to be
* overridden */
if(cur->values && !(flags & SASL_AUXPROP_OVERRIDE))
* overridden. userPassword is a special case, because it's value
is always present if SASL_AUXPROP_VERIFY_AGAINST_HASH is specified.
When SASL_AUXPROP_VERIFY_AGAINST_HASH is set, we just clear userPassword. */
if (cur->values && !(flags & SASL_AUXPROP_OVERRIDE) &&
(verify_against_hashed_password == 0 ||
strcasecmp(realname, SASL_AUX_PASSWORD_PROP) != 0)) {
continue;
else if(cur->values)
} else if (cur->values) {
sparams->utils->prop_erase(sparams->propctx, cur->name);

}

cur_ret = _sasldb_getdata(sparams->utils,
sparams->utils->conn, userid, realm,
realname, value, sizeof(value), &value_len);

0 comments on commit 62ce076

Please sign in to comment.