Пример #1
0
/*
 * Frees memories allocated for the passed account fields.
 */
void
smb_account_free(smb_account_t *account)
{
	free(account->a_name);
	free(account->a_domain);
	smb_sid_free(account->a_sid);
	smb_sid_free(account->a_domsid);
}
Пример #2
0
/*
 * smb_sd_term
 *
 * Free non-NULL members of 'sd' which has to be in
 * absolute (pointer) form.
 */
void
smb_sd_term(smb_sd_t *sd)
{
	ASSERT(sd);
	ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0);

	smb_sid_free(sd->sd_owner);
	smb_sid_free(sd->sd_group);
	smb_acl_free(sd->sd_dacl);
	smb_acl_free(sd->sd_sacl);

	bzero(sd, sizeof (smb_sd_t));
}
Пример #3
0
void
smb_ids_free(smb_ids_t *ids)
{
	smb_id_t *id;
	int i;

	if ((ids != NULL) && (ids->i_ids != NULL)) {
		id = ids->i_ids;
		for (i = 0; i < ids->i_cnt; i++, id++)
			smb_sid_free(id->i_sid);

		free(ids->i_ids);
	}
}
Пример #4
0
/*
 * Lookup local SMB user account database (/var/smb/smbpasswd)
 * if there's a match query its SID from idmap service and make
 * sure the SID is a local SID.
 *
 * The memory for the returned SID must be freed by the caller.
 */
static uint32_t
smb_sam_lookup_user(char *name, smb_sid_t **sid)
{
	smb_passwd_t smbpw;

	if (smb_pwd_getpwnam(name, &smbpw) == NULL)
		return (NT_STATUS_NO_SUCH_USER);

	if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid)
	    != IDMAP_SUCCESS)
		return (NT_STATUS_NONE_MAPPED);

	if (!smb_sid_islocal(*sid)) {
		smb_sid_free(*sid);
		return (NT_STATUS_NONE_MAPPED);
	}

	return (NT_STATUS_SUCCESS);
}
Пример #5
0
void
smb_acl_free(smb_acl_t *acl)
{
	int i, size;
	void *ace;

	if (acl == NULL)
		return;

	for (i = 0; i < acl->sl_acecnt; i++)
		smb_sid_free(acl->sl_aces[i].se_sid);

	while ((ace = list_head(&acl->sl_sorted)) != NULL)
		list_remove(&acl->sl_sorted, ace);
	list_destroy(&acl->sl_sorted);

	size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
	kmem_free(acl, size);
}
Пример #6
0
/*
 * Updates a list of groups in which the given user is a member
 * by adding any local (SAM) groups.
 *
 * We are a member of local groups where the local group
 * contains either the user's primary SID, or any of their
 * other SIDs such as from domain groups, SID history, etc.
 * We can have indirect membership via domain groups.
 */
