Beispiel #1
0
BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
{
	/* Trivial case */

	if (!s1 && !s2) {
		return True;
	}

	if (!s1 || !s2) {
		return False;
	}

	/* Check top level stuff */

	if (s1->type != s2->type || s1->flags != s2->flags ||
	    s1->access_mask != s2->access_mask) {
		return False;
	}

	/* Check SID */

	if (!sid_equal(&s1->trustee, &s2->trustee)) {
		return False;
	}

	return True;
}
Beispiel #2
0
bool non_mappable_sid(DOM_SID *sid)
{
	DOM_SID dom;
	uint32 rid;

	sid_copy(&dom, sid);
	sid_split_rid(&dom, &rid);

	if (sid_equal(&dom, &global_sid_Builtin))
		return True;

	if (sid_equal(&dom, &global_sid_NT_Authority))
		return True;

	return False;
}
Beispiel #3
0
NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
{
	struct idmap_methods *map = remote_map;
	DOM_SID tmp_sid;

	if (proxyonly)
		return NT_STATUS_UNSUCCESSFUL;

	DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
		   sid_string_static(sid),
		   ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID",
		   ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid : 
		   (unsigned long)id.gid));

	if ( (NT_STATUS_IS_OK(cache_map->
			      get_sid_from_id(&tmp_sid, id,
					      id_type | ID_QUERY_ONLY))) &&
	     sid_equal(sid, &tmp_sid) ) {
		/* Nothing to do, we already have that mapping */
		DEBUG(10, ("idmap_set_mapping: Mapping already there\n"));
		return NT_STATUS_OK;
	}

	if (map == NULL) {
		/* Ok, we don't have a authoritative remote
			mapping. So update our local cache only. */
		map = cache_map;
	}

	return map->set_mapping(sid, id, id_type);
}
Beispiel #4
0
BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain)
{
	fstring sid_str;
	int i = 0;
	
	sid_to_string(sid_str, sid);

	if (!sid_name_map_initialized) 
		init_sid_name_map();

	DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));

	if (nt_domain == NULL)
		return False;

	while (sid_name_map[i].sid != NULL) {
		sid_to_string(sid_str, sid_name_map[i].sid);
		DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
		if (sid_equal(sid_name_map[i].sid, sid)) {		
			fstrcpy(nt_domain, sid_name_map[i].name);
			DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
			return True;
		}
		i++;
	}

	DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));

    return False;
}
Beispiel #5
0
BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
{
	int i = 0;
	struct sid_name_map_info *psnm;

	if (!sid_name_map_initialized) 
		init_sid_name_map();

	for(i = 0; sid_name_map[i].sid != NULL; i++) {
		psnm = &sid_name_map[i];
		if(sid_equal(psnm->sid, sid)) {
			int j;
			for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
				if(rid == psnm->known_users[j].rid) {
					DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '******'\n",
						(unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
					fstrcpy( name, psnm->known_users[j].known_user_name);
					*psid_name_use = psnm->known_users[j].sid_name_use;
					return True;
				}
			}
		}
	}

	return False;
}
Beispiel #6
0
BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
{
	DOM_SID dom_sid;
	uint32 rid;

	sid_copy(&dom_sid, sid);
	sid_split_rid(&dom_sid, &rid);
	
	return sid_equal(&dom_sid, get_global_sam_sid());
}
Beispiel #7
0
BOOL sid_check_is_in_builtin(const DOM_SID *sid)
{
	DOM_SID dom_sid;
	uint32 rid;

	sid_copy(&dom_sid, sid);
	sid_split_rid(&dom_sid, &rid);
	
	return sid_equal(&dom_sid, &global_sid_Builtin);
}
Beispiel #8
0
BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
{
	size_t i;

	for (i = 0; i < token->num_sids; i++) {
		if (sid_equal(&ace->trustee, &token->user_sids[i]))
			return True;
	}

	return False;
}
Beispiel #9
0
bool token_sid_in_ace(const NT_USER_TOKEN *token, const struct security_ace *ace)
{
	size_t i;

	for (i = 0; i < token->num_sids; i++) {
		if (sid_equal(&ace->trustee, &token->user_sids[i]))
			return true;
	}

	return false;
}
Beispiel #10
0
/**
 * Turn SID into UID/GID and setup a struct ifs_identity
 */
