Пример #1
0
bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check)
{
	int result;
	struct ldb_dn *root_base_dn = ldb_get_root_basedn(ldb);
	result = ldb_dn_compare(root_base_dn,dn_to_check);
	return (result==0);
}
Пример #2
0
/* 
 * GetUniqueFMID
 *
 * This function is a copy of original openchangedb_get_new_folderID from libproxy/openchangedb.C
 *
 * I extract this function because :
 *    - Function can be implemented directly in the backend
 *    - 
 */
enum MAPISTATUS GetUniqueFMID(struct EasyLinuxContext *elContext, uint64_t *FMID)
{
int			ret;
struct ldb_result	*res;
struct ldb_message	*msg;
const char * const	attrs[] = { "*", NULL };

/* Get the current GlobalCount */
ret = ldb_search(elContext->LdbTable, elContext->mem_ctx, &res, ldb_get_root_basedn(elContext->LdbTable),
			 LDB_SCOPE_SUBTREE, attrs, "(objectClass=server)");
if( ret != LDB_SUCCESS || !res->count )
  return MAPI_E_NOT_FOUND;			 

*FMID = ldb_msg_find_attr_as_uint64(res->msgs[0], "GlobalCount", 0);

/* Update GlobalCount value */
msg = ldb_msg_new(elContext->mem_ctx);
msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(elContext->LdbTable, elContext->mem_ctx, res->msgs[0], "distinguishedName"));
ldb_msg_add_fmt(msg, "GlobalCount", "%llu", (long long unsigned int) ((*FMID) + 1));
msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
ret = ldb_modify(elContext->LdbTable, msg);
if( ret != LDB_SUCCESS || !res->count )
  return MAPI_E_NOT_FOUND;			 

*FMID = (exchange_globcnt(*FMID) << 16) | 0x0001;

