From 4c8edc8f5e9db9a08b5d672707ce71d82efdad15 Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Tue, 6 Jul 2010 18:16:32 +0200 Subject: 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). --- source4/kdc/kpasswdd.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file 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, -- cgit