return LDB_SUCCESS;
}
- /* We might not have an old NT password */
+ /* We might not have an old LM password */
io->g.lm_history = talloc_array(io->ac,
struct samr_Password,
io->ac->status->domain_data.pwdHistoryLength);
}
/* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
- ndr_err = ndr_pull_struct_blob(&blob, io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), &_old_pkb,
+ ndr_err = ndr_pull_struct_blob(&blob, io->ac, &_old_pkb,
(ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
/* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
ndr_err = ndr_pull_struct_blob(&blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&_old_pkb,
(ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
/* if there's an old supplementaCredentials blob then parse it */
if (io->o.supplemental) {
ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&_old_scb,
(ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
}
ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&pknb,
(ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
}
ndr_err = ndr_push_struct_blob(&pkb_blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&pkb,
(ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
}
ndr_err = ndr_push_struct_blob(&pdb_blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&pdb,
(ndr_push_flags_fn_t)ndr_push_package_PrimaryWDigestBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
pcb.cleartext = *io->n.cleartext_utf16;
ndr_err = ndr_push_struct_blob(&pcb_blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&pcb,
(ndr_push_flags_fn_t)ndr_push_package_PrimaryCLEARTEXTBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
*/
pb.names = names;
ndr_err = ndr_push_struct_blob(&pb_blob, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&pb,
(ndr_push_flags_fn_t)ndr_push_package_PackagesBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
scb.sub.packages = packages;
ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
&scb,
(ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- if (!convert_string_talloc_convenience(io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ if (!convert_string_talloc(io->ac,
CH_UTF8, CH_UTF16,
g->cleartext_utf8->data,
g->cleartext_utf8->length,
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- if (!convert_string_talloc_convenience(io->ac,
- lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ if (!convert_string_talloc(io->ac,
CH_UTF16MUNGED, CH_UTF8,
g->cleartext_utf16->data,
g->cleartext_utf16->length,
g->cleartext_utf16->length);
}
- if (g->cleartext_utf8 &&
- lp_lanman_auth(ldb_get_opaque(ldb, "loadparm"))) {
+ if (g->cleartext_utf8) {
struct samr_Password *lm_hash;
lm_hash = talloc(io->ac, struct samr_Password);
static int setup_password_fields(struct setup_password_fields_io *io)
{
- struct ldb_context *ldb;
+ struct ldb_context *ldb = ldb_module_get_ctx(io->ac->module);
+ struct loadparm_context *lp_ctx =
+ lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
+ struct loadparm_context);
int ret;
- ldb = ldb_module_get_ctx(io->ac->module);
-
/* transform the old password (for password changes) */
ret = setup_given_passwords(io, &io->og);
if (ret != LDB_SUCCESS) {
return ret;
}
- ret = setup_lm_fields(io);
- if (ret != LDB_SUCCESS) {
- return ret;
+ if (lp_lanman_auth(lp_ctx)) {
+ ret = setup_lm_fields(io);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ } else {
+ io->g.lm_hash = NULL;
+ io->g.lm_history_len = 0;
}
ret = setup_supplemental_field(io);
return LDB_ERR_UNWILLING_TO_PERFORM;
}
} else if (io->og.lm_hash) {
- struct loadparm_context *lp_ctx =
- (struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
-
- if (!lp_lanman_auth(lp_ctx)) {
- ldb_asprintf_errstring(ldb,
- "check_password_restrictions: "
- "The password change through the LM hash is deactivated!");
- return LDB_ERR_UNWILLING_TO_PERFORM;
- }
-
if (!io->o.lm_hash) {
ldb_asprintf_errstring(ldb,
"check_password_restrictions: "
}
/*
- * Fundamental password checks done by the call "samdb_check_password".
+ * Fundamental password checks done by the call
+ * "samdb_check_password".
* It is also in use by "dcesrv_samr_ValidatePassword".
*/
- stat = samdb_check_password(io->n.cleartext_utf8,
- io->ac->status->domain_data.pwdProperties,
- io->ac->status->domain_data.minPwdLength);
- switch (stat) {
- case SAMR_VALIDATION_STATUS_SUCCESS:
- /* perfect -> proceed! */
- break;
+ if (io->n.cleartext_utf8 != NULL) {
+ stat = samdb_check_password(io->n.cleartext_utf8,
+ io->ac->status->domain_data.pwdProperties,
+ io->ac->status->domain_data.minPwdLength);
+ switch (stat) {
+ case SAMR_VALIDATION_STATUS_SUCCESS:
+ /* perfect -> proceed! */
+ break;
- case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
- ldb_asprintf_errstring(ldb,
- "check_password_restrictions: "
- "the password is too short. It should be equal or longer than %i characters!",
- io->ac->status->domain_data.minPwdLength);
+ case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
+ ldb_asprintf_errstring(ldb,
+ "check_password_restrictions: "
+ "the password is too short. It should be equal or longer than %i characters!",
+ io->ac->status->domain_data.minPwdLength);
- io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ io->ac->status->reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
+ return LDB_ERR_CONSTRAINT_VIOLATION;
- case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
- ldb_asprintf_errstring(ldb,
- "check_password_restrictions: "
- "the password does not meet the complexity criterias!");
- io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
+ case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
+ ldb_asprintf_errstring(ldb,
+ "check_password_restrictions: "
+ "the password does not meet the complexity criterias!");
+ io->ac->status->reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ return LDB_ERR_CONSTRAINT_VIOLATION;
- default:
- ldb_asprintf_errstring(ldb,
- "check_password_restrictions: "
- "the password doesn't fit by a certain reason!");
+ default:
+ ldb_asprintf_errstring(ldb,
+ "check_password_restrictions: "
+ "the password doesn't fit by a certain reason!");
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
}
if (io->ac->pwd_reset) {
{
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);
int ret;
ZERO_STRUCTP(io);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- /* FIXME: fix to don't break provision */
- io->ac->hash_values = true;
-
/* 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
io->n.cleartext_utf16 = quoted_utf16_2;
io->n.nt_hash = NULL;
- } else {
+ } else if (quoted_utf16) {
/* We have only the hash available -> so no plaintext here */
if (!ac->hash_values) {
/* refuse the change if someone wants to change
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- if (quoted_utf16 != NULL) {
- io->n.nt_hash = talloc(io->ac, struct samr_Password);
- memcpy(io->n.nt_hash->hash, quoted_utf16->data,
- MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
- }
+ io->n.nt_hash = talloc(io->ac, struct samr_Password);
+ memcpy(io->n.nt_hash->hash, quoted_utf16->data,
+ MIN(quoted_utf16->length, sizeof(io->n.nt_hash->hash)));
}
/* Checks and converts the previous "unicodePwd" attribute */
io->og.cleartext_utf16 = old_quoted_utf16_2;
io->og.nt_hash = NULL;
- } else {
+ } else if (old_quoted_utf16) {
/* We have only the hash available -> so no plaintext here */
if (!ac->hash_values) {
/* refuse the change if someone wants to change
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (old_quoted_utf16 != NULL) {
- io->og.nt_hash = talloc(io->ac, struct samr_Password);
- memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
- MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
- }
+ io->og.nt_hash = talloc(io->ac, struct samr_Password);
+ memcpy(io->og.nt_hash->hash, old_quoted_utf16->data,
+ MIN(old_quoted_utf16->length, sizeof(io->og.nt_hash->hash)));
}
/* Handles the "dBCSPwd" attribute (LM hash) */
"it's not allowed to set the LM hash password directly'");
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (lm_hash != NULL) {
+
+ if (lp_lanman_auth(lp_ctx) && (lm_hash != NULL)) {
io->n.lm_hash = talloc(io->ac, struct samr_Password);
memcpy(io->n.lm_hash->hash, lm_hash->data, MIN(lm_hash->length,
sizeof(io->n.lm_hash->hash)));
}
-
- if (old_lm_hash != NULL) {
+ if (lp_lanman_auth(lp_ctx) && (old_lm_hash != NULL)) {
io->og.lm_hash = talloc(io->ac, struct samr_Password);
memcpy(io->og.lm_hash->hash, old_lm_hash->data, MIN(old_lm_hash->length,
sizeof(io->og.lm_hash->hash)));
return LDB_ERR_UNWILLING_TO_PERFORM;
}
+ /* refuse the change if someone tries to set/change the password by
+ * the lanman hash alone and we've deactivated that mechanism. This
+ * would end in an account without any password! */
+ if ((!io->n.cleartext_utf8) && (!io->n.cleartext_utf16)
+ && (!io->n.nt_hash) && (!io->n.lm_hash)) {
+ ldb_asprintf_errstring(ldb,
+ "setup_io: "
+ "The password change/set operations performed using the LAN Manager hash alone are deactivated!");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
/* refuse the change if someone wants to compare against a plaintext
or hash at the same time for a "password modify" operation... */
if ((io->og.cleartext_utf8 || io->og.cleartext_utf16)
struct ldb_message_element *userPasswordAttr, *clearTextPasswordAttr,
*ntAttr, *lmAttr;
int ret;
+ struct ldb_control *bypass = NULL;
ldb = ldb_module_get_ctx(module);
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_add (bypassing)\n");
+ return ldb_next_request(module, req);
+ }
+
/* nobody must touch password histories and 'supplementalCredentials' */
if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
return LDB_ERR_UNWILLING_TO_PERFORM;
return LDB_ERR_OPERATIONS_ERROR;
}
- /* remove attributes that we just read into 'io' (handle also superfluous
- * "password modify" trials - multiple attributes with the same name -
- * on add operations) */
- while (ldb_msg_find_element(msg, "userPassword") != NULL) {
- ldb_msg_remove_attr(msg, "userPassword");
- }
- while (ldb_msg_find_element(msg, "clearTextPassword") != NULL) {
- ldb_msg_remove_attr(msg, "clearTextPassword");
- }
- while (ldb_msg_find_element(msg, "unicodePwd") != NULL) {
- ldb_msg_remove_attr(msg, "unicodePwd");
- }
- while (ldb_msg_find_element(msg, "dBCSPwd") != NULL) {
- ldb_msg_remove_attr(msg, "dBCSPwd");
- }
-
+ /* remove attributes that we just read into 'io' */
+ ldb_msg_remove_attr(msg, "userPassword");
+ ldb_msg_remove_attr(msg, "clearTextPassword");
+ ldb_msg_remove_attr(msg, "unicodePwd");
+ ldb_msg_remove_attr(msg, "dBCSPwd");
ldb_msg_remove_attr(msg, "pwdLastSet");
ldb = ldb_module_get_ctx(ac->module);
struct ldb_message *msg;
struct ldb_request *down_req;
int ret;
+ struct ldb_control *bypass = NULL;
ldb = ldb_module_get_ctx(module);
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 ldb_next_request(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;
*l);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- ldb_msg_remove_attr(msg, *l);
+ ldb_msg_remove_element(msg, passwordAttr);
}
}
if ((del_attr_cnt > 0) && (add_attr_cnt == 0)) {
static int password_hash_mod_do_mod(struct ph_context *ac)
{
- struct ldb_context *ldb;
+ 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 ldb_request *mod_req;
struct ldb_message *msg;
const struct ldb_message *orig_msg, *searched_msg;
int ret;
NTSTATUS status;
- ldb = ldb_module_get_ctx(ac->module);
-
/* use a new message structure so that we can modify it */
msg = ldb_msg_new(ac);
if (msg == NULL) {
/* Get the old password from the database */
status = samdb_result_passwords(io.ac,
- ldb_get_opaque(ldb, "loadparm"),
- searched_msg,
+ lp_ctx,
+ discard_const_p(struct ldb_message, searched_msg),
&io.o.lm_hash, &io.o.nt_hash);
if (!NT_STATUS_IS_OK(status)) {
return LDB_ERR_OPERATIONS_ERROR;