uint32_t
smb_sam_usr_groups(smb_sid_t *user_sid, smb_ids_t *gids)
{
	smb_ids_t new_gids;
	smb_id_t *ids, *new_ids;
	smb_giter_t gi;
	smb_group_t lgrp;
	int i, gcnt, total_cnt;
	uint32_t ret;
	boolean_t member;

	/*
	 * First pass: count groups to be added (gcnt)
	 */
	gcnt = 0;
	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
		return (NT_STATUS_INTERNAL_ERROR);

	while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
		member = B_FALSE;
		if (smb_lgrp_is_member(&lgrp, user_sid))
			member = B_TRUE;
		else for (i = 0, ids = gids->i_ids;
		    i < gids->i_cnt; i++, ids++) {
			if (smb_lgrp_is_member(&lgrp, ids->i_sid)) {
				member = B_TRUE;
				break;
			}
		}
		/* Careful: only count lgrp once */
		if (member)
			gcnt++;
		smb_lgrp_free(&lgrp);
	}
	smb_lgrp_iterclose(&gi);

	if (gcnt == 0)
		return (NT_STATUS_SUCCESS);

	/*
	 * Second pass: add to groups list.
	 * Do not modify gcnt after here.
	 */
	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
		return (NT_STATUS_INTERNAL_ERROR);

	/*
	 * Expand the list (copy to a new, larger one)
	 * Note: were're copying pointers from the old
	 * array to the new (larger) array, and then
	 * adding new pointers after what we copied.
	 */
	ret = 0;
	new_gids.i_cnt = gids->i_cnt;
	total_cnt = gids->i_cnt + gcnt;
	new_gids.i_ids = malloc(total_cnt * sizeof (smb_id_t));
	if (new_gids.i_ids == NULL) {
		ret = NT_STATUS_NO_MEMORY;
		goto out;
	}
	(void) memcpy(new_gids.i_ids, gids->i_ids,
	    gids->i_cnt * sizeof (smb_id_t));
	new_ids = new_gids.i_ids + gids->i_cnt;
	(void) memset(new_ids, 0, gcnt * sizeof (smb_id_t));

	/*
	 * Add group SIDs starting at the end of the
	 * previous list.  (new_ids)
	 */
	while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
		member = B_FALSE;
		if (smb_lgrp_is_member(&lgrp, user_sid))
			member = B_TRUE;
		else for (i = 0, ids = gids->i_ids;
		    i < gids->i_cnt; i++, ids++) {
			if (smb_lgrp_is_member(&lgrp, ids->i_sid)) {
				member = B_TRUE;
				break;
			}
		}
		if (member && (new_gids.i_cnt < (gids->i_cnt + gcnt))) {
			new_ids->i_sid = smb_sid_dup(lgrp.sg_id.gs_sid);
			if (new_ids->i_sid == NULL) {
				smb_lgrp_free(&lgrp);
				ret = NT_STATUS_NO_MEMORY;
				goto out;
			}
			new_ids->i_attrs = lgrp.sg_attr;
			new_ids++;
			new_gids.i_cnt++;
		}
		smb_lgrp_free(&lgrp);
	}

out:
	smb_lgrp_iterclose(&gi);

	if (ret != 0) {
		if (new_gids.i_ids != NULL) {
			/*
			 * Free only the new sids we added.
			 * The old ones were copied ptrs.
			 */
			ids = new_gids.i_ids + gids->i_cnt;
			for (i = 0; i < gcnt; i++, ids++) {
				smb_sid_free(ids->i_sid);
			}
			free(new_gids.i_ids);
		}
		return (ret);
	}

	/*
	 * Success! Update passed gids and
	 * free the old array.
	 */
	free(gids->i_ids);
	*gids = new_gids;

	return (NT_STATUS_SUCCESS);
}
Пример #7
0
/*
 * smb_lucache_do_update
 *
 * This function takes care of updating the AVL tree.
 * If an entry has been updated, it'll be modified in place.
 *
 * New entries will be added to a temporary AVL tree then
 * passwod file is unlocked and all the new entries will
 * be transferred to the main cache from the temporary tree.
 *
 * This function MUST NOT be called directly
 */
