summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Dieter Wallnöfer <mdw@samba.org>2010-07-06 18:16:32 +0200
committerMatthias Dieter Wallnöfer <mdw@samba.org>2010-08-17 18:45:34 +0200
commit4c8edc8f5e9db9a08b5d672707ce71d82efdad15 (patch)
treec4c37c0ba08a2e6f5013cbb90382769cc2f2c9ac
parentcd711da6ca206a6fe6911c55882ee3e7e7ecedc9 (diff)
downloadsamba-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).
-rw-r--r--source4/kdc/kpasswdd.c47
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,