#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <lutil.h>
#include "slap.h"
#include "back-netinfo.h"
int netinfo_back_exop_passwd(
struct slap_op *op,
struct slap_rep *rs)
{
struct dsinfo *di = (struct dsinfo *)op->o_bd->be_private;
char *hashMechanism;
struct berval *ndn, hash = { 0, NULL };
struct berval new = { 0, NULL };
struct berval ndn_buf = { 0, NULL };
struct berval id = { 0, NULL };
dsdata *value = NULL;
dsrecord *user = NULL;
dsattribute *passwd = NULL;
dsstatus status;
u_int32_t dsid;
struct atmap map;
int rc;
assert(op->ore_reqoid.bv_val != NULL);
assert(strcmp(LDAP_EXOP_MODIFY_PASSWD, op->ore_reqoid.bv_val) == 0);
rc = slap_passwd_parse(op->ore_reqdata, &id, NULL, &new, &rs->sr_text);
if (rc != LDAP_SUCCESS)
return rc;
#ifdef NEW_LOGGING
LDAP_LOG(("backend", LDAP_LEVEL_ARGS, "netinfo_back_exop_passwd: \"%s\"\n",
(id.bv_val != NULL) ? id.bv_val : "(null)"));
#else
Debug(LDAP_DEBUG_ARGS, "==> netinfo_back_exop_passwd: \"%s\"\n",
id.bv_val ? id.bv_val : "(null)", 0, 0);
#endif
rs->sr_text = NULL;
if (new.bv_len == 0)
{
slap_passwd_generate(&new);
if (new.bv_val == NULL || new.bv_len == 0)
{
rs->sr_text = "Password generation failed";
return LDAP_OTHER;
}
rs->sr_rspdata = slap_passwd_return(&new);
}
if (id.bv_val != NULL)
{
ndn = &ndn_buf;
dnNormalize(0, NULL, NULL, &id, &ndn_buf, NULL);
}
else
{
ndn = &op->o_ndn;
}
if (ndn->bv_len == 0)
{
if (ndn_buf.bv_val != NULL)
ch_free(ndn_buf.bv_val);
rs->sr_text = "No password is associated with the Root DSE";
return LDAP_OPERATIONS_ERROR;
}
ENGINE_LOCK(di);
status = netinfo_back_dn_pathmatch(op->o_bd, ndn, &dsid);
if (status != DSStatusOK)
{
goto out;
}
status = dsengine_fetch(di->engine, dsid, &user);
dsengine_flush_cache(di->engine);
if (status != DSStatusOK)
{
goto out;
}
status = schemamap_x500_to_ni_at(op->o_bd, SUPER(user),
slap_schema.si_ad_userPassword, &map);
if (status != DSStatusOK)
{
goto out;
}
if (map.x500ToNiTransform == removeCaseIgnorePrefixTransform &&
map.x500ToNiArg != NULL)
{
hashMechanism = ((struct berval *)map.x500ToNiArg)->bv_val;
}
else
{
#ifdef LUTIL_SHA1_BYTES
hashMechanism = (default_passwd_hash != NULL && *default_passwd_hash != NULL) ? *default_passwd_hash : "{SSHA}";
#else
hashMechanism = (default_passwd_hash != NULL && *default_passwd_hash != NULL) ? *default_passwd_hash : "{SMD5}";
#endif
}
#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
ldap_pvt_thread_mutex_lock(&passwd_mutex);
#endif
status = lutil_passwd_hash(&new, hashMechanism, &hash, &rs->sr_text);
#if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
ldap_pvt_thread_mutex_unlock(&passwd_mutex);
#endif
if (hash.bv_len == 0)
{
status = DSStatusFailed;
goto out;
}
status = netinfo_back_access_allowed(op, dsid,
slap_schema.si_ad_userPassword, NULL, ACL_WRITE);
if (status != DSStatusOK)
{
goto out;
}
dsrecord_remove_key(user, map.ni_key, map.selector);
passwd = dsattribute_new(map.ni_key);
if (passwd == NULL)
{
status = DSStatusFailed;
goto out;
}
status = (map.x500ToNiTransform)(op->o_bd, &value, &hash, map.type, map.x500ToNiArg);
if (status != DSStatusOK)
{
goto out;
}
dsattribute_insert(passwd, value, 0);
dsrecord_append_attribute(user, passwd, map.selector);
status = dsengine_save_attribute(di->engine, user, passwd, map.selector);
out:
ENGINE_UNLOCK(di);
if (ndn_buf.bv_val != NULL)
ch_free(ndn_buf.bv_val);
if (hash.bv_val != NULL)
ch_free(hash.bv_val);
if (user != NULL)
dsrecord_release(user);
if (passwd != NULL)
dsattribute_release(passwd);
schemamap_atmap_release(&map);
if (value != NULL)
dsdata_release(value);
rs->sr_text = dsstatus_message(status);
return dsstatus_to_ldap_err(status);
}