diff options
-rw-r--r-- | source4/dsdb/samdb/samdb.c | 317 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.h | 1 | ||||
-rw-r--r-- | source4/rpc_server/samr/samr_password.c | 309 |
3 files changed, 318 insertions, 309 deletions
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index 0f6e57c9cf..35de578f38 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -27,6 +27,9 @@ #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" #include "libcli/security/proto.h" +#include "auth/credentials/credentials.h" +#include "libcli/auth/proto.h" +#include "libcli/ldap/ldap.h" #include "system/time.h" #include "system/filesys.h" #include "db_wrap.h" @@ -1036,3 +1039,317 @@ failed: talloc_free(tmp_ctx); return NULL; } + +/* + check that a password is sufficiently complex +*/ +static BOOL samdb_password_complexity_ok(const char *pass) +{ + return check_password_quality(pass); +} + + + +/* + set the user password using plaintext, obeying any user or domain + password restrictions + + note that this function doesn't actually store the result in the + database, it just fills in the "mod" structure with ldb modify + elements to setup the correct change when samdb_replace() is + called. This allows the caller to combine the change with other + changes (as is needed by some of the set user info levels) + + The caller should probably have a transaction wrapping this +*/ +_PUBLIC_ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, + const struct ldb_dn *user_dn, + const struct ldb_dn *domain_dn, + struct ldb_message *mod, + const char *new_pass, + struct samr_Password *lmNewHash, + struct samr_Password *ntNewHash, + BOOL user_change, + BOOL restrictions, + enum samr_RejectReason *reject_reason, + struct samr_DomInfo1 **_dominfo) +{ + const char * const user_attrs[] = { "userAccountControl", "sambaLMPwdHistory", + "sambaNTPwdHistory", + "lmPwdHash", "ntPwdHash", + "objectSid", + "pwdLastSet", NULL }; + const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength", + "maxPwdAge", "minPwdAge", + "minPwdLength", NULL }; + NTTIME pwdLastSet; + int64_t minPwdAge; + uint_t minPwdLength, pwdProperties, pwdHistoryLength; + uint_t userAccountControl; + struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory, *lmPwdHash, *ntPwdHash; + struct samr_Password local_lmNewHash, local_ntNewHash; + int sambaLMPwdHistory_len, sambaNTPwdHistory_len; + struct dom_sid *domain_sid; + struct ldb_message **res; + int count; + time_t now = time(NULL); + NTTIME now_nt; + int i; + + /* we need to know the time to compute password age */ + unix_to_nt_time(&now_nt, now); + + /* pull all the user parameters */ + count = gendb_search_dn(ctx, mem_ctx, user_dn, &res, user_attrs); + if (count != 1) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0); + sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0], + "sambaLMPwdHistory", &sambaLMPwdHistory); + sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0], + "sambaNTPwdHistory", &sambaNTPwdHistory); + lmPwdHash = samdb_result_hash(mem_ctx, res[0], "lmPwdHash"); + ntPwdHash = samdb_result_hash(mem_ctx, res[0], "ntPwdHash"); + pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0); + + if (domain_dn) { + /* pull the domain parameters */ + count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs); + if (count != 1) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + } else { + /* work out the domain sid, and pull the domain from there */ + domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid"); + if (domain_sid == NULL) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs, + "(objectSid=%s)", + ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); + if (count != 1) { + return NT_STATUS_NO_SUCH_DOMAIN; + } + } + + pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0); + pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0); + minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0); + minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0); + + if (_dominfo) { + struct samr_DomInfo1 *dominfo; + /* on failure we need to fill in the reject reasons */ + dominfo = talloc(mem_ctx, struct samr_DomInfo1); + if (dominfo == NULL) { + return NT_STATUS_NO_MEMORY; + } + dominfo->min_password_length = minPwdLength; + dominfo->password_properties = pwdProperties; + dominfo->password_history_length = pwdHistoryLength; + dominfo->max_password_age = minPwdAge; + dominfo->min_password_age = minPwdAge; + *_dominfo = dominfo; + } + + if (new_pass) { + /* check the various password restrictions */ + if (restrictions && minPwdLength > strlen_m(new_pass)) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_TOO_SHORT; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + + /* possibly check password complexity */ + if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX && + !samdb_password_complexity_ok(new_pass)) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + + /* compute the new nt and lm hashes */ + if (E_deshash(new_pass, local_lmNewHash.hash)) { + lmNewHash = &local_lmNewHash; + } + E_md4hash(new_pass, local_ntNewHash.hash); + ntNewHash = &local_ntNewHash; + } + + if (restrictions && user_change) { + /* are all password changes disallowed? */ + if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_OTHER; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + + /* can this user change password? */ + if (userAccountControl & UF_PASSWD_CANT_CHANGE) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_OTHER; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + + /* yes, this is a minus. The ages are in negative 100nsec units! */ + if (pwdLastSet - minPwdAge > now_nt) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_OTHER; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + + /* check the immediately past password */ + if (pwdHistoryLength > 0) { + if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + + /* check the password history */ + sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len, pwdHistoryLength); + sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len, pwdHistoryLength); + + for (i=0; lmNewHash && i<sambaLMPwdHistory_len;i++) { + if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash, 16) == 0) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + for (i=0; ntNewHash && i<sambaNTPwdHistory_len;i++) { + if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash, 16) == 0) { + if (reject_reason) { + *reject_reason = SAMR_REJECT_COMPLEXITY; + } + return NT_STATUS_PASSWORD_RESTRICTION; + } + } + } + +#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0) + + /* the password is acceptable. Start forming the new fields */ + if (new_pass) { + /* if we know the cleartext, then only set it. + * Modules in ldb will set all the appropriate + * hashes */ + CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod, + "sambaPassword", new_pass)); + } else { + /* We don't have the cleartext, so delete the old one + * and set what we have of the hashes */ + CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "sambaPassword")); + + if (lmNewHash) { + CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "lmPwdHash", lmNewHash)); + } else { + CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "lmPwdHash")); + } + + if (ntNewHash) { + CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "ntPwdHash", ntNewHash)); + } else { + CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "ntPwdHash")); + } + } + + return NT_STATUS_OK; +} + + +/* + set the user password using plaintext, obeying any user or domain + password restrictions + + This wrapper function takes a SID as input, rather than a user DN, + and actually performs the password change + +*/ +_PUBLIC_ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + const char *new_pass, + struct samr_Password *lmNewHash, + struct samr_Password *ntNewHash, + BOOL user_change, + BOOL restrictions, + enum samr_RejectReason *reject_reason, + struct samr_DomInfo1 **_dominfo) +{ + NTSTATUS nt_status; + struct ldb_dn *user_dn; + struct ldb_message *msg; + int ret; + + ret = ldb_transaction_start(ctx); + if (ret) { + DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx))); + return NT_STATUS_TRANSACTION_ABORTED; + } + + user_dn = samdb_search_dn(ctx, mem_ctx, NULL, + "(&(objectSid=%s)(objectClass=user))", + ldap_encode_ndr_dom_sid(mem_ctx, user_sid)); + if (!user_dn) { + ldb_transaction_cancel(ctx); + DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n", + dom_sid_string(mem_ctx, user_sid))); + return NT_STATUS_NO_SUCH_USER; + } + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + ldb_transaction_cancel(ctx); + return NT_STATUS_NO_MEMORY; + } + + msg->dn = ldb_dn_copy(msg, user_dn); + if (!msg->dn) { + ldb_transaction_cancel(ctx); + return NT_STATUS_NO_MEMORY; + } + + nt_status = samdb_set_password(ctx, mem_ctx, + user_dn, NULL, + msg, new_pass, + lmNewHash, ntNewHash, + user_change, /* This is a password set, not change */ + restrictions, /* run restriction tests */ + reject_reason, _dominfo); + if (!NT_STATUS_IS_OK(nt_status)) { + ldb_transaction_cancel(ctx); + return nt_status; + } + + /* modify the samdb record */ + ret = samdb_replace(ctx, mem_ctx, msg); + if (ret != 0) { + ldb_transaction_cancel(ctx); + return NT_STATUS_ACCESS_DENIED; + } + + ret = ldb_transaction_commit(ctx); + if (ret != 0) { + DEBUG(0,("Failed to commit transaction to change password on %s: %s\n", + ldb_dn_linearize(mem_ctx, msg->dn), + ldb_errstring(ctx))); + return NT_STATUS_TRANSACTION_ABORTED; + } + return NT_STATUS_OK; +} diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 292307f423..36bff2f7ff 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -28,6 +28,7 @@ struct drsuapi_DsNameInfo1; #include "librpc/gen_ndr/security.h" #include "lib/ldb/include/ldb.h" +#include "librpc/gen_ndr/samr.h" #include "dsdb/samdb/samdb_proto.h" #endif /* __SAMDB_H__ */ diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index 07a2d678fe..1235d0c769 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -505,237 +505,6 @@ NTSTATUS samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX /* - check that a password is sufficiently complex -*/ -static BOOL samdb_password_complexity_ok(const char *pass) -{ - return check_password_quality(pass); -} - -/* - set the user password using plaintext, obeying any user or domain - password restrictions - - note that this function doesn't actually store the result in the - database, it just fills in the "mod" structure with ldb modify - elements to setup the correct change when samdb_replace() is - called. This allows the caller to combine the change with other - changes (as is needed by some of the set user info levels) - - The caller should probably have a transaction wrapping this -*/ -NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, - const struct ldb_dn *user_dn, - const struct ldb_dn *domain_dn, - struct ldb_message *mod, - const char *new_pass, - struct samr_Password *lmNewHash, - struct samr_Password *ntNewHash, - BOOL user_change, - BOOL restrictions, - enum samr_RejectReason *reject_reason, - struct samr_DomInfo1 **_dominfo) -{ - const char * const user_attrs[] = { "userAccountControl", "sambaLMPwdHistory", - "sambaNTPwdHistory", - "lmPwdHash", "ntPwdHash", - "objectSid", - "pwdLastSet", NULL }; - const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength", - "maxPwdAge", "minPwdAge", - "minPwdLength", NULL }; - NTTIME pwdLastSet; - int64_t minPwdAge; - uint_t minPwdLength, pwdProperties, pwdHistoryLength; - uint_t userAccountControl; - struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory, *lmPwdHash, *ntPwdHash; - struct samr_Password local_lmNewHash, local_ntNewHash; - int sambaLMPwdHistory_len, sambaNTPwdHistory_len; - struct dom_sid *domain_sid; - struct ldb_message **res; - int count; - time_t now = time(NULL); - NTTIME now_nt; - int i; - - /* we need to know the time to compute password age */ - unix_to_nt_time(&now_nt, now); - - /* pull all the user parameters */ - count = gendb_search_dn(ctx, mem_ctx, user_dn, &res, user_attrs); - if (count != 1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0); - sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0], - "sambaLMPwdHistory", &sambaLMPwdHistory); - sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0], - "sambaNTPwdHistory", &sambaNTPwdHistory); - lmPwdHash = samdb_result_hash(mem_ctx, res[0], "lmPwdHash"); - ntPwdHash = samdb_result_hash(mem_ctx, res[0], "ntPwdHash"); - pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0); - - if (domain_dn) { - /* pull the domain parameters */ - count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs); - if (count != 1) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - } else { - /* work out the domain sid, and pull the domain from there */ - domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid"); - if (domain_sid == NULL) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs, - "(objectSid=%s)", - ldap_encode_ndr_dom_sid(mem_ctx, domain_sid)); - if (count != 1) { - return NT_STATUS_NO_SUCH_DOMAIN; - } - } - - pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0); - pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0); - minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0); - minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0); - - if (_dominfo) { - struct samr_DomInfo1 *dominfo; - /* on failure we need to fill in the reject reasons */ - dominfo = talloc(mem_ctx, struct samr_DomInfo1); - if (dominfo == NULL) { - return NT_STATUS_NO_MEMORY; - } - dominfo->min_password_length = minPwdLength; - dominfo->password_properties = pwdProperties; - dominfo->password_history_length = pwdHistoryLength; - dominfo->max_password_age = minPwdAge; - dominfo->min_password_age = minPwdAge; - *_dominfo = dominfo; - } - - if (new_pass) { - /* check the various password restrictions */ - if (restrictions && minPwdLength > strlen_m(new_pass)) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_TOO_SHORT; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* possibly check password complexity */ - if (restrictions && pwdProperties & DOMAIN_PASSWORD_COMPLEX && - !samdb_password_complexity_ok(new_pass)) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* compute the new nt and lm hashes */ - if (E_deshash(new_pass, local_lmNewHash.hash)) { - lmNewHash = &local_lmNewHash; - } - E_md4hash(new_pass, local_ntNewHash.hash); - ntNewHash = &local_ntNewHash; - } - - if (restrictions && user_change) { - /* are all password changes disallowed? */ - if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_OTHER; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* can this user change password? */ - if (userAccountControl & UF_PASSWD_CANT_CHANGE) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_OTHER; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* yes, this is a minus. The ages are in negative 100nsec units! */ - if (pwdLastSet - minPwdAge > now_nt) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_OTHER; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - - /* check the immediately past password */ - if (pwdHistoryLength > 0) { - if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - } - - /* check the password history */ - sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len, pwdHistoryLength); - sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len, pwdHistoryLength); - - for (i=0; lmNewHash && i<sambaLMPwdHistory_len;i++) { - if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash, 16) == 0) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - } - for (i=0; ntNewHash && i<sambaNTPwdHistory_len;i++) { - if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash, 16) == 0) { - if (reject_reason) { - *reject_reason = SAMR_REJECT_COMPLEXITY; - } - return NT_STATUS_PASSWORD_RESTRICTION; - } - } - } - -#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0) - - /* the password is acceptable. Start forming the new fields */ - if (new_pass) { - /* if we know the cleartext, then only set it. - * Modules in ldb will set all the appropriate - * hashes */ - CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod, - "sambaPassword", new_pass)); - } else { - /* We don't have the cleartext, so delete the old one - * and set what we have of the hashes */ - CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "sambaPassword")); - - if (lmNewHash) { - CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "lmPwdHash", lmNewHash)); - } else { - CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "lmPwdHash")); - } - - if (ntNewHash) { - CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "ntPwdHash", ntNewHash)); - } else { - CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "ntPwdHash")); - } - } - - return NT_STATUS_OK; -} - -/* set password via a samr_CryptPassword buffer this will in the 'msg' with modify operations that will update the user password when applied @@ -830,82 +599,4 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call, NULL, NULL); } -/* - set the user password using plaintext, obeying any user or domain - password restrictions - - This wrapper function takes a SID as input, rather than a user DN, - and actually performs the password change - -*/ -NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx, - const struct dom_sid *user_sid, - const char *new_pass, - struct samr_Password *lmNewHash, - struct samr_Password *ntNewHash, - BOOL user_change, - BOOL restrictions, - enum samr_RejectReason *reject_reason, - struct samr_DomInfo1 **_dominfo) -{ - NTSTATUS nt_status; - struct ldb_dn *user_dn; - struct ldb_message *msg; - int ret; - ret = ldb_transaction_start(ctx); - if (ret) { - DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx))); - return NT_STATUS_TRANSACTION_ABORTED; - } - - user_dn = samdb_search_dn(ctx, mem_ctx, NULL, - "(&(objectSid=%s)(objectClass=user))", - ldap_encode_ndr_dom_sid(mem_ctx, user_sid)); - if (!user_dn) { - ldb_transaction_cancel(ctx); - DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n", - dom_sid_string(mem_ctx, user_sid))); - return NT_STATUS_NO_SUCH_USER; - } - - msg = ldb_msg_new(mem_ctx); - if (msg == NULL) { - ldb_transaction_cancel(ctx); - return NT_STATUS_NO_MEMORY; - } - - msg->dn = ldb_dn_copy(msg, user_dn); - if (!msg->dn) { - ldb_transaction_cancel(ctx); - return NT_STATUS_NO_MEMORY; - } - - nt_status = samdb_set_password(ctx, mem_ctx, - user_dn, NULL, - msg, new_pass, - lmNewHash, ntNewHash, - user_change, /* This is a password set, not change */ - restrictions, /* run restriction tests */ - reject_reason, _dominfo); - if (!NT_STATUS_IS_OK(nt_status)) { - ldb_transaction_cancel(ctx); - return nt_status; - } - - /* modify the samdb record */ - ret = samdb_replace(ctx, mem_ctx, msg); - if (ret != 0) { - ldb_transaction_cancel(ctx); - return NT_STATUS_ACCESS_DENIED; - } - - ret = ldb_transaction_commit(ctx); - if (ret != 0) { - DEBUG(0,("Failed to commit transaction to change password on %s: %s\n", - ldb_dn_linearize(mem_ctx, msg->dn), - ldb_errstring(ctx))); - return NT_STATUS_TRANSACTION_ABORTED; - } - return NT_STATUS_OK; -} |