sasldb.c   sasldb.c 
/* SASL server API implementation /* SASL server API implementation
* Rob Siemborski * Rob Siemborski
* Tim Martin * Tim Martin
* $Id: sasldb.c,v 1.11 2006/04/03 10:58:19 mel Exp $ * $Id: sasldb.c,v 1.17 2009/03/10 14:37:03 mel Exp $
*/ */
/* /*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved . * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved .
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
skipping to change at line 59 skipping to change at line 59
#include <stdio.h> #include <stdio.h>
#include "sasl.h" #include "sasl.h"
#include "saslutil.h" #include "saslutil.h"
#include "saslplug.h" #include "saslplug.h"
#include "../sasldb/sasldb.h" #include "../sasldb/sasldb.h"
#include "plugin_common.h" #include "plugin_common.h"
static void sasldb_auxprop_lookup(void *glob_context __attribute__((unused) ), static int sasldb_auxprop_lookup(void *glob_context __attribute__((unused)) ,
sasl_server_params_t *sparams, sasl_server_params_t *sparams,
unsigned flags, unsigned flags,
const char *user, const char *user,
unsigned ulen) unsigned ulen)
{ {
char *userid = NULL; char *userid = NULL;
char *realm = NULL; char *realm = NULL;
const char *user_realm = NULL; const char *user_realm = NULL;
int ret; int ret;
const struct propval *to_fetch, *cur; const struct propval *to_fetch, *cur;
char value[8192]; char value[8192];
size_t value_len; size_t value_len;
char *user_buf; char *user_buf;
int verify_against_hashed_password;
int saw_user_password = 0;
if(!sparams || !user) return; if (!sparams || !user) return SASL_BADPARAM;
user_buf = sparams->utils->malloc(ulen + 1); user_buf = sparams->utils->malloc(ulen + 1);
if(!user_buf) { if(!user_buf) {
ret = SASL_NOMEM;
goto done; goto done;
} }
memcpy(user_buf, user, ulen); memcpy(user_buf, user, ulen);
user_buf[ulen] = '\0'; user_buf[ulen] = '\0';
if(sparams->user_realm) { if(sparams->user_realm) {
user_realm = sparams->user_realm; user_realm = sparams->user_realm;
} else { } else {
user_realm = sparams->serverFQDN; user_realm = sparams->serverFQDN;
} }
ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm, ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm,
sparams->serverFQDN, user_buf); sparams->serverFQDN, user_buf);
if(ret != SASL_OK) goto done; if(ret != SASL_OK) goto done;
to_fetch = sparams->utils->prop_get(sparams->propctx); to_fetch = sparams->utils->prop_get(sparams->propctx);
if(!to_fetch) goto done; if (!to_fetch) {
ret = SASL_NOMEM;
goto done;
}
verify_against_hashed_password = flags & SASL_AUXPROP_VERIFY_AGAINST_HA
SH;
/* Use a fake value to signal that we have no property to lookup */
ret = SASL_CONTINUE;
for(cur = to_fetch; cur->name; cur++) { for(cur = to_fetch; cur->name; cur++) {
int cur_ret;
const char *realname = cur->name; const char *realname = cur->name;
/* Only look up properties that apply to this lookup! */ /* Only look up properties that apply to this lookup! */
if(cur->name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID)) continue; if(cur->name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID)) continue;
if(!(flags & SASL_AUXPROP_AUTHZID)) { if(!(flags & SASL_AUXPROP_AUTHZID)) {
if(cur->name[0] != '*') continue; if(cur->name[0] != '*') continue;
else realname = cur->name + 1; else realname = cur->name + 1;
} }
/* If it's there already, we want to see if it needs to be /* If it's there already, we want to see if it needs to be
* overridden */ * overridden. userPassword is a special case, because it's value
if(cur->values && !(flags & SASL_AUXPROP_OVERRIDE)) is always present if SASL_AUXPROP_VERIFY_AGAINST_HASH is specifie
d.
When SASL_AUXPROP_VERIFY_AGAINST_HASH is set, we just clear userP
assword. */
if (cur->values && !(flags & SASL_AUXPROP_OVERRIDE) &&
(verify_against_hashed_password == 0 ||
strcasecmp(realname, SASL_AUX_PASSWORD_PROP) != 0)) {
continue; continue;
else if(cur->values) } else if (cur->values) {
sparams->utils->prop_erase(sparams->propctx, cur->name); sparams->utils->prop_erase(sparams->propctx, cur->name);
}
if (strcasecmp(realname, SASL_AUX_PASSWORD_PROP) == 0) {
saw_user_password = 1;
}
ret = _sasldb_getdata(sparams->utils, cur_ret = _sasldb_getdata(sparams->utils,
sparams->utils->conn, userid, realm, sparams->utils->conn, userid, realm,
realname, value, sizeof(value), &value_len); realname, value, sizeof(value), &value_len);
if(ret != SASL_OK) {
/* Assumption: cur_ret is never SASL_CONTINUE */
/* If this is the first property we've tried to fetch ==>
always set the global error code.
If we had SASL_NOUSER ==> any other error code overrides it
(including SASL_NOUSER). */
if (ret == SASL_CONTINUE || ret == SASL_NOUSER) {
ret = cur_ret;
} else if (ret == SASL_OK) {
/* Any error code other than SASL_NOUSER overrides SASL_OK.
(And SASL_OK overrides SASL_OK as well) */
if (cur_ret != SASL_NOUSER) {
ret = cur_ret;
}
}
/* Any other global error code is left as is */
if (cur_ret != SASL_OK) {
if (cur_ret != SASL_NOUSER) {
/* No point in continuing if we hit any serious error */
break;
}
/* We didn't find it, leave it as not found */ /* We didn't find it, leave it as not found */
continue; continue;
} }
sparams->utils->prop_set(sparams->propctx, cur->name, sparams->utils->prop_set(sparams->propctx, cur->name,
value, (unsigned) value_len); value, (unsigned) value_len);
} }
/* [Keep in sync with LDAPDB, SQL]
If ret is SASL_CONTINUE, it means that no properties were requested
(or maybe some were requested, but they already have values and
SASL_AUXPROP_OVERRIDE flag is not set).
Always return SASL_OK in this case. */
if (ret == SASL_CONTINUE) {
ret = SASL_OK;
}
if (flags & SASL_AUXPROP_AUTHZID) {
/* This is a lie, but the caller can't handle
when we return SASL_NOUSER for authorization identity lookup. */
if (ret == SASL_NOUSER) {
ret = SASL_OK;
}
} else {
if (ret == SASL_NOUSER && saw_user_password == 0) {
/* Verify user existence by checking presence of
the userPassword attribute */
ret = _sasldb_getdata(sparams->utils,
sparams->utils->conn,
userid,
realm,
SASL_AUX_PASSWORD_PROP,
value,
sizeof(value),
&value_len);
}
}
done: done:
if (userid) sparams->utils->free(userid); if (userid) sparams->utils->free(userid);
if (realm) sparams->utils->free(realm); if (realm) sparams->utils->free(realm);
if (user_buf) sparams->utils->free(user_buf); if (user_buf) sparams->utils->free(user_buf);
return ret;
} }
static int sasldb_auxprop_store(void *glob_context __attribute__((unused)), static int sasldb_auxprop_store(void *glob_context __attribute__((unused)),
sasl_server_params_t *sparams, sasl_server_params_t *sparams,
struct propctx *ctx, struct propctx *ctx,
const char *user, const char *user,
unsigned ulen) unsigned ulen)
{ {
char *userid = NULL; char *userid = NULL;
char *realm = NULL; char *realm = NULL;
const char *user_realm = NULL; const char *user_realm = NULL;
int ret = SASL_FAIL; int ret = SASL_FAIL;
int tmp_res;
const struct propval *to_store, *cur; const struct propval *to_store, *cur;
char *user_buf; char *user_buf;
/* just checking if we are enabled */ /* just checking if we are enabled */
if(!ctx) return SASL_OK; if(!ctx) return SASL_OK;
if(!sparams || !user) return SASL_BADPARAM; if(!sparams || !user) return SASL_BADPARAM;
user_buf = sparams->utils->malloc(ulen + 1); user_buf = sparams->utils->malloc(ulen + 1);
if(!user_buf) { if(!user_buf) {
skipping to change at line 176 skipping to change at line 249
ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm, ret = _plug_parseuser(sparams->utils, &userid, &realm, user_realm,
sparams->serverFQDN, user_buf); sparams->serverFQDN, user_buf);
if(ret != SASL_OK) goto done; if(ret != SASL_OK) goto done;
to_store = sparams->utils->prop_get(ctx); to_store = sparams->utils->prop_get(ctx);
if(!to_store) { if(!to_store) {
ret = SASL_BADPARAM; ret = SASL_BADPARAM;
goto done; goto done;
} }
/* All iterations return SASL_NOUSER ==> ret = SASL_N ret = SASL_OK;
OUSER for (cur = to_store; cur->name; cur++) {
Some iterations return SASL_OK and some SASL_NOUSER ==> ret = SASL_O char * value = (cur->values && cur->values[0]) ? cur->values[0] : NU
K LL;
At least one iteration returns any other error ==> ret = the er
ror */ if (cur->name[0] == '*') {
ret = SASL_NOUSER; continue;
for(cur = to_store; cur->name; cur++) { }
/* We only support one value at a time right now. */
tmp_res = _sasldb_putdata(sparams->utils, sparams->utils->conn, /* WARN: We only support one value right now. */
userid, realm, cur->name, ret = _sasldb_putdata(sparams->utils,
cur->values && cur->values[0] ? sparams->utils->conn,
cur->values[0] : NULL, userid,
cur->values && cur->values[0] ? realm,
strlen(cur->values[0]) : 0); cur->name,
/* SASL_NOUSER is returned when _sasldb_putdata fails to delete value,
a non-existent entry, which should not be treated as an error */ value ? strlen(value) : 0);
if ((tmp_res != SASL_NOUSER) &&
(ret == SASL_NOUSER || ret == SASL_OK)) { if (value == NULL && ret == SASL_NOUSER) {
ret = tmp_res; /* Deleting something which is not there is not an error */
} ret = SASL_OK;
}
/* Abort the loop if an error has occurred */
if (ret != SASL_NOUSER && ret != SASL_OK) { if (ret != SASL_OK) {
break; /* We've already failed, no point in continuing */
} break;
}
} }
done: done:
if (userid) sparams->utils->free(userid); if (userid) sparams->utils->free(userid);
if (realm) sparams->utils->free(realm); if (realm) sparams->utils->free(realm);
if (user_buf) sparams->utils->free(user_buf); if (user_buf) sparams->utils->free(user_buf);
return ret; return ret;
} }
skipping to change at line 233 skipping to change at line 309
const char *plugname __attribute__((unused))) const char *plugname __attribute__((unused)))
{ {
if(!out_version || !plug) return SASL_BADPARAM; if(!out_version || !plug) return SASL_BADPARAM;
/* Do we have database support? */ /* Do we have database support? */
/* Note that we can use a NULL sasl_conn_t because our /* Note that we can use a NULL sasl_conn_t because our
* sasl_utils_t is "blessed" with the global callbacks */ * sasl_utils_t is "blessed" with the global callbacks */
if(_sasl_check_db(utils, NULL) != SASL_OK) if(_sasl_check_db(utils, NULL) != SASL_OK)
return SASL_NOMECH; return SASL_NOMECH;
/* Check if libsasl API is older than ours. If it is, fail */
if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS; if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS;
*out_version = SASL_AUXPROP_PLUG_VERSION; *out_version = SASL_AUXPROP_PLUG_VERSION;
*plug = &sasldb_auxprop_plugin; *plug = &sasldb_auxprop_plugin;
return SASL_OK; return SASL_OK;
} }
 End of changes. 18 change blocks. 
36 lines changed or deleted 114 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/