/* * lsarpc_s_UpdateDomainTable * * This routine is responsible for maintaining the domain table which * will be returned from a SID lookup. Whenever a name is added to the * name table, this function should be called with the corresponding * domain name. If the domain information is not already in the table, * it is added. On success return 0; Otherwise -1 is returned. */ static int lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa, smb_account_t *account, struct mslsa_domain_table *domain_table, DWORD *domain_idx) { struct mslsa_domain_entry *dentry; DWORD n_entry; DWORD i; int rc; if (account->a_type == SidTypeUnknown || account->a_type == SidTypeInvalid) { /* * These types don't need to reference an entry in the * domain table. So return -1. */ *domain_idx = (DWORD)-1; return (0); } if ((dentry = domain_table->entries) == NULL) return (-1); if ((n_entry = domain_table->n_entry) >= MLSVC_DOMAIN_MAX) return (-1); for (i = 0; i < n_entry; ++i) { if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid, account->a_domsid)) { *domain_idx = i; return (0); } } if (i == MLSVC_DOMAIN_MAX) return (-1); rc = NDR_MSTRING(mxa, account->a_domain, (ndr_mstring_t *)&dentry[i].domain_name); dentry[i].domain_sid = (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid); if (rc == -1 || dentry[i].domain_sid == NULL) return (-1); ++domain_table->n_entry; *domain_idx = i; return (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); }
/* * smb_acl_to_zfs * * Converts given Windows ACL to a ZFS ACL. * * fs_acl will contain a pointer to the created ZFS ACL. * The allocated memory should be freed by calling * smb_fsacl_free(). * * Since the output parameter, fs_acl, is allocated in this * function, the caller has to make sure *fs_acl is NULL which * means it's not pointing to any memory. */ uint32_t smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) { smb_ace_t *ace; acl_t *zacl; ace_t *zace; smb_idmap_batch_t sib; smb_idmap_t *sim; idmap_stat idm_stat; int i; ASSERT(fs_acl); ASSERT(*fs_acl == NULL); if (acl && !smb_acl_isvalid(acl, which_acl)) return (NT_STATUS_INVALID_ACL); if ((acl == NULL) || (acl->sl_acecnt == 0)) { if (which_acl == SMB_DACL_SECINFO) { *fs_acl = smb_fsacl_null_empty(acl == NULL); } return (NT_STATUS_SUCCESS); } idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, SMB_IDMAP_SID2ID); if (idm_stat != IDMAP_SUCCESS) return (NT_STATUS_INTERNAL_ERROR); zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); zace = zacl->acl_aclp; ace = acl->sl_aces; sim = sib.sib_maps; for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags); if (smb_sid_cmp(ace->se_sid, &everyone_sid)) zace->a_flags |= ACE_EVERYONE; else { sim->sim_id = &zace->a_who; idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, ace->se_sid, -1); if (idm_stat != IDMAP_SUCCESS) { smb_fsacl_free(zacl); smb_idmap_batch_destroy(&sib); return (NT_STATUS_INTERNAL_ERROR); } } } idm_stat = smb_idmap_batch_getmappings(&sib); if (idm_stat != IDMAP_SUCCESS) { smb_fsacl_free(zacl); smb_idmap_batch_destroy(&sib); return (NT_STATUS_NONE_MAPPED); } /* * Set the ACEs group flag based on the type of ID returned. */ zace = zacl->acl_aclp; ace = acl->sl_aces; sim = sib.sib_maps; for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { if (zace->a_flags & ACE_EVERYONE) continue; if (sim->sim_idtype == SMB_IDMAP_GROUP) zace->a_flags |= ACE_IDENTIFIER_GROUP; } smb_idmap_batch_destroy(&sib); *fs_acl = zacl; return (NT_STATUS_SUCCESS); }