return MAPI_E_SUCCESS;
}
Пример #3
0
static int acl_add(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.add.message->dn);
	struct ldb_context *ldb;
	struct ldb_message_element *oc_el;
	const struct GUID *guid;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;

	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}

	if (ldb_dn_is_special(req->op.add.message->dn)) {
		return ldb_next_request(module, req);
	}
	ldb = ldb_module_get_ctx(module);
	/* Creating an NC. There is probably something we should do here,
	 * but we will establish that later */
	if ((ldb_dn_compare(req->op.add.message->dn, (ldb_get_schema_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.add.message->dn, (ldb_get_config_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.add.message->dn, (ldb_get_root_basedn(ldb))) == 0)) {
		return ldb_next_request(module, req);
	}

	oc_el = ldb_msg_find_element(req->op.add.message, "objectClass");
	if (!oc_el || oc_el->num_values == 0) {
		DEBUG(10,("acl:operation error %s\n", ldb_dn_get_linearized(req->op.add.message->dn)));
		return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
	}

	guid = class_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb),
						      (char *)oc_el->values[oc_el->num_values-1].data);

	if (!insert_in_object_tree(req, guid, SEC_ADS_CREATE_CHILD, &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = check_access_on_dn(module, req, parent, SEC_ADS_CREATE_CHILD, root);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	return ldb_next_request(module, req);
}
Пример #4
0
/* similar to the modify for the time being.
 * We need to concider the special delete tree case, though - TODO */
static int acl_delete(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_dn *parent = ldb_dn_get_parent(req, req->op.del.dn);
	struct ldb_context *ldb;

	DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}

	if (ldb_dn_is_special(req->op.del.dn)) {
		return ldb_next_request(module, req);
	}
	ldb = ldb_module_get_ctx(module);
	/* first check if we have delete object right */
	ret = check_access_on_dn(module, req, req->op.del.dn, SEC_STD_DELETE, NULL);
	if (ret == LDB_SUCCESS) {
		return ldb_next_request(module, req);
	}

	/* Nope, we don't have delete object. Lets check if we have delete child on the parent */
	/* No parent, so check fails */
	if ((ldb_dn_compare(req->op.del.dn, (ldb_get_schema_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.del.dn, (ldb_get_config_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.del.dn, (ldb_get_root_basedn(ldb))) == 0)) {
		DEBUG(10,("acl:deleting an NC\n"));
		return ldb_module_done(req, NULL, NULL, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS);
	}

	ret = check_access_on_dn(module, req, parent, SEC_ADS_DELETE_CHILD, NULL);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	return ldb_next_request(module, req);
}
Пример #5
0
static int acl_rename(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_dn *oldparent = ldb_dn_get_parent(req, req->op.rename.olddn);
	struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn);
	struct ldb_context *ldb;
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	struct ldb_result *acl_res;
	const struct GUID *guid;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(req);
	NTSTATUS status;
	uint32_t access_granted;
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectClass",
		"objectSid",
		NULL
	};

	DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}
	if (ldb_dn_is_special(req->op.rename.olddn)) {
		return ldb_next_request(module, req);
	}
	ldb = ldb_module_get_ctx(module);

	/* TODO search to include deleted objects */
	ret = ldb_search(ldb, req, &acl_res, req->op.rename.olddn,
			 LDB_SCOPE_BASE, acl_attrs, NULL);
	/* we sould be able to find the parent */
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl: failed to find object %s\n",
			  ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}

	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	guid = attribute_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb),
							  "name");
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &new_node, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);

	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}
	ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_ADS_WRITE_PROP,
				     &access_granted,
				     root,
				     sid);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Object %s nas no wp on name\n",
			   ldb_dn_get_linearized(req->op.rename.olddn)));
		acl_debug(sd,
			  acl_user_token(module),
			  req->op.rename.olddn,
			  true,
			  10);
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}

	if (ldb_dn_compare(oldparent, newparent) == 0) {
		/* regular rename, not move, nothing more to do */
		return ldb_next_request(module, req);
	}

	/* What exactly to do in this case? It would fail anyway.. */
	if ((ldb_dn_compare(req->op.rename.newdn, (ldb_get_schema_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_config_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_root_basedn(ldb))) == 0)) {
		DEBUG(10,("acl:moving as an NC\n"));
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	/* new parent should have create child */
	talloc_free(tmp_ctx);
	tmp_ctx = talloc_new(req);
	root = NULL;
	new_node = NULL;
	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!guid) {
		DEBUG(10,("acl:renamed object has no object class\n"));
		return ldb_module_done(req, NULL, NULL,  LDB_ERR_OPERATIONS_ERROR);
	}
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_CREATE_CHILD,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ret = check_access_on_dn(module, req, newparent, SEC_ADS_CREATE_CHILD, root);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}
	/* do we have delete object on the object? */

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_STD_DELETE,
				     &access_granted,
				     NULL,
				     sid);

	if (NT_STATUS_IS_OK(status)) {
		return ldb_next_request(module, req);
	}
	/* what about delete child on the current parent */
	ret = check_access_on_dn(module, req, oldparent, SEC_ADS_DELETE_CHILD, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ldb_module_done(req, NULL, NULL, ret);
	}
	return ldb_next_request(module, req);
}
Пример #6
0
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
				     struct lsa_policy_state **_state)
{
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0);
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* and the privilege database */
	state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
	if (state->pdb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	*_state = state;

	return NT_STATUS_OK;
}
Пример #7
0
/*
  work out the principal to use for DRS replication connections
 */
NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s,
				       TALLOC_CTX *mem_ctx,
				       const struct repsFromTo1 *rft,
				       const char **target_principal)
{
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	const char *attrs_server[] = { "dNSHostName", NULL };
	const char *attrs_ntds[] = { "msDS-HasDomainNCs", "hasMasterNCs", NULL };
	int ret;
	const char *hostname, *dnsdomain=NULL;
	struct ldb_dn *ntds_dn, *server_dn;
	struct ldb_dn *forest_dn, *nc_dn;

	*target_principal = NULL;

	tmp_ctx = talloc_new(mem_ctx);

	/* we need to find their hostname */
	ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, &ntds_dn);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their NTDSDSA DN not to be in our database */
		return NT_STATUS_OK;
	}

	server_dn = ldb_dn_copy(tmp_ctx, ntds_dn);
	if (server_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	/* strip off the NTDS Settings */
	if (!ldb_dn_remove_child_components(server_dn, 1)) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, server_dn, attrs_server, 0);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their server DN not to be in our database */
		return NT_STATUS_OK;
	}

	forest_dn = ldb_get_root_basedn(s->samdb);
	if (forest_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
	if (hostname != NULL) {
		char *local_principal;

		/*
		  if we have the dNSHostName attribute then we can use
		  the GC/hostname/realm SPN. All DCs should have this SPN

		  Windows DC may set up it's dNSHostName before setting up
		  GC/xx/xx SPN. So make sure it exists, before using it.
		 */
		local_principal = talloc_asprintf(mem_ctx, "GC/%s/%s",
						    hostname,
						    samdb_dn_to_dns_domain(tmp_ctx, forest_dn));
		if (dreplsrv_spn_exists(s->samdb, ntds_dn, local_principal)) {
			*target_principal = local_principal;
			talloc_free(tmp_ctx);
			return NT_STATUS_OK;
		}

		talloc_free(local_principal);
	}

	/*
	   if we can't find the dNSHostName then we will try for the
	   E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN}
	   SPN. To use that we need the DNS domain name of the target
	   DC. We find that by first looking for the msDS-HasDomainNCs
	   in the NTDSDSA object of the DC, and if we don't find that,
	   then we look for the hasMasterNCs attribute, and eliminate
	   the known schema and configuruation DNs. Despite how
	   bizarre this seems, Hongwei tells us that this is in fact
	   what windows does to find the SPN!!
	*/
	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs_ntds, 0);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	nc_dn = ldb_msg_find_attr_as_dn(s->samdb, tmp_ctx, res->msgs[0], "msDS-HasDomainNCs");
	if (nc_dn != NULL) {
		dnsdomain = samdb_dn_to_dns_domain(tmp_ctx, nc_dn);
	}

	if (dnsdomain == NULL) {
		struct ldb_message_element *el;
		int i;
		el = ldb_msg_find_element(res->msgs[0], "hasMasterNCs");
		for (i=0; el && i<el->num_values; i++) {
			nc_dn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
			if (nc_dn == NULL ||
			    ldb_dn_compare(ldb_get_config_basedn(s->samdb), nc_dn) == 0 ||
			    ldb_dn_compare(ldb_get_schema_basedn(s->samdb), nc_dn) == 0) {
				continue;
			}
			/* it must be a domain DN, get the equivalent
			   DNS domain name */
			dnsdomain = samdb_dn_to_dns_domain(tmp_ctx, nc_dn);
			break;
		}
	}

	if (dnsdomain != NULL) {
		*target_principal = talloc_asprintf(mem_ctx,
						    "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s",
						    GUID_string(tmp_ctx, &rft->source_dsa_obj_guid),
						    dnsdomain);
	}

	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Пример #8
0
struct dnsserver_serverinfo *dnsserver_init_serverinfo(TALLOC_CTX *mem_ctx,
							struct loadparm_context *lp_ctx,
							struct ldb_context *samdb)
{
	struct dnsserver_serverinfo *serverinfo;
	struct dcerpc_server_info *dinfo;
	struct ldb_dn *domain_dn, *forest_dn;
	struct interface *ifaces;
	int num_interfaces, i;

	serverinfo = talloc_zero(mem_ctx, struct dnsserver_serverinfo);
	if (serverinfo == NULL) {
		return NULL;
	}

	dinfo = lpcfg_dcerpc_server_info(mem_ctx, lp_ctx);
	if (dinfo) {
		serverinfo->dwVersion = (dinfo->version_build & 0x0000FFFF) << 16 |
				(dinfo->version_minor & 0x000000FF) << 8 |
				(dinfo->version_major & 0x000000FF);
		talloc_free(dinfo);
	} else {
		serverinfo->dwVersion = 0x0ECE0205; /* build, os_minor, os_major */;
	}

	serverinfo->fBootMethod = DNS_BOOT_METHOD_DIRECTORY;
	serverinfo->fAdminConfigured = 0;
	serverinfo->fAllowUpdate = 1;
	serverinfo->fDsAvailable = 1;

	serverinfo->pszServerName = talloc_asprintf(mem_ctx, "%s.%s",
					lpcfg_netbios_name(lp_ctx),
					lpcfg_dnsdomain(lp_ctx));

	domain_dn = ldb_get_default_basedn(samdb);
	forest_dn = ldb_get_root_basedn(samdb);

	serverinfo->pszDsContainer = talloc_asprintf(mem_ctx,
					"CN=MicrosoftDNS,DC=DomainDnsZones,%s",
					ldb_dn_get_linearized(domain_dn));

	serverinfo->dwDsForestVersion = dsdb_forest_functional_level(samdb);
	serverinfo->dwDsDomainVersion = dsdb_functional_level(samdb);
	serverinfo->dwDsDsaVersion = 4; /* need to do ldb search here */

	serverinfo->pszDomainName = samdb_dn_to_dns_domain(mem_ctx, domain_dn);
	serverinfo->pszForestName = samdb_dn_to_dns_domain(mem_ctx, forest_dn);

	serverinfo->pszDomainDirectoryPartition = talloc_asprintf(mem_ctx,
							"DC=DomainDnsZones,%s",
							ldb_dn_get_linearized(domain_dn));
	serverinfo->pszForestDirectoryPartition = talloc_asprintf(mem_ctx,
							"DC=ForestDnsZones,%s",
							ldb_dn_get_linearized(forest_dn));

