17f667e74Sjose borrego /* 27f667e74Sjose borrego * CDDL HEADER START 37f667e74Sjose borrego * 47f667e74Sjose borrego * The contents of this file are subject to the terms of the 57f667e74Sjose borrego * Common Development and Distribution License (the "License"). 67f667e74Sjose borrego * You may not use this file except in compliance with the License. 77f667e74Sjose borrego * 87f667e74Sjose borrego * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97f667e74Sjose borrego * or http://www.opensolaris.org/os/licensing. 107f667e74Sjose borrego * See the License for the specific language governing permissions 117f667e74Sjose borrego * and limitations under the License. 127f667e74Sjose borrego * 137f667e74Sjose borrego * When distributing Covered Code, include this CDDL HEADER in each 147f667e74Sjose borrego * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157f667e74Sjose borrego * If applicable, add the following below this CDDL HEADER, with the 167f667e74Sjose borrego * fields enclosed by brackets "[]" replaced with your own identifying 177f667e74Sjose borrego * information: Portions Copyright [yyyy] [name of copyright owner] 187f667e74Sjose borrego * 197f667e74Sjose borrego * CDDL HEADER END 207f667e74Sjose borrego */ 217f667e74Sjose borrego /* 229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237f667e74Sjose borrego * Use is subject to license terms. 24*b819cea2SGordon Ross * 25*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 267f667e74Sjose borrego */ 277f667e74Sjose borrego 287f667e74Sjose borrego #include <strings.h> 297f667e74Sjose borrego #include <smbsrv/libsmb.h> 307f667e74Sjose borrego 317f667e74Sjose borrego extern int smb_pwd_num(void); 329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States extern int smb_lgrp_numbydomain(smb_domain_type_t, int *); 337f667e74Sjose borrego 347f667e74Sjose borrego static uint32_t smb_sam_lookup_user(char *, smb_sid_t **); 357f667e74Sjose borrego static uint32_t smb_sam_lookup_group(char *, smb_sid_t **); 367f667e74Sjose borrego 377f667e74Sjose borrego /* 3829bd2886SAlan Wright * Local well-known accounts data structure table and prototypes 3929bd2886SAlan Wright */ 4029bd2886SAlan Wright typedef struct smb_lwka { 4129bd2886SAlan Wright uint32_t lwka_rid; 4229bd2886SAlan Wright char *lwka_name; 4329bd2886SAlan Wright uint16_t lwka_type; 4429bd2886SAlan Wright } smb_lwka_t; 4529bd2886SAlan Wright 4629bd2886SAlan Wright static smb_lwka_t lwka_tbl[] = { 4729bd2886SAlan Wright { 500, "Administrator", SidTypeUser }, 4829bd2886SAlan Wright { 501, "Guest", SidTypeUser }, 4929bd2886SAlan Wright { 502, "KRBTGT", SidTypeUser }, 5029bd2886SAlan Wright { 512, "Domain Admins", SidTypeGroup }, 5129bd2886SAlan Wright { 513, "Domain Users", SidTypeGroup }, 5229bd2886SAlan Wright { 514, "Domain Guests", SidTypeGroup }, 5329bd2886SAlan Wright { 516, "Domain Controllers", SidTypeGroup }, 5429bd2886SAlan Wright { 517, "Cert Publishers", SidTypeGroup }, 5529bd2886SAlan Wright { 518, "Schema Admins", SidTypeGroup }, 5629bd2886SAlan Wright { 519, "Enterprise Admins", SidTypeGroup }, 5729bd2886SAlan Wright { 520, "Global Policy Creator Owners", SidTypeGroup }, 5829bd2886SAlan Wright { 533, "RAS and IAS Servers", SidTypeGroup } 5929bd2886SAlan Wright }; 6029bd2886SAlan Wright 6129bd2886SAlan Wright #define SMB_LWKA_NUM (sizeof (lwka_tbl)/sizeof (lwka_tbl[0])) 6229bd2886SAlan Wright 6329bd2886SAlan Wright static smb_lwka_t *smb_lwka_lookup_name(char *); 6429bd2886SAlan Wright static smb_lwka_t *smb_lwka_lookup_sid(smb_sid_t *); 6529bd2886SAlan Wright 6629bd2886SAlan Wright /* 677f667e74Sjose borrego * Looks up the given name in local account databases: 687f667e74Sjose borrego * 697f667e74Sjose borrego * SMB Local users are looked up in /var/smb/smbpasswd 707f667e74Sjose borrego * SMB Local groups are looked up in /var/smb/smbgroup.db 717f667e74Sjose borrego * 727f667e74Sjose borrego * If the account is found, its information is populated 737f667e74Sjose borrego * in the passed smb_account_t structure. Caller must free 747f667e74Sjose borrego * allocated memories by calling smb_account_free() upon 757f667e74Sjose borrego * successful return. 767f667e74Sjose borrego * 777f667e74Sjose borrego * The type of account is specified by 'type', which can be user, 787f667e74Sjose borrego * alias (local group) or unknown. If the caller doesn't know 797f667e74Sjose borrego * whether the name is a user or group name then SidTypeUnknown 807f667e74Sjose borrego * should be passed. 817f667e74Sjose borrego * 827f667e74Sjose borrego * If a local user and group have the same name, the user will 837f667e74Sjose borrego * always be picked. Note that this situation cannot happen on 847f667e74Sjose borrego * Windows systems. 857f667e74Sjose borrego * 867f667e74Sjose borrego * If a SMB local user/group is found but it turns out that 877f667e74Sjose borrego * it'll be mapped to a domain user/group the lookup is considered 887f667e74Sjose borrego * failed and NT_STATUS_NONE_MAPPED is returned. 897f667e74Sjose borrego * 907f667e74Sjose borrego * Return status: 917f667e74Sjose borrego * 927f667e74Sjose borrego * NT_STATUS_NOT_FOUND This is not a local account 937f667e74Sjose borrego * NT_STATUS_NONE_MAPPED It's a local account but cannot be 947f667e74Sjose borrego * translated. 957f667e74Sjose borrego * other error status codes. 967f667e74Sjose borrego */ 977f667e74Sjose borrego uint32_t 987f667e74Sjose borrego smb_sam_lookup_name(char *domain, char *name, uint16_t type, 997f667e74Sjose borrego smb_account_t *account) 1007f667e74Sjose borrego { 101a0aa776eSAlan Wright smb_domain_t di; 1027f667e74Sjose borrego smb_sid_t *sid; 1037f667e74Sjose borrego uint32_t status; 10429bd2886SAlan Wright smb_lwka_t *lwka; 1057f667e74Sjose borrego 1067f667e74Sjose borrego bzero(account, sizeof (smb_account_t)); 1077f667e74Sjose borrego 1087f667e74Sjose borrego if (domain != NULL) { 109a0aa776eSAlan Wright if (!smb_domain_lookup_name(domain, &di) || 110a0aa776eSAlan Wright (di.di_type != SMB_DOMAIN_LOCAL)) 1117f667e74Sjose borrego return (NT_STATUS_NOT_FOUND); 1127f667e74Sjose borrego 1137f667e74Sjose borrego /* Only Netbios hostname is accepted */ 114bbf6f00cSJordan Brown if (smb_strcasecmp(domain, di.di_nbname, 0) != 0) 1157f667e74Sjose borrego return (NT_STATUS_NONE_MAPPED); 11629bd2886SAlan Wright } else { 117a0aa776eSAlan Wright if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) 11829bd2886SAlan Wright return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 1197f667e74Sjose borrego } 1207f667e74Sjose borrego 121bbf6f00cSJordan Brown if (smb_strcasecmp(name, di.di_nbname, 0) == 0) { 12229bd2886SAlan Wright /* This is the local domain name */ 12329bd2886SAlan Wright account->a_type = SidTypeDomain; 12429bd2886SAlan Wright account->a_name = strdup(""); 12529bd2886SAlan Wright account->a_domain = strdup(di.di_nbname); 12629bd2886SAlan Wright account->a_sid = smb_sid_dup(di.di_binsid); 12729bd2886SAlan Wright account->a_domsid = smb_sid_dup(di.di_binsid); 12829bd2886SAlan Wright account->a_rid = (uint32_t)-1; 12929bd2886SAlan Wright 13029bd2886SAlan Wright if (!smb_account_validate(account)) { 13129bd2886SAlan Wright smb_account_free(account); 13229bd2886SAlan Wright return (NT_STATUS_NO_MEMORY); 13329bd2886SAlan Wright } 13429bd2886SAlan Wright 13529bd2886SAlan Wright return (NT_STATUS_SUCCESS); 13629bd2886SAlan Wright } 13729bd2886SAlan Wright 13829bd2886SAlan Wright if ((lwka = smb_lwka_lookup_name(name)) != NULL) { 13929bd2886SAlan Wright sid = smb_sid_splice(di.di_binsid, lwka->lwka_rid); 14029bd2886SAlan Wright type = lwka->lwka_type; 14129bd2886SAlan Wright } else { 1427f667e74Sjose borrego switch (type) { 1437f667e74Sjose borrego case SidTypeUser: 1447f667e74Sjose borrego status = smb_sam_lookup_user(name, &sid); 1457f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) 1467f667e74Sjose borrego return (status); 1477f667e74Sjose borrego break; 1487f667e74Sjose borrego 1497f667e74Sjose borrego case SidTypeAlias: 1507f667e74Sjose borrego status = smb_sam_lookup_group(name, &sid); 1517f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) 1527f667e74Sjose borrego return (status); 1537f667e74Sjose borrego break; 1547f667e74Sjose borrego 1557f667e74Sjose borrego case SidTypeUnknown: 1567f667e74Sjose borrego type = SidTypeUser; 1577f667e74Sjose borrego status = smb_sam_lookup_user(name, &sid); 1587f667e74Sjose borrego if (status == NT_STATUS_SUCCESS) 1597f667e74Sjose borrego break; 1607f667e74Sjose borrego 1617f667e74Sjose borrego if (status == NT_STATUS_NONE_MAPPED) 1627f667e74Sjose borrego return (status); 1637f667e74Sjose borrego 1647f667e74Sjose borrego type = SidTypeAlias; 1657f667e74Sjose borrego status = smb_sam_lookup_group(name, &sid); 1667f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) 1677f667e74Sjose borrego return (status); 1687f667e74Sjose borrego break; 1697f667e74Sjose borrego 1707f667e74Sjose borrego default: 1717f667e74Sjose borrego return (NT_STATUS_INVALID_PARAMETER); 1727f667e74Sjose borrego } 17329bd2886SAlan Wright } 1747f667e74Sjose borrego 1757f667e74Sjose borrego account->a_name = strdup(name); 1767f667e74Sjose borrego account->a_sid = sid; 17729bd2886SAlan Wright account->a_domain = strdup(di.di_nbname); 1787f667e74Sjose borrego account->a_domsid = smb_sid_split(sid, &account->a_rid); 1797f667e74Sjose borrego account->a_type = type; 1807f667e74Sjose borrego 1817f667e74Sjose borrego if (!smb_account_validate(account)) { 1827f667e74Sjose borrego smb_account_free(account); 1837f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 1847f667e74Sjose borrego } 1857f667e74Sjose borrego 1867f667e74Sjose borrego return (NT_STATUS_SUCCESS); 1877f667e74Sjose borrego } 1887f667e74Sjose borrego 1897f667e74Sjose borrego /* 1907f667e74Sjose borrego * Looks up the given SID in local account databases: 1917f667e74Sjose borrego * 1927f667e74Sjose borrego * SMB Local users are looked up in /var/smb/smbpasswd 1937f667e74Sjose borrego * SMB Local groups are looked up in /var/smb/smbgroup.db 1947f667e74Sjose borrego * 1957f667e74Sjose borrego * If the account is found, its information is populated 1967f667e74Sjose borrego * in the passed smb_account_t structure. Caller must free 1977f667e74Sjose borrego * allocated memories by calling smb_account_free() upon 1987f667e74Sjose borrego * successful return. 1997f667e74Sjose borrego * 2007f667e74Sjose borrego * Return status: 2017f667e74Sjose borrego * 2027f667e74Sjose borrego * NT_STATUS_NOT_FOUND This is not a local account 2037f667e74Sjose borrego * NT_STATUS_NONE_MAPPED It's a local account but cannot be 2047f667e74Sjose borrego * translated. 2057f667e74Sjose borrego * other error status codes. 2067f667e74Sjose borrego */ 2077f667e74Sjose borrego uint32_t 2087f667e74Sjose borrego smb_sam_lookup_sid(smb_sid_t *sid, smb_account_t *account) 2097f667e74Sjose borrego { 2107f667e74Sjose borrego char hostname[MAXHOSTNAMELEN]; 2117f667e74Sjose borrego smb_passwd_t smbpw; 2127f667e74Sjose borrego smb_group_t grp; 21329bd2886SAlan Wright smb_lwka_t *lwka; 214a0aa776eSAlan Wright smb_domain_t di; 2157f667e74Sjose borrego uint32_t rid; 2167f667e74Sjose borrego uid_t id; 2177f667e74Sjose borrego int id_type; 2187f667e74Sjose borrego int rc; 2197f667e74Sjose borrego 2207f667e74Sjose borrego bzero(account, sizeof (smb_account_t)); 2217f667e74Sjose borrego 222a0aa776eSAlan Wright if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) 22329bd2886SAlan Wright return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 2247f667e74Sjose borrego 22529bd2886SAlan Wright if (smb_sid_cmp(sid, di.di_binsid)) { 22629bd2886SAlan Wright /* This is the local domain SID */ 22729bd2886SAlan Wright account->a_type = SidTypeDomain; 22829bd2886SAlan Wright account->a_name = strdup(""); 22929bd2886SAlan Wright account->a_domain = strdup(di.di_nbname); 23029bd2886SAlan Wright account->a_sid = smb_sid_dup(sid); 23129bd2886SAlan Wright account->a_domsid = smb_sid_dup(sid); 23229bd2886SAlan Wright account->a_rid = (uint32_t)-1; 23329bd2886SAlan Wright 23429bd2886SAlan Wright if (!smb_account_validate(account)) { 23529bd2886SAlan Wright smb_account_free(account); 23629bd2886SAlan Wright return (NT_STATUS_NO_MEMORY); 23729bd2886SAlan Wright } 23829bd2886SAlan Wright 23929bd2886SAlan Wright return (NT_STATUS_SUCCESS); 24029bd2886SAlan Wright } 24129bd2886SAlan Wright 24229bd2886SAlan Wright if (!smb_sid_indomain(di.di_binsid, sid)) { 24329bd2886SAlan Wright /* This is not a local SID */ 24429bd2886SAlan Wright return (NT_STATUS_NOT_FOUND); 24529bd2886SAlan Wright } 24629bd2886SAlan Wright 24729bd2886SAlan Wright if ((lwka = smb_lwka_lookup_sid(sid)) != NULL) { 24829bd2886SAlan Wright account->a_type = lwka->lwka_type; 24929bd2886SAlan Wright account->a_name = strdup(lwka->lwka_name); 25029bd2886SAlan Wright } else { 2517f667e74Sjose borrego id_type = SMB_IDMAP_UNKNOWN; 2527f667e74Sjose borrego if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS) 2537f667e74Sjose borrego return (NT_STATUS_NONE_MAPPED); 2547f667e74Sjose borrego 2557f667e74Sjose borrego switch (id_type) { 2567f667e74Sjose borrego case SMB_IDMAP_USER: 2577f667e74Sjose borrego account->a_type = SidTypeUser; 2587f667e74Sjose borrego if (smb_pwd_getpwuid(id, &smbpw) == NULL) 2597f667e74Sjose borrego return (NT_STATUS_NO_SUCH_USER); 2607f667e74Sjose borrego 2617f667e74Sjose borrego account->a_name = strdup(smbpw.pw_name); 2627f667e74Sjose borrego break; 2637f667e74Sjose borrego 2647f667e74Sjose borrego case SMB_IDMAP_GROUP: 2657f667e74Sjose borrego account->a_type = SidTypeAlias; 2667f667e74Sjose borrego (void) smb_sid_getrid(sid, &rid); 2679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_lgrp_getbyrid(rid, SMB_DOMAIN_LOCAL, &grp); 2687f667e74Sjose borrego if (rc != SMB_LGRP_SUCCESS) 2697f667e74Sjose borrego return (NT_STATUS_NO_SUCH_ALIAS); 2707f667e74Sjose borrego 2717f667e74Sjose borrego account->a_name = strdup(grp.sg_name); 2727f667e74Sjose borrego smb_lgrp_free(&grp); 2737f667e74Sjose borrego break; 2747f667e74Sjose borrego 2757f667e74Sjose borrego default: 2767f667e74Sjose borrego return (NT_STATUS_NONE_MAPPED); 2777f667e74Sjose borrego } 27829bd2886SAlan Wright } 2797f667e74Sjose borrego 2807f667e74Sjose borrego if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) == 0) 2817f667e74Sjose borrego account->a_domain = strdup(hostname); 2827f667e74Sjose borrego account->a_sid = smb_sid_dup(sid); 2837f667e74Sjose borrego account->a_domsid = smb_sid_split(sid, &account->a_rid); 2847f667e74Sjose borrego 2857f667e74Sjose borrego if (!smb_account_validate(account)) { 2867f667e74Sjose borrego smb_account_free(account); 2877f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 2887f667e74Sjose borrego } 2897f667e74Sjose borrego 2907f667e74Sjose borrego return (NT_STATUS_SUCCESS); 2917f667e74Sjose borrego } 2927f667e74Sjose borrego 2937f667e74Sjose borrego /* 2947f667e74Sjose borrego * Returns number of SMB users, i.e. users who have entry 2957f667e74Sjose borrego * in /var/smb/smbpasswd 2967f667e74Sjose borrego */ 2977f667e74Sjose borrego int 2987f667e74Sjose borrego smb_sam_usr_cnt(void) 2997f667e74Sjose borrego { 3007f667e74Sjose borrego return (smb_pwd_num()); 3017f667e74Sjose borrego } 3027f667e74Sjose borrego 3037f667e74Sjose borrego /* 30436a00406SGordon Ross * Updates a list of groups in which the given user is a member 30536a00406SGordon Ross * by adding any local (SAM) groups. 30636a00406SGordon Ross * 30736a00406SGordon Ross * We are a member of local groups where the local group 30836a00406SGordon Ross * contains either the user's primary SID, or any of their 30936a00406SGordon Ross * other SIDs such as from domain groups, SID history, etc. 31036a00406SGordon Ross * We can have indirect membership via domain groups. 3117f667e74Sjose borrego */ 3127f667e74Sjose borrego uint32_t 3137f667e74Sjose borrego smb_sam_usr_groups(smb_sid_t *user_sid, smb_ids_t *gids) 3147f667e74Sjose borrego { 31536a00406SGordon Ross smb_ids_t new_gids; 31636a00406SGordon Ross smb_id_t *ids, *new_ids; 3177f667e74Sjose borrego smb_giter_t gi; 3187f667e74Sjose borrego smb_group_t lgrp; 31936a00406SGordon Ross int i, gcnt, total_cnt; 32036a00406SGordon Ross uint32_t ret; 32136a00406SGordon Ross boolean_t member; 3227f667e74Sjose borrego 32336a00406SGordon Ross /* 32436a00406SGordon Ross * First pass: count groups to be added (gcnt) 32536a00406SGordon Ross */ 3267f667e74Sjose borrego gcnt = 0; 3277f667e74Sjose borrego if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) 3287f667e74Sjose borrego return (NT_STATUS_INTERNAL_ERROR); 3297f667e74Sjose borrego 3307f667e74Sjose borrego while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) { 33136a00406SGordon Ross member = B_FALSE; 3327f667e74Sjose borrego if (smb_lgrp_is_member(&lgrp, user_sid)) 33336a00406SGordon Ross member = B_TRUE; 33436a00406SGordon Ross else for (i = 0, ids = gids->i_ids; 33536a00406SGordon Ross i < gids->i_cnt; i++, ids++) { 33636a00406SGordon Ross if (smb_lgrp_is_member(&lgrp, ids->i_sid)) { 33736a00406SGordon Ross member = B_TRUE; 33836a00406SGordon Ross break; 33936a00406SGordon Ross } 34036a00406SGordon Ross } 34136a00406SGordon Ross /* Careful: only count lgrp once */ 34236a00406SGordon Ross if (member) 3437f667e74Sjose borrego gcnt++; 3447f667e74Sjose borrego smb_lgrp_free(&lgrp); 3457f667e74Sjose borrego } 3467f667e74Sjose borrego smb_lgrp_iterclose(&gi); 3477f667e74Sjose borrego 3487f667e74Sjose borrego if (gcnt == 0) 3497f667e74Sjose borrego return (NT_STATUS_SUCCESS); 3507f667e74Sjose borrego 35136a00406SGordon Ross /* 35236a00406SGordon Ross * Second pass: add to groups list. 35336a00406SGordon Ross * Do not modify gcnt after here. 35436a00406SGordon Ross */ 3557f667e74Sjose borrego if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) 3567f667e74Sjose borrego return (NT_STATUS_INTERNAL_ERROR); 3577f667e74Sjose borrego 35836a00406SGordon Ross /* 35936a00406SGordon Ross * Expand the list (copy to a new, larger one) 36036a00406SGordon Ross * Note: were're copying pointers from the old 36136a00406SGordon Ross * array to the new (larger) array, and then 36236a00406SGordon Ross * adding new pointers after what we copied. 36336a00406SGordon Ross */ 36436a00406SGordon Ross ret = 0; 36536a00406SGordon Ross new_gids.i_cnt = gids->i_cnt; 36636a00406SGordon Ross total_cnt = gids->i_cnt + gcnt; 36736a00406SGordon Ross new_gids.i_ids = malloc(total_cnt * sizeof (smb_id_t)); 36836a00406SGordon Ross if (new_gids.i_ids == NULL) { 36936a00406SGordon Ross ret = NT_STATUS_NO_MEMORY; 37036a00406SGordon Ross goto out; 37136a00406SGordon Ross } 37236a00406SGordon Ross (void) memcpy(new_gids.i_ids, gids->i_ids, 37336a00406SGordon Ross gids->i_cnt * sizeof (smb_id_t)); 37436a00406SGordon Ross new_ids = new_gids.i_ids + gids->i_cnt; 37536a00406SGordon Ross (void) memset(new_ids, 0, gcnt * sizeof (smb_id_t)); 37636a00406SGordon Ross 37736a00406SGordon Ross /* 37836a00406SGordon Ross * Add group SIDs starting at the end of the 37936a00406SGordon Ross * previous list. (new_ids) 38036a00406SGordon Ross */ 3817f667e74Sjose borrego while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) { 38236a00406SGordon Ross member = B_FALSE; 38336a00406SGordon Ross if (smb_lgrp_is_member(&lgrp, user_sid)) 38436a00406SGordon Ross member = B_TRUE; 38536a00406SGordon Ross else for (i = 0, ids = gids->i_ids; 38636a00406SGordon Ross i < gids->i_cnt; i++, ids++) { 38736a00406SGordon Ross if (smb_lgrp_is_member(&lgrp, ids->i_sid)) { 38836a00406SGordon Ross member = B_TRUE; 3897f667e74Sjose borrego break; 3907f667e74Sjose borrego } 3917f667e74Sjose borrego } 39236a00406SGordon Ross if (member && (new_gids.i_cnt < (gids->i_cnt + gcnt))) { 39336a00406SGordon Ross new_ids->i_sid = smb_sid_dup(lgrp.sg_id.gs_sid); 39436a00406SGordon Ross if (new_ids->i_sid == NULL) { 39536a00406SGordon Ross smb_lgrp_free(&lgrp); 39636a00406SGordon Ross ret = NT_STATUS_NO_MEMORY; 39736a00406SGordon Ross goto out; 39836a00406SGordon Ross } 39936a00406SGordon Ross new_ids->i_attrs = lgrp.sg_attr; 40036a00406SGordon Ross new_ids++; 40136a00406SGordon Ross new_gids.i_cnt++; 4027f667e74Sjose borrego } 4037f667e74Sjose borrego smb_lgrp_free(&lgrp); 4047f667e74Sjose borrego } 40536a00406SGordon Ross 40636a00406SGordon Ross out: 4077f667e74Sjose borrego smb_lgrp_iterclose(&gi); 4087f667e74Sjose borrego 40936a00406SGordon Ross if (ret != 0) { 41036a00406SGordon Ross if (new_gids.i_ids != NULL) { 41136a00406SGordon Ross /* 41236a00406SGordon Ross * Free only the new sids we added. 41336a00406SGordon Ross * The old ones were copied ptrs. 41436a00406SGordon Ross */ 41536a00406SGordon Ross ids = new_gids.i_ids + gids->i_cnt; 41636a00406SGordon Ross for (i = 0; i < gcnt; i++, ids++) { 41736a00406SGordon Ross smb_sid_free(ids->i_sid); 41836a00406SGordon Ross } 41936a00406SGordon Ross free(new_gids.i_ids); 42036a00406SGordon Ross } 42136a00406SGordon Ross return (ret); 42236a00406SGordon Ross } 42336a00406SGordon Ross 42436a00406SGordon Ross /* 42536a00406SGordon Ross * Success! Update passed gids and 42636a00406SGordon Ross * free the old array. 42736a00406SGordon Ross */ 42836a00406SGordon Ross free(gids->i_ids); 42936a00406SGordon Ross *gids = new_gids; 43036a00406SGordon Ross 4317f667e74Sjose borrego return (NT_STATUS_SUCCESS); 4327f667e74Sjose borrego } 4337f667e74Sjose borrego 4347f667e74Sjose borrego /* 4357f667e74Sjose borrego * Returns the number of built-in or local groups stored 4367f667e74Sjose borrego * in /var/smb/smbgroup.db 4377f667e74Sjose borrego */ 4387f667e74Sjose borrego int 439a0aa776eSAlan Wright smb_sam_grp_cnt(smb_domain_type_t dtype) 4407f667e74Sjose borrego { 4417f667e74Sjose borrego int grpcnt; 4427f667e74Sjose borrego int rc; 4437f667e74Sjose borrego 4447f667e74Sjose borrego switch (dtype) { 445a0aa776eSAlan Wright case SMB_DOMAIN_BUILTIN: 4469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_lgrp_numbydomain(SMB_DOMAIN_BUILTIN, &grpcnt); 4477f667e74Sjose borrego break; 4487f667e74Sjose borrego 449a0aa776eSAlan Wright case SMB_DOMAIN_LOCAL: 4509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_lgrp_numbydomain(SMB_DOMAIN_LOCAL, &grpcnt); 4517f667e74Sjose borrego break; 4527f667e74Sjose borrego 4537f667e74Sjose borrego default: 4547f667e74Sjose borrego rc = SMB_LGRP_INVALID_ARG; 4557f667e74Sjose borrego } 4567f667e74Sjose borrego 4577f667e74Sjose borrego return ((rc == SMB_LGRP_SUCCESS) ? grpcnt : 0); 4587f667e74Sjose borrego } 4597f667e74Sjose borrego 4607f667e74Sjose borrego /* 4617f667e74Sjose borrego * Determines whether the given SID is a member of the group 4627f667e74Sjose borrego * specified by gname. 4637f667e74Sjose borrego */ 4647f667e74Sjose borrego boolean_t 4657f667e74Sjose borrego smb_sam_grp_ismember(const char *gname, smb_sid_t *sid) 4667f667e74Sjose borrego { 4677f667e74Sjose borrego smb_group_t grp; 4687f667e74Sjose borrego boolean_t ismember = B_FALSE; 4697f667e74Sjose borrego 4707f667e74Sjose borrego if (smb_lgrp_getbyname((char *)gname, &grp) == SMB_LGRP_SUCCESS) { 4717f667e74Sjose borrego ismember = smb_lgrp_is_member(&grp, sid); 4727f667e74Sjose borrego smb_lgrp_free(&grp); 4737f667e74Sjose borrego } 4747f667e74Sjose borrego 4757f667e74Sjose borrego return (ismember); 4767f667e74Sjose borrego } 4777f667e74Sjose borrego 4787f667e74Sjose borrego /* 4797f667e74Sjose borrego * Frees memories allocated for the passed account fields. 4807f667e74Sjose borrego */ 4817f667e74Sjose borrego void 4827f667e74Sjose borrego smb_account_free(smb_account_t *account) 4837f667e74Sjose borrego { 4847f667e74Sjose borrego free(account->a_name); 4857f667e74Sjose borrego free(account->a_domain); 4867f667e74Sjose borrego smb_sid_free(account->a_sid); 4877f667e74Sjose borrego smb_sid_free(account->a_domsid); 4887f667e74Sjose borrego } 4897f667e74Sjose borrego 4907f667e74Sjose borrego /* 4917f667e74Sjose borrego * Validates the given account. 4927f667e74Sjose borrego */ 4937f667e74Sjose borrego boolean_t 4947f667e74Sjose borrego smb_account_validate(smb_account_t *account) 4957f667e74Sjose borrego { 4967f667e74Sjose borrego return ((account->a_name != NULL) && (account->a_sid != NULL) && 4977f667e74Sjose borrego (account->a_domain != NULL) && (account->a_domsid != NULL)); 4987f667e74Sjose borrego } 4997f667e74Sjose borrego 5007f667e74Sjose borrego /* 5017f667e74Sjose borrego * Lookup local SMB user account database (/var/smb/smbpasswd) 5027f667e74Sjose borrego * if there's a match query its SID from idmap service and make 5037f667e74Sjose borrego * sure the SID is a local SID. 5047f667e74Sjose borrego * 5057f667e74Sjose borrego * The memory for the returned SID must be freed by the caller. 5067f667e74Sjose borrego */ 5077f667e74Sjose borrego static uint32_t 5087f667e74Sjose borrego smb_sam_lookup_user(char *name, smb_sid_t **sid) 5097f667e74Sjose borrego { 5107f667e74Sjose borrego smb_passwd_t smbpw; 5117f667e74Sjose borrego 5127f667e74Sjose borrego if (smb_pwd_getpwnam(name, &smbpw) == NULL) 5137f667e74Sjose borrego return (NT_STATUS_NO_SUCH_USER); 5147f667e74Sjose borrego 5157f667e74Sjose borrego if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid) 5167f667e74Sjose borrego != IDMAP_SUCCESS) 5177f667e74Sjose borrego return (NT_STATUS_NONE_MAPPED); 5187f667e74Sjose borrego 5197f667e74Sjose borrego if (!smb_sid_islocal(*sid)) { 5207f667e74Sjose borrego smb_sid_free(*sid); 5217f667e74Sjose borrego return (NT_STATUS_NONE_MAPPED); 5227f667e74Sjose borrego } 5237f667e74Sjose borrego 5247f667e74Sjose borrego return (NT_STATUS_SUCCESS); 5257f667e74Sjose borrego } 5267f667e74Sjose borrego 5277f667e74Sjose borrego /* 5287f667e74Sjose borrego * Lookup local SMB group account database (/var/smb/smbgroup.db) 5297f667e74Sjose borrego * The memory for the returned SID must be freed by the caller. 5307f667e74Sjose borrego */ 5317f667e74Sjose borrego static uint32_t 5327f667e74Sjose borrego smb_sam_lookup_group(char *name, smb_sid_t **sid) 5337f667e74Sjose borrego { 5347f667e74Sjose borrego smb_group_t grp; 5357f667e74Sjose borrego 5367f667e74Sjose borrego if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS) 5377f667e74Sjose borrego return (NT_STATUS_NO_SUCH_ALIAS); 5387f667e74Sjose borrego 5397f667e74Sjose borrego *sid = smb_sid_dup(grp.sg_id.gs_sid); 5407f667e74Sjose borrego smb_lgrp_free(&grp); 5417f667e74Sjose borrego 5427f667e74Sjose borrego return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS); 5437f667e74Sjose borrego } 54429bd2886SAlan Wright 54529bd2886SAlan Wright static smb_lwka_t * 54629bd2886SAlan Wright smb_lwka_lookup_name(char *name) 54729bd2886SAlan Wright { 54829bd2886SAlan Wright int i; 54929bd2886SAlan Wright 55029bd2886SAlan Wright for (i = 0; i < SMB_LWKA_NUM; i++) { 551bbf6f00cSJordan Brown if (smb_strcasecmp(name, lwka_tbl[i].lwka_name, 0) == 0) 55229bd2886SAlan Wright return (&lwka_tbl[i]); 55329bd2886SAlan Wright } 55429bd2886SAlan Wright 55529bd2886SAlan Wright return (NULL); 55629bd2886SAlan Wright } 55729bd2886SAlan Wright 55829bd2886SAlan Wright static smb_lwka_t * 55929bd2886SAlan Wright smb_lwka_lookup_sid(smb_sid_t *sid) 56029bd2886SAlan Wright { 56129bd2886SAlan Wright uint32_t rid; 56229bd2886SAlan Wright int i; 56329bd2886SAlan Wright 56429bd2886SAlan Wright (void) smb_sid_getrid(sid, &rid); 56529bd2886SAlan Wright if (rid > 999) 56629bd2886SAlan Wright return (NULL); 56729bd2886SAlan Wright 56829bd2886SAlan Wright for (i = 0; i < SMB_LWKA_NUM; i++) { 56929bd2886SAlan Wright if (rid == lwka_tbl[i].lwka_rid) 57029bd2886SAlan Wright return (&lwka_tbl[i]); 57129bd2886SAlan Wright } 57229bd2886SAlan Wright 57329bd2886SAlan Wright return (NULL); 57429bd2886SAlan Wright } 575*b819cea2SGordon Ross 576*b819cea2SGordon Ross /* 577*b819cea2SGordon Ross * smb_sid_islocal 578*b819cea2SGordon Ross * 579*b819cea2SGordon Ross * Check a SID to see if it belongs to the local domain. 580*b819cea2SGordon Ross */ 581*b819cea2SGordon Ross boolean_t 582*b819cea2SGordon Ross smb_sid_islocal(smb_sid_t *sid) 583*b819cea2SGordon Ross { 584*b819cea2SGordon Ross smb_domain_t di; 585*b819cea2SGordon Ross boolean_t islocal = B_FALSE; 586*b819cea2SGordon Ross 587*b819cea2SGordon Ross if (smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) 588*b819cea2SGordon Ross islocal = smb_sid_indomain(di.di_binsid, sid); 589*b819cea2SGordon Ross 590*b819cea2SGordon Ross return (islocal); 591*b819cea2SGordon Ross } 592*b819cea2SGordon Ross 593*b819cea2SGordon Ross void 594*b819cea2SGordon Ross smb_ids_free(smb_ids_t *ids) 595*b819cea2SGordon Ross { 596*b819cea2SGordon Ross smb_id_t *id; 597*b819cea2SGordon Ross int i; 598*b819cea2SGordon Ross 599*b819cea2SGordon Ross if ((ids != NULL) && (ids->i_ids != NULL)) { 600*b819cea2SGordon Ross id = ids->i_ids; 601*b819cea2SGordon Ross for (i = 0; i < ids->i_cnt; i++, id++) 602*b819cea2SGordon Ross smb_sid_free(id->i_sid); 603*b819cea2SGordon Ross 604*b819cea2SGordon Ross free(ids->i_ids); 605*b819cea2SGordon Ross } 606*b819cea2SGordon Ross } 607