xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_sam.c (revision 11963:061945695ce1)
18670SJose.Borrego@Sun.COM /*
28670SJose.Borrego@Sun.COM  * CDDL HEADER START
38670SJose.Borrego@Sun.COM  *
48670SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58670SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68670SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78670SJose.Borrego@Sun.COM  *
88670SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98670SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108670SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118670SJose.Borrego@Sun.COM  * and limitations under the License.
128670SJose.Borrego@Sun.COM  *
138670SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148670SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158670SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168670SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178670SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188670SJose.Borrego@Sun.COM  *
198670SJose.Borrego@Sun.COM  * CDDL HEADER END
208670SJose.Borrego@Sun.COM  */
218670SJose.Borrego@Sun.COM /*
22*11963SAfshin.Ardakani@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238670SJose.Borrego@Sun.COM  * Use is subject to license terms.
248670SJose.Borrego@Sun.COM  */
258670SJose.Borrego@Sun.COM 
268670SJose.Borrego@Sun.COM #include <strings.h>
278670SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
288670SJose.Borrego@Sun.COM 
298670SJose.Borrego@Sun.COM extern int smb_pwd_num(void);
30*11963SAfshin.Ardakani@Sun.COM extern int smb_lgrp_numbydomain(smb_domain_type_t, int *);
318670SJose.Borrego@Sun.COM 
328670SJose.Borrego@Sun.COM static uint32_t smb_sam_lookup_user(char *, smb_sid_t **);
338670SJose.Borrego@Sun.COM static uint32_t smb_sam_lookup_group(char *, smb_sid_t **);
348670SJose.Borrego@Sun.COM 
358670SJose.Borrego@Sun.COM /*
369832Samw@Sun.COM  * Local well-known accounts data structure table and prototypes
379832Samw@Sun.COM  */
389832Samw@Sun.COM typedef struct smb_lwka {
399832Samw@Sun.COM 	uint32_t	lwka_rid;
409832Samw@Sun.COM 	char		*lwka_name;
419832Samw@Sun.COM 	uint16_t	lwka_type;
429832Samw@Sun.COM } smb_lwka_t;
439832Samw@Sun.COM 
449832Samw@Sun.COM static smb_lwka_t lwka_tbl[] = {
459832Samw@Sun.COM 	{ 500, "Administrator", SidTypeUser },
469832Samw@Sun.COM 	{ 501, "Guest", SidTypeUser },
479832Samw@Sun.COM 	{ 502, "KRBTGT", SidTypeUser },
489832Samw@Sun.COM 	{ 512, "Domain Admins", SidTypeGroup },
499832Samw@Sun.COM 	{ 513, "Domain Users", SidTypeGroup },
509832Samw@Sun.COM 	{ 514, "Domain Guests", SidTypeGroup },
519832Samw@Sun.COM 	{ 516, "Domain Controllers", SidTypeGroup },
529832Samw@Sun.COM 	{ 517, "Cert Publishers", SidTypeGroup },
539832Samw@Sun.COM 	{ 518, "Schema Admins", SidTypeGroup },
549832Samw@Sun.COM 	{ 519, "Enterprise Admins", SidTypeGroup },
559832Samw@Sun.COM 	{ 520, "Global Policy Creator Owners", SidTypeGroup },
569832Samw@Sun.COM 	{ 533, "RAS and IAS Servers", SidTypeGroup }
579832Samw@Sun.COM };
589832Samw@Sun.COM 
599832Samw@Sun.COM #define	SMB_LWKA_NUM	(sizeof (lwka_tbl)/sizeof (lwka_tbl[0]))
609832Samw@Sun.COM 
619832Samw@Sun.COM static smb_lwka_t *smb_lwka_lookup_name(char *);
629832Samw@Sun.COM static smb_lwka_t *smb_lwka_lookup_sid(smb_sid_t *);
639832Samw@Sun.COM 
649832Samw@Sun.COM /*
658670SJose.Borrego@Sun.COM  * Looks up the given name in local account databases:
668670SJose.Borrego@Sun.COM  *
678670SJose.Borrego@Sun.COM  * SMB Local users are looked up in /var/smb/smbpasswd
688670SJose.Borrego@Sun.COM  * SMB Local groups are looked up in /var/smb/smbgroup.db
698670SJose.Borrego@Sun.COM  *
708670SJose.Borrego@Sun.COM  * If the account is found, its information is populated
718670SJose.Borrego@Sun.COM  * in the passed smb_account_t structure. Caller must free
728670SJose.Borrego@Sun.COM  * allocated memories by calling smb_account_free() upon
738670SJose.Borrego@Sun.COM  * successful return.
748670SJose.Borrego@Sun.COM  *
758670SJose.Borrego@Sun.COM  * The type of account is specified by 'type', which can be user,
768670SJose.Borrego@Sun.COM  * alias (local group) or unknown. If the caller doesn't know
778670SJose.Borrego@Sun.COM  * whether the name is a user or group name then SidTypeUnknown
788670SJose.Borrego@Sun.COM  * should be passed.
798670SJose.Borrego@Sun.COM  *
808670SJose.Borrego@Sun.COM  * If a local user and group have the same name, the user will
818670SJose.Borrego@Sun.COM  * always be picked. Note that this situation cannot happen on
828670SJose.Borrego@Sun.COM  * Windows systems.
838670SJose.Borrego@Sun.COM  *
848670SJose.Borrego@Sun.COM  * If a SMB local user/group is found but it turns out that
858670SJose.Borrego@Sun.COM  * it'll be mapped to a domain user/group the lookup is considered
868670SJose.Borrego@Sun.COM  * failed and NT_STATUS_NONE_MAPPED is returned.
878670SJose.Borrego@Sun.COM  *
888670SJose.Borrego@Sun.COM  * Return status:
898670SJose.Borrego@Sun.COM  *
908670SJose.Borrego@Sun.COM  *   NT_STATUS_NOT_FOUND	This is not a local account
918670SJose.Borrego@Sun.COM  *   NT_STATUS_NONE_MAPPED	It's a local account but cannot be
928670SJose.Borrego@Sun.COM  *   				translated.
938670SJose.Borrego@Sun.COM  *   other error status codes.
948670SJose.Borrego@Sun.COM  */
958670SJose.Borrego@Sun.COM uint32_t
smb_sam_lookup_name(char * domain,char * name,uint16_t type,smb_account_t * account)968670SJose.Borrego@Sun.COM smb_sam_lookup_name(char *domain, char *name, uint16_t type,
978670SJose.Borrego@Sun.COM     smb_account_t *account)
988670SJose.Borrego@Sun.COM {
9910717Samw@Sun.COM 	smb_domain_t di;
1008670SJose.Borrego@Sun.COM 	smb_sid_t *sid;
1018670SJose.Borrego@Sun.COM 	uint32_t status;
1029832Samw@Sun.COM 	smb_lwka_t *lwka;
1038670SJose.Borrego@Sun.COM 
1048670SJose.Borrego@Sun.COM 	bzero(account, sizeof (smb_account_t));
1058670SJose.Borrego@Sun.COM 
1068670SJose.Borrego@Sun.COM 	if (domain != NULL) {
10710717Samw@Sun.COM 		if (!smb_domain_lookup_name(domain, &di) ||
10810717Samw@Sun.COM 		    (di.di_type != SMB_DOMAIN_LOCAL))
1098670SJose.Borrego@Sun.COM 			return (NT_STATUS_NOT_FOUND);
1108670SJose.Borrego@Sun.COM 
1118670SJose.Borrego@Sun.COM 		/* Only Netbios hostname is accepted */
11210966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(domain, di.di_nbname, 0) != 0)
1138670SJose.Borrego@Sun.COM 			return (NT_STATUS_NONE_MAPPED);
1149832Samw@Sun.COM 	} else {
11510717Samw@Sun.COM 		if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
1169832Samw@Sun.COM 			return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
1179832Samw@Sun.COM 	}
1189832Samw@Sun.COM 
11910966SJordan.Brown@Sun.COM 	if (smb_strcasecmp(name, di.di_nbname, 0) == 0) {
1209832Samw@Sun.COM 		/* This is the local domain name */
1219832Samw@Sun.COM 		account->a_type = SidTypeDomain;
1229832Samw@Sun.COM 		account->a_name = strdup("");
1239832Samw@Sun.COM 		account->a_domain = strdup(di.di_nbname);
1249832Samw@Sun.COM 		account->a_sid = smb_sid_dup(di.di_binsid);
1259832Samw@Sun.COM 		account->a_domsid = smb_sid_dup(di.di_binsid);
1269832Samw@Sun.COM 		account->a_rid = (uint32_t)-1;
1279832Samw@Sun.COM 
1289832Samw@Sun.COM 		if (!smb_account_validate(account)) {
1299832Samw@Sun.COM 			smb_account_free(account);
1309832Samw@Sun.COM 			return (NT_STATUS_NO_MEMORY);
1319832Samw@Sun.COM 		}
1329832Samw@Sun.COM 
1339832Samw@Sun.COM 		return (NT_STATUS_SUCCESS);
1348670SJose.Borrego@Sun.COM 	}
1358670SJose.Borrego@Sun.COM 
1369832Samw@Sun.COM 	if ((lwka = smb_lwka_lookup_name(name)) != NULL) {
1379832Samw@Sun.COM 		sid = smb_sid_splice(di.di_binsid, lwka->lwka_rid);
1389832Samw@Sun.COM 		type = lwka->lwka_type;
1399832Samw@Sun.COM 	} else {
1409832Samw@Sun.COM 		switch (type) {
1419832Samw@Sun.COM 		case SidTypeUser:
1429832Samw@Sun.COM 			status = smb_sam_lookup_user(name, &sid);
1439832Samw@Sun.COM 			if (status != NT_STATUS_SUCCESS)
1449832Samw@Sun.COM 				return (status);
1459832Samw@Sun.COM 			break;
1468670SJose.Borrego@Sun.COM 
1479832Samw@Sun.COM 		case SidTypeAlias:
1489832Samw@Sun.COM 			status = smb_sam_lookup_group(name, &sid);
1499832Samw@Sun.COM 			if (status != NT_STATUS_SUCCESS)
1509832Samw@Sun.COM 				return (status);
1518670SJose.Borrego@Sun.COM 			break;
1528670SJose.Borrego@Sun.COM 
1539832Samw@Sun.COM 		case SidTypeUnknown:
1549832Samw@Sun.COM 			type = SidTypeUser;
1559832Samw@Sun.COM 			status = smb_sam_lookup_user(name, &sid);
1569832Samw@Sun.COM 			if (status == NT_STATUS_SUCCESS)
1579832Samw@Sun.COM 				break;
1589832Samw@Sun.COM 
1599832Samw@Sun.COM 			if (status == NT_STATUS_NONE_MAPPED)
1609832Samw@Sun.COM 				return (status);
1618670SJose.Borrego@Sun.COM 
1629832Samw@Sun.COM 			type = SidTypeAlias;
1639832Samw@Sun.COM 			status = smb_sam_lookup_group(name, &sid);
1649832Samw@Sun.COM 			if (status != NT_STATUS_SUCCESS)
1659832Samw@Sun.COM 				return (status);
1669832Samw@Sun.COM 			break;
1678670SJose.Borrego@Sun.COM 
1689832Samw@Sun.COM 		default:
1699832Samw@Sun.COM 			return (NT_STATUS_INVALID_PARAMETER);
1709832Samw@Sun.COM 		}
1718670SJose.Borrego@Sun.COM 	}
1728670SJose.Borrego@Sun.COM 
1738670SJose.Borrego@Sun.COM 	account->a_name = strdup(name);
1748670SJose.Borrego@Sun.COM 	account->a_sid = sid;
1759832Samw@Sun.COM 	account->a_domain = strdup(di.di_nbname);
1768670SJose.Borrego@Sun.COM 	account->a_domsid = smb_sid_split(sid, &account->a_rid);
1778670SJose.Borrego@Sun.COM 	account->a_type = type;
1788670SJose.Borrego@Sun.COM 
1798670SJose.Borrego@Sun.COM 	if (!smb_account_validate(account)) {
1808670SJose.Borrego@Sun.COM 		smb_account_free(account);
1818670SJose.Borrego@Sun.COM 		return (NT_STATUS_NO_MEMORY);
1828670SJose.Borrego@Sun.COM 	}
1838670SJose.Borrego@Sun.COM 
1848670SJose.Borrego@Sun.COM 	return (NT_STATUS_SUCCESS);
1858670SJose.Borrego@Sun.COM }
1868670SJose.Borrego@Sun.COM 
1878670SJose.Borrego@Sun.COM /*
1888670SJose.Borrego@Sun.COM  * Looks up the given SID in local account databases:
1898670SJose.Borrego@Sun.COM  *
1908670SJose.Borrego@Sun.COM  * SMB Local users are looked up in /var/smb/smbpasswd
1918670SJose.Borrego@Sun.COM  * SMB Local groups are looked up in /var/smb/smbgroup.db
1928670SJose.Borrego@Sun.COM  *
1938670SJose.Borrego@Sun.COM  * If the account is found, its information is populated
1948670SJose.Borrego@Sun.COM  * in the passed smb_account_t structure. Caller must free
1958670SJose.Borrego@Sun.COM  * allocated memories by calling smb_account_free() upon
1968670SJose.Borrego@Sun.COM  * successful return.
1978670SJose.Borrego@Sun.COM  *
1988670SJose.Borrego@Sun.COM  * Return status:
1998670SJose.Borrego@Sun.COM  *
2008670SJose.Borrego@Sun.COM  *   NT_STATUS_NOT_FOUND	This is not a local account
2018670SJose.Borrego@Sun.COM  *   NT_STATUS_NONE_MAPPED	It's a local account but cannot be
2028670SJose.Borrego@Sun.COM  *   				translated.
2038670SJose.Borrego@Sun.COM  *   other error status codes.
2048670SJose.Borrego@Sun.COM  */
2058670SJose.Borrego@Sun.COM uint32_t
smb_sam_lookup_sid(smb_sid_t * sid,smb_account_t * account)2068670SJose.Borrego@Sun.COM smb_sam_lookup_sid(smb_sid_t *sid, smb_account_t *account)
2078670SJose.Borrego@Sun.COM {
2088670SJose.Borrego@Sun.COM 	char hostname[MAXHOSTNAMELEN];
2098670SJose.Borrego@Sun.COM 	smb_passwd_t smbpw;
2108670SJose.Borrego@Sun.COM 	smb_group_t grp;
2119832Samw@Sun.COM 	smb_lwka_t *lwka;
21210717Samw@Sun.COM 	smb_domain_t di;
2138670SJose.Borrego@Sun.COM 	uint32_t rid;
2148670SJose.Borrego@Sun.COM 	uid_t id;
2158670SJose.Borrego@Sun.COM 	int id_type;
2168670SJose.Borrego@Sun.COM 	int rc;
2178670SJose.Borrego@Sun.COM 
2188670SJose.Borrego@Sun.COM 	bzero(account, sizeof (smb_account_t));
2198670SJose.Borrego@Sun.COM 
22010717Samw@Sun.COM 	if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
2219832Samw@Sun.COM 		return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
2229832Samw@Sun.COM 
2239832Samw@Sun.COM 	if (smb_sid_cmp(sid, di.di_binsid)) {
2249832Samw@Sun.COM 		/* This is the local domain SID */
2259832Samw@Sun.COM 		account->a_type = SidTypeDomain;
2269832Samw@Sun.COM 		account->a_name = strdup("");
2279832Samw@Sun.COM 		account->a_domain = strdup(di.di_nbname);
2289832Samw@Sun.COM 		account->a_sid = smb_sid_dup(sid);
2299832Samw@Sun.COM 		account->a_domsid = smb_sid_dup(sid);
2309832Samw@Sun.COM 		account->a_rid = (uint32_t)-1;
2318670SJose.Borrego@Sun.COM 
2329832Samw@Sun.COM 		if (!smb_account_validate(account)) {
2339832Samw@Sun.COM 			smb_account_free(account);
2349832Samw@Sun.COM 			return (NT_STATUS_NO_MEMORY);
2359832Samw@Sun.COM 		}
2368670SJose.Borrego@Sun.COM 
2379832Samw@Sun.COM 		return (NT_STATUS_SUCCESS);
2389832Samw@Sun.COM 	}
2399832Samw@Sun.COM 
2409832Samw@Sun.COM 	if (!smb_sid_indomain(di.di_binsid, sid)) {
2419832Samw@Sun.COM 		/* This is not a local SID */
2429832Samw@Sun.COM 		return (NT_STATUS_NOT_FOUND);
2439832Samw@Sun.COM 	}
2448670SJose.Borrego@Sun.COM 
2459832Samw@Sun.COM 	if ((lwka = smb_lwka_lookup_sid(sid)) != NULL) {
2469832Samw@Sun.COM 		account->a_type = lwka->lwka_type;
2479832Samw@Sun.COM 		account->a_name = strdup(lwka->lwka_name);
2489832Samw@Sun.COM 	} else {
2499832Samw@Sun.COM 		id_type = SMB_IDMAP_UNKNOWN;
2509832Samw@Sun.COM 		if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS)
2519832Samw@Sun.COM 			return (NT_STATUS_NONE_MAPPED);
2529832Samw@Sun.COM 
2539832Samw@Sun.COM 		switch (id_type) {
2549832Samw@Sun.COM 		case SMB_IDMAP_USER:
2559832Samw@Sun.COM 			account->a_type = SidTypeUser;
2569832Samw@Sun.COM 			if (smb_pwd_getpwuid(id, &smbpw) == NULL)
2579832Samw@Sun.COM 				return (NT_STATUS_NO_SUCH_USER);
2588670SJose.Borrego@Sun.COM 
2599832Samw@Sun.COM 			account->a_name = strdup(smbpw.pw_name);
2609832Samw@Sun.COM 			break;
2618670SJose.Borrego@Sun.COM 
2629832Samw@Sun.COM 		case SMB_IDMAP_GROUP:
2639832Samw@Sun.COM 			account->a_type = SidTypeAlias;
2649832Samw@Sun.COM 			(void) smb_sid_getrid(sid, &rid);
265*11963SAfshin.Ardakani@Sun.COM 			rc = smb_lgrp_getbyrid(rid, SMB_DOMAIN_LOCAL, &grp);
2669832Samw@Sun.COM 			if (rc != SMB_LGRP_SUCCESS)
2679832Samw@Sun.COM 				return (NT_STATUS_NO_SUCH_ALIAS);
2688670SJose.Borrego@Sun.COM 
2699832Samw@Sun.COM 			account->a_name = strdup(grp.sg_name);
2709832Samw@Sun.COM 			smb_lgrp_free(&grp);
2719832Samw@Sun.COM 			break;
2729832Samw@Sun.COM 
2739832Samw@Sun.COM 		default:
2749832Samw@Sun.COM 			return (NT_STATUS_NONE_MAPPED);
2759832Samw@Sun.COM 		}
2768670SJose.Borrego@Sun.COM 	}
2778670SJose.Borrego@Sun.COM 
2788670SJose.Borrego@Sun.COM 	if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) == 0)
2798670SJose.Borrego@Sun.COM 		account->a_domain = strdup(hostname);
2808670SJose.Borrego@Sun.COM 	account->a_sid = smb_sid_dup(sid);
2818670SJose.Borrego@Sun.COM 	account->a_domsid = smb_sid_split(sid, &account->a_rid);
2828670SJose.Borrego@Sun.COM 
2838670SJose.Borrego@Sun.COM 	if (!smb_account_validate(account)) {
2848670SJose.Borrego@Sun.COM 		smb_account_free(account);
2858670SJose.Borrego@Sun.COM 		return (NT_STATUS_NO_MEMORY);
2868670SJose.Borrego@Sun.COM 	}
2878670SJose.Borrego@Sun.COM 
2888670SJose.Borrego@Sun.COM 	return (NT_STATUS_SUCCESS);
2898670SJose.Borrego@Sun.COM }
2908670SJose.Borrego@Sun.COM 
2918670SJose.Borrego@Sun.COM /*
2928670SJose.Borrego@Sun.COM  * Returns number of SMB users, i.e. users who have entry
2938670SJose.Borrego@Sun.COM  * in /var/smb/smbpasswd
2948670SJose.Borrego@Sun.COM  */
2958670SJose.Borrego@Sun.COM int
smb_sam_usr_cnt(void)2968670SJose.Borrego@Sun.COM smb_sam_usr_cnt(void)
2978670SJose.Borrego@Sun.COM {
2988670SJose.Borrego@Sun.COM 	return (smb_pwd_num());
2998670SJose.Borrego@Sun.COM }
3008670SJose.Borrego@Sun.COM 
3018670SJose.Borrego@Sun.COM /*
3028670SJose.Borrego@Sun.COM  * Returns a list of local groups which the given user is
3038670SJose.Borrego@Sun.COM  * their member. A pointer to an array of smb_ids_t
3048670SJose.Borrego@Sun.COM  * structure is returned which must be freed by caller.
3058670SJose.Borrego@Sun.COM  */
3068670SJose.Borrego@Sun.COM uint32_t
smb_sam_usr_groups(smb_sid_t * user_sid,smb_ids_t * gids)3078670SJose.Borrego@Sun.COM smb_sam_usr_groups(smb_sid_t *user_sid, smb_ids_t *gids)
3088670SJose.Borrego@Sun.COM {
3098670SJose.Borrego@Sun.COM 	smb_id_t *ids;
3108670SJose.Borrego@Sun.COM 	smb_giter_t gi;
3118670SJose.Borrego@Sun.COM 	smb_group_t lgrp;
3128670SJose.Borrego@Sun.COM 	int total_cnt, gcnt;
3138670SJose.Borrego@Sun.COM 
3148670SJose.Borrego@Sun.COM 	gcnt = 0;
3158670SJose.Borrego@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
3168670SJose.Borrego@Sun.COM 		return (NT_STATUS_INTERNAL_ERROR);
3178670SJose.Borrego@Sun.COM 
3188670SJose.Borrego@Sun.COM 	while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
3198670SJose.Borrego@Sun.COM 		if (smb_lgrp_is_member(&lgrp, user_sid))
3208670SJose.Borrego@Sun.COM 			gcnt++;
3218670SJose.Borrego@Sun.COM 		smb_lgrp_free(&lgrp);
3228670SJose.Borrego@Sun.COM 	}
3238670SJose.Borrego@Sun.COM 	smb_lgrp_iterclose(&gi);
3248670SJose.Borrego@Sun.COM 
3258670SJose.Borrego@Sun.COM 	if (gcnt == 0)
3268670SJose.Borrego@Sun.COM 		return (NT_STATUS_SUCCESS);
3278670SJose.Borrego@Sun.COM 
3288670SJose.Borrego@Sun.COM 	total_cnt = gids->i_cnt + gcnt;
3298670SJose.Borrego@Sun.COM 	gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
3308670SJose.Borrego@Sun.COM 	if (gids->i_ids == NULL)
3318670SJose.Borrego@Sun.COM 		return (NT_STATUS_NO_MEMORY);
3328670SJose.Borrego@Sun.COM 
3338670SJose.Borrego@Sun.COM 	if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
3348670SJose.Borrego@Sun.COM 		return (NT_STATUS_INTERNAL_ERROR);
3358670SJose.Borrego@Sun.COM 
3368670SJose.Borrego@Sun.COM 	ids = gids->i_ids + gids->i_cnt;
3378670SJose.Borrego@Sun.COM 	while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
3388670SJose.Borrego@Sun.COM 		if (gcnt == 0) {
3398670SJose.Borrego@Sun.COM 			smb_lgrp_free(&lgrp);
3408670SJose.Borrego@Sun.COM 			break;
3418670SJose.Borrego@Sun.COM 		}
3428670SJose.Borrego@Sun.COM 		if (smb_lgrp_is_member(&lgrp, user_sid)) {
3438670SJose.Borrego@Sun.COM 			ids->i_sid = smb_sid_dup(lgrp.sg_id.gs_sid);
3448670SJose.Borrego@Sun.COM 			if (ids->i_sid == NULL) {
3458670SJose.Borrego@Sun.COM 				smb_lgrp_free(&lgrp);
3468670SJose.Borrego@Sun.COM 				return (NT_STATUS_NO_MEMORY);
3478670SJose.Borrego@Sun.COM 			}
3488670SJose.Borrego@Sun.COM 			ids->i_attrs = lgrp.sg_attr;
3498670SJose.Borrego@Sun.COM 			gids->i_cnt++;
3508670SJose.Borrego@Sun.COM 			gcnt--;
3518670SJose.Borrego@Sun.COM 			ids++;
3528670SJose.Borrego@Sun.COM 		}
3538670SJose.Borrego@Sun.COM 		smb_lgrp_free(&lgrp);
3548670SJose.Borrego@Sun.COM 	}
3558670SJose.Borrego@Sun.COM 	smb_lgrp_iterclose(&gi);
3568670SJose.Borrego@Sun.COM 
3578670SJose.Borrego@Sun.COM 	return (NT_STATUS_SUCCESS);
3588670SJose.Borrego@Sun.COM }
3598670SJose.Borrego@Sun.COM 
3608670SJose.Borrego@Sun.COM /*
3618670SJose.Borrego@Sun.COM  * Returns the number of built-in or local groups stored
3628670SJose.Borrego@Sun.COM  * in /var/smb/smbgroup.db
3638670SJose.Borrego@Sun.COM  */
3648670SJose.Borrego@Sun.COM int
smb_sam_grp_cnt(smb_domain_type_t dtype)36510717Samw@Sun.COM smb_sam_grp_cnt(smb_domain_type_t dtype)
3668670SJose.Borrego@Sun.COM {
3678670SJose.Borrego@Sun.COM 	int grpcnt;
3688670SJose.Borrego@Sun.COM 	int rc;
3698670SJose.Borrego@Sun.COM 
3708670SJose.Borrego@Sun.COM 	switch (dtype) {
37110717Samw@Sun.COM 	case SMB_DOMAIN_BUILTIN:
372*11963SAfshin.Ardakani@Sun.COM 		rc = smb_lgrp_numbydomain(SMB_DOMAIN_BUILTIN, &grpcnt);
3738670SJose.Borrego@Sun.COM 		break;
3748670SJose.Borrego@Sun.COM 
37510717Samw@Sun.COM 	case SMB_DOMAIN_LOCAL:
376*11963SAfshin.Ardakani@Sun.COM 		rc = smb_lgrp_numbydomain(SMB_DOMAIN_LOCAL, &grpcnt);
3778670SJose.Borrego@Sun.COM 		break;
3788670SJose.Borrego@Sun.COM 
3798670SJose.Borrego@Sun.COM 	default:
3808670SJose.Borrego@Sun.COM 		rc = SMB_LGRP_INVALID_ARG;
3818670SJose.Borrego@Sun.COM 	}
3828670SJose.Borrego@Sun.COM 
3838670SJose.Borrego@Sun.COM 	return ((rc == SMB_LGRP_SUCCESS) ? grpcnt : 0);
3848670SJose.Borrego@Sun.COM }
3858670SJose.Borrego@Sun.COM 
3868670SJose.Borrego@Sun.COM /*
3878670SJose.Borrego@Sun.COM  * Determines whether the given SID is a member of the group
3888670SJose.Borrego@Sun.COM  * specified by gname.
3898670SJose.Borrego@Sun.COM  */
3908670SJose.Borrego@Sun.COM boolean_t
smb_sam_grp_ismember(const char * gname,smb_sid_t * sid)3918670SJose.Borrego@Sun.COM smb_sam_grp_ismember(const char *gname, smb_sid_t *sid)
3928670SJose.Borrego@Sun.COM {
3938670SJose.Borrego@Sun.COM 	smb_group_t grp;
3948670SJose.Borrego@Sun.COM 	boolean_t ismember = B_FALSE;
3958670SJose.Borrego@Sun.COM 
3968670SJose.Borrego@Sun.COM 	if (smb_lgrp_getbyname((char *)gname, &grp) == SMB_LGRP_SUCCESS) {
3978670SJose.Borrego@Sun.COM 		ismember = smb_lgrp_is_member(&grp, sid);
3988670SJose.Borrego@Sun.COM 		smb_lgrp_free(&grp);
3998670SJose.Borrego@Sun.COM 	}
4008670SJose.Borrego@Sun.COM 
4018670SJose.Borrego@Sun.COM 	return (ismember);
4028670SJose.Borrego@Sun.COM }
4038670SJose.Borrego@Sun.COM 
4048670SJose.Borrego@Sun.COM /*
4058670SJose.Borrego@Sun.COM  * Frees memories allocated for the passed account fields.
4068670SJose.Borrego@Sun.COM  */
4078670SJose.Borrego@Sun.COM void
smb_account_free(smb_account_t * account)4088670SJose.Borrego@Sun.COM smb_account_free(smb_account_t *account)
4098670SJose.Borrego@Sun.COM {
4108670SJose.Borrego@Sun.COM 	free(account->a_name);
4118670SJose.Borrego@Sun.COM 	free(account->a_domain);
4128670SJose.Borrego@Sun.COM 	smb_sid_free(account->a_sid);
4138670SJose.Borrego@Sun.COM 	smb_sid_free(account->a_domsid);
4148670SJose.Borrego@Sun.COM }
4158670SJose.Borrego@Sun.COM 
4168670SJose.Borrego@Sun.COM /*
4178670SJose.Borrego@Sun.COM  * Validates the given account.
4188670SJose.Borrego@Sun.COM  */
4198670SJose.Borrego@Sun.COM boolean_t
smb_account_validate(smb_account_t * account)4208670SJose.Borrego@Sun.COM smb_account_validate(smb_account_t *account)
4218670SJose.Borrego@Sun.COM {
4228670SJose.Borrego@Sun.COM 	return ((account->a_name != NULL) && (account->a_sid != NULL) &&
4238670SJose.Borrego@Sun.COM 	    (account->a_domain != NULL) && (account->a_domsid != NULL));
4248670SJose.Borrego@Sun.COM }
4258670SJose.Borrego@Sun.COM 
4268670SJose.Borrego@Sun.COM /*
4278670SJose.Borrego@Sun.COM  * Lookup local SMB user account database (/var/smb/smbpasswd)
4288670SJose.Borrego@Sun.COM  * if there's a match query its SID from idmap service and make
4298670SJose.Borrego@Sun.COM  * sure the SID is a local SID.
4308670SJose.Borrego@Sun.COM  *
4318670SJose.Borrego@Sun.COM  * The memory for the returned SID must be freed by the caller.
4328670SJose.Borrego@Sun.COM  */
4338670SJose.Borrego@Sun.COM static uint32_t
smb_sam_lookup_user(char * name,smb_sid_t ** sid)4348670SJose.Borrego@Sun.COM smb_sam_lookup_user(char *name, smb_sid_t **sid)
4358670SJose.Borrego@Sun.COM {
4368670SJose.Borrego@Sun.COM 	smb_passwd_t smbpw;
4378670SJose.Borrego@Sun.COM 
4388670SJose.Borrego@Sun.COM 	if (smb_pwd_getpwnam(name, &smbpw) == NULL)
4398670SJose.Borrego@Sun.COM 		return (NT_STATUS_NO_SUCH_USER);
4408670SJose.Borrego@Sun.COM 
4418670SJose.Borrego@Sun.COM 	if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid)
4428670SJose.Borrego@Sun.COM 	    != IDMAP_SUCCESS)
4438670SJose.Borrego@Sun.COM 		return (NT_STATUS_NONE_MAPPED);
4448670SJose.Borrego@Sun.COM 
4458670SJose.Borrego@Sun.COM 	if (!smb_sid_islocal(*sid)) {
4468670SJose.Borrego@Sun.COM 		smb_sid_free(*sid);
4478670SJose.Borrego@Sun.COM 		return (NT_STATUS_NONE_MAPPED);
4488670SJose.Borrego@Sun.COM 	}
4498670SJose.Borrego@Sun.COM 
4508670SJose.Borrego@Sun.COM 	return (NT_STATUS_SUCCESS);
4518670SJose.Borrego@Sun.COM }
4528670SJose.Borrego@Sun.COM 
4538670SJose.Borrego@Sun.COM /*
4548670SJose.Borrego@Sun.COM  * Lookup local SMB group account database (/var/smb/smbgroup.db)
4558670SJose.Borrego@Sun.COM  * The memory for the returned SID must be freed by the caller.
4568670SJose.Borrego@Sun.COM  */
4578670SJose.Borrego@Sun.COM static uint32_t
smb_sam_lookup_group(char * name,smb_sid_t ** sid)4588670SJose.Borrego@Sun.COM smb_sam_lookup_group(char *name, smb_sid_t **sid)
4598670SJose.Borrego@Sun.COM {
4608670SJose.Borrego@Sun.COM 	smb_group_t grp;
4618670SJose.Borrego@Sun.COM 
4628670SJose.Borrego@Sun.COM 	if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS)
4638670SJose.Borrego@Sun.COM 		return (NT_STATUS_NO_SUCH_ALIAS);
4648670SJose.Borrego@Sun.COM 
4658670SJose.Borrego@Sun.COM 	*sid = smb_sid_dup(grp.sg_id.gs_sid);
4668670SJose.Borrego@Sun.COM 	smb_lgrp_free(&grp);
4678670SJose.Borrego@Sun.COM 
4688670SJose.Borrego@Sun.COM 	return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS);
4698670SJose.Borrego@Sun.COM }
4709832Samw@Sun.COM 
4719832Samw@Sun.COM static smb_lwka_t *
smb_lwka_lookup_name(char * name)4729832Samw@Sun.COM smb_lwka_lookup_name(char *name)
4739832Samw@Sun.COM {
4749832Samw@Sun.COM 	int i;
4759832Samw@Sun.COM 
4769832Samw@Sun.COM 	for (i = 0; i < SMB_LWKA_NUM; i++) {
47710966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(name, lwka_tbl[i].lwka_name, 0) == 0)
4789832Samw@Sun.COM 			return (&lwka_tbl[i]);
4799832Samw@Sun.COM 	}
4809832Samw@Sun.COM 
4819832Samw@Sun.COM 	return (NULL);
4829832Samw@Sun.COM }
4839832Samw@Sun.COM 
4849832Samw@Sun.COM static smb_lwka_t *
smb_lwka_lookup_sid(smb_sid_t * sid)4859832Samw@Sun.COM smb_lwka_lookup_sid(smb_sid_t *sid)
4869832Samw@Sun.COM {
4879832Samw@Sun.COM 	uint32_t rid;
4889832Samw@Sun.COM 	int i;
4899832Samw@Sun.COM 
4909832Samw@Sun.COM 	(void) smb_sid_getrid(sid, &rid);
4919832Samw@Sun.COM 	if (rid > 999)
4929832Samw@Sun.COM 		return (NULL);
4939832Samw@Sun.COM 
4949832Samw@Sun.COM 	for (i = 0; i < SMB_LWKA_NUM; i++) {
4959832Samw@Sun.COM 		if (rid == lwka_tbl[i].lwka_rid)
4969832Samw@Sun.COM 			return (&lwka_tbl[i]);
4979832Samw@Sun.COM 	}
4989832Samw@Sun.COM 
4999832Samw@Sun.COM 	return (NULL);
5009832Samw@Sun.COM }
501