static bool
onefs_sid_to_identity(const struct dom_sid *sid, struct ifs_identity *id,
    bool is_group)
{
	enum ifs_identity_type type = IFS_ID_TYPE_LAST+1;
	uid_t uid = 0;
	gid_t gid = 0;

	if (!sid || sid_equal(sid, &global_sid_NULL))
		type = IFS_ID_TYPE_NULL;
	else if (sid_equal(sid, &global_sid_World))
		type = IFS_ID_TYPE_EVERYONE;
	else if (sid_equal(sid, &global_sid_Creator_Owner))
		type = IFS_ID_TYPE_CREATOR_OWNER;
	else if (sid_equal(sid, &global_sid_Creator_Group))
		type = IFS_ID_TYPE_CREATOR_GROUP;
	else if (is_group) {
		if (!sid_to_gid(sid, &gid))
			return false;
		type = IFS_ID_TYPE_GID;
	} else {
		if (sid_to_uid(sid, &uid))
			type = IFS_ID_TYPE_UID;
		else if (sid_to_gid(sid, &gid))
			type = IFS_ID_TYPE_GID;
		else
			return false;
	}

	if (aclu_initialize_identity(id, type, uid, gid, is_group)) {
		DEBUG(3, ("Call to aclu_initialize_identity failed! id=%x, "
		    "type=%d, uid=%u, gid=%u, is_group=%d\n",
		    (unsigned int)id, type, uid, gid, is_group));
		return false;
	}

	return true;
}
Beispiel #11
0
/* this function searches up to IDMAP_LDAP_MAX_IDS entries
 * in maps for a match */
