krb5_data cleartext_data;
ldb = ldb_module_get_ctx(io->ac->module);
- cleartext_data.data = io->n.cleartext_utf8->data;
+ cleartext_data.data = (char *)io->n.cleartext_utf8->data;
cleartext_data.length = io->n.cleartext_utf8->length;
/* Many, many thanks to lukeh@padl.com for this
static int setup_last_set_field(struct setup_password_fields_io *io)
{
const struct ldb_message *msg = NULL;
+ struct timeval tv = { .tv_sec = 0 };
switch (io->ac->req->operation) {
case LDB_ADD:
}
/* set it as now */
- unix_to_nt_time(&io->g.last_set, time(NULL));
+ GetTimeOfDay(&tv);
+ io->g.last_set = timeval_to_nttime(&tv);
return LDB_SUCCESS;
}
/* checks the LM hash password history */
for (i = 0; i < io->o.lm_history_len; i++) {
- ret = memcmp(io->n.nt_hash, io->o.lm_history[i].hash, 16);
+ ret = memcmp(io->n.lm_hash, io->o.lm_history[i].hash, 16);
if (ret == 0) {
ret = LDB_ERR_CONSTRAINT_VIOLATION;
ldb_asprintf_errstring(ldb,
{
const struct ldb_val *quoted_utf16, *old_quoted_utf16, *lm_hash, *old_lm_hash;
struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
- struct loadparm_context *lp_ctx =
- lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
- struct loadparm_context);
+ struct loadparm_context *lp_ctx = talloc_get_type(
+ ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
int ret;
ZERO_STRUCTP(io);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
+ if (io->u.userAccountControl & UF_INTERDOMAIN_TRUST_ACCOUNT) {
+ struct ldb_control *permit_trust = ldb_request_get_control(ac->req,
+ DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID);
+
+ if (permit_trust == NULL) {
+ ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
+ ldb_asprintf_errstring(ldb,
+ "%08X: %s - setup_io: changing the interdomain trust password "
+ "on %s not allowed via LDAP. Use LSA or NETLOGON",
+ W_ERROR_V(WERR_ACCESS_DENIED),
+ ldb_strerror(ret),
+ ldb_dn_get_linearized(searched_msg->dn));
+ return ret;
+ }
+ }
+
/* Only non-trust accounts have restrictions (possibly this test is the
* wrong way around, but we like to be restrictive if possible */
io->u.restrictions = !(io->u.userAccountControl
return ret;
}
-static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
+static int password_hash_needed(struct ldb_module *module,
+ struct ldb_request *req,
+ struct ph_context **_ac)
{
- struct ldb_context *ldb;
- struct ph_context *ac;
- struct ldb_message_element *userPasswordAttr, *clearTextPasswordAttr,
- *ntAttr, *lmAttr;
- int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ const char *operation = NULL;
+ const struct ldb_message *msg = NULL;
+ struct ph_context *ac = NULL;
+ const char *passwordAttrs[] = {
+ "userPassword",
+ "clearTextPassword",
+ "unicodePwd",
+ "dBCSPwd",
+ NULL
+ };
+ const char **a = NULL;
+ unsigned int attr_cnt = 0;
struct ldb_control *bypass = NULL;
bool userPassword = dsdb_user_password_support(module, req, req);
- ldb = ldb_module_get_ctx(module);
+ *_ac = NULL;
- ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_needed\n");
+
+ switch (req->operation) {
+ case LDB_ADD:
+ operation = "add";
+ msg = req->op.add.message;
+ break;
+ case LDB_MODIFY:
+ operation = "modify";
+ msg = req->op.mod.message;
+ break;
+ default:
+ return ldb_next_request(module, req);
+ }
- if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
+ if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
return ldb_next_request(module, req);
}
if (bypass != NULL) {
/* Mark the "bypass" control as uncritical (done) */
bypass->critical = false;
- ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add (bypassing)\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE,
+ "password_hash_needed(%s) (bypassing)\n",
+ operation);
return password_hash_bypass(module, req);
}
/* nobody must touch password histories and 'supplementalCredentials' */
- if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
+ if (ldb_msg_find_element(msg, "ntPwdHistory")) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {
+ if (ldb_msg_find_element(msg, "lmPwdHistory")) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {
+ if (ldb_msg_find_element(msg, "supplementalCredentials")) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
- * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes. */
+ /*
+ * If no part of this touches the 'userPassword' OR 'clearTextPassword'
+ * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
+ * For password changes/set there should be a 'delete' or a 'modify'
+ * on these attributes.
+ */
+ for (a = passwordAttrs; *a != NULL; a++) {
+ if ((!userPassword) && (ldb_attr_cmp(*a, "userPassword") == 0)) {
+ continue;
+ }
- userPasswordAttr = NULL;
- if (userPassword) {
- userPasswordAttr = ldb_msg_find_element(req->op.add.message,
- "userPassword");
- /* MS-ADTS 3.1.1.3.1.5.2 */
- if ((userPasswordAttr != NULL) &&
- (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ if (ldb_msg_find_element(msg, *a) != NULL) {
+ /* MS-ADTS 3.1.1.3.1.5.2 */
+ if ((ldb_attr_cmp(*a, "userPassword") == 0) &&
+ (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
+ ++attr_cnt;
}
}
- clearTextPasswordAttr = ldb_msg_find_element(req->op.add.message, "clearTextPassword");
- ntAttr = ldb_msg_find_element(req->op.add.message, "unicodePwd");
- lmAttr = ldb_msg_find_element(req->op.add.message, "dBCSPwd");
- if ((!userPasswordAttr) && (!clearTextPasswordAttr) && (!ntAttr) && (!lmAttr)) {
+ if (attr_cnt == 0) {
return ldb_next_request(module, req);
}
+ ac = ph_init_context(module, req, userPassword);
+ if (!ac) {
+ DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
+ return ldb_operr(ldb);
+ }
+ ph_apply_controls(ac);
+
+ *_ac = ac;
+ return LDB_SUCCESS;
+}
+
+static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct ph_context *ac = NULL;
+ int ret;
+
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_add\n");
+
+ ret = password_hash_needed(module, req, &ac);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (ac == NULL) {
+ return ret;
+ }
+
/* Make sure we are performing the password set action on a (for us)
* valid object. Those are instances of either "user" and/or
* "inetOrgPerson". Otherwise continue with the submodules. */
if ((!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "user"))
&& (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "inetOrgPerson"))) {
+ TALLOC_FREE(ac);
+
if (ldb_msg_find_element(req->op.add.message, "clearTextPassword") != NULL) {
ldb_set_errstring(ldb,
"'clearTextPassword' is only allowed on objects of class 'user' and/or 'inetOrgPerson'!");
return ldb_next_request(module, req);
}
- ac = ph_init_context(module, req, userPassword);
- if (ac == NULL) {
- DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
- return ldb_operr(ldb);
- }
- ph_apply_controls(ac);
-
/* get user domain data */
ret = build_domain_data_request(ac);
if (ret != LDB_SUCCESS) {
static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_context *ldb;
- struct ph_context *ac;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct ph_context *ac = NULL;
const char *passwordAttrs[] = { "userPassword", "clearTextPassword",
"unicodePwd", "dBCSPwd", NULL }, **l;
- unsigned int attr_cnt, del_attr_cnt, add_attr_cnt, rep_attr_cnt;
+ unsigned int del_attr_cnt, add_attr_cnt, rep_attr_cnt;
struct ldb_message_element *passwordAttr;
struct ldb_message *msg;
struct ldb_request *down_req;
int ret;
- struct ldb_control *bypass = NULL;
- bool userPassword = dsdb_user_password_support(module, req, req);
-
- ldb = ldb_module_get_ctx(module);
ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
- if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
- return ldb_next_request(module, req);
- }
-
- bypass = ldb_request_get_control(req,
- DSDB_CONTROL_BYPASS_PASSWORD_HASH_OID);
- if (bypass != NULL) {
- /* Mark the "bypass" control as uncritical (done) */
- bypass->critical = false;
- ldb_debug(ldb, LDB_DEBUG_TRACE, "password_hash_modify (bypassing)\n");
- return password_hash_bypass(module, req);
- }
-
- /* nobody must touch password histories and 'supplementalCredentials' */
- if (ldb_msg_find_element(req->op.mod.message, "ntPwdHistory")) {
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
- if (ldb_msg_find_element(req->op.mod.message, "lmPwdHistory")) {
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
- if (ldb_msg_find_element(req->op.mod.message, "supplementalCredentials")) {
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
-
- /* If no part of this touches the 'userPassword' OR 'clearTextPassword'
- * OR 'unicodePwd' OR 'dBCSPwd' we don't need to make any changes.
- * For password changes/set there should be a 'delete' or a 'modify'
- * on these attributes. */
- attr_cnt = 0;
- for (l = passwordAttrs; *l != NULL; l++) {
- if ((!userPassword) && (ldb_attr_cmp(*l, "userPassword") == 0)) {
- continue;
- }
-
- if (ldb_msg_find_element(req->op.mod.message, *l) != NULL) {
- /* MS-ADTS 3.1.1.3.1.5.2 */
- if ((ldb_attr_cmp(*l, "userPassword") == 0) &&
- (dsdb_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- ++attr_cnt;
- }
- }
- if (attr_cnt == 0) {
- return ldb_next_request(module, req);
+ ret = password_hash_needed(module, req, &ac);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
-
- ac = ph_init_context(module, req, userPassword);
- if (!ac) {
- DEBUG(0,(__location__ ": %s\n", ldb_errstring(ldb)));
- return ldb_operr(ldb);
+ if (ac == NULL) {
+ return ret;
}
- ph_apply_controls(ac);
/* use a new message structure so that we can modify it */
msg = ldb_msg_copy_shallow(ac, req->op.mod.message);