static int
smb_lucache_do_update(void)
{
	avl_tree_t tmp_cache;
	smb_pwbuf_t pwbuf;
	smb_passwd_t smbpw;
	smb_ucnode_t uc_node;
	smb_ucnode_t *uc_newnode;
	smb_luser_t *user;
	smb_sid_t *sid;
	idmap_stat idm_stat;
	int rc = SMB_PWE_SUCCESS;
	void *cookie = NULL;
	FILE *fp;

	if ((rc = smb_pwd_lock()) != SMB_PWE_SUCCESS) {
		syslog(LOG_WARNING, "smb_pwdutil: lock failed, err=%d", rc);
		return (rc);
	}

	if ((fp = fopen(SMB_PASSWD, "rF")) == NULL) {
		syslog(LOG_WARNING, "smb_pwdutil: open failed, %m");
		(void) smb_pwd_unlock();
		return (SMB_PWE_OPEN_FAILED);
	}

	avl_create(&tmp_cache, smb_lucache_cmp,
	    sizeof (smb_ucnode_t), offsetof(smb_ucnode_t, cn_link));

	bzero(&pwbuf, sizeof (smb_pwbuf_t));
	pwbuf.pw_pwd = &smbpw;

	(void) rw_rdlock(&smb_uch.uc_cache_lck);

	while (smb_pwd_fgetent(fp, &pwbuf, SMB_PWD_GETF_NOPWD) != NULL) {
		uc_node.cn_user.su_name = smbpw.pw_name;
		uc_newnode = avl_find(&smb_uch.uc_cache, &uc_node, NULL);
		if (uc_newnode) {
			/* update the node info */
			uc_newnode->cn_user.su_ctrl = smbpw.pw_flags;
			continue;
		}

		/* create a new node */
		if ((uc_newnode = malloc(sizeof (smb_ucnode_t))) == NULL) {
			rc = SMB_PWE_NO_MEMORY;
			break;
		}

		bzero(uc_newnode, sizeof (smb_ucnode_t));
		user = &uc_newnode->cn_user;
		user->su_ctrl = smbpw.pw_flags;

		idm_stat = smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, &sid);
		if (idm_stat != IDMAP_SUCCESS) {
			syslog(LOG_WARNING, "smb_pwdutil: couldn't obtain SID "
			    "for uid=%u (%d)", smbpw.pw_uid, idm_stat);
			free(uc_newnode);
			continue;
		}
		(void) smb_sid_getrid(sid, &user->su_rid);
		smb_sid_free(sid);

		user->su_name = strdup(smbpw.pw_name);
		if (user->su_name == NULL) {
			rc = SMB_PWE_NO_MEMORY;
			free(uc_newnode);
			break;
		}

		avl_add(&tmp_cache, uc_newnode);
	}

	(void) rw_unlock(&smb_uch.uc_cache_lck);
	(void) fclose(fp);
	(void) smb_pwd_unlock();

	/* Destroy the temporary list */
	(void) rw_wrlock(&smb_uch.uc_cache_lck);
	while ((uc_newnode = avl_destroy_nodes(&tmp_cache, &cookie)) != NULL) {
		avl_add(&smb_uch.uc_cache, uc_newnode);
	}
	(void) rw_unlock(&smb_uch.uc_cache_lck);

	avl_destroy(&tmp_cache);

	return (rc);
}
Пример #8
0
/*
 * smbadm_group_delmember
 */
static int
smbadm_group_delmember(int argc, char **argv)
{
	lsa_account_t	acct;
	char *gname = NULL;
	char **mname;
	char option;
	smb_gsid_t msid;
	int status;
	int mcnt = 0;
	int ret = 0;
	int i;

	mname = (char **)malloc(argc * sizeof (char *));
	if (mname == NULL) {
		warn(gettext("failed to delete group member"));
		return (1);
	}
	bzero(mname, argc * sizeof (char *));

	while ((option = getopt(argc, argv, "m:")) != -1) {
		switch (option) {
		case 'm':
			mname[mcnt++] = optarg;
			break;

		default:
			free(mname);
			smbadm_usage(B_FALSE);
		}
	}

	if (mcnt == 0) {
		(void) fprintf(stderr, gettext("missing member name\n"));
		free(mname);
		smbadm_usage(B_FALSE);
	}

	gname = argv[optind];
	if (optind >= argc || gname == NULL || *gname == 0) {
		(void) fprintf(stderr, gettext("missing group name\n"));
		free(mname);
		smbadm_usage(B_FALSE);
	}


	for (i = 0; i < mcnt; i++) {
		ret = 0;
		if (mname[i] == NULL)
			continue;

		ret = smb_lookup_name(mname[i], SidTypeUnknown, &acct);
		if ((ret != 0) || (acct.a_status != NT_STATUS_SUCCESS)) {
			(void) fprintf(stderr,
			    gettext("failed to remove %s: "
			    "unable to obtain SID\n"),
			    mname[i]);
			continue;
		}

		msid.gs_type = acct.a_sidtype;

		if ((msid.gs_sid = smb_sid_fromstr(acct.a_sid)) == NULL) {
			(void) fprintf(stderr,
			    gettext("failed to remove %s: no memory\n"),
			    mname[i]);
			continue;
		}

		status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type);
		smb_sid_free(msid.gs_sid);
		if (status != SMB_LGRP_SUCCESS) {
			(void) fprintf(stderr,
			    gettext("failed to remove %s (%s)\n"),
			    mname[i], smb_lgrp_strerror(status));
			ret = 1;
		} else {
			(void) printf(
			    gettext("'%s' has been removed from %s\n"),
			    mname[i], gname);
		}
	}

	return (ret);
}