static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
{
	int i;

	for (i = 0; i < IDMAP_LDAP_MAX_IDS; i++) {
		if (maps[i] == NULL) { /* end of the run */
			return NULL;
		}
		if (sid_equal(maps[i]->sid, sid)) {
			return maps[i];
		}
	}

	return NULL;
}
Beispiel #12
0
/* 
   add a SID to the list of SIDs for a right
*/
NTSTATUS privilege_add_account_right(const char *right, 
				     DOM_SID *sid)
{
	NTSTATUS status;
	DOM_SID *current_sids;
	uint32 current_count;
	int i;

	status = privilege_lock_right(right);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = privilege_enum_account_with_right(right, &current_count, &current_sids);
	if (!NT_STATUS_IS_OK(status)) {
		privilege_unlock_right(right);
		return status;
	}	

	/* maybe that SID is already listed? this is not an error */
	for (i=0;i<current_count;i++) {
		if (sid_equal(&current_sids[i], sid)) {
			privilege_unlock_right(right);
			free(current_sids);
			return NT_STATUS_OK;
		}
	}

	/* add it in */
	current_sids = Realloc(current_sids, sizeof(current_sids[0]) * (current_count+1));
	if (!current_sids) {
		privilege_unlock_right(right);
		return NT_STATUS_NO_MEMORY;
	}

	sid_copy(&current_sids[current_count], sid);
	current_count++;
	
	status = privilege_set_accounts_with_right(right, current_count, current_sids);

	free(current_sids);
	privilege_unlock_right(right);

	return status;
}
Beispiel #13
0
enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
{
	extern DOM_SID global_sid_Builtin;
	enum SID_NAME_USE type;
	DOM_SID sid, tmp_sid;
	uint32 rid;
	fstring name;
	fstring dom_name;

	/* Ensure null termination */
	state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';

	DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
		  state->request.data.sid));

	/* Lookup sid from PDC using lsa_lookup_sids() */

	if (!string_to_sid(&sid, state->request.data.sid)) {
		DEBUG(5, ("%s not a SID\n", state->request.data.sid));
		return WINBINDD_ERROR;
	}

	/* Don't look up BUILTIN sids */

	sid_copy(&tmp_sid, &sid);
	sid_split_rid(&tmp_sid, &rid);

	if (sid_equal(&tmp_sid, &global_sid_Builtin)) {
		return WINBINDD_ERROR;
	}

	/* Lookup the sid */

	if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) {
		return WINBINDD_ERROR;
	}

	fstrcpy(state->response.data.name.dom_name, dom_name);
	fstrcpy(state->response.data.name.name, name);

	state->response.data.name.type = type;

	return WINBINDD_OK;
}
Beispiel #14
0
/* 
   remove a SID from the list of SIDs for a right
*/
NTSTATUS privilege_remove_account_right(const char *right, 
					DOM_SID *sid)
{
	NTSTATUS status;
	DOM_SID *current_sids;
	uint32 current_count;
	int i;

	status = privilege_lock_right(right);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = privilege_enum_account_with_right(right, &current_count, &current_sids);
	if (!NT_STATUS_IS_OK(status)) {
		privilege_unlock_right(right);
		return status;
	}	

	for (i=0;i<current_count;i++) {
		if (sid_equal(&current_sids[i], sid)) {
			/* found it - so remove it */
			if (current_count-i > 1) {
				memmove(&current_sids[i], &current_sids[i+1],
					sizeof(current_sids[0]) * ((current_count-i)-1));
			}
			current_count--;
			status = privilege_set_accounts_with_right(right, 
								   current_count, 
								   current_sids);
			free(current_sids);
			privilege_unlock_right(right);
			return status;
		}
	}

	/* removing a right that you don't have is not an error */
	
	safe_free(current_sids);
	privilege_unlock_right(right);
	return NT_STATUS_OK;
}
Beispiel #15
0
/*
  an internal function for checking if a SID has a right
*/
static BOOL privilege_sid_has_right(DOM_SID *sid, const char *right)
{
	NTSTATUS status;
	uint32 count;
	DOM_SID *sids;
	int i;

	status = privilege_enum_account_with_right(right, &count, &sids);
	if (!NT_STATUS_IS_OK(status)) {
		return False;
	}
	for (i=0;i<count;i++) {
		if (sid_equal(sid, &sids[i])) {
			free(sids);
			return True;
		}
	}	

	safe_free(sids);
	return False;
}
Beispiel #16
0
BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
{
	if (!name_type)
		return False;

	*name_type = SID_NAME_UNKNOWN;

	/* Check if this is our own sid.  This should perhaps be done by
	   winbind?  For the moment handle it here. */

	if (sid->num_auths == 5) {
		DOM_SID tmp_sid;
		uint32 rid;

		sid_copy(&tmp_sid, sid);
		sid_split_rid(&tmp_sid, &rid);

		if (sid_equal(&global_sam_sid, &tmp_sid)) {

			return map_domain_sid_to_name(&tmp_sid, dom_name) &&
				local_lookup_rid(rid, name, name_type);
		}
	}

	if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
		fstring sid_str;
		DOM_SID tmp_sid;
		uint32 rid;

		DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));

		sid_copy(&tmp_sid, sid);
		sid_split_rid(&tmp_sid, &rid);
		return map_domain_sid_to_name(&tmp_sid, dom_name) &&
				lookup_known_rid(&tmp_sid, rid, name, name_type);
	}
	return True;
}
Beispiel #17
0
static bool
sid_in_ignore_list(struct dom_sid * sid, int snum)
{
	const char ** sid_list = NULL;
	struct dom_sid match;

	sid_list = lp_parm_string_list(snum, PARM_ONEFS_TYPE,
	    PARM_UNMAPPABLE_SIDS_IGNORE_LIST,
	    PARM_UNMAPPABLE_SIDS_IGNORE_LIST_DEFAULT);

	/* Fast path a NULL list */
	if (!sid_list || *sid_list == NULL)
		return false;

	while (*sid_list) {
		if (string_to_sid(&match, *sid_list))
			if (sid_equal(sid, &match))
				return true;
		sid_list++;
	}

	return false;
}
Beispiel #18
0
void del_sid_from_array(const DOM_SID *sid, DOM_SID **sids, size_t *num)
{
	DOM_SID *sid_list = *sids;
	size_t i;

	for ( i=0; i<*num; i++ ) {

		/* if we find the SID, then decrement the count
		   and break out of the loop */

		if ( sid_equal(sid, &sid_list[i]) ) {
			*num -= 1;
			break;
		}
	}

	/* This loop will copy the remainder of the array 
	   if i < num of sids ni the array */

	for ( ; i<*num; i++ ) 
		sid_copy( &sid_list[i], &sid_list[i+1] );
	
	return;
}
Beispiel #19
0
BOOL sid_check_is_builtin(const DOM_SID *sid)
{
	return sid_equal(sid, &global_sid_Builtin);
}
Beispiel #20
0
bool sid_check_is_unix_groups(const DOM_SID *sid)
{
	return sid_equal(sid, &global_sid_Unix_Groups);
}
Beispiel #21
0
bool sid_check_is_unix_users(const DOM_SID *sid)
{
	return sid_equal(sid, &global_sid_Unix_Users);
}
Beispiel #22
0
static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx, 
				     NET_USER_INFO_3 *info3,
				     const char *group_sid) 
{
	DOM_SID required_membership_sid;
	DOM_SID *all_sids;
	size_t num_all_sids = (2 + info3->num_groups2 + info3->num_other_sids);
	size_t i, j = 0;

	/* Parse the 'required group' SID */
	
	if (!group_sid || !group_sid[0]) {
		/* NO sid supplied, all users may access */
		return NT_STATUS_OK;
	}
	
	if (!string_to_sid(&required_membership_sid, group_sid)) {
		DEBUG(0, ("check_info3_in_group: could not parse %s as a SID!", 
			  group_sid));

		return NT_STATUS_INVALID_PARAMETER;
	}

	all_sids = talloc(mem_ctx, sizeof(DOM_SID) * num_all_sids);
	if (!all_sids)
		return NT_STATUS_NO_MEMORY;

	/* and create (by appending rids) the 'domain' sids */
	
	sid_copy(&all_sids[0], &(info3->dom_sid.sid));
	
	if (!sid_append_rid(&all_sids[0], info3->user_rid)) {
		DEBUG(3,("could not append user's primary RID 0x%x\n",
			 info3->user_rid));			
		
		return NT_STATUS_INVALID_PARAMETER;
	}
	j++;

	sid_copy(&all_sids[1], &(info3->dom_sid.sid));
		
	if (!sid_append_rid(&all_sids[1], info3->group_rid)) {
		DEBUG(3,("could not append additional group rid 0x%x\n",
			 info3->group_rid));			
		
		return NT_STATUS_INVALID_PARAMETER;
	}
	j++;	

	for (i = 0; i < info3->num_groups2; i++) {
	
		sid_copy(&all_sids[j], &(info3->dom_sid.sid));
		
		if (!sid_append_rid(&all_sids[j], info3->gids[j].g_rid)) {
			DEBUG(3,("could not append additional group rid 0x%x\n",
				info3->gids[j].g_rid));			
				
			return NT_STATUS_INVALID_PARAMETER;
		}
		j++;
	}

	/* Copy 'other' sids.  We need to do sid filtering here to
 	   prevent possible elevation of privileges.  See:

           http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
         */

	for (i = 0; i < info3->num_other_sids; i++) {
		sid_copy(&all_sids[info3->num_groups2 + i + 2],
			 &info3->other_sids[j].sid);
		j++;
	}

	for (i = 0; i < j; i++) {
		fstring sid1, sid2;
		DEBUG(10, ("User has SID: %s\n", 
			   sid_to_string(sid1, &all_sids[i])));
		if (sid_equal(&required_membership_sid, &all_sids[i])) {
			DEBUG(10, ("SID %s matches %s - user permitted to authenticate!\n", 
				   sid_to_string(sid1, &required_membership_sid), sid_to_string(sid2, &all_sids[i])));
			return NT_STATUS_OK;
		}
	}
	
	/* Do not distinguish this error from a wrong username/pw */

	return NT_STATUS_LOGON_FAILURE;
}
Beispiel #23
0
/* dump sam database via samsync rpc calls */
NTSTATUS rpc_vampire_internals(struct net_context *c,
				const DOM_SID *domain_sid,
				const char *domain_name,
				struct cli_state *cli,
				struct rpc_pipe_client *pipe_hnd,
				TALLOC_CTX *mem_ctx,
				int argc,
				const char **argv)
{
	NTSTATUS result;
	struct samsync_context *ctx = NULL;

	if (!sid_equal(domain_sid, get_global_sam_sid())) {
		d_printf("Cannot import users from %s at this time, "
			 "as the current domain:\n\t%s: %s\nconflicts "
			 "with the remote domain\n\t%s: %s\n"
			 "Perhaps you need to set: \n\n\tsecurity=user\n\t"
			 "workgroup=%s\n\n in your smb.conf?\n",
			 domain_name,
			 get_global_sam_name(),
			 sid_string_dbg(get_global_sam_sid()),
			 domain_name,
			 sid_string_dbg(domain_sid),
			 domain_name);
		return NT_STATUS_UNSUCCESSFUL;
	}

	result = libnet_samsync_init_context(mem_ctx,
					     domain_sid,
					     &ctx);
	if (!NT_STATUS_IS_OK(result)) {
		return result;
	}

	ctx->mode		= NET_SAMSYNC_MODE_FETCH_PASSDB;
	ctx->cli		= pipe_hnd;
	ctx->ops		= &libnet_samsync_passdb_ops;
	ctx->domain_name	= domain_name;

	ctx->force_full_replication = c->opt_force_full_repl ? true : false;
	ctx->clean_old_entries = c->opt_clean_old_entries ? true : false;

	parse_samsync_partial_replication_objects(ctx, argc, argv,
						  &ctx->single_object_replication,
						  &ctx->objects,
						  &ctx->num_objects);

	/* fetch domain */
	result = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);

	if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
		d_fprintf(stderr, "%s\n", ctx->error_message);
		goto fail;
	}

	if (ctx->result_message) {
		d_fprintf(stdout, "%s\n", ctx->result_message);
	}

	/* fetch builtin */
	ctx->domain_sid = sid_dup_talloc(mem_ctx, &global_sid_Builtin);
	ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
	result = libnet_samsync(SAM_DATABASE_BUILTIN, ctx);

	if (!NT_STATUS_IS_OK(result) && ctx->error_message) {
		d_fprintf(stderr, "%s\n", ctx->error_message);
		goto fail;
	}

	if (ctx->result_message) {
		d_fprintf(stdout, "%s\n", ctx->result_message);
	}

 fail:
	TALLOC_FREE(ctx);
	return result;
}
Beispiel #24
0
BOOL sid_check_is_domain(const DOM_SID *sid)
{
	return sid_equal(sid, get_global_sam_sid());
}
static WERROR NetLocalGroupModifyMembers_r(struct libnetapi_ctx *ctx,
					   struct NetLocalGroupAddMembers *add,
					   struct NetLocalGroupDelMembers *del,
					   struct NetLocalGroupSetMembers *set)
{
	struct NetLocalGroupAddMembers *r = NULL;

