diff options
author | Matthias Dieter Wallnöfer <mdw@samba.org> | 2010-07-06 18:16:32 +0200 |
---|---|---|
committer | Matthias Dieter Wallnöfer <mdw@samba.org> | 2010-08-17 18:45:34 +0200 |
commit | 4c8edc8f5e9db9a08b5d672707ce71d82efdad15 (patch) | |
tree | c4c37c0ba08a2e6f5013cbb90382769cc2f2c9ac /source4 | |
parent | cd711da6ca206a6fe6911c55882ee3e7e7ecedc9 (diff) | |
download | samba-4c8edc8f5e9db9a08b5d672707ce71d82efdad15.tar.gz samba-4c8edc8f5e9db9a08b5d672707ce71d82efdad15.tar.bz2 samba-4c8edc8f5e9db9a08b5d672707ce71d82efdad15.zip |
s4:kdc/kpasswdd.c - let the user change his own password with his own rights
Now it's finally possible that the user can change his password with a DSDB
connection using his credentials.
NOTICE: I had to extract the old password from the SAMDB since I was unable to
find it somewhere else (authinfo for example).
Diffstat (limited to 'source4')
-rw-r--r-- | source4/kdc/kpasswdd.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/source4/kdc/kpasswdd.c b/source4/kdc/kpasswdd.c index 6767f30c9d..e08a5149b9 100644 --- a/source4/kdc/kpasswdd.c +++ b/source4/kdc/kpasswdd.c @@ -33,6 +33,7 @@ #include "auth/credentials/credentials_krb5.h" #include "auth/auth.h" #include "dsdb/samdb/samdb.h" +#include "../lib/util/util_ldb.h" #include "rpc_server/dcerpc_server.h" #include "rpc_server/samr/proto.h" #include "libcli/security/security.h" @@ -170,9 +171,49 @@ static bool kpasswdd_change_password(struct kdc_server *kdc, NTSTATUS status; enum samPwdChangeReason reject_reason; struct samr_DomInfo1 *dominfo; + struct samr_Password *oldLmHash, *oldNtHash; struct ldb_context *samdb; + const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL }; + struct ldb_message **res; + int ret; + + /* Connect to a SAMDB with system privileges for fetching the old pw + * hashes. */ + samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, + system_session(kdc->task->lp_ctx)); + if (!samdb) { + return kpasswdd_make_error_reply(kdc, mem_ctx, + KRB5_KPASSWD_HARDERROR, + "Failed to open samdb", + reply); + } + + /* Fetch the old hashes to get the old password in order to perform + * the password change operation. Naturally it would be much better to + * have a password hash from an authentication around but this doesn't + * seem to be the case here. */ + ret = gendb_search(samdb, mem_ctx, NULL, &res, attrs, + "(&(objectClass=user)(sAMAccountName=%s))", + session_info->server_info->account_name); + if (ret != 1) { + return kpasswdd_make_error_reply(kdc, mem_ctx, + KRB5_KPASSWD_ACCESSDENIED, + "No such user when changing password", + reply); + } + + status = samdb_result_passwords(mem_ctx, kdc->task->lp_ctx, res[0], + &oldLmHash, &oldNtHash); + if (!NT_STATUS_IS_OK(status)) { + return kpasswdd_make_error_reply(kdc, mem_ctx, + KRB5_KPASSWD_ACCESSDENIED, + "Not permitted to change password", + reply); + } - samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(kdc->task->lp_ctx)); + /* Start a SAM with user privileges for the password change */ + samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, + session_info); if (!samdb) { return kpasswdd_make_error_reply(kdc, mem_ctx, KRB5_KPASSWD_HARDERROR, @@ -185,11 +226,11 @@ static bool kpasswdd_change_password(struct kdc_server *kdc, session_info->server_info->account_name, dom_sid_string(mem_ctx, session_info->security_token->user_sid))); - /* User password change */ + /* Performs the password change */ status = samdb_set_password_sid(samdb, mem_ctx, session_info->security_token->user_sid, password, NULL, NULL, - true, /* this is a user password change */ + oldLmHash, oldNtHash, /* this is a user password change */ &reject_reason, &dominfo); return kpasswd_make_pwchange_reply(kdc, mem_ctx, |