samr_password.c

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

C
602
字号
	/* 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(user_dn),			 ldb_errstring(sam_ctx)));		return NT_STATUS_TRANSACTION_ABORTED;	}	return NT_STATUS_OK;}/*   samr_ChangePasswordUser3 */NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, 				  TALLOC_CTX *mem_ctx,				  struct samr_ChangePasswordUser3 *r){		NTSTATUS status;	char new_pass[512];	uint32_t new_pass_len;	struct ldb_context *sam_ctx = NULL;	struct ldb_dn *user_dn;	int ret;	struct ldb_message **res, *mod;	const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };	struct samr_Password *nt_pwd, *lm_pwd;	DATA_BLOB nt_pwd_blob;	struct samr_DomInfo1 *dominfo = NULL;	struct samr_ChangeReject *reject = NULL;	enum samr_RejectReason reason = SAMR_REJECT_OTHER;	uint8_t new_nt_hash[16], new_lm_hash[16];	struct samr_Password nt_verifier, lm_verifier;	ZERO_STRUCT(r->out);	if (r->in.nt_password == NULL ||	    r->in.nt_verifier == 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) {		talloc_free(sam_ctx);		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 and nt password hashes	   in order to decrypt the incoming passwords */	ret = gendb_search(sam_ctx, 			   mem_ctx, NULL, &res, attrs,			   "(&(sAMAccountName=%s)(objectclass=user))",			   r->in.account->string);	if (ret != 1) {		/* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */		status = NT_STATUS_WRONG_PASSWORD;		goto failed;	}	user_dn = res[0]->dn;	status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, &nt_pwd);	if (!NT_STATUS_IS_OK(status) ) {		goto failed;	}	if (!nt_pwd) {		status = NT_STATUS_WRONG_PASSWORD;		goto failed;	}	/* decrypt the password we have been given */	nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));	arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);	data_blob_free(&nt_pwd_blob);	if (!decode_pw_buffer(r->in.nt_password->data, new_pass, sizeof(new_pass),			      &new_pass_len, STR_UNICODE)) {		DEBUG(3,("samr: failed to decode password buffer\n"));		status = NT_STATUS_WRONG_PASSWORD;		goto failed;	}	if (r->in.nt_verifier == NULL) {		status = NT_STATUS_WRONG_PASSWORD;		goto failed;	}	/* check NT verifier */	E_md4hash(new_pass, new_nt_hash);	E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);	if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {		status = NT_STATUS_WRONG_PASSWORD;		goto failed;	}	/* check LM verifier */	if (lm_pwd && r->in.lm_verifier != NULL) {		E_deshash(new_pass, new_lm_hash);		E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);		if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {			status = NT_STATUS_WRONG_PASSWORD;			goto failed;		}	}	mod = ldb_msg_new(mem_ctx);	if (mod == NULL) {		return NT_STATUS_NO_MEMORY;	}	mod->dn = ldb_dn_copy(mod, user_dn);	if (!mod->dn) {		status = NT_STATUS_NO_MEMORY;		goto failed;	}	/* 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 */				    &reason, 				    &dominfo);	if (!NT_STATUS_IS_OK(status)) {		goto failed;	}	/* 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,("samdb_replace failed to change password for %s: %s\n",			 ldb_dn_get_linearized(user_dn),			 ldb_errstring(sam_ctx)));		status = NT_STATUS_UNSUCCESSFUL;		goto failed;	}	/* 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(user_dn),			 ldb_errstring(sam_ctx)));		status = NT_STATUS_TRANSACTION_ABORTED;		goto failed;	}	return NT_STATUS_OK;failed:	ldb_transaction_cancel(sam_ctx);	talloc_free(sam_ctx);	reject = talloc(mem_ctx, struct samr_ChangeReject);	r->out.dominfo = dominfo;	r->out.reject = reject;	if (reject == NULL) {		return status;	}	ZERO_STRUCTP(reject);	reject->reason = reason;	return status;}/*   samr_ChangePasswordUser2   easy - just a subset of samr_ChangePasswordUser3*/NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct samr_ChangePasswordUser2 *r){	struct samr_ChangePasswordUser3 r2;	r2.in.server = r->in.server;	r2.in.account = r->in.account;	r2.in.nt_password = r->in.nt_password;	r2.in.nt_verifier = r->in.nt_verifier;	r2.in.lm_change = r->in.lm_change;	r2.in.lm_password = r->in.lm_password;	r2.in.lm_verifier = r->in.lm_verifier;	r2.in.password3 = NULL;	return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);}/*  set password via a samr_CryptPassword buffer  this will in the 'msg' with modify operations that will update the user  password when applied*/NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,			   void *sam_ctx,			   struct ldb_dn *account_dn, struct ldb_dn *domain_dn,			   TALLOC_CTX *mem_ctx,			   struct ldb_message *msg, 			   struct samr_CryptPassword *pwbuf){	NTSTATUS nt_status;	char new_pass[512];	uint32_t new_pass_len;	DATA_BLOB session_key = data_blob(NULL, 0);	nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);	if (!NT_STATUS_IS_OK(nt_status)) {		return nt_status;	}	arcfour_crypt_blob(pwbuf->data, 516, &session_key);	if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),			      &new_pass_len, STR_UNICODE)) {		DEBUG(3,("samr: failed to decode password buffer\n"));		return NT_STATUS_WRONG_PASSWORD;	}	/* set the password - samdb needs to know both the domain and user DNs,	   so the domain password policy can be used */	return samdb_set_password(sam_ctx, mem_ctx,				  account_dn, domain_dn, 				  msg, new_pass, 				  NULL, NULL,				  false, /* This is a password set, not change */				  NULL, NULL);}/*  set password via a samr_CryptPasswordEx buffer  this will in the 'msg' with modify operations that will update the user  password when applied*/NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,			      struct ldb_context *sam_ctx,			      struct ldb_dn *account_dn, struct ldb_dn *domain_dn,			      TALLOC_CTX *mem_ctx,			      struct ldb_message *msg, 			      struct samr_CryptPasswordEx *pwbuf){	NTSTATUS nt_status;	char new_pass[512];	uint32_t new_pass_len;	DATA_BLOB co_session_key;	DATA_BLOB session_key = data_blob(NULL, 0);	struct MD5Context ctx;	nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);	if (!NT_STATUS_IS_OK(nt_status)) {		return nt_status;	}	co_session_key = data_blob_talloc(mem_ctx, NULL, 16);	if (!co_session_key.data) {		return NT_STATUS_NO_MEMORY;	}	MD5Init(&ctx);	MD5Update(&ctx, &pwbuf->data[516], 16);	MD5Update(&ctx, session_key.data, session_key.length);	MD5Final(co_session_key.data, &ctx);		arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);	if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),			      &new_pass_len, STR_UNICODE)) {		DEBUG(3,("samr: failed to decode password buffer\n"));		return NT_STATUS_WRONG_PASSWORD;	}	/* set the password - samdb needs to know both the domain and user DNs,	   so the domain password policy can be used */	return samdb_set_password(sam_ctx, mem_ctx,				  account_dn, domain_dn, 				  msg, new_pass, 				  NULL, NULL,				  false, /* This is a password set, not change */				  NULL, NULL);}

⌨️ 快捷键说明

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