	struct cli_state *cli = NULL;
	struct rpc_pipe_client *pipe_cli = NULL;
	struct rpc_pipe_client *lsa_pipe = NULL;
	NTSTATUS status;
	WERROR werr;
	struct lsa_String lsa_account_name;
	struct policy_handle connect_handle, domain_handle, builtin_handle, alias_handle;
	struct dom_sid2 *domain_sid = NULL;
	struct dom_sid *member_sids = NULL;
	int i = 0, k = 0;

	struct LOCALGROUP_MEMBERS_INFO_0 *info0 = NULL;
	struct LOCALGROUP_MEMBERS_INFO_3 *info3 = NULL;

	struct dom_sid *add_sids = NULL;
	struct dom_sid *del_sids = NULL;
	size_t num_add_sids = 0;
	size_t num_del_sids = 0;

	if ((!add && !del && !set) || (add && del && set)) {
		return WERR_INVALID_PARAM;
	}

	if (add) {
		r = add;
	}

	if (del) {
		r = (struct NetLocalGroupAddMembers *)del;
	}

	if (set) {
		r = (struct NetLocalGroupAddMembers *)set;
	}

	if (!r->in.group_name) {
		return WERR_INVALID_PARAM;
	}

	switch (r->in.level) {
		case 0:
		case 3:
			break;
		default:
			return WERR_UNKNOWN_LEVEL;
	}