	load_interface_list(mem_ctx, lp_ctx, &ifaces);
	num_interfaces = iface_list_count(ifaces);

	serverinfo->aipServerAddrs = talloc_zero(mem_ctx, struct IP4_ARRAY);

	if (serverinfo->aipServerAddrs) {
		serverinfo->aipServerAddrs->AddrCount = num_interfaces;
		if (num_interfaces > 0) {
			serverinfo->aipServerAddrs->AddrArray = talloc_zero_array(mem_ctx,
									unsigned int,
									num_interfaces);
			if (serverinfo->aipServerAddrs->AddrArray) {
				for (i=0; i<num_interfaces; i++) {
					serverinfo->aipServerAddrs->AddrArray[i] = inet_addr(iface_list_n_ip(ifaces, i));
				}
			} else {
				serverinfo->aipServerAddrs->AddrCount = 0;
			}
		}
Пример #9
0
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                                   struct smb_krb5_context *smb_krb5_context,
                                   uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                                   struct ldb_dn *name_dn, const char *name,
                                   const char *domain_filter, const char *result_filter,
                                   struct drsuapi_DsNameInfo1 *info1)
{
    int ldb_ret;
    struct ldb_result *domain_res = NULL;
    const char * const *domain_attrs;
    const char * const *result_attrs;
    struct ldb_message **result_res = NULL;
    struct ldb_message *result = NULL;
    struct ldb_dn *result_basedn = NULL;
    int i;
    char *p;
    struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);

