dcesrv_lsa.c

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

C
2,518
字号
/*    Unix SMB/CIFS implementation.   endpoint server for the lsarpc pipe   Copyright (C) Andrew Tridgell 2004   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007      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 "rpc_server/lsa/lsa.h"#include "util/util_ldb.h"#include "libcli/ldap/ldap_ndr.h"/*  this type allows us to distinguish handle types*//*  state associated with a lsa_OpenAccount() operation*/struct lsa_account_state {	struct lsa_policy_state *policy;	uint32_t access_mask;	struct dom_sid *account_sid;};/*  state associated with a lsa_OpenSecret() operation*/struct lsa_secret_state {	struct lsa_policy_state *policy;	uint32_t access_mask;	struct ldb_dn *secret_dn;	struct ldb_context *sam_ldb;	bool global;};/*  state associated with a lsa_OpenTrustedDomain() operation*/struct lsa_trusted_domain_state {	struct lsa_policy_state *policy;	uint32_t access_mask;	struct ldb_dn *trusted_domain_dn;};static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 				      TALLOC_CTX *mem_ctx,				      struct lsa_EnumAccountRights *r);static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 					   TALLOC_CTX *mem_ctx,					   struct lsa_policy_state *state,					   int ldb_flag,					   struct dom_sid *sid,					   const struct lsa_RightSet *rights);/*   lsa_Close */static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,			  struct lsa_Close *r){	struct dcesrv_handle *h;	*r->out.handle = *r->in.handle;	DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);	talloc_free(h);	ZERO_STRUCTP(r->out.handle);	return NT_STATUS_OK;}/*   lsa_Delete */static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,			   struct lsa_Delete *r){	struct dcesrv_handle *h;	int ret;	DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);	if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {		struct lsa_secret_state *secret_state = h->data;		/* Ensure user is permitted to delete this... */		switch (security_session_user_level(dce_call->conn->auth_state.session_info))		{		case SECURITY_SYSTEM:		case SECURITY_ADMINISTRATOR:			break;		default:			/* Users and annonymous are not allowed delete things */			return NT_STATUS_ACCESS_DENIED;		}		ret = ldb_delete(secret_state->sam_ldb, 				 secret_state->secret_dn);		talloc_free(h);		if (ret != 0) {			return NT_STATUS_INVALID_HANDLE;		}		return NT_STATUS_OK;	} else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {		struct lsa_trusted_domain_state *trusted_domain_state = h->data;		ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 				 trusted_domain_state->trusted_domain_dn);		talloc_free(h);		if (ret != 0) {			return NT_STATUS_INVALID_HANDLE;		}		return NT_STATUS_OK;	} else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {		struct lsa_RightSet *rights;		struct lsa_account_state *astate;		struct lsa_EnumAccountRights r2;		NTSTATUS status;		rights = talloc(mem_ctx, struct lsa_RightSet);		DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);				astate = h->data;		r2.in.handle = &astate->policy->handle->wire_handle;		r2.in.sid = astate->account_sid;		r2.out.rights = rights;		status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {			return NT_STATUS_OK;		}		if (!NT_STATUS_IS_OK(status)) {			return status;		}		status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 						    LDB_FLAG_MOD_DELETE, astate->account_sid,						    r2.out.rights);		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {			return NT_STATUS_OK;		}		if (!NT_STATUS_IS_OK(status)) {			return status;		}	} 		return NT_STATUS_INVALID_HANDLE;}/*   lsa_EnumPrivs */static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,			      struct lsa_EnumPrivs *r){	struct dcesrv_handle *h;	struct lsa_policy_state *state;	int i;	const char *privname;	DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);	state = h->data;	i = *r->in.resume_handle;	if (i == 0) i = 1;	while ((privname = sec_privilege_name(i)) &&	       r->out.privs->count < r->in.max_count) {		struct lsa_PrivEntry *e;		r->out.privs->privs = talloc_realloc(r->out.privs,						       r->out.privs->privs, 						       struct lsa_PrivEntry, 						       r->out.privs->count+1);		if (r->out.privs->privs == NULL) {			return NT_STATUS_NO_MEMORY;		}		e = &r->out.privs->privs[r->out.privs->count];		e->luid.low = i;		e->luid.high = 0;		e->name.string = privname;		r->out.privs->count++;		i++;	}	*r->out.resume_handle = i;	return NT_STATUS_OK;}/*   lsa_QuerySecObj */static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct lsa_QuerySecurity *r){	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);}/*   lsa_SetSecObj */static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,			      struct lsa_SetSecObj *r){	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);}/*   lsa_ChangePassword */static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				   struct lsa_ChangePassword *r){	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);}/*   dssetup_DsRoleGetPrimaryDomainInformation   This is not an LSA call, but is the only call left on the DSSETUP  pipe (after the pipe was truncated), and needs lsa_get_policy_state*/static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 						 TALLOC_CTX *mem_ctx,						 struct dssetup_DsRoleGetPrimaryDomainInformation *r){	union dssetup_DsRoleInfo *info;	info = talloc(mem_ctx, union dssetup_DsRoleInfo);	W_ERROR_HAVE_NO_MEMORY(info);	switch (r->in.level) {	case DS_ROLE_BASIC_INFORMATION:	{		enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;		uint32_t flags = 0;		const char *domain = NULL;		const char *dns_domain = NULL;		const char *forest = NULL;		struct GUID domain_guid;		struct lsa_policy_state *state;		NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);		if (!NT_STATUS_IS_OK(status)) {			return ntstatus_to_werror(status);		}		ZERO_STRUCT(domain_guid);		switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {		case ROLE_STANDALONE:			role		= DS_ROLE_STANDALONE_SERVER;			break;		case ROLE_DOMAIN_MEMBER:			role		= DS_ROLE_MEMBER_SERVER;			break;		case ROLE_DOMAIN_CONTROLLER:			if (samdb_is_pdc(state->sam_ldb)) {				role	= DS_ROLE_PRIMARY_DC;			} else {				role    = DS_ROLE_BACKUP_DC;			}			break;		}		switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {		case ROLE_STANDALONE:			domain		= talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));			W_ERROR_HAVE_NO_MEMORY(domain);			break;		case ROLE_DOMAIN_MEMBER:			domain		= talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));			W_ERROR_HAVE_NO_MEMORY(domain);			/* TODO: what is with dns_domain and forest and guid? */			break;		case ROLE_DOMAIN_CONTROLLER:			flags		= DS_ROLE_PRIMARY_DS_RUNNING;			if (state->mixed_domain == 1) {				flags	|= DS_ROLE_PRIMARY_DS_MIXED_MODE;			}						domain		= state->domain_name;			dns_domain	= state->domain_dns;			forest		= state->forest_dns;			domain_guid	= state->domain_guid;			flags	|= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;			break;		}		info->basic.role        = role; 		info->basic.flags       = flags;		info->basic.domain      = domain;		info->basic.dns_domain  = dns_domain;		info->basic.forest      = forest;		info->basic.domain_guid = domain_guid;		r->out.info = info;		return WERR_OK;	}	case DS_ROLE_UPGRADE_STATUS:	{		info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;		info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;		r->out.info = info;		return WERR_OK;	}	case DS_ROLE_OP_STATUS:	{		info->opstatus.status = DS_ROLE_OP_IDLE;		r->out.info = info;		return WERR_OK;	}	default:		return WERR_INVALID_PARAM;	}	return WERR_INVALID_PARAM;}/*  fill in the AccountDomain info*/static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,				       struct lsa_DomainInfo *info){	info->name.string = state->domain_name;	info->sid         = state->domain_sid;	return NT_STATUS_OK;}/*  fill in the DNS domain info*/static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,			     struct lsa_DnsDomainInfo *info){	info->name.string = state->domain_name;	info->sid         = state->domain_sid;	info->dns_domain.string = state->domain_dns;	info->dns_forest.string = state->forest_dns;	info->domain_guid       = state->domain_guid;	return NT_STATUS_OK;}/*   lsa_QueryInfoPolicy2*/static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				     struct lsa_QueryInfoPolicy2 *r){	struct lsa_policy_state *state;	struct dcesrv_handle *h;	r->out.info = NULL;	DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);	state = h->data;	r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);	if (!r->out.info) {		return NT_STATUS_NO_MEMORY;	}	ZERO_STRUCTP(r->out.info);	switch (r->in.level) {	case LSA_POLICY_INFO_DOMAIN:	case LSA_POLICY_INFO_ACCOUNT_DOMAIN:		return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);	case LSA_POLICY_INFO_DNS:		return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);	case LSA_POLICY_INFO_DB:	case LSA_POLICY_INFO_AUDIT_FULL_SET:	case LSA_POLICY_INFO_AUDIT_FULL_QUERY:		return NT_STATUS_INVALID_PARAMETER;	}	return NT_STATUS_INVALID_INFO_CLASS;}/*   lsa_QueryInfoPolicy */static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				    struct lsa_QueryInfoPolicy *r){	struct lsa_QueryInfoPolicy2 r2;	NTSTATUS status;	r2.in.handle = r->in.handle;	r2.in.level = r->in.level;		status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);	r->out.info = r2.out.info;	return status;}/*   lsa_SetInfoPolicy */static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct lsa_SetInfoPolicy *r){	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);}/*   lsa_ClearAuditLog */static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct lsa_ClearAuditLog *r){	DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);}/*   lsa_CreateAccount   This call does not seem to have any long-term effects, hence no database operations*/static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct lsa_CreateAccount *r){	struct lsa_account_state *astate;	struct lsa_policy_state *state;	struct dcesrv_handle *h, *ah;	ZERO_STRUCTP(r->out.acct_handle);	DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);	state = h->data;	astate = talloc(dce_call->conn, struct lsa_account_state);	if (astate == NULL) {		return NT_STATUS_NO_MEMORY;	}	astate->account_sid = dom_sid_dup(astate, r->in.sid);	if (astate->account_sid == NULL) {		talloc_free(astate);		return NT_STATUS_NO_MEMORY;	}		astate->policy = talloc_reference(astate, state);	astate->access_mask = r->in.access_mask;	ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);	if (!ah) {		talloc_free(astate);		return NT_STATUS_NO_MEMORY;	}	ah->data = talloc_steal(ah, astate);	*r->out.acct_handle = ah->wire_handle;	return NT_STATUS_OK;}

⌨️ 快捷键说明

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