samr_password.c

来自「samba最新软件」· C语言 代码 · 共 602 行 · 第 1/2 页

C
602
字号
/*    Unix SMB/CIFS implementation.   samr server password set/change handling   Copyright (C) Andrew Tridgell 2004   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "rpc_server/dcerpc_server.h"#include "rpc_server/common/common.h"#include "rpc_server/samr/dcesrv_samr.h"#include "system/time.h"#include "lib/crypto/crypto.h"#include "dsdb/common/flags.h"#include "libcli/ldap/ldap.h"#include "dsdb/samdb/samdb.h"#include "auth/auth.h"#include "rpc_server/samr/proto.h"#include "libcli/auth/libcli_auth.h"#include "util/util_ldb.h"#include "param/param.h"/*   samr_ChangePasswordUser */NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 					TALLOC_CTX *mem_ctx,					struct samr_ChangePasswordUser *r){	struct dcesrv_handle *h;	struct samr_account_state *a_state;	struct ldb_context *sam_ctx;	struct ldb_message **res, *msg;	int ret;	struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;	struct samr_Password *lm_pwd, *nt_pwd;	NTSTATUS status = NT_STATUS_OK;	const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };	DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);	a_state = h->data;	/* basic sanity checking on parameters.  Do this before any database ops */	if (!r->in.lm_present || !r->in.nt_present ||	    !r->in.old_lm_crypted || !r->in.new_lm_crypted ||	    !r->in.old_nt_crypted || !r->in.new_nt_crypted) {		/* we should really handle a change with lm not		   present */		return NT_STATUS_INVALID_PARAMETER_MIX;	}	/* To change a password we need to open as system */	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));	if (sam_ctx == NULL) {		return NT_STATUS_INVALID_SYSTEM_SERVICE;	}	ret = ldb_transaction_start(sam_ctx);	if (ret) {		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));		return NT_STATUS_TRANSACTION_ABORTED;	}	/* fetch the old hashes */	ret = gendb_search_dn(sam_ctx, mem_ctx,			      a_state->account_dn, &res, attrs);	if (ret != 1) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	msg = res[0];	status = samdb_result_passwords(mem_ctx, msg, &lm_pwd, &nt_pwd);	if (!NT_STATUS_IS_OK(status) || !lm_pwd || !nt_pwd) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	/* decrypt and check the new lm hash */	D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);	D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);	if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	/* decrypt and check the new nt hash */	D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);	D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);	if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}		/* The NT Cross is not required by Win2k3 R2, but if present	   check the nt cross hash */	if (r->in.cross1_present && r->in.nt_cross) {		D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);		if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {			ldb_transaction_cancel(sam_ctx);			return NT_STATUS_WRONG_PASSWORD;		}	}	/* The LM Cross is not required by Win2k3 R2, but if present	   check the lm cross hash */	if (r->in.cross2_present && r->in.lm_cross) {		D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);		if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {			ldb_transaction_cancel(sam_ctx);			return NT_STATUS_WRONG_PASSWORD;		}	}	msg = ldb_msg_new(mem_ctx);	if (msg == NULL) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_NO_MEMORY;	}	msg->dn = ldb_dn_copy(msg, a_state->account_dn);	if (!msg->dn) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_NO_MEMORY;	}	/* setup password modify mods on the user DN specified.  This may fail	 * due to password policies.  */	status = samdb_set_password(sam_ctx, mem_ctx,				    a_state->account_dn, a_state->domain_state->domain_dn,				    msg, NULL, &new_lmPwdHash, &new_ntPwdHash, 				    true, /* this is a user password change */				    NULL,				    NULL);	if (!NT_STATUS_IS_OK(status)) {		ldb_transaction_cancel(sam_ctx);		return status;	}	/* The above call only setup the modifications, this actually	 * makes the write to the database. */	ret = samdb_replace(sam_ctx, mem_ctx, msg);	if (ret != 0) {		DEBUG(2,("Failed to modify record to change password on %s: %s\n",			 ldb_dn_get_linearized(a_state->account_dn),			 ldb_errstring(sam_ctx)));		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	/* And this confirms it in a transaction commit */	ret = ldb_transaction_commit(sam_ctx);	if (ret != 0) {		DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",			 ldb_dn_get_linearized(a_state->account_dn),			 ldb_errstring(sam_ctx)));		return NT_STATUS_TRANSACTION_ABORTED;	}	return NT_STATUS_OK;}/*   samr_OemChangePasswordUser2 */NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				     struct samr_OemChangePasswordUser2 *r){	NTSTATUS status;	char new_pass[512];	uint32_t new_pass_len;	struct samr_CryptPassword *pwbuf = r->in.password;	struct ldb_context *sam_ctx;	struct ldb_dn *user_dn;	int ret;	struct ldb_message **res, *mod;	const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };	struct samr_Password *lm_pwd;	DATA_BLOB lm_pwd_blob;	uint8_t new_lm_hash[16];	struct samr_Password lm_verifier;	if (pwbuf == NULL) {		return NT_STATUS_INVALID_PARAMETER;	}	if (r->in.hash == NULL) {		return NT_STATUS_INVALID_PARAMETER;	}	/* To change a password we need to open as system */	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));	if (sam_ctx == NULL) {		return NT_STATUS_INVALID_SYSTEM_SERVICE;	}	ret = ldb_transaction_start(sam_ctx);	if (ret) {		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));		return NT_STATUS_TRANSACTION_ABORTED;	}	/* we need the users dn and the domain dn (derived from the	   user SID). We also need the current lm password hash in	   order to decrypt the incoming password */	ret = gendb_search(sam_ctx, 			   mem_ctx, NULL, &res, attrs,			   "(&(sAMAccountName=%s)(objectclass=user))",			   r->in.account->string);	if (ret != 1) {		ldb_transaction_cancel(sam_ctx);		/* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */		return NT_STATUS_WRONG_PASSWORD;	}	user_dn = res[0]->dn;	status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, NULL);	if (!NT_STATUS_IS_OK(status) || !lm_pwd) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	/* decrypt the password we have been given */	lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash)); 	arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);	data_blob_free(&lm_pwd_blob);		if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),			      &new_pass_len, STR_ASCII)) {		ldb_transaction_cancel(sam_ctx);		DEBUG(3,("samr: failed to decode password buffer\n"));		return NT_STATUS_WRONG_PASSWORD;	}	/* check LM verifier */	if (lm_pwd == NULL) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	E_deshash(new_pass, new_lm_hash);	E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);	if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_WRONG_PASSWORD;	}	mod = ldb_msg_new(mem_ctx);	if (mod == NULL) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_NO_MEMORY;	}	mod->dn = ldb_dn_copy(mod, user_dn);	if (!mod->dn) {		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_NO_MEMORY;	}	/* set the password on the user DN specified.  This may fail	 * due to password policies */	status = samdb_set_password(sam_ctx, mem_ctx,				    user_dn, NULL, 				    mod, new_pass, 				    NULL, NULL,				    true, /* this is a user password change */				    NULL, 				    NULL);	if (!NT_STATUS_IS_OK(status)) {		ldb_transaction_cancel(sam_ctx);		return status;	}	/* The above call only setup the modifications, this actually	 * makes the write to the database. */	ret = samdb_replace(sam_ctx, mem_ctx, mod);	if (ret != 0) {		DEBUG(2,("Failed to modify record to change password on %s: %s\n",			 ldb_dn_get_linearized(user_dn),			 ldb_errstring(sam_ctx)));		ldb_transaction_cancel(sam_ctx);		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?