    const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL};
    const char * const _result_attrs_null[] = { NULL };

    const char * const _domain_attrs_canonical[] = { "ncName", "dnsRoot", NULL};
    const char * const _result_attrs_canonical[] = { "canonicalName", NULL };

    const char * const _domain_attrs_nt4[] = { "ncName", "dnsRoot", "nETBIOSName", NULL};
    const char * const _result_attrs_nt4[] = { "sAMAccountName", "objectSid", "objectClass", NULL};

    const char * const _domain_attrs_guid[] = { "ncName", "dnsRoot", NULL};
    const char * const _result_attrs_guid[] = { "objectGUID", NULL};

    const char * const _domain_attrs_display[] = { "ncName", "dnsRoot", NULL};
    const char * const _result_attrs_display[] = { "displayName", "samAccountName", NULL};

    const char * const _domain_attrs_none[] = { "ncName", "dnsRoot" , NULL};
    const char * const _result_attrs_none[] = { NULL};

    /* here we need to set the attrs lists for domain and result lookups */
    switch (format_desired) {
    case DRSUAPI_DS_NAME_FORMAT_FQDN_1779:
    case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
        domain_attrs = _domain_attrs_1779;
        result_attrs = _result_attrs_null;
        break;
    case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
        domain_attrs = _domain_attrs_canonical;
        result_attrs = _result_attrs_canonical;
        break;
    case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT:
        domain_attrs = _domain_attrs_nt4;
        result_attrs = _result_attrs_nt4;
        break;
    case DRSUAPI_DS_NAME_FORMAT_GUID:
        domain_attrs = _domain_attrs_guid;
        result_attrs = _result_attrs_guid;
        break;
    case DRSUAPI_DS_NAME_FORMAT_DISPLAY:
        domain_attrs = _domain_attrs_display;
        result_attrs = _result_attrs_display;
        break;
    default:
        domain_attrs = _domain_attrs_none;
        result_attrs = _result_attrs_none;
        break;
    }

    if (domain_filter) {
        /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
        ldb_ret = ldb_search(sam_ctx, mem_ctx, &domain_res,
                             partitions_basedn,
                             LDB_SCOPE_ONELEVEL,
                             domain_attrs,
                             "%s", domain_filter);

        if (ldb_ret != LDB_SUCCESS) {
            DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx)));
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        switch (domain_res->count) {
        case 1:
            break;
        case 0:
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        default:
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
            return WERR_OK;
        }

        info1->dns_domain_name	= samdb_result_string(domain_res->msgs[0], "dnsRoot", NULL);
        W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
        info1->status		= DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
    } else {
        info1->dns_domain_name	= NULL;
        info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    }

    if (result_filter) {
        int ret;
        struct ldb_result *res;
        if (domain_res) {
            result_basedn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);

            ret = ldb_search(sam_ctx, mem_ctx, &res,
                             result_basedn, LDB_SCOPE_SUBTREE,
                             result_attrs, "%s", result_filter);
            if (ret != LDB_SUCCESS) {
                talloc_free(result_res);
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }
            ldb_ret = res->count;
            result_res = res->msgs;
        } else {
            /* search with the 'phantom root' flag */
            struct ldb_request *req;

            res = talloc_zero(mem_ctx, struct ldb_result);
            W_ERROR_HAVE_NO_MEMORY(res);

            ret = ldb_build_search_req(&req, sam_ctx, mem_ctx,
                                       ldb_get_root_basedn(sam_ctx),
                                       LDB_SCOPE_SUBTREE,
                                       result_filter,
                                       result_attrs,
                                       NULL,
                                       res,
                                       ldb_search_default_callback,
                                       NULL);
            if (ret == LDB_SUCCESS) {
                struct ldb_search_options_control *search_options;
                search_options = talloc(req, struct ldb_search_options_control);
                W_ERROR_HAVE_NO_MEMORY(search_options);
                search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;

                ret = ldb_request_add_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
            }
            if (ret != LDB_SUCCESS) {
                talloc_free(res);
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }

            ret = ldb_request(sam_ctx, req);

            if (ret == LDB_SUCCESS) {
                ret = ldb_wait(req->handle, LDB_WAIT_ALL);
            }

            talloc_free(req);

            if (ret != LDB_SUCCESS) {
                DEBUG(2, ("DsCrackNameOneFilter phantom root search failed: %s",
                          ldb_errstring(sam_ctx)));
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }
            ldb_ret = res->count;
            result_res = res->msgs;
        }
    } else if (format_offered == DRSUAPI_DS_NAME_FORMAT_FQDN_1779) {
Пример #10
0
/*
  work out the principal to use for DRS replication connections
 */
NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s,
				       TALLOC_CTX *mem_ctx,
				       const struct repsFromTo1 *rft,
				       const char **target_principal)
{
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	const char *attrs[] = { "dNSHostName", NULL };
	int ret;
	const char *hostname;
	struct ldb_dn *dn;
	struct ldb_dn *forest_dn;

	*target_principal = NULL;

	tmp_ctx = talloc_new(mem_ctx);

	/* we need to find their hostname */
	ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, &dn);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their NTDSDSA DN not to be in our database */
		return NT_STATUS_OK;
	}

	/* strip off the NTDS Settings */
	if (!ldb_dn_remove_child_components(dn, 1)) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, dn, attrs, 0);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		/* its OK for their account DN not to be in our database */
		return NT_STATUS_OK;
	}

	hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
	if (hostname == NULL) {
		talloc_free(tmp_ctx);
		/* its OK to not have a dnshostname */
		return NT_STATUS_OK;
	}

	/* All DCs have the GC/hostname/realm name, but if some of the
	 * preconditions are not satisfied, then we will fall back to
	 * the
	 * E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN}
	 * name.  This means that if a AD server has a dnsHostName set
	 * on it's record, it must also have GC/hostname/realm
	 * servicePrincipalName */

	forest_dn = ldb_get_root_basedn(s->samdb);
	if (forest_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	*target_principal = talloc_asprintf(mem_ctx, "GC/%s/%s",
					    hostname,
					    samdb_dn_to_dns_domain(tmp_ctx, forest_dn));
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Пример #11
0
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
				     TALLOC_CTX *mem_ctx,
				     uint32_t access_desired,
				     struct lsa_policy_state **_state)
{
	struct auth_session_info *session_info = dce_call->conn->auth_state.session_info;
	enum security_user_level security_level;
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc_zero(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state,
				       dce_call->event_ctx,
				       dce_call->conn->dce_ctx->lp_ctx,
				       dce_call->conn->auth_state.session_info,
				       dce_call->conn->remote_address,
				       0);
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* and the privilege database */
	state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
	if (state->pdb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
				state->domain_sid);
	if (state->sd == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;

	se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
	security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);

	security_level = security_session_user_level(session_info, NULL);
	if (security_level >= SECURITY_SYSTEM) {
		/*
		 * The security descriptor doesn't allow system,
		 * but we want to allow system via ncalrpc as root.
		 */
		state->access_mask = access_desired;
		if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
			state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
			state->access_mask |= LSA_POLICY_ALL_ACCESS;
		}
	} else {
		NTSTATUS status;

		status = se_access_check(state->sd,
					 session_info->security_token,
					 access_desired,
					 &state->access_mask);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
				 __func__,
				 (unsigned)access_desired,
				 (unsigned)state->access_mask,
				 nt_errstr(status)));
			return status;
		}
	}

	DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
		  __func__,
		 (unsigned)access_desired,
		 (unsigned)state->access_mask));

	*_state = state;

	return NT_STATUS_OK;
}