Esempio n. 1
0
/*
 * Lookup local SMB group account database (/var/smb/smbgroup.db)
 * The memory for the returned SID must be freed by the caller.
 */
static uint32_t
smb_sam_lookup_group(char *name, smb_sid_t **sid)
{
	smb_group_t grp;

	if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS)
		return (NT_STATUS_NO_SUCH_ALIAS);

	*sid = smb_sid_dup(grp.sg_id.gs_sid);
	smb_lgrp_free(&grp);

	return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS);
}
Esempio n. 2
0
/*
 * Determines whether the given SID is a member of the group
 * specified by gname.
 */
boolean_t
smb_sam_grp_ismember(const char *gname, smb_sid_t *sid)
{
	smb_group_t grp;
	boolean_t ismember = B_FALSE;

	if (smb_lgrp_getbyname((char *)gname, &grp) == SMB_LGRP_SUCCESS) {
		ismember = smb_lgrp_is_member(&grp, sid);
		smb_lgrp_free(&grp);
	}

	return (ismember);
}
Esempio n. 3
0
/*
 * Looks up the given SID in local account databases:
 *
 * SMB Local users are looked up in /var/smb/smbpasswd
 * SMB Local groups are looked up in /var/smb/smbgroup.db
 *
 * If the account is found, its information is populated
 * in the passed smb_account_t structure. Caller must free
 * allocated memories by calling smb_account_free() upon
 * successful return.
 *
 * Return status:
 *
 *   NT_STATUS_NOT_FOUND	This is not a local account
 *   NT_STATUS_NONE_MAPPED	It's a local account but cannot be
 *   				translated.
 *   other error status codes.
 */
uint32_t
smb_sam_lookup_sid(smb_sid_t *sid, smb_account_t *account)
{
	char hostname[MAXHOSTNAMELEN];
	smb_passwd_t smbpw;
	smb_group_t grp;
	smb_lwka_t *lwka;
	smb_domain_t di;
	uint32_t rid;
	uid_t id;
	int id_type;
	int rc;

	bzero(account, sizeof (smb_account_t));

	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);

	if (smb_sid_cmp(sid, di.di_binsid)) {
		/* This is the local domain SID */
		account->a_type = SidTypeDomain;
		account->a_name = strdup("");
		account->a_domain = strdup(di.di_nbname);
		account->a_sid = smb_sid_dup(sid);
		account->a_domsid = smb_sid_dup(sid);
		account->a_rid = (uint32_t)-1;

		if (!smb_account_validate(account)) {
			smb_account_free(account);
			return (NT_STATUS_NO_MEMORY);
		}

		return (NT_STATUS_SUCCESS);
	}

	if (!smb_sid_indomain(di.di_binsid, sid)) {
		/* This is not a local SID */
		return (NT_STATUS_NOT_FOUND);
	}

	if ((lwka = smb_lwka_lookup_sid(sid)) != NULL) {
		account->a_type = lwka->lwka_type;
		account->a_name = strdup(lwka->lwka_name);
	} else {
		id_type = SMB_IDMAP_UNKNOWN;
		if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS)
			return (NT_STATUS_NONE_MAPPED);

		switch (id_type) {
		case SMB_IDMAP_USER:
			account->a_type = SidTypeUser;
			if (smb_pwd_getpwuid(id, &smbpw) == NULL)
				return (NT_STATUS_NO_SUCH_USER);

			account->a_name = strdup(smbpw.pw_name);
			break;

		case SMB_IDMAP_GROUP:
			account->a_type = SidTypeAlias;
			(void) smb_sid_getrid(sid, &rid);
			rc = smb_lgrp_getbyrid(rid, SMB_DOMAIN_LOCAL, &grp);
			if (rc != SMB_LGRP_SUCCESS)
				return (NT_STATUS_NO_SUCH_ALIAS);

			account->a_name = strdup(grp.sg_name);
			smb_lgrp_free(&grp);
			break;

		default:
			return (NT_STATUS_NONE_MAPPED);
		}
	}

	if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) == 0)
		account->a_domain = strdup(hostname);
	account->a_sid = smb_sid_dup(sid);
	account->a_domsid = smb_sid_split(sid, &account->a_rid);

	if (!smb_account_validate(account)) {
		smb_account_free(account);
		return (NT_STATUS_NO_MEMORY);
	}

	return (NT_STATUS_SUCCESS);
}
Esempio n. 4
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);
}
Esempio n. 5
0
/*
 * smbadm_group_show
 *
 */
static int
smbadm_group_show(int argc, char **argv)
{
	char *gname = NULL;
	boolean_t show_privs;
	boolean_t show_members;
	char option;
	int status;
	smb_group_t grp;
	smb_giter_t gi;

	show_privs = show_members = B_FALSE;

	while ((option = getopt(argc, argv, "mp")) != -1) {
		switch (option) {
		case 'm':
			show_members = B_TRUE;
			break;
		case 'p':
			show_privs = B_TRUE;
			break;

		default:
			smbadm_usage(B_FALSE);
		}
	}

	gname = argv[optind];
	if (optind >= argc || gname == NULL || *gname == '\0')
		gname = "*";

	if (strcmp(gname, "*")) {
		status = smb_lgrp_getbyname(gname, &grp);
		if (status == SMB_LGRP_SUCCESS) {
			smbadm_group_dump(&grp, show_members, show_privs);
			smb_lgrp_free(&grp);
		} else {
			(void) fprintf(stderr,
			    gettext("failed to find %s (%s)\n"),
			    gname, smb_lgrp_strerror(status));
		}
		return (status);
	}

	if ((status = smb_lgrp_iteropen(&gi)) != SMB_LGRP_SUCCESS) {
		(void) fprintf(stderr, gettext("failed to list groups (%s)\n"),
		    smb_lgrp_strerror(status));
		return (status);
	}

	while ((status = smb_lgrp_iterate(&gi, &grp)) == SMB_LGRP_SUCCESS) {
		smbadm_group_dump(&grp, show_members, show_privs);
		smb_lgrp_free(&grp);
	}

	smb_lgrp_iterclose(&gi);

	if ((status != SMB_LGRP_NO_MORE) || smb_lgrp_itererror(&gi)) {
		if (status != SMB_LGRP_NO_MORE)
			syslog(LOG_ERR, "smb_lgrp_iterate: %s",
			    smb_lgrp_strerror(status));

		(void) fprintf(stderr,
		    gettext("\nAn error occurred while retrieving group data.\n"
		    "Check the system log for more information.\n"));
		return (status);
	}

	return (0);
}