	if (r->in.total_entries == 0 || !r->in.buffer) {
		return WERR_INVALID_PARAM;
	}

	ZERO_STRUCT(connect_handle);
	ZERO_STRUCT(builtin_handle);
	ZERO_STRUCT(domain_handle);
	ZERO_STRUCT(alias_handle);

	member_sids = TALLOC_ZERO_ARRAY(ctx, struct dom_sid,
					r->in.total_entries);
	W_ERROR_HAVE_NO_MEMORY(member_sids);

	switch (r->in.level) {
		case 0:
			info0 = (struct LOCALGROUP_MEMBERS_INFO_0 *)r->in.buffer;
			for (i=0; i < r->in.total_entries; i++) {
				sid_copy(&member_sids[i], (struct dom_sid *)info0[i].lgrmi0_sid);
			}
			break;
		case 3:
			info3 = (struct LOCALGROUP_MEMBERS_INFO_3 *)r->in.buffer;
			break;
		default:
			break;
	}

	if (r->in.level == 3) {
		werr = libnetapi_open_pipe(ctx, r->in.server_name,
					   &ndr_table_lsarpc.syntax_id,
					   &cli,
					   &lsa_pipe);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}

		for (i=0; i < r->in.total_entries; i++) {
			status = libnetapi_lsa_lookup_names3(ctx, lsa_pipe,
							     info3[i].lgrmi3_domainandname,
							     &member_sids[i]);
			if (!NT_STATUS_IS_OK(status)) {
				werr = ntstatus_to_werror(status);
				goto done;
			}
		}
		TALLOC_FREE(lsa_pipe);
	}

	werr = libnetapi_open_pipe(ctx, r->in.server_name,
				   &ndr_table_samr.syntax_id,
				   &cli,
				   &pipe_cli);
	if (!W_ERROR_IS_OK(werr)) {
		goto done;
	}

	werr = libnetapi_samr_open_builtin_domain(ctx, pipe_cli,
						  SAMR_ACCESS_LOOKUP_DOMAIN |
						  SAMR_ACCESS_ENUM_DOMAINS,
						  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
						  &connect_handle,
						  &builtin_handle);
	if (!W_ERROR_IS_OK(werr)) {
		goto done;
	}

	init_lsa_String(&lsa_account_name, r->in.group_name);

	status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
						      &builtin_handle,
						      r->in.group_name,
						      SAMR_ALIAS_ACCESS_ADD_MEMBER |
						      SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
						      SAMR_ALIAS_ACCESS_GET_MEMBERS |
						      SAMR_ALIAS_ACCESS_LOOKUP_INFO,
						      &alias_handle);

	if (ctx->disable_policy_handle_cache) {
		libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
	}

	if (NT_STATUS_IS_OK(status)) {
		goto modify_membership;
	}

	werr = libnetapi_samr_open_domain(ctx, pipe_cli,
					  SAMR_ACCESS_ENUM_DOMAINS |
					  SAMR_ACCESS_LOOKUP_DOMAIN,
					  SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
					  &connect_handle,
					  &domain_handle,
					  &domain_sid);
	if (!W_ERROR_IS_OK(werr)) {
		goto done;
	}

	status = libnetapi_samr_lookup_and_open_alias(ctx, pipe_cli,
						      &domain_handle,
						      r->in.group_name,
						      SAMR_ALIAS_ACCESS_ADD_MEMBER |
						      SAMR_ALIAS_ACCESS_REMOVE_MEMBER |
						      SAMR_ALIAS_ACCESS_GET_MEMBERS |
						      SAMR_ALIAS_ACCESS_LOOKUP_INFO,
						      &alias_handle);
	if (!NT_STATUS_IS_OK(status)) {
		werr = ntstatus_to_werror(status);
		goto done;
	}

	if (ctx->disable_policy_handle_cache) {
		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
	}

 modify_membership:

	if (add) {
		for (i=0; i < r->in.total_entries; i++) {
			status = add_sid_to_array_unique(ctx, &member_sids[i],
							 &add_sids,
							 &num_add_sids);
			if (!NT_STATUS_IS_OK(status)) {
				werr = ntstatus_to_werror(status);
				goto done;
			}
		}
	}

	if (del) {
		for (i=0; i < r->in.total_entries; i++) {
			status = add_sid_to_array_unique(ctx, &member_sids[i],
							 &del_sids,
							 &num_del_sids);
			if (!NT_STATUS_IS_OK(status)) {
				werr = ntstatus_to_werror(status);
				goto done;
			}
		}
	}

	if (set) {

		struct lsa_SidArray current_sids;

		status = rpccli_samr_GetMembersInAlias(pipe_cli, ctx,
						       &alias_handle,
						       &current_sids);
		if (!NT_STATUS_IS_OK(status)) {
			werr = ntstatus_to_werror(status);
			goto done;
		}

		/* add list */

		for (i=0; i < r->in.total_entries; i++) {
			bool already_member = false;
			for (k=0; k < current_sids.num_sids; k++) {
				if (sid_equal(&member_sids[i],
					      current_sids.sids[k].sid)) {
					already_member = true;
					break;
				}
			}
			if (!already_member) {
				status = add_sid_to_array_unique(ctx,
					&member_sids[i],
					&add_sids, &num_add_sids);
				if (!NT_STATUS_IS_OK(status)) {
					werr = ntstatus_to_werror(status);
					goto done;
				}
			}
		}

		/* del list */

		for (k=0; k < current_sids.num_sids; k++) {
			bool keep_member = false;
			for (i=0; i < r->in.total_entries; i++) {
				if (sid_equal(&member_sids[i],
					      current_sids.sids[k].sid)) {
					keep_member = true;
					break;
				}
			}
			if (!keep_member) {
				status = add_sid_to_array_unique(ctx,
						current_sids.sids[k].sid,
						&del_sids, &num_del_sids);
				if (!NT_STATUS_IS_OK(status)) {
					werr = ntstatus_to_werror(status);
					goto done;
				}
			}
		}
	}

	/* add list */

	for (i=0; i < num_add_sids; i++) {
		status = rpccli_samr_AddAliasMember(pipe_cli, ctx,
						    &alias_handle,
						    &add_sids[i]);
		if (!NT_STATUS_IS_OK(status)) {
			werr = ntstatus_to_werror(status);
			goto done;
		}
	}

	/* del list */

	for (i=0; i < num_del_sids; i++) {
		status = rpccli_samr_DeleteAliasMember(pipe_cli, ctx,
						       &alias_handle,
						       &del_sids[i]);
		if (!NT_STATUS_IS_OK(status)) {
			werr = ntstatus_to_werror(status);
			goto done;
		}
	}

	werr = WERR_OK;

 done:
	if (!cli) {
		return werr;
	}

	if (is_valid_policy_hnd(&alias_handle)) {
		rpccli_samr_Close(pipe_cli, ctx, &alias_handle);
	}

	if (ctx->disable_policy_handle_cache) {
		libnetapi_samr_close_domain_handle(ctx, &domain_handle);
		libnetapi_samr_close_builtin_handle(ctx, &builtin_handle);
		libnetapi_samr_close_connect_handle(ctx, &connect_handle);
	}

	return werr;
}
Beispiel #26
0
static BOOL pdb_generate_sam_sid(void)
{
	DOM_SID domain_sid;
	char *fname = NULL;
	BOOL is_dc = False;

	if(global_sam_sid==NULL)
		if(!(global_sam_sid=(DOM_SID *)malloc(sizeof(DOM_SID))))
			return False;
			
	generate_wellknown_sids();

	switch (lp_server_role()) {
	case ROLE_DOMAIN_PDC:
	case ROLE_DOMAIN_BDC:
		is_dc = True;
		break;
	default:
		is_dc = False;
		break;
	}

	if (is_dc) {
		if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
			sid_copy(global_sam_sid, &domain_sid);
			return True;
		}
	}

	if (secrets_fetch_domain_sid(global_myname(), global_sam_sid)) {

		/* We got our sid. If not a pdc/bdc, we're done. */
		if (!is_dc)
			return True;

		if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {

			/* No domain sid and we're a pdc/bdc. Store it */

			if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
				return False;
			}
			return True;
		}

		if (!sid_equal(&domain_sid, global_sam_sid)) {

			/* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */

			DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
			if (!secrets_store_domain_sid(global_myname(), &domain_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
				return False;
			}
			return True;
		}

		return True;
		
	}

	/* check for an old MACHINE.SID file for backwards compatibility */
	asprintf(&fname, "%s/MACHINE.SID", lp_private_dir());

	if (read_sid_from_file(fname, global_sam_sid)) {
		/* remember it for future reference and unlink the old MACHINE.SID */
		if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
			SAFE_FREE(fname);
			return False;
		}
		unlink(fname);
		if (is_dc) {
			if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
				SAFE_FREE(fname);
				return False;
			}
		}

		/* Stored the old sid from MACHINE.SID successfully.*/
		SAFE_FREE(fname);
		return True;
	}

	SAFE_FREE(fname);

	/* we don't have the SID in secrets.tdb, we will need to
           generate one and save it */
	generate_random_sid(global_sam_sid);

	if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) {
		DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
		return False;
	}
	if (is_dc) {
		if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
			return False;
		}
	}

	return True;
}   
Beispiel #27
0
bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
{
	/* Trivial case */

	if (!s1 && !s2) {
		goto done;
	}

	if (!s1 || !s2) {
		return False;
	}

	/* Check top level stuff */

	if (s1->revision != s2->revision) {
		DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
			   s1->revision, s2->revision));
		return False;
	}

	if (s1->type!= s2->type) {
		DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
			   s1->type, s2->type));
		return False;
	}

	/* Check owner and group */

	if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
		DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
			   sid_string_dbg(s1->owner_sid),
			   sid_string_dbg(s2->owner_sid)));
		return False;
	}

	if (!sid_equal(s1->group_sid, s2->group_sid)) {
		DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
			   sid_string_dbg(s1->group_sid),
			   sid_string_dbg(s2->group_sid)));
		return False;
	}

	/* Check ACLs present in one but not the other */

	if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
	    (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
		DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
		return False;
	}

	/* Sigh - we have to do it the hard way by iterating over all
	   the ACEs in the ACLs */

	if (!sec_acl_equal(s1->dacl, s2->dacl) ||
	    !sec_acl_equal(s1->sacl, s2->sacl)) {
		DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
		return False;
	}

 done:
	DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
	return True;
}
Beispiel #28
0
/*******************************************************************
 gets a domain user's groups
 ********************************************************************/
NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid)
{
	SAM_ACCOUNT *sam_pass=NULL;
	int i, cur_rid=0;
	gid_t gid;
	gid_t *groups = NULL;
	int num_groups;
	GROUP_MAP map;
	DOM_SID tmp_sid;
	fstring user_name;
	fstring str_domsid, str_qsid;
	uint32 rid,grid;
	uint32 *rids=NULL, *new_rids=NULL;
	gid_t winbind_gid_low, winbind_gid_high;
	BOOL ret;
	BOOL winbind_groups_exist;

	/*
	 * this code is far from perfect.
	 * first it enumerates the full /etc/group and that can be slow.
	 * second, it works only with users' SIDs
	 * whereas the day we support nested groups, it will have to
	 * support both users's SIDs and domain groups' SIDs
	 *
	 * having our own ldap backend would be so much faster !
	 * we're far from that, but hope one day ;-) JFM.
	 */

	*prids=NULL;
	*numgroups=0;

	winbind_groups_exist = lp_idmap_gid(&winbind_gid_low, &winbind_gid_high);


	DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n", 
	          sid_to_string(str_qsid, q_sid), sid_to_string(str_domsid, sid)));

	pdb_init_sam(&sam_pass);
	become_root();
	ret = pdb_getsampwsid(sam_pass, q_sid);
	unbecome_root();
	if (ret == False) {
		pdb_free_sam(&sam_pass);
		return NT_STATUS_NO_SUCH_USER;
	}

	fstrcpy(user_name, pdb_get_username(sam_pass));
	grid=pdb_get_group_rid(sam_pass);
	if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) {
		/* this should never happen */
		DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n"));
		pdb_free_sam(&sam_pass);
		return NT_STATUS_UNSUCCESSFUL;
	}

	become_root();
	/* on some systems this must run as root */
	num_groups = getgroups_user(user_name, &groups);	
	unbecome_root();
	if (num_groups == -1) {
		/* this should never happen */
		DEBUG(2,("get_alias_user_groups: getgroups_user failed\n"));
		pdb_free_sam(&sam_pass);
		return NT_STATUS_UNSUCCESSFUL;
	}

	for (i=0;i<num_groups;i++) {

		if (!get_group_from_gid(groups[i], &map)) {
			DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i]));
			continue;
		}
		
		/* if it's not an alias, continue */
		if (map.sid_name_use != SID_NAME_ALIAS) {
			DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
			continue;
		}

		sid_copy(&tmp_sid, &map.sid);
		sid_split_rid(&tmp_sid, &rid);
		
		/* if the sid is not in the correct domain, continue */
		if (!sid_equal(&tmp_sid, sid)) {
			DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
			continue;
		}

		/* Don't return winbind groups as they are not local! */
		if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) {
			DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name));
			continue;
		}

		/* Don't return user private groups... */
		if (Get_Pwnam(map.nt_name) != 0) {
			DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name));
			continue;			
		}
		
		new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
		if (new_rids==NULL) {
			DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
			pdb_free_sam(&sam_pass);
			free(groups);
			return NT_STATUS_NO_MEMORY;
		}
		rids=new_rids;
		
		sid_peek_rid(&map.sid, &(rids[cur_rid]));
		cur_rid++;
		break;
	}

	if(num_groups) 
		free(groups);

	/* now check for the user's gid (the primary group rid) */
	for (i=0; i<cur_rid && grid!=rids[i]; i++)
		;

	/* the user's gid is already there */
	if (i!=cur_rid) {
		DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n"));
		goto done;
	}

	DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name));

	if(!get_group_from_gid(gid, &map)) {
		DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your "
		"/etc/passwd and /etc/group files\n", user_name));
		goto done;
	}	

	/* the primary group isn't an alias */
	if (map.sid_name_use!=SID_NAME_ALIAS) {
		DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
		goto done;
	}

	sid_copy(&tmp_sid, &map.sid);
	sid_split_rid(&tmp_sid, &rid);

	/* if the sid is not in the correct domain, continue */
	if (!sid_equal(&tmp_sid, sid)) {
		DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
		goto done;
	}

	/* Don't return winbind groups as they are not local! */
	if (winbind_groups_exist && (gid >= winbind_gid_low) && (gid <= winbind_gid_high)) {
		DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name ));
		goto done;
	}

	/* Don't return user private groups... */
	if (Get_Pwnam(map.nt_name) != 0) {
		DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name ));
		goto done;			
	}

	new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
	if (new_rids==NULL) {
		DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
		pdb_free_sam(&sam_pass);
		return NT_STATUS_NO_MEMORY;
	}
	rids=new_rids;

 	sid_peek_rid(&map.sid, &(rids[cur_rid]));
	cur_rid++;

done:
 	*prids=rids;
	*numgroups=cur_rid;
	pdb_free_sam(&sam_pass);

	return NT_STATUS_OK;
}
Beispiel #29
0
bool is_null_sid(const DOM_SID *sid)
{
	static const DOM_SID null_sid = {0};
	return sid_equal(sid, &null_sid);
}
Beispiel #30
0
static int change_share_sec(TALLOC_CTX *mem_ctx, const char *sharename, char *the_acl, enum acl_mode mode)
{
	SEC_DESC *sd = NULL;
	SEC_DESC *old = NULL;
	size_t sd_size = 0;
	uint32 i, j;
	
	if (mode != SMB_ACL_SET) {
	    if (!(old = get_share_security( mem_ctx, sharename, &sd_size )) ) {
		fprintf(stderr, "Unable to retrieve permissions for share [%s]\n", sharename);
		return -1;
	    }
	}

	if ( (mode != SMB_ACL_VIEW) && !(sd = parse_acl_string(mem_ctx, the_acl, &sd_size )) ) {
		fprintf( stderr, "Failed to parse acl\n");
		return -1;
	}
	
	switch (mode) {
	case SMB_ACL_VIEW:
		sec_desc_print( stdout, old);
		return 0;
	case SMB_ACL_DELETE:
	    for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
		bool found = False;

		for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
		    if (sec_ace_equal(&sd->dacl->aces[i], &old->dacl->aces[j])) {
			uint32 k;
			for (k=j; k<old->dacl->num_aces-1;k++) {
			    old->dacl->aces[k] = old->dacl->aces[k+1];
			}
			old->dacl->num_aces--;
			found = True;
			break;
		    }
		}

		if (!found) {
		printf("ACL for ACE:");
		print_ace(stdout, &sd->dacl->aces[i]);
		printf(" not found\n");
		}
	    }

	    break;
	case SMB_ACL_MODIFY:
	    for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
		bool found = False;

		for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
		    if (sid_equal(&sd->dacl->aces[i].trustee,
			&old->dacl->aces[j].trustee)) {
			old->dacl->aces[j] = sd->dacl->aces[i];
			found = True;
		    }
		}

		if (!found) {
		    printf("ACL for SID %s not found\n",
			   sid_string_tos(&sd->dacl->aces[i].trustee));
		}
	    }

	    if (sd->owner_sid) {
		old->owner_sid = sd->owner_sid;
	    }

	    if (sd->group_sid) {
		old->group_sid = sd->group_sid;
	    }
	    break;
	case SMB_ACL_ADD:
	    for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
		add_ace(mem_ctx, &old->dacl, &sd->dacl->aces[i]);
	    }
	    break;
	case SMB_ACL_SET:
	    old = sd;
	    break;
	}

	/* Denied ACE entries must come before allowed ones */
	sort_acl(old->dacl);

	if ( !set_share_security( sharename, old ) ) {
	    fprintf( stderr, "Failed to store acl for share [%s]\n", sharename );
	    return 2;
	}
	return 0;
}