summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs
diff options
context:
space:
mode:
authoras200622 <none@none>2007-11-26 18:29:15 -0800
committeras200622 <none@none>2007-11-26 18:29:15 -0800
commit55bf511df53aad0fdb7eb3fa349f0308cc05234c (patch)
treea153d7bae39c0480da0107072553ce0b07b02f23 /usr/src/uts/common/fs
parentb3d911cb99b7e5dd9df4c81fd7b58a97c82d07db (diff)
downloadillumos-joyent-55bf511df53aad0fdb7eb3fa349f0308cc05234c.tar.gz
6575640 rename/rmdir/remove on mixed file systems work incorrectly for mangled names
6582182 64-bit libraries 6588720 Unable to create new folder in autohome share from Solaris10u3 with UFS & ZFS. 6611820 Unable to map a SMB share on SPARC system. 6612193 Rework ADS client, DynDNS client and Auth IPC to use host principal 6614664 CIFS server should not request ctime changes 6614864 Security tab not available after a share is mapped on SPARC system 6614953 An error occurred while creating a notepad file on X86 32-bit system. 6616349 Sparc-Get error "input not UTF-8" and (Abort)(core dumped) in sharemgr with Korean resource name 6622828 Resolve unreferenced makefiles 6626833 SUNWsmbsu package issues with snv_77. 6627415 SmbCreateTemporary fails on SPARC 6627469 Unable to map SIDs to names for Windows Vista clients 6627471 Remove winpipe door server from name space 6628747 smbd crash and in maintenance state 6629402 The adjoin operation triggered by smbadm join CLI shouldn't overwrite the Kerberos keytab file. 6629410 SMB daemon should remove its ccache on refresh or restart 6629428 smb daemon crashes at smb_nic_clear_niclist+0x45(815ff10, 2) 6629797 sharemgr: Deleting an SMB resource that has an option leads to core dump 6630470 Get core in sharemgr:libshare_smb.so.1`smb_enable_service+0x78(2ec90, fe87c49c, 0, ff396000,17e54,6) --HG-- rename : usr/src/uts/common/smbsrv/smb_secdesc.h => deleted_files/usr/src/uts/common/smbsrv/smb_secdesc.h
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_acl.c1571
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_create.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c245
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_init.c12
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_lock_svc.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c30
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c440
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c16
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_open_andx.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c28
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_read.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_rpc.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_sd.c812
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c20
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c18
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c17
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c221
-rwxr-xr-xusr/src/uts/common/fs/smbsrv/smb_winpipe.c50
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_write.c10
25 files changed, 1612 insertions, 1919 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_acl.c b/usr/src/uts/common/fs/smbsrv/smb_acl.c
index 2617268d9e..5491e927f1 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_acl.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_acl.c
@@ -25,68 +25,15 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-/*
- * Platform SDK: Security
- *
- * ACE Inheritance Rules
- *
- * The system propagates inheritable ACEs to child objects according to a
- * set of inheritance rules. The system places inherited ACEs in the child's
- * DACL according to the preferred order of ACEs in a DACL. For Windows
- * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
- *
- * The following table shows the ACEs inherited by container and noncontainer
- * child objects for different combinations of inheritance flags. These
- * inheritance rules work the same for both DACLs and SACLs.
- *
- * Parent ACE type Effect on Child ACL
- * ----------------------- -------------------
- * OBJECT_INHERIT_ACE only Noncontainer child objects:
- * Inherited as an effective ACE.
- * Container child objects:
- * Containers inherit an inherit-only ACE
- * unless the NO_PROPAGATE_INHERIT_ACE bit
- * flag is also set.
- *
- * CONTAINER_INHERIT_ACE only Noncontainer child objects:
- * No effect on the child object.
- * Container child objects:
- * The child object inherits an effective ACE.
- * The inherited ACE is inheritable unless the
- * NO_PROPAGATE_INHERIT_ACE bit flag is also set.
- *
- * CONTAINER_INHERIT_ACE and
- * OBJECT_INHERIT_ACE Noncontainer child objects:
- * Inherited as an effective ACE.
- * Container child objects:
- * The child object inherits an effective ACE.
- * The inherited ACE is inheritable unless the
- * NO_PROPAGATE_INHERIT_ACE bit flag is also set
- *
- * No inheritance flags set No effect on child container or noncontainer
- * objects.
- *
- * If an inherited ACE is an effective ACE for the child object, the system
- * maps any generic rights to the specific rights for the child object.
- * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
- * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
- * rights or generic SIDs are left unchanged so that they can be mapped
- * appropriately when the ACE is inherited by the next generation of child
- * objects.
- *
- * For a case in which a container object inherits an ACE that is both
- * effective on the container and inheritable by its descendants, the
- * container may inherit two ACEs. This occurs if the inheritable ACE
- * contains generic information. The container inherits an inherit-only
- * ACE containing the generic information and an effective-only ACE in
- * which the generic information has been mapped.
- */
-
#include <sys/acl.h>
-#include <smbsrv/smb_incl.h>
+#include <acl/acl_common.h>
#include <smbsrv/ntsid.h>
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_idmap.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smbvar.h>
+#include <smbsrv/ntstatus.h>
+#include <smbsrv/ntaccess.h>
#define ACE_FD_INHERIT_ACE (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE)
@@ -111,195 +58,143 @@
#define ZACE_IS_CREATOR(zace) \
(ZACE_IS_CREATOR_OWNER(zace) || ZACE_IS_CREATOR_GROUP(zace))
-static int smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl);
-static int smb_ace_append_generic(smb_acl_t *acl, void *generic_ace);
-
-static int smb_ace_common_add(
- smb_acl_t *acl,
- uint8_t type,
- uint8_t flags,
- uint32_t access_mask,
- nt_sid_t *sid);
-
-static void smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir);
-static uint16_t smb_ace_flags_tozfs(uint8_t c_flags, int isdir);
-static uint8_t smb_ace_flags_fromzfs(uint16_t z_flags);
-static void smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev);
-
-static int
-smb_ace_isvalid(smb_ace_hdr_t *ace, int which_acl)
-{
- uint16_t min_len;
- smb_ace_t *p;
+/*
+ * ACE groups within a DACL
+ *
+ * This is from lower to higher ACE order priority
+ */
+#define SMB_AG_START 0
+#define SMB_AG_ALW_INHRT 0
+#define SMB_AG_DNY_INHRT 1
+#define SMB_AG_ALW_DRCT 2
+#define SMB_AG_DNY_DRCT 3
+#define SMB_AG_NUM 4
- min_len = sizeof (smb_ace_hdr_t);
+/*
+ * SID for Everyone group: S-1-1-0.
+ */
+nt_sid_t everyone_sid = {
+ NT_SID_REVISION,
+ 1,
+ NT_SECURITY_WORLD_AUTH,
+ { 0 }
+};
- if (ace->se_size < min_len)
- return (0);
+#define DEFAULT_DACL_ACENUM 2
+/*
+ * Default ACL:
+ * owner: full access
+ * SYSTEM: full access
+ */
+static ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
+ { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
+ { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
+ ACE_ACCESS_ALLOWED_ACE_TYPE }
+};
- if (smb_ace_is_access(ace->se_type) &&
- (which_acl != SMB_DACL_SECINFO)) {
- return (0);
- }
+/*
+ * Note:
+ *
+ * smb_acl_xxx functions work with smb_acl_t which represents the CIFS format
+ * smb_fsacl_xxx functions work with acl_t which represents the Solaris native
+ * format
+ */
- if (smb_ace_is_audit(ace->se_type) &&
- (which_acl != SMB_SACL_SECINFO)) {
- return (0);
- }
+static idmap_stat smb_acl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t);
+static acl_t *smb_acl_null_empty(boolean_t null);
- if (smb_ace_is_generic(ace->se_type)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- p = (smb_ace_t *)ace;
+static int smb_fsacl_inheritable(acl_t *, int);
- if (ace->se_size < sizeof (*p))
- return (0); /* won't handle empty SubAuthority[] */
- if (nt_sid_is_valid(&p->se_sid) == 0)
- return (0);
+static void smb_ace_inherit(ace_t *, ace_t *, int);
+static boolean_t smb_ace_isvalid(smb_ace_t *, int);
+static uint16_t smb_ace_len(smb_ace_t *);
+static uint32_t smb_ace_mask_g2s(uint32_t);
+static uint16_t smb_ace_flags_tozfs(uint8_t, int);
+static uint8_t smb_ace_flags_fromzfs(uint16_t);
- min_len += sizeof (p->se_mask);
- min_len += nt_sid_length(&p->se_sid);
+smb_acl_t *
+smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt)
+{
+ smb_acl_t *acl;
+ int size;
- if (ace->se_size < min_len)
- return (0);
- }
+ size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t));
+ acl = kmem_zalloc(size, KM_SLEEP);
+ acl->sl_revision = revision;
+ acl->sl_bsize = bsize;
+ acl->sl_acecnt = acecnt;
+ acl->sl_aces = (smb_ace_t *)(acl + 1);
- /*
- * XXX object-specific ACE validation will be added later.
- */
- return (1);
+ list_create(&acl->sl_sorted, sizeof (smb_ace_t),
+ offsetof(smb_ace_t, se_sln));
+ return (acl);
}
-int
-smb_acl_isvalid(smb_acl_t *acl, int which_acl)
+void
+smb_acl_free(smb_acl_t *acl)
{
- uint16_t min_len;
- unsigned char *scan;
- unsigned char *scan_end;
- smb_ace_hdr_t *ace;
- uint16_t count = 0;
-
- min_len = sizeof (smb_acl_t);
-
- if (acl->sl_size < min_len)
- return (0);
-
- if (acl->sl_revision != ACL_REVISION) {
- /*
- * XXX we are rejecting ACLs with object-specific ACEs for now
- */
- return (0);
- }
+ int i, size;
+ void *ace;
- scan = (unsigned char *) &acl[0];
- scan_end = scan + acl->sl_size;
- scan = (unsigned char *) &acl[1]; /* skip Acl header */
+ if (acl == NULL)
+ return;
- while (count < acl->sl_acecnt && scan < scan_end) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ace = (smb_ace_hdr_t *)scan;
-
- if (scan + sizeof (smb_ace_hdr_t) >= scan_end)
- return (0);
-
- if (scan + ace->se_size > scan_end)
- return (0); /* overflow */
-
- if (!smb_ace_isvalid(ace, which_acl))
- return (0);
-
- scan += ace->se_size;
- count++;
+ for (i = 0; i < acl->sl_acecnt; i++) {
+ MEM_FREE("smbsrv", acl->sl_aces[i].se_sid);
}
- return (1);
-}
-
+ while ((ace = list_head(&acl->sl_sorted)) != NULL)
+ list_remove(&acl->sl_sorted, ace);
+ list_destroy(&acl->sl_sorted);
-static void
-smb_acl_init(smb_acl_t *acl, uint16_t size, uint8_t rev)
-{
- bzero(acl, size);
- acl->sl_revision = rev;
- acl->sl_size = size;
+ size = sizeof (smb_acl_t) + (acl->sl_acecnt * sizeof (smb_ace_t));
+ kmem_free(acl, size);
}
+/*
+ * smb_acl_len
+ *
+ * Returns the size of given ACL in bytes. Note that this
+ * is not an in-memory size, it's the ACL's size as it would
+ * appear on the wire
+ */
uint16_t
smb_acl_len(smb_acl_t *acl)
{
- smb_ace_hdr_t *ace;
- unsigned char *scan_beg;
- unsigned char *scan_end;
- unsigned char *scan;
- uint16_t length;
- uint16_t count;
-
- scan_beg = (unsigned char *) &acl[0];
- scan_end = scan_beg + acl->sl_size;
- scan = (unsigned char *) &acl[1];
- length = sizeof (smb_acl_t);
- count = 0;
-
- while ((count < acl->sl_acecnt) && (scan < scan_end)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ace = (smb_ace_hdr_t *)scan;
- length += ace->se_size;
- scan += ace->se_size;
- count++;
- }
+ if (acl == NULL)
+ return (0);
- return (length);
+ return (acl->sl_bsize);
}
-/*
- * Append the generic ACE to the ACL. This is used to put any
- * kind of ACE on the ACL so the argument is declared as a void*. We cast it
- * to an ACCESS_ALLOWED_ACE just because there is no sense of a generic ACE.
- */
-static int
-smb_ace_append_generic(smb_acl_t *acl, void *generic_ace)
+boolean_t
+smb_acl_isvalid(smb_acl_t *acl, int which_acl)
{
- smb_ace_t *ace = (smb_ace_t *)generic_ace;
- uint16_t acl_len = smb_acl_len(acl);
- unsigned char *scan = (uchar_t *)acl;
+ int i;
- if ((acl_len + ace->se_header.se_size) > acl->sl_size) {
- /* no room in the acl for this ace */
- return (0);
+ if (acl->sl_bsize < SMB_ACL_HDRSIZE)
+ return (B_FALSE);
+
+ if (acl->sl_revision != ACL_REVISION) {
+ /*
+ * we are rejecting ACLs with object-specific ACEs for now
+ */
+ return (B_FALSE);
}
- /* append the ace to the acl and inc ace count */
- bcopy(ace, &scan[acl_len], ace->se_header.se_size);
- acl->sl_acecnt++;
+ for (i = 0; i < acl->sl_acecnt; i++) {
+ if (!smb_ace_isvalid(&acl->sl_aces[i], which_acl))
+ return (B_FALSE);
+ }
- return (1);
+ return (B_TRUE);
}
/*
- * Helper for the ACL sort routine
- */
-typedef struct smb_ace_entry {
- smb_ace_t *e_ace;
- list_node_t e_node;
-} smb_ace_entry_t;
-
-/*
- * ACE groups within a DACL
- *
- * This is from lower to higher ACE order priority
- */
-#define SMB_AG_START 0
-#define SMB_AG_ALW_INHRT 0
-#define SMB_AG_DNY_INHRT 1
-#define SMB_AG_ALW_DRCT 2
-#define SMB_AG_DNY_DRCT 3
-#define SMB_AG_NUM 4
-
-/*
- * smb_acl_do_sort
+ * smb_acl_sort
*
- * Sorts the given ACL, acl, and returns the result
- * in a newly allocated memory.
+ * Sorts the given ACL in place if it needs to be sorted.
*
* The following is an excerpt from MSDN website.
*
@@ -327,82 +222,20 @@ typedef struct smb_ace_entry {
* . Access-allowed ACEs that apply to the object itself
* . Access-allowed ACEs that apply to a subobject of the object
*
- * Of course, not all ACE types are required in an ACL.
- */
-static smb_acl_t *
-smb_acl_do_sort(smb_acl_t *acl, list_t *ace_grps)
-{
- smb_acl_t *sorted_acl;
- smb_ace_entry_t *nae;
- int i;
-
- sorted_acl = kmem_alloc(acl->sl_size, KM_SLEEP);
- *sorted_acl = *acl;
-
- /* start with no ACE in the sorted ACL */
- sorted_acl->sl_acecnt = 0;
-
- /*
- * start with highest priority ACE group and append
- * the ACEs to the ACL.
- */
- for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
- nae = list_head(&ace_grps[i]);
- while (nae) {
- if (!smb_ace_append_generic(sorted_acl, nae->e_ace)) {
- kmem_free(sorted_acl, acl->sl_size);
- return (NULL);
- }
- nae = list_next(&ace_grps[i], nae);
- }
- }
-
- return (sorted_acl);
-}
-
-/*
- * smb_acl_need_sort
- *
- * Here is the desired ACE order
+ * So, here is the desired ACE order
*
* deny-direct, allow-direct, deny-inherited, allow-inherited
*
- * If any ace has been encountered which belongs to a group
- * with lower priority of the specified ace_grp then the acl
- * should be sorted.
- */
-static int
-smb_acl_need_sort(list_t *ace_grps, int ace_grp)
-{
- int i;
-
- for (i = SMB_AG_START; i < ace_grp; i++)
- if (!list_is_empty(&ace_grps[i]))
- return (1);
-
- return (0);
-}
-
-/*
- * smb_acl_sort
- *
- * Returns NULL upon failure.
- * Returns pointer to the passed (original) acl if no sort is required.
- * Returns pointer to a new acl upon successful sort in which case the
- * caller is responsible for freeing the allocated memory.
+ * Of course, not all ACE types are required in an ACL.
*/
-smb_acl_t *
+void
smb_acl_sort(smb_acl_t *acl)
{
- smb_acl_t *sorted_acl;
- smb_ace_t *ace;
- smb_ace_entry_t *ace_list;
- int ace_list_size;
list_t ace_grps[SMB_AG_NUM];
- int ag;
- int do_sort = 0;
- uint16_t i;
+ list_t *alist;
+ smb_ace_t *ace;
uint8_t ace_flags;
+ int ag, i;
ASSERT(acl);
@@ -411,46 +244,26 @@ smb_acl_sort(smb_acl_t *acl)
* ACL with no entry is a valid ACL and it means
* no access for anybody.
*/
- return (acl);
+ return;
}
for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
- list_create(&ace_grps[i], sizeof (smb_ace_entry_t),
- offsetof(smb_ace_entry_t, e_node));
+ list_create(&ace_grps[i], sizeof (smb_ace_t),
+ offsetof(smb_ace_t, se_sln));
}
- /*
- * Allocate the helper entries to group the ACEs based on
- * the desired priorities.
- */
- ace_list_size = sizeof (smb_ace_entry_t) * acl->sl_acecnt;
- ace_list = kmem_alloc(ace_list_size, KM_SLEEP);
-
- for (i = 0; i < acl->sl_acecnt; ++i) {
- ace_list[i].e_ace = smb_ace_get(acl, i);
- ace = ace_list[i].e_ace;
- ASSERT(ace);
+ for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) {
+ ace_flags = ace->se_hdr.se_flags;
- ace_flags = ace->se_header.se_flags;
-
- switch (ace->se_header.se_type) {
+ switch (ace->se_hdr.se_type) {
case ACCESS_DENIED_ACE_TYPE:
- if (ace_flags & INHERITED_ACE) {
- ag = SMB_AG_DNY_INHRT;
- do_sort |= smb_acl_need_sort(ace_grps, ag);
- } else {
- ag = SMB_AG_DNY_DRCT;
- do_sort |= smb_acl_need_sort(ace_grps, ag);
- }
+ ag = (ace_flags & INHERITED_ACE) ?
+ SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT;
break;
case ACCESS_ALLOWED_ACE_TYPE:
- if (ace_flags & INHERITED_ACE) {
- ag = SMB_AG_ALW_INHRT;
- } else {
- ag = SMB_AG_ALW_DRCT;
- do_sort |= smb_acl_need_sort(ace_grps, ag);
- }
+ ag = (ace_flags & INHERITED_ACE) ?
+ SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT;
break;
default:
@@ -462,185 +275,177 @@ smb_acl_sort(smb_acl_t *acl)
break;
}
- /* Put the element on the appropriate list */
- list_insert_tail(&ace_grps[ag], &ace_list[i]);
+ /* Add the ACE to the selected group */
+ list_insert_tail(&ace_grps[ag], ace);
}
- if (do_sort)
- sorted_acl = smb_acl_do_sort(acl, ace_grps);
- else
- sorted_acl = acl;
-
- for (i = SMB_AG_START; i < SMB_AG_NUM; i++) {
- void *ent;
- list_t *alist = &ace_grps[i];
-
- while ((ent = list_head(alist)) != NULL)
- list_remove(alist, ent);
+ /*
+ * start with highest priority ACE group and append
+ * the ACEs to the ACL.
+ */
+ for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) {
+ alist = &ace_grps[i];
+ while ((ace = list_head(alist)) != NULL) {
+ list_remove(alist, ace);
+ list_insert_tail(&acl->sl_sorted, ace);
+ }
list_destroy(alist);
}
-
- kmem_free(ace_list, ace_list_size);
-
- return (sorted_acl);
}
-static int
-smb_ace_common_add(
- smb_acl_t *acl,
- uint8_t type,
- uint8_t flags,
- uint32_t access_mask,
- nt_sid_t *sid)
+/*
+ * smb_acl_from_zfs
+ *
+ * Converts given ZFS ACL to a Windows ACL.
+ *
+ * A pointer to allocated memory for the Win ACL will be
+ * returned upon successful conversion.
+ */
+smb_acl_t *
+smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid)
{
+ ace_t *zace;
+ int numaces;
+ smb_acl_t *acl;
smb_ace_t *ace;
- unsigned char *scan = (unsigned char *) acl;
- uint16_t used = smb_acl_len(acl);
- uint16_t sid_len = nt_sid_length(sid);
- uint16_t size;
+ smb_idmap_batch_t sib;
+ smb_idmap_t *sim;
+ idmap_stat idm_stat;
- size = sizeof (ace->se_header) + sizeof (ace->se_mask) + sid_len;
+ idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
+ SMB_IDMAP_ID2SID);
+ if (idm_stat != IDMAP_SUCCESS)
+ return (NULL);
- if (size + used > acl->sl_size) {
- /* won't fit */
- return (0);
+ if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) {
+ smb_idmap_batch_destroy(&sib);
+ return (NULL);
}
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ace = (smb_ace_t *)&scan[used];
+ acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt);
+
+ sim = sib.sib_maps;
+ for (numaces = 0, zace = zacl->acl_aclp;
+ numaces < zacl->acl_cnt;
+ zace++, numaces++, sim++) {
+ ASSERT(sim->sim_sid);
+ if (sim->sim_sid == NULL) {
+ smb_acl_free(acl);
+ acl = NULL;
+ break;
+ }
- ace->se_header.se_type = type;
- ace->se_header.se_flags = flags;
- ace->se_header.se_size = size;
- ace->se_mask = access_mask;
- bcopy(sid, &ace->se_sid, sid_len);
+ ace = &acl->sl_aces[numaces];
+ ace->se_hdr.se_type = zace->a_type;
+ ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags);
+ ace->se_mask = zace->a_access_mask;
+ ace->se_sid = nt_sid_dup(sim->sim_sid);
+ ace->se_hdr.se_bsize = smb_ace_len(ace);
- acl->sl_acecnt++;
+ acl->sl_bsize += ace->se_hdr.se_bsize;
+ }
- return (1);
+ smb_idmap_batch_destroy(&sib);
+ return (acl);
}
-smb_ace_t *
-smb_ace_get(smb_acl_t *acl, uint16_t idx)
+/*
+ * 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;
- unsigned char *scan_beg = (unsigned char *) &acl[0];
- unsigned char *scan_end = scan_beg + acl->sl_size;
- unsigned char *scan = (unsigned char *) &acl[1];
- uint16_t count = 0;
+ acl_t *zacl;
+ ace_t *zace;
+ smb_idmap_batch_t sib;
+ smb_idmap_t *sim;
+ idmap_stat idm_stat;
+ int i, isdir;
- if (idx >= acl->sl_acecnt)
- return (NULL);
+ ASSERT(fs_acl);
+ ASSERT(*fs_acl == NULL);
- while (count <= idx && scan < scan_end) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ace = (smb_ace_t *)scan;
+ if (acl && !smb_acl_isvalid(acl, which_acl))
+ return (NT_STATUS_INVALID_ACL);
- if (count == idx) {
- return (ace);
+ if ((acl == NULL) || (acl->sl_acecnt == 0)) {
+ if (which_acl == SMB_DACL_SECINFO) {
+ *fs_acl = smb_acl_null_empty(acl == NULL);
}
- scan += ace->se_header.se_size;
- count++;
+ return (NT_STATUS_SUCCESS);
}
- return (NULL);
-}
-
-int
-smb_acl_copy(uint16_t buflen, smb_acl_t *dst_acl, smb_acl_t *src_acl)
-{
- smb_ace_hdr_t *dst_ace;
- smb_ace_hdr_t *src_ace;
- unsigned char *scan = (unsigned char *) &src_acl[1];
- unsigned char *dest_beg = (unsigned char *) &dst_acl[0];
- unsigned char *dest_end;
- unsigned char *dest = (unsigned char *) &dst_acl[1];
- uint16_t count = 0;
- uint16_t n_bytes;
-
- n_bytes = smb_acl_len(src_acl);
- if (n_bytes > buflen)
- return (0);
+ idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
+ SMB_IDMAP_SID2ID);
+ if (idm_stat != IDMAP_SUCCESS)
+ return (NT_STATUS_INTERNAL_ERROR);
- dest_end = dest_beg + n_bytes;
-
- dst_acl->sl_revision = src_acl->sl_revision;
- dst_acl->sl_sbz1 = 0;
- dst_acl->sl_size = n_bytes;
- dst_acl->sl_acecnt = 0;
- dst_acl->sl_sbz2 = 0;
-
- while (count < src_acl->sl_acecnt && dest < dest_end) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- src_ace = (smb_ace_hdr_t *)scan;
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- dst_ace = (smb_ace_hdr_t *)dest;
- bcopy(src_ace, dst_ace, src_ace->se_size);
- dest += dst_ace->se_size;
- dst_acl->sl_acecnt++;
- scan += src_ace->se_size;
- count++;
- }
+ isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR);
- /*LINTED E_PTRDIFF_OVERFLOW*/
- return (dest - dest_beg);
-}
+ zacl = smb_fsacl_alloc(acl->sl_acecnt, flags);
-/*
- * smb_ace_len
- *
- * Returns the length of an ACE with the given SID
- *
- * struct smb_ace {
- * smb_ace_hdr_t se_header;
- * uint32_t se_mask;
- * nt_sid_t se_sid;
- * };
- */
-uint16_t
-smb_ace_len(nt_sid_t *sid)
-{
- ASSERT(sid);
+ zace = zacl->acl_aclp;
+ ace = acl->sl_aces;
+ sim = sib.sib_maps;
- return (sizeof (smb_ace_hdr_t)
- + sizeof (uint32_t) + nt_sid_length(sid));
-}
+ 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,
+ isdir);
-/*
- * smb_ace_mask_g2s
- *
- * Converts generic access bits in the given mask (if any)
- * to file specific bits. Generic access masks shouldn't be
- * stored in filesystem ACEs.
- */
-uint32_t
-smb_ace_mask_g2s(DWORD mask)
-{
- if (mask & GENERIC_ALL) {
- mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
- | GENERIC_EXECUTE);
+ if (nt_sid_is_equal(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);
- mask |= FILE_ALL_ACCESS;
- return (mask);
+ if (idm_stat != IDMAP_SUCCESS) {
+ smb_fsacl_free(zacl);
+ smb_idmap_batch_destroy(&sib);
+ return (NT_STATUS_INTERNAL_ERROR);
+ }
+ }
}
- if (mask & GENERIC_READ) {
- mask &= ~GENERIC_READ;
- mask |= FILE_GENERIC_READ;
+ 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);
}
- if (mask & GENERIC_WRITE) {
- mask &= ~GENERIC_WRITE;
- mask |= FILE_GENERIC_WRITE;
- }
+ /*
+ * 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 (mask & GENERIC_EXECUTE) {
- mask &= ~GENERIC_EXECUTE;
- mask |= FILE_GENERIC_EXECUTE;
+ if (sim->sim_idtype == SMB_IDMAP_GROUP)
+ zace->a_flags |= ACE_IDENTIFIER_GROUP;
}
- return (mask);
+ smb_idmap_batch_destroy(&sib);
+
+ *fs_acl = zacl;
+ return (NT_STATUS_SUCCESS);
}
/*
@@ -702,239 +507,488 @@ smb_acl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid)
}
/*
- * smb_acl_grow
+ * smb_acl_null_empty
+ *
+ * NULL DACL means everyone full-access
+ * Empty DACL means everyone full-deny
*
- * Grow the acl size by given number of bytes in 'grow'
- * Returns pointer to the newly allocated memory.
+ * ZFS ACL must have at least one entry so smb server has
+ * to simulate the aforementioned expected behavior by adding
+ * an entry in case the requested DACL is null or empty. Adding
+ * a everyone full-deny entry has proved to be problematic in
+ * tests since a deny entry takes precedence over allow entries.
+ * So, instead of adding a everyone full-deny, an owner ACE with
+ * owner implicit permissions will be set.
*/
-static smb_acl_t *
-smb_acl_grow(smb_acl_t *acl, uint16_t grow)
+static acl_t *
+smb_acl_null_empty(boolean_t null)
{
- smb_acl_t *new_acl;
- uint16_t smb_aclsz;
+ acl_t *zacl;
+ ace_t *zace;
- ASSERT(acl);
+ zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT);
+ zace = zacl->acl_aclp;
- smb_aclsz = acl->sl_size;
- new_acl = kmem_alloc(smb_aclsz + grow, KM_SLEEP);
- (void) memcpy(new_acl, acl, smb_aclsz);
- kmem_free(acl, smb_aclsz);
- new_acl->sl_size = smb_aclsz + grow;
+ zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ if (null) {
+ zace->a_access_mask = ACE_ALL_PERMS;
+ zace->a_flags = ACE_EVERYONE;
+ } else {
+ zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
+ ACE_READ_ATTRIBUTES;
+ zace->a_flags = ACE_OWNER;
+ }
- return (new_acl);
+ return (zacl);
}
/*
- * smb_acl_from_zfs
+ * FS ACL (acl_t) Functions
+ */
+acl_t *
+smb_fsacl_alloc(int acenum, int flags)
+{
+ acl_t *acl;
+
+ acl = acl_alloc(ACE_T);
+ acl->acl_cnt = acenum;
+ acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP);
+ acl->acl_flags = flags;
+ return (acl);
+}
+
+void
+smb_fsacl_free(acl_t *acl)
+{
+ if (acl)
+ acl_free(acl);
+}
+
+/*
+ * smb_fsop_aclmerge
*
- * Converts given ZFS ACL to a Windows ACL.
+ * smb_fsop_aclread/write routines which interact with filesystem
+ * work with single ACL. This routine merges given DACL and SACL
+ * which might have been created during CIFS to FS conversion into
+ * one single ACL.
+ */
+acl_t *
+smb_fsacl_merge(acl_t *dacl, acl_t *sacl)
+{
+ acl_t *acl;
+ int dacl_size;
+
+ ASSERT(dacl);
+ ASSERT(sacl);
+
+ acl = smb_fsacl_alloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags);
+ dacl_size = dacl->acl_cnt * dacl->acl_entry_size;
+ bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size);
+ bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size,
+ sacl->acl_cnt * sacl->acl_entry_size);
+
+ return (acl);
+}
+
+/*
+ * smb_fsacl_split
*
- * A pointer to allocated memory for the Win ACL will be
- * returned upon successful conversion.
+ * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on
+ * the 'which_acl' parameter. Note that output dacl/sacl parameters could be
+ * NULL even if they're specified in 'which_acl', which means the target
+ * doesn't have any access and/or audit ACEs.
*/
-smb_acl_t *
-smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid)
+void
+smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
{
ace_t *zace;
+ ace_t *access_ace;
+ ace_t *audit_ace;
+ int naccess, naudit;
+ int get_dacl, get_sacl;
+ int i;
+
+ *dacl = *sacl = NULL;
+ naccess = naudit = 0;
+ get_dacl = (which_acl & SMB_DACL_SECINFO);
+ get_sacl = (which_acl & SMB_SACL_SECINFO);
+
+ for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
+ if (get_dacl && smb_ace_is_access(zace->a_type))
+ naccess++;
+ else if (get_sacl && smb_ace_is_audit(zace->a_type))
+ naudit++;
+ }
+
+ if (naccess) {
+ *dacl = smb_fsacl_alloc(naccess, zacl->acl_flags);
+ access_ace = (*dacl)->acl_aclp;
+ }
+
+ if (naudit) {
+ *sacl = smb_fsacl_alloc(naudit, zacl->acl_flags);
+ audit_ace = (*sacl)->acl_aclp;
+ }
+
+ for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
+ if (get_dacl && smb_ace_is_access(zace->a_type)) {
+ *access_ace = *zace;
+ access_ace++;
+ } else if (get_sacl && smb_ace_is_audit(zace->a_type)) {
+ *audit_ace = *zace;
+ audit_ace++;
+ }
+ }
+}
+
+/*
+ * ACE Inheritance Rules
+ *
+ * The system propagates inheritable ACEs to child objects according to a
+ * set of inheritance rules. The system places inherited ACEs in the child's
+ * DACL according to the preferred order of ACEs in a DACL. For Windows
+ * 2000 or later, the system sets the INHERITED_ACE flag in all inherited ACEs.
+ *
+ * The following table shows the ACEs inherited by container and noncontainer
+ * child objects for different combinations of inheritance flags. These
+ * inheritance rules work the same for both DACLs and SACLs.
+ *
+ * Parent ACE type Effect on Child ACL
+ * ----------------------- -------------------
+ * OBJECT_INHERIT_ACE only Noncontainer child objects:
+ * Inherited as an effective ACE.
+ * Container child objects:
+ * Containers inherit an inherit-only ACE
+ * unless the NO_PROPAGATE_INHERIT_ACE bit
+ * flag is also set.
+ *
+ * CONTAINER_INHERIT_ACE only Noncontainer child objects:
+ * No effect on the child object.
+ * Container child objects:
+ * The child object inherits an effective ACE.
+ * The inherited ACE is inheritable unless the
+ * NO_PROPAGATE_INHERIT_ACE bit flag is also set.
+ *
+ * CONTAINER_INHERIT_ACE and
+ * OBJECT_INHERIT_ACE Noncontainer child objects:
+ * Inherited as an effective ACE.
+ * Container child objects:
+ * The child object inherits an effective ACE.
+ * The inherited ACE is inheritable unless the
+ * NO_PROPAGATE_INHERIT_ACE bit flag is also set
+ *
+ * No inheritance flags set No effect on child container or noncontainer
+ * objects.
+ *
+ * If an inherited ACE is an effective ACE for the child object, the system
+ * maps any generic rights to the specific rights for the child object.
+ * Similarly, the system maps generic SIDs, such as CREATOR_OWNER, to the
+ * appropriate SID. If an inherited ACE is an inherit-only ACE, any generic
+ * rights or generic SIDs are left unchanged so that they can be mapped
+ * appropriately when the ACE is inherited by the next generation of child
+ * objects.
+ *
+ * For a case in which a container object inherits an ACE that is both
+ * effective on the container and inheritable by its descendants, the
+ * container may inherit two ACEs. This occurs if the inheritable ACE
+ * contains generic information. The container inherits an inherit-only
+ * ACE containing the generic information and an effective-only ACE in
+ * which the generic information has been mapped.
+ */
+
+/*
+ * smb_fsacl_inherit
+ *
+ * Manufacture the inherited ACL from the given ACL considering
+ * the new object type (file/dir) specified by 'is_dir'. The
+ * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
+ * This function implements Windows inheritance rules explained above.
+ *
+ * Note that the in/out ACLs are ZFS ACLs not Windows ACLs
+ */
+acl_t *
+smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid)
+{
+ boolean_t use_default = B_FALSE;
+ int num_inheritable = 0;
int numaces;
- smb_acl_t *acl;
- uint16_t smb_aclsz;
- smb_idmap_batch_t sib;
- smb_idmap_t *sim;
- idmap_stat idm_stat;
- int status;
+ ace_t *dir_zace;
+ acl_t *new_zacl;
+ ace_t *new_zace;
- idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt,
- SMB_IDMAP_ID2SID);
- if (idm_stat != IDMAP_SUCCESS)
- return (NULL);
+ num_inheritable = smb_fsacl_inheritable(dir_zacl, is_dir);
- if (smb_acl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) {
- smb_idmap_batch_destroy(&sib);
- return (NULL);
+ if (num_inheritable == 0) {
+ if (which_acl == SMB_DACL_SECINFO) {
+ /* No inheritable access ACEs -> default DACL */
+ num_inheritable = DEFAULT_DACL_ACENUM;
+ use_default = B_TRUE;
+ } else {
+ return (NULL);
+ }
}
- smb_aclsz = sizeof (smb_acl_t);
+ new_zacl = smb_fsacl_alloc(num_inheritable, ACL_AUTO_INHERIT);
+ new_zace = new_zacl->acl_aclp;
- acl = kmem_alloc(smb_aclsz, KM_SLEEP);
- smb_acl_init(acl, smb_aclsz, ACL_REVISION);
+ if (use_default) {
+ bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
+ new_zace->a_who = owner_uid;
+ return (new_zacl);
+ }
- sim = sib.sib_maps;
- for (numaces = 0, zace = zacl->acl_aclp;
- numaces < zacl->acl_cnt;
- zace++, numaces++, sim++) {
- ASSERT(sim->sim_sid);
- if (sim->sim_sid == NULL) {
- kmem_free(acl, acl->sl_size);
- acl = NULL;
+ for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
+ numaces < dir_zacl->acl_cnt;
+ dir_zace++, numaces++) {
+ switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
+ case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
+ /*
+ * Files inherit an effective ACE.
+ *
+ * Dirs inherit an effective ACE.
+ * The inherited ACE is inheritable unless the
+ * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
+ */
+ smb_ace_inherit(dir_zace, new_zace, is_dir);
+ new_zace++;
+
+ if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
+ (ZACE_IS_PROPAGATE(dir_zace))) {
+ *new_zace = *dir_zace;
+ new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
+ ACE_INHERITED_ACE);
+ new_zace++;
+ }
break;
- }
- /* Make room for this ACE */
- acl = smb_acl_grow(acl, smb_ace_len(sim->sim_sid));
+ case ACE_FILE_INHERIT_ACE:
+ /*
+ * Files inherit as an effective ACE.
+ *
+ * Dirs inherit an inherit-only ACE
+ * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
+ * flag is also set.
+ */
+ if (is_dir == 0) {
+ smb_ace_inherit(dir_zace, new_zace, is_dir);
+ new_zace++;
+ } else if (ZACE_IS_PROPAGATE(dir_zace)) {
+ *new_zace = *dir_zace;
+ new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
+ ACE_INHERITED_ACE);
+ new_zace++;
+ }
+ break;
- status = smb_ace_common_add(acl,
- zace->a_type,
- smb_ace_flags_fromzfs(zace->a_flags),
- zace->a_access_mask,
- sim->sim_sid);
+ case ACE_DIRECTORY_INHERIT_ACE:
+ /*
+ * No effect on files
+ *
+ * Dirs inherit an effective ACE.
+ * The inherited ACE is inheritable unless the
+ * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
+ */
+ if (is_dir == 0)
+ break;
- if (status == 0) {
- kmem_free(acl, acl->sl_size);
- acl = NULL;
+ smb_ace_inherit(dir_zace, new_zace, is_dir);
+ new_zace++;
+
+ if (ZACE_IS_CREATOR(dir_zace) &&
+ (ZACE_IS_PROPAGATE(dir_zace))) {
+ *new_zace = *dir_zace;
+ new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
+ ACE_INHERITED_ACE);
+ new_zace++;
+ }
+
+ break;
+
+ default:
break;
}
}
- smb_idmap_batch_destroy(&sib);
- return (acl);
+ return (new_zacl);
}
/*
- * SID for Everyone group: S-1-1-0.
- */
-nt_sid_t everyone_sid = {
- NT_SID_REVISION,
- 1,
- NT_SECURITY_WORLD_AUTH,
- { 0 }
-};
-
-/*
- * smb_acl_null_empty
+ * smb_fsacl_from_vsa
*
- * NULL DACL means everyone full-access
- * Empty DACL means everyone full-deny
+ * Converts given vsecattr_t structure to a acl_t structure.
*
- * ZFS ACL must have at least one entry so smb server has
- * to simulate the aforementioned expected behavior by adding
- * an entry in case the requested DACL is null or empty. Adding
- * a everyone full-deny entry has proved to be problematic in
- * tests since a deny entry takes precedence over allow entries.
- * So, instead of adding a everyone full-deny, an owner ACE with
- * owner implicit permissions will be set.
+ * The allocated memory for retuned acl_t should be freed by
+ * calling acl_free().
*/
acl_t *
-smb_acl_null_empty(int null)
+smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type)
{
- acl_t *zacl;
- ace_t *zace;
+ int aclbsize = 0; /* size of acl list in bytes */
+ int dfaclbsize = 0; /* size of default acl list in bytes */
+ int numacls;
+ acl_t *acl_info;
- zacl = smb_fsop_aclalloc(1, ACL_AUTO_INHERIT);
- zace = zacl->acl_aclp;
+ ASSERT(vsecattr);
- zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
- if (null) {
- zace->a_access_mask = ACE_ALL_PERMS;
- zace->a_flags = ACE_EVERYONE;
- } else {
- zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL |
- ACE_READ_ATTRIBUTES;
- zace->a_flags = ACE_OWNER;
+ acl_info = acl_alloc(acl_type);
+ if (acl_info == NULL)
+ return (NULL);
+
+ acl_info->acl_flags = 0;
+
+ switch (acl_type) {
+
+ case ACLENT_T:
+ numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt;
+ aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t);
+ dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t);
+
+ acl_info->acl_cnt = numacls;
+ acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize,
+ KM_SLEEP);
+ (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
+ aclbsize);
+ (void) memcpy((char *)acl_info->acl_aclp + aclbsize,
+ vsecattr->vsa_dfaclentp, dfaclbsize);
+
+ if (acl_info->acl_cnt <= MIN_ACL_ENTRIES)
+ acl_info->acl_flags |= ACL_IS_TRIVIAL;
+
+ break;
+
+ case ACE_T:
+ aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
+ acl_info->acl_cnt = vsecattr->vsa_aclcnt;
+ acl_info->acl_flags = vsecattr->vsa_aclflags;
+ acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP);
+ (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
+ aclbsize);
+ if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
+ acl_info->acl_flags |= ACL_IS_TRIVIAL;
+
+ break;
+
+ default:
+ acl_free(acl_info);
+ return (NULL);
}
- return (zacl);
+ if (aclbsize && vsecattr->vsa_aclentp)
+ kmem_free(vsecattr->vsa_aclentp, aclbsize);
+ if (dfaclbsize && vsecattr->vsa_dfaclentp)
+ kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize);
+
+ return (acl_info);
}
/*
- * smb_acl_to_zfs
+ * smb_fsacl_to_vsa
*
- * Converts given Windows ACL to a ZFS ACL.
+ * Converts given acl_t structure to a vsecattr_t structure.
*
- * fs_acl will contain a pointer to the created ZFS ACL.
- * The allocated memory should be freed by calling
- * smb_fsop_aclfree().
- *
- * 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.
+ * IMPORTANT:
+ * Upon successful return the memory allocated for vsa_aclentp
+ * should be freed by calling kmem_free(). The size is returned
+ * in aclbsize.
*/
-uint32_t
-smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
+int
+smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
{
- 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, isdir;
+ int error = 0;
+ int numacls;
+ aclent_t *aclp;
- ASSERT(fs_acl);
- ASSERT(*fs_acl == NULL);
+ ASSERT(acl_info);
+ ASSERT(vsecattr);
+ ASSERT(aclbsize);
- if (acl && !smb_acl_isvalid(acl, which_acl))
- return (NT_STATUS_INVALID_ACL);
+ bzero(vsecattr, sizeof (vsecattr_t));
+ *aclbsize = 0;
- if ((acl == NULL) || (acl->sl_acecnt == 0)) {
- if (which_acl == SMB_DACL_SECINFO) {
- *fs_acl = smb_acl_null_empty(acl == NULL);
+ switch (acl_info->acl_type) {
+ case ACLENT_T:
+ numacls = acl_info->acl_cnt;
+ /*
+ * Minimum ACL size is three entries so might as well
+ * bail out here. Also limit request size to prevent user
+ * from allocating too much kernel memory. Maximum size
+ * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES
+ * for the default ACL part.
+ */
+ if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) {
+ error = EINVAL;
+ break;
}
- return (NT_STATUS_SUCCESS);
- }
+ vsecattr->vsa_mask = VSA_ACL;
- idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt,
- SMB_IDMAP_SID2ID);
- if (idm_stat != IDMAP_SUCCESS)
- return (NT_STATUS_INTERNAL_ERROR);
+ vsecattr->vsa_aclcnt = numacls;
+ *aclbsize = numacls * sizeof (aclent_t);
+ vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
+ (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
+ *aclbsize);
- isdir = ((flags & ACL_IS_DIR) == ACL_IS_DIR);
+ /* Sort the acl list */
+ ksort((caddr_t)vsecattr->vsa_aclentp,
+ vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls);
- zacl = smb_fsop_aclalloc(acl->sl_acecnt, flags);
+ /* Break into acl and default acl lists */
+ for (numacls = 0, aclp = vsecattr->vsa_aclentp;
+ numacls < vsecattr->vsa_aclcnt;
+ aclp++, numacls++) {
+ if (aclp->a_type & ACL_DEFAULT)
+ break;
+ }
- zace = zacl->acl_aclp;
- sim = sib.sib_maps;
+ /* Find where defaults start (if any) */
+ if (numacls < vsecattr->vsa_aclcnt) {
+ vsecattr->vsa_mask |= VSA_DFACL;
+ vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls;
+ vsecattr->vsa_dfaclentp = aclp;
+ vsecattr->vsa_aclcnt = numacls;
+ }
- for (i = 0; ace = smb_ace_get(acl, i); i++, zace++, sim++) {
- zace->a_type = ace->se_header.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_header.se_flags,
- isdir);
+ /* Adjust if they're all defaults */
+ if (vsecattr->vsa_aclcnt == 0) {
+ vsecattr->vsa_mask &= ~VSA_ACL;
+ vsecattr->vsa_aclentp = NULL;
+ }
- if (nt_sid_is_equal(&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);
+ /* Only directories can have defaults */
+ if (vsecattr->vsa_dfaclcnt &&
+ (acl_info->acl_flags & ACL_IS_DIR)) {
+ error = ENOTDIR;
+ }
- if (idm_stat != IDMAP_SUCCESS) {
- smb_fsop_aclfree(zacl);
- smb_idmap_batch_destroy(&sib);
- return (NT_STATUS_INTERNAL_ERROR);
- }
+ break;
+
+ case ACE_T:
+ if (acl_info->acl_cnt < 1 ||
+ acl_info->acl_cnt > MAX_ACL_ENTRIES) {
+ error = EINVAL;
+ break;
}
- }
- idm_stat = smb_idmap_batch_getmappings(&sib);
- if (idm_stat != IDMAP_SUCCESS) {
- smb_fsop_aclfree(zacl);
- smb_idmap_batch_destroy(&sib);
- return (NT_STATUS_NONE_MAPPED);
- }
+ vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
+ vsecattr->vsa_aclcnt = acl_info->acl_cnt;
+ vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL;
+ *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
+ vsecattr->vsa_aclentsz = *aclbsize;
+ vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
+ (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
+ *aclbsize);
- /*
- * Set the ACEs group flag based on the type of ID returned.
- */
- zace = zacl->acl_aclp;
- sim = sib.sib_maps;
- for (i = 0; i < acl->sl_acecnt; i++, zace++, sim++) {
- if (zace->a_flags & ACE_EVERYONE)
- continue;
+ break;
- if (sim->sim_idtype == SMB_IDMAP_GROUP)
- zace->a_flags |= ACE_IDENTIFIER_GROUP;
+ default:
+ error = EINVAL;
}
- smb_idmap_batch_destroy(&sib);
-
- *fs_acl = zacl;
- return (NT_STATUS_SUCCESS);
+ return (error);
}
/*
- * smb_acl_inheritable
+ * smb_fsacl_inheritable
*
* Checks to see if there are any inheritable ACEs in the
* given ZFS ACL. Returns the number of inheritable ACEs.
@@ -984,7 +1038,7 @@ smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl)
* 1c: one creator owner/group ACE
*/
static int
-smb_acl_inheritable(acl_t *zacl, int is_dir)
+smb_fsacl_inheritable(acl_t *zacl, int is_dir)
{
int numaces;
int num_inheritable = 0;
@@ -1053,132 +1107,92 @@ smb_acl_inheritable(acl_t *zacl, int is_dir)
return (num_inheritable);
}
-#define DEFAULT_DACL_ACENUM 2
+
/*
- * Default ACL:
- * owner: full access
- * SYSTEM: full access
+ * ACE Functions
*/
-static ace_t default_dacl[DEFAULT_DACL_ACENUM] = {
- { (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
- { IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
- ACE_ACCESS_ALLOWED_ACE_TYPE }
-};
/*
- * smb_acl_inherit
- *
- * Manufacture the inherited ACL from the given ACL considering
- * the new object type (file/dir) specified by 'is_dir'. The
- * returned ACL is used in smb_fsop_create/smb_fsop_mkdir functions.
- * This function implements Windows inheritance rules.
- *
- * Note that the in/our ACLs are ZFS ACLs not Windows ACLs
+ * This is generic (ACL version 2) vs. object-specific
+ * (ACL version 4) ACE types.
*/
-acl_t *
-smb_acl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, uid_t owner_uid)
+boolean_t
+smb_ace_is_generic(int type)
{
- boolean_t use_default = B_FALSE;
- int num_inheritable = 0;
- int numaces;
- ace_t *dir_zace;
- acl_t *new_zacl;
- ace_t *new_zace;
-
- num_inheritable = smb_acl_inheritable(dir_zacl, is_dir);
+ switch (type) {
+ case ACE_ACCESS_ALLOWED_ACE_TYPE:
+ case ACE_ACCESS_DENIED_ACE_TYPE:
+ case ACE_SYSTEM_AUDIT_ACE_TYPE:
+ case ACE_SYSTEM_ALARM_ACE_TYPE:
+ case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
+ case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
+ case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
+ case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
+ return (B_TRUE);
- if (num_inheritable == 0) {
- if (which_acl == SMB_DACL_SECINFO) {
- /* No inheritable access ACEs -> default DACL */
- num_inheritable = DEFAULT_DACL_ACENUM;
- use_default = B_TRUE;
- } else {
- return (NULL);
- }
+ default:
+ break;
}
- new_zacl = smb_fsop_aclalloc(num_inheritable, ACL_AUTO_INHERIT);
- new_zace = new_zacl->acl_aclp;
-
- if (use_default) {
- bcopy(default_dacl, new_zacl->acl_aclp, sizeof (default_dacl));
- new_zace->a_who = owner_uid;
- return (new_zacl);
- }
+ return (B_FALSE);
+}
- for (numaces = 0, dir_zace = dir_zacl->acl_aclp;
- numaces < dir_zacl->acl_cnt;
- dir_zace++, numaces++) {
- switch (dir_zace->a_flags & ACE_FD_INHERIT_ACE) {
- case (ACE_FILE_INHERIT_ACE | ACE_DIRECTORY_INHERIT_ACE):
- /*
- * Files inherit an effective ACE.
- *
- * Dirs inherit an effective ACE.
- * The inherited ACE is inheritable unless the
- * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set
- */
- smb_ace_inherit(dir_zace, new_zace, is_dir);
- new_zace++;
+boolean_t
+smb_ace_is_access(int type)
+{
+ switch (type) {
+ case ACE_ACCESS_ALLOWED_ACE_TYPE:
+ case ACE_ACCESS_DENIED_ACE_TYPE:
+ case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
+ case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
+ case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
+ case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
+ case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
+ case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
+ case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
+ return (B_TRUE);
- if (is_dir && ZACE_IS_CREATOR(dir_zace) &&
- (ZACE_IS_PROPAGATE(dir_zace))) {
- *new_zace = *dir_zace;
- new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
- ACE_INHERITED_ACE);
- new_zace++;
- }
- break;
+ default:
+ break;
+ }
- case ACE_FILE_INHERIT_ACE:
- /*
- * Files inherit as an effective ACE.
- *
- * Dirs inherit an inherit-only ACE
- * unless the ACE_NO_PROPAGATE_INHERIT_ACE bit
- * flag is also set.
- */
- if (is_dir == 0) {
- smb_ace_inherit(dir_zace, new_zace, is_dir);
- new_zace++;
- } else if (ZACE_IS_PROPAGATE(dir_zace)) {
- *new_zace = *dir_zace;
- new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
- ACE_INHERITED_ACE);
- new_zace++;
- }
- break;
+ return (B_FALSE);
+}
- case ACE_DIRECTORY_INHERIT_ACE:
- /*
- * No effect on files
- *
- * Dirs inherit an effective ACE.
- * The inherited ACE is inheritable unless the
- * ACE_NO_PROPAGATE_INHERIT_ACE bit flag is also set.
- */
- if (is_dir == 0)
- break;
+boolean_t
+smb_ace_is_audit(int type)
+{
+ switch (type) {
+ case ACE_SYSTEM_AUDIT_ACE_TYPE:
+ case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
+ case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
+ case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
+ return (B_TRUE);
- smb_ace_inherit(dir_zace, new_zace, is_dir);
- new_zace++;
+ default:
+ break;
+ }
- if (ZACE_IS_CREATOR(dir_zace) &&
- (ZACE_IS_PROPAGATE(dir_zace))) {
- *new_zace = *dir_zace;
- new_zace->a_flags |= (ACE_INHERIT_ONLY_ACE |
- ACE_INHERITED_ACE);
- new_zace++;
- }
+ return (B_FALSE);
+}
- break;
+/*
+ * smb_ace_len
+ *
+ * Returns the length of the given ACE as it appears in an
+ * ACL on the wire (i.e. a flat buffer which contains the SID)
+ */
+static uint16_t
+smb_ace_len(smb_ace_t *ace)
+{
+ ASSERT(ace);
+ ASSERT(ace->se_sid);
- default:
- break;
- }
- }
+ if (ace == NULL)
+ return (0);
- return (new_zacl);
+ return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) +
+ nt_sid_length(ace->se_sid));
}
static void
@@ -1202,6 +1216,42 @@ smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir)
}
}
+/*
+ * smb_ace_mask_g2s
+ *
+ * Converts generic access bits in the given mask (if any)
+ * to file specific bits. Generic access masks shouldn't be
+ * stored in filesystem ACEs.
+ */
+static uint32_t
+smb_ace_mask_g2s(uint32_t mask)
+{
+ if (mask & GENERIC_ALL) {
+ mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE
+ | GENERIC_EXECUTE);
+
+ mask |= FILE_ALL_ACCESS;
+ return (mask);
+ }
+
+ if (mask & GENERIC_READ) {
+ mask &= ~GENERIC_READ;
+ mask |= FILE_GENERIC_READ;
+ }
+
+ if (mask & GENERIC_WRITE) {
+ mask &= ~GENERIC_WRITE;
+ mask |= FILE_GENERIC_WRITE;
+ }
+
+ if (mask & GENERIC_EXECUTE) {
+ mask &= ~GENERIC_EXECUTE;
+ mask |= FILE_GENERIC_EXECUTE;
+ }
+
+ return (mask);
+}
+
static uint16_t
smb_ace_flags_tozfs(uint8_t c_flags, int isdir)
{
@@ -1245,66 +1295,37 @@ smb_ace_flags_fromzfs(uint16_t z_flags)
return (c_flags);
}
-/*
- * This is generic (ACL version 2) vs. object-specific
- * (ACL version 4) ACE types.
- */
-int
-smb_ace_is_generic(int type)
+static boolean_t
+smb_ace_isvalid(smb_ace_t *ace, int which_acl)
{
- switch (type) {
- case ACE_ACCESS_ALLOWED_ACE_TYPE:
- case ACE_ACCESS_DENIED_ACE_TYPE:
- case ACE_SYSTEM_AUDIT_ACE_TYPE:
- case ACE_SYSTEM_ALARM_ACE_TYPE:
- case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
- case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
- case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
- case ACE_SYSTEM_ALARM_CALLBACK_ACE_TYPE:
- return (1);
+ uint16_t min_len;
- default:
- break;
- }
+ min_len = sizeof (smb_acehdr_t);
- return (0);
-}
+ if (ace->se_hdr.se_bsize < min_len)
+ return (B_FALSE);
-int
-smb_ace_is_access(int type)
-{
- switch (type) {
- case ACE_ACCESS_ALLOWED_ACE_TYPE:
- case ACE_ACCESS_DENIED_ACE_TYPE:
- case ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
- case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
- case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
- case ACE_ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
- case ACE_ACCESS_DENIED_CALLBACK_ACE_TYPE:
- case ACE_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
- case ACE_ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
- return (1);
+ if (smb_ace_is_access(ace->se_hdr.se_type) &&
+ (which_acl != SMB_DACL_SECINFO))
+ return (B_FALSE);
- default:
- break;
- }
+ if (smb_ace_is_audit(ace->se_hdr.se_type) &&
+ (which_acl != SMB_SACL_SECINFO))
+ return (B_FALSE);
- return (0);
-}
+ if (smb_ace_is_generic(ace->se_hdr.se_type)) {
+ if (nt_sid_is_valid(ace->se_sid) == 0)
+ return (B_FALSE);
-int
-smb_ace_is_audit(int type)
-{
- switch (type) {
- case ACE_SYSTEM_AUDIT_ACE_TYPE:
- case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:
- case ACE_SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
- case ACE_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
- return (1);
+ min_len += sizeof (ace->se_mask);
+ min_len += nt_sid_length(ace->se_sid);
- default:
- break;
+ if (ace->se_hdr.se_bsize < min_len)
+ return (B_FALSE);
}
- return (0);
+ /*
+ * object-specific ACE validation will be added later.
+ */
+ return (B_TRUE);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 30058e8f82..d3a462fbc5 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -879,7 +879,7 @@ smb_open_subr(struct smb_request *sr)
op->dattr &= ~SMB_FA_READONLY;
}
smb_node_set_dosattr(node, op->dattr | SMB_FA_ARCHIVE);
- if (op->utime.tv_sec == 0 || op->utime.tv_sec == 0xffffffff)
+ if (op->utime.tv_sec == 0 || op->utime.tv_sec == UINT_MAX)
(void) microtime(&op->utime);
smb_node_set_time(node, NULL, &op->utime, 0, 0, SMB_AT_MTIME);
(void) smb_sync_fsattr(sr, sr->user_cr, node);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c
index fccdf5ba9e..8fd289bb75 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_create.c
@@ -176,7 +176,7 @@ smb_com_create_temporary(struct smb_request *sr)
break;
}
- smbsr_encode_result(sr, 1, 0, "bwwwbs", 1, sr->smb_fid, bcc, 4, name);
+ smbsr_encode_result(sr, 1, 0, "bwwbs", 1, sr->smb_fid, bcc, 4, name);
return (SDRC_NORMAL_REPLY);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 655e5ad3ff..3d7292961e 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -26,29 +26,19 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sid.h>
-#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_fsops.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smbvar.h>
+#include <smbsrv/ntstatus.h>
+#include <smbsrv/ntaccess.h>
#include <acl/acl_common.h>
u_longlong_t smb_caller_id;
static int smb_fsop_amask_to_omode(uint32_t granted_access);
-
-extern uint32_t smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd);
-
-extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd,
- uint32_t secinfo);
-
-extern int smb_vop_acl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr,
- int *aclbsize);
-
static int smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode,
smb_fssd_t *fs_sd);
-static void smb_fsop_aclsplit(acl_t *zacl, acl_t **dacl, acl_t **sacl,
- int which_acl);
-static acl_t *smb_fsop_aclmerge(acl_t *dacl, acl_t *sacl);
-
/*
* The smb_fsop_* functions have knowledge of CIFS semantics.
*
@@ -161,6 +151,7 @@ smb_fsop_create_with_sd(
int flags = 0;
int is_dir;
int rc;
+ boolean_t no_xvattr = B_FALSE;
ASSERT(fs_sd);
@@ -178,14 +169,14 @@ smb_fsop_create_with_sd(
sacl = fs_sd->sd_zsacl;
ASSERT(dacl || sacl);
if (dacl && sacl) {
- acl = smb_fsop_aclmerge(dacl, sacl);
+ acl = smb_fsacl_merge(dacl, sacl);
} else if (dacl) {
acl = dacl;
} else {
acl = sacl;
}
- rc = smb_vop_acl_to_vsa(acl, &vsecattr, &aclbsize);
+ rc = smb_fsacl_to_vsa(acl, &vsecattr, &aclbsize);
if (dacl && sacl)
acl_free(acl);
@@ -231,8 +222,11 @@ smb_fsop_create_with_sd(
}
if (set_attr.sa_mask) {
+ if (sr && sr->tid_tree)
+ if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS)
+ no_xvattr = B_TRUE;
rc = smb_vop_setattr(snode->vp, NULL, &set_attr,
- 0, kcred, &ct);
+ 0, kcred, no_xvattr, &ct);
}
} else {
@@ -253,7 +247,10 @@ smb_fsop_create_with_sd(
cr, &ct, NULL);
}
- if (rc == 0)
+ if (rc != 0)
+ return (rc);
+
+ if ((sr->tid_tree->t_flags & SMB_TREE_FLAG_NFS_MOUNTED) == 0)
rc = smb_fsop_sdwrite(sr, kcred, snode, fs_sd, 1);
}
@@ -267,6 +264,14 @@ smb_fsop_create_with_sd(
}
}
+ if (rc != 0) {
+ if (is_dir) {
+ (void) smb_vop_rmdir(snode->vp, name, flags, cr, &ct);
+ } else {
+ (void) smb_vop_remove(snode->vp, name, flags, cr, &ct);
+ }
+ }
+
return (rc);
}
@@ -417,36 +422,36 @@ smb_fsop_create(
return (ENOMEM);
}
} else {
- if (op->sd_buf) {
+ if (op->sd) {
/*
* SD sent by client in Windows format. Needs to be
* converted to FS format. No inheritance.
*/
- secinfo = smb_sd_get_secinfo((smb_sdbuf_t *)op->sd_buf);
- smb_fsop_sdinit(&fs_sd, secinfo, 0);
+ secinfo = smb_sd_get_secinfo(op->sd);
+ smb_fssd_init(&fs_sd, secinfo, 0);
- status = smb_sd_tofs(op->sd_buf, &fs_sd);
+ status = smb_sd_tofs(op->sd, &fs_sd);
if (status == NT_STATUS_SUCCESS) {
rc = smb_fsop_create_with_sd(sr, cr, dir_snode,
name, attr, ret_snode, ret_attr, &fs_sd);
}
else
rc = EINVAL;
- smb_fsop_sdterm(&fs_sd);
+ smb_fssd_term(&fs_sd);
} else if (sr->tid_tree->t_acltype == ACE_T) {
/*
* No incoming SD and filesystem is ZFS
* Server applies Windows inheritance rules,
* see smb_fsop_sdinherit() comments as to why.
*/
- smb_fsop_sdinit(&fs_sd, SMB_ACL_SECINFO, 0);
+ smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, 0);
rc = smb_fsop_sdinherit(sr, dir_snode, &fs_sd);
if (rc == 0) {
rc = smb_fsop_create_with_sd(sr, cr, dir_snode,
name, attr, ret_snode, ret_attr, &fs_sd);
}
- smb_fsop_sdterm(&fs_sd);
+ smb_fssd_term(&fs_sd);
} else {
/*
* No incoming SD and filesystem is not ZFS
@@ -554,36 +559,36 @@ smb_fsop_mkdir(
smb_get_caller_context(sr, &ct);
- if (op->sd_buf) {
+ if (op->sd) {
/*
* SD sent by client in Windows format. Needs to be
* converted to FS format. No inheritance.
*/
- secinfo = smb_sd_get_secinfo((smb_sdbuf_t *)op->sd_buf);
- smb_fsop_sdinit(&fs_sd, secinfo, SMB_FSSD_FLAGS_DIR);
+ secinfo = smb_sd_get_secinfo(op->sd);
+ smb_fssd_init(&fs_sd, secinfo, SMB_FSSD_FLAGS_DIR);
- status = smb_sd_tofs(op->sd_buf, &fs_sd);
+ status = smb_sd_tofs(op->sd, &fs_sd);
if (status == NT_STATUS_SUCCESS) {
rc = smb_fsop_create_with_sd(sr, cr, dir_snode,
name, attr, ret_snode, ret_attr, &fs_sd);
}
else
rc = EINVAL;
- smb_fsop_sdterm(&fs_sd);
+ smb_fssd_term(&fs_sd);
} else if (sr->tid_tree->t_acltype == ACE_T) {
/*
* No incoming SD and filesystem is ZFS
* Server applies Windows inheritance rules,
* see smb_fsop_sdinherit() comments as to why.
*/
- smb_fsop_sdinit(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR);
+ smb_fssd_init(&fs_sd, SMB_ACL_SECINFO, SMB_FSSD_FLAGS_DIR);
rc = smb_fsop_sdinherit(sr, dir_snode, &fs_sd);
if (rc == 0) {
rc = smb_fsop_create_with_sd(sr, cr, dir_snode,
name, attr, ret_snode, ret_attr, &fs_sd);
}
- smb_fsop_sdterm(&fs_sd);
+ smb_fssd_term(&fs_sd);
} else {
rc = smb_vop_mkdir(dir_snode->vp, name, attr, &vp, flags, cr,
@@ -1242,6 +1247,7 @@ smb_fsop_setattr(
uint32_t access = 0;
int rc = 0;
int flags = 0;
+ boolean_t no_xvattr = B_FALSE;
ASSERT(cr);
ASSERT(snode);
@@ -1281,8 +1287,12 @@ smb_fsop_setattr(
ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
unnamed_vp = unnamed_node->vp;
}
+ if (sr && sr->tid_tree)
+ if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS)
+ no_xvattr = B_TRUE;
- rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr, &ct);
+ rc = smb_vop_setattr(snode->vp, unnamed_vp,
+ set_attr, flags, cr, no_xvattr, &ct);
if ((rc == 0) && ret_attr) {
/*
@@ -1930,34 +1940,6 @@ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode)
}
/*
- * smb_fsop_sdinit
- *
- * Initializes the given FS SD structure.
- */
-void
-smb_fsop_sdinit(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags)
-{
- bzero(fs_sd, sizeof (smb_fssd_t));
- fs_sd->sd_secinfo = secinfo;
- fs_sd->sd_flags = flags;
-}
-
-/*
- * smb_fsop_sdterm
- *
- * Frees allocated memory for acl fields.
- */
-void
-smb_fsop_sdterm(smb_fssd_t *fs_sd)
-{
- ASSERT(fs_sd);
-
- smb_fsop_aclfree(fs_sd->sd_zdacl);
- smb_fsop_aclfree(fs_sd->sd_zsacl);
- bzero(fs_sd, sizeof (smb_fssd_t));
-}
-
-/*
* smb_fsop_aclread
*
* Retrieve filesystem ACL. Depends on requested ACLs in
@@ -1969,7 +1951,7 @@ smb_fsop_sdterm(smb_fssd_t *fs_sd)
*
* Returned ACL is always in ACE_T (aka ZFS) format.
* If successful the allocated memory for the ACL should be freed
- * using smb_fsop_aclfree() or smb_fsop_sdterm()
+ * using smb_fsacl_free() or smb_fssd_term()
*/
int
smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
@@ -2022,7 +2004,7 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
(snode->vp->v_type == VDIR), fs_sd->sd_uid, fs_sd->sd_gid);
if (error == 0) {
- smb_fsop_aclsplit(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl,
+ smb_fsacl_split(acl, &fs_sd->sd_zdacl, &fs_sd->sd_zsacl,
fs_sd->sd_secinfo);
}
@@ -2097,7 +2079,7 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
return (EINVAL);
if (dacl && sacl)
- acl = smb_fsop_aclmerge(dacl, sacl);
+ acl = smb_fsacl_merge(dacl, sacl);
else if (dacl)
acl = dacl;
else
@@ -2119,102 +2101,6 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
return (error);
}
-acl_t *
-smb_fsop_aclalloc(int acenum, int flags)
-{
- acl_t *acl;
-
- acl = acl_alloc(ACE_T);
- acl->acl_cnt = acenum;
- acl->acl_aclp = kmem_zalloc(acl->acl_entry_size * acenum, KM_SLEEP);
- acl->acl_flags = flags;
- return (acl);
-}
-
-void
-smb_fsop_aclfree(acl_t *acl)
-{
- if (acl)
- acl_free(acl);
-}
-
-/*
- * smb_fsop_aclmerge
- *
- * smb_fsop_aclread/write routines which interact with filesystem
- * work with single ACL. This routine merges given DACL and SACL
- * which might have been created during CIFS to FS conversion into
- * one single ACL.
- */
-static acl_t *
-smb_fsop_aclmerge(acl_t *dacl, acl_t *sacl)
-{
- acl_t *acl;
- int dacl_size;
-
- ASSERT(dacl);
- ASSERT(sacl);
-
- acl = smb_fsop_aclalloc(dacl->acl_cnt + sacl->acl_cnt, dacl->acl_flags);
- dacl_size = dacl->acl_cnt * dacl->acl_entry_size;
- bcopy(dacl->acl_aclp, acl->acl_aclp, dacl_size);
- bcopy(sacl->acl_aclp, (char *)acl->acl_aclp + dacl_size,
- sacl->acl_cnt * sacl->acl_entry_size);
-
- return (acl);
-}
-
-/*
- * smb_fsop_aclsplit
- *
- * splits the given ACE_T ACL (zacl) to one or two ACLs (DACL/SACL) based on
- * the 'which_acl' parameter. Note that output dacl/sacl parameters could be
- * NULL even if they're specified in 'which_acl', which means the target
- * doesn't have any access and/or audit ACEs.
- */
-static void
-smb_fsop_aclsplit(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
-{
- ace_t *zace;
- ace_t *access_ace;
- ace_t *audit_ace;
- int naccess, naudit;
- int get_dacl, get_sacl;
- int i;
-
- *dacl = *sacl = NULL;
- naccess = naudit = 0;
- get_dacl = (which_acl & SMB_DACL_SECINFO);
- get_sacl = (which_acl & SMB_SACL_SECINFO);
-
- for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
- if (get_dacl && smb_ace_is_access(zace->a_type))
- naccess++;
- else if (get_sacl && smb_ace_is_audit(zace->a_type))
- naudit++;
- }
-
- if (naccess) {
- *dacl = smb_fsop_aclalloc(naccess, zacl->acl_flags);
- access_ace = (*dacl)->acl_aclp;
- }
-
- if (naudit) {
- *sacl = smb_fsop_aclalloc(naudit, zacl->acl_flags);
- audit_ace = (*sacl)->acl_aclp;
- }
-
- for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; zace++, i++) {
- if (get_dacl && smb_ace_is_access(zace->a_type)) {
- *access_ace = *zace;
- access_ace++;
- } else if (get_sacl && smb_ace_is_audit(zace->a_type)) {
- *audit_ace = *zace;
- audit_ace++;
- }
- }
-}
-
acl_type_t
smb_fsop_acltype(smb_node_t *snode)
{
@@ -2328,7 +2214,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd)
/*
* Don't overwrite existing audit entries
*/
- smb_fsop_sdinit(&cur_sd, SMB_SACL_SECINFO,
+ smb_fssd_init(&cur_sd, SMB_SACL_SECINFO,
fs_sd->sd_flags);
error = smb_fsop_sdread(sr, kcred, snode, &cur_sd);
@@ -2343,7 +2229,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd)
/*
* Don't overwrite existing access entries
*/
- smb_fsop_sdinit(&cur_sd, SMB_DACL_SECINFO,
+ smb_fssd_init(&cur_sd, SMB_DACL_SECINFO,
fs_sd->sd_flags);
error = smb_fsop_sdread(sr, kcred, snode, &cur_sd);
@@ -2357,7 +2243,7 @@ smb_fsop_sdmerge(smb_request_t *sr, smb_node_t *snode, smb_fssd_t *fs_sd)
}
if (error)
- smb_fsop_sdterm(&cur_sd);
+ smb_fssd_term(&cur_sd);
}
return (error);
@@ -2460,15 +2346,6 @@ smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
return (error);
}
-/*ARGSUSED*/
-void
-smb_get_caller_context(smb_request_t *sr, caller_context_t *ct)
-{
- ct->cc_caller_id = smb_caller_id;
- ct->cc_pid = 0; /* TBD */
- ct->cc_sysid = 0; /* TBD */
-}
-
/*
* smb_fsop_sdinherit
*
@@ -2498,8 +2375,8 @@ static int
smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd)
{
int is_dir;
- acl_t *dacl;
- acl_t *sacl;
+ acl_t *dacl = NULL;
+ acl_t *sacl = NULL;
ksid_t *owner_sid;
int error;
@@ -2523,13 +2400,16 @@ smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd)
is_dir = (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR);
owner_sid = crgetsid(sr->user_cr, KSID_OWNER);
ASSERT(owner_sid);
- dacl = smb_acl_inherit(fs_sd->sd_zdacl, is_dir, SMB_DACL_SECINFO,
+ dacl = smb_fsacl_inherit(fs_sd->sd_zdacl, is_dir, SMB_DACL_SECINFO,
owner_sid->ks_id);
- sacl = smb_acl_inherit(fs_sd->sd_zsacl, is_dir, SMB_SACL_SECINFO,
+ sacl = smb_fsacl_inherit(fs_sd->sd_zsacl, is_dir, SMB_SACL_SECINFO,
(uid_t)-1);
- smb_fsop_aclfree(fs_sd->sd_zdacl);
- smb_fsop_aclfree(fs_sd->sd_zsacl);
+ if (sacl == NULL)
+ fs_sd->sd_secinfo &= ~SMB_SACL_SECINFO;
+
+ smb_fsacl_free(fs_sd->sd_zdacl);
+ smb_fsacl_free(fs_sd->sd_zsacl);
fs_sd->sd_zdacl = dacl;
fs_sd->sd_zsacl = sacl;
@@ -2593,3 +2473,12 @@ smb_fsop_eaccess(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
*eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
}
+
+/*ARGSUSED*/
+void
+smb_get_caller_context(smb_request_t *sr, caller_context_t *ct)
+{
+ ct->cc_caller_id = smb_caller_id;
+ ct->cc_pid = 0; /* TBD */
+ ct->cc_sysid = 0; /* TBD */
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_init.c b/usr/src/uts/common/fs/smbsrv/smb_init.c
index 1d3d8f39cb..897f09bded 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_init.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_init.c
@@ -292,21 +292,29 @@ smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flag, cred_t *cred,
int *retval)
{
int gmtoff;
+ int door_id;
switch (cmd) {
-
case SMB_IOC_GMTOFF:
if (ddi_copyin((int *)argp, &gmtoff, sizeof (int), flag))
return (EFAULT);
(void) smb_set_gmtoff((uint32_t)gmtoff);
break;
- case SMB_IOC_CONFIG_REFRESH:
+ case SMB_IOC_CONFIG:
#if 0
smb_svcstate_event(SMB_SVCEVT_CONFIG, NULL);
#endif
break;
+ case SMB_IOC_WINPIPE:
+ if (ddi_copyin((int *)argp, &door_id, sizeof (int), flag))
+ return (EFAULT);
+
+ if (smb_winpipe_open(door_id) != 0)
+ return (EPIPE);
+ break;
+
default:
break;
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c
index 53e8d0326e..cb5aa042ee 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c
@@ -88,7 +88,7 @@ smb_com_lock_byte_range(struct smb_request *sr)
* normal lock (write lock).
*/
result = smb_lock_range(sr, sr->fid_ofile,
- (off_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE);
+ (u_offset_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE);
if (result != NT_STATUS_SUCCESS) {
smb_lock_range_raise_error(sr, result);
/* NOT REACHED */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
index e043472af5..7326d5a12c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c
@@ -571,7 +571,7 @@ smb_lock_create(
* in cv_timedwait.
*/
lock->l_end_time = lbolt + MSEC_TO_TICK(timeout);
- if (timeout == 0xffffffff) {
+ if (timeout == UINT_MAX) {
lock->l_flags |= SMB_LOCK_FLAG_INDEFINITE;
}
mutex_init(&lock->l_mutex, NULL, MUTEX_DEFAULT, NULL);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
index 63f1f81440..00d648cc32 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
@@ -35,9 +35,15 @@
* support them at this time.
*/
-#include <smbsrv/smb_incl.h>
+#include <smbsrv/smbvar.h>
+#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
-#include <smbsrv/smb_vops.h>
+#include <smbsrv/ntstatus.h>
+#include <smbsrv/ntaccess.h>
+#include <smbsrv/nterror.h>
+#include <smbsrv/ntifs.h>
+#include <smbsrv/cifs.h>
+#include <smbsrv/doserror.h>
/*
* smb_nt_transact_create
@@ -68,6 +74,7 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa)
uint32_t NameLength;
smb_attr_t new_attr;
smb_node_t *node;
+ smb_sd_t sd;
DWORD status;
int rc;
@@ -112,18 +119,15 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa)
/* NOTREACHED */
}
- if (sd_len >= sizeof (smb_sdbuf_t)) {
- /* ignore security setting for files on Unix volumes */
- op->sd_buf = kmem_alloc(sd_len, KM_SLEEP);
-
- if ((smb_decode_mbc(&xa->req_data_mb, "#c", sd_len,
- (char *)op->sd_buf)) != 0) {
- kmem_free(op->sd_buf, sd_len);
- smbsr_raise_nt_error(sr, NT_STATUS_BUFFER_TOO_SMALL);
+ if (sd_len) {
+ status = smb_decode_sd(xa, &sd);
+ if (status != NT_STATUS_SUCCESS) {
+ smbsr_raise_nt_error(sr, status);
/* NOTREACHED */
}
+ op->sd = &sd;
} else {
- op->sd_buf = 0;
+ op->sd = NULL;
}
op->fqi.srch_attr = 0;
@@ -168,8 +172,8 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa)
}
status = smb_open_subr(sr);
- if (op->sd_buf)
- kmem_free(op->sd_buf, sd_len);
+ if (op->sd)
+ smb_sd_term(op->sd);
if (status != NT_STATUS_SUCCESS) {
if (status == NT_STATUS_SHARING_VIOLATION)
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c
index 70d8437cdf..fec95a2835 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c
@@ -25,14 +25,21 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <smbsrv/smb_secdesc.h>
-#include <smbsrv/smb_incl.h>
-#include <smbsrv/smb_fsops.h>
+#include <smbsrv/smbvar.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/ntstatus.h>
+#include <smbsrv/nterror.h>
+#include <smbsrv/doserror.h>
+#include <smbsrv/cifs.h>
-extern uint32_t smb_sd_read(smb_request_t *sr, smb_sdbuf_t **sr_sd,
- uint32_t secinfo, uint32_t *buflen);
-extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd,
- uint32_t secinfo);
+static void smb_encode_sd(struct smb_xa *, smb_sd_t *, uint32_t);
+static void smb_encode_sid(struct smb_xa *, nt_sid_t *);
+static void smb_encode_sacl(struct smb_xa *, smb_acl_t *);
+static void smb_encode_dacl(struct smb_xa *, smb_acl_t *);
+
+uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *);
+static nt_sid_t *smb_decode_sid(struct smb_xa *, uint32_t);
+static smb_acl_t *smb_decode_acl(struct smb_xa *, uint32_t);
/*
* smb_nt_transact_query_security_info
@@ -63,20 +70,15 @@ extern uint32_t smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd,
int
smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
{
- smb_sdbuf_t *sr_sd;
- uint32_t secinfo;
- uint32_t sr_sdlen;
- uint32_t status;
+ smb_sd_t sd;
+ uint32_t secinfo;
+ uint32_t sdlen;
+ uint32_t status;
+
if (smb_decode_mbc(&xa->req_param_mb, "w2.l",
&sr->smb_fid, &secinfo) != 0) {
- /*
- * It's not clear why ERRnomem is returned here.
- * This should rarely happen and we're not sure if
- * it's going to break something if we change this
- * error code, so we're going to keep it for now.
- */
- smbsr_raise_error(sr, ERRSRV, ERRnomem);
+ smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER);
/* NOTREACHED */
}
@@ -90,7 +92,8 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
if ((sr->fid_ofile->f_node == NULL) ||
(sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
- smbsr_raise_nt_error(sr, NT_STATUS_ACCESS_DENIED);
+ smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED,
+ ERRDOS, ERROR_ACCESS_DENIED);
/* NOTREACHED */
}
@@ -102,31 +105,36 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
secinfo &= ~SMB_SACL_SECINFO;
}
- sr_sdlen = xa->smb_mdrcnt;
- status = smb_sd_read(sr, &sr_sd, secinfo, &sr_sdlen);
-
+ status = smb_sd_read(sr, &sd, secinfo);
if (status != NT_STATUS_SUCCESS) {
- if (status == NT_STATUS_BUFFER_TOO_SMALL) {
- /*
- * The maximum data return count specified by the
- * client is not big enough to hold the security
- * descriptor. We have to return an error but we
- * can provide a buffer size hint for the client.
- */
- (void) smb_encode_mbc(&xa->rep_param_mb, "l", sr_sdlen);
- smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR,
- NT_STATUS_BUFFER_TOO_SMALL);
- return (SDRC_NORMAL_REPLY);
- }
-
smbsr_raise_nt_error(sr, status);
/* NOTREACHED */
}
- (void) smb_encode_mbc(&xa->rep_data_mb, "#c", (int)sr_sdlen, sr_sd);
- (void) smb_encode_mbc(&xa->rep_param_mb, "l", sr_sdlen);
+ sdlen = smb_sd_len(&sd, secinfo);
+ if (sdlen == 0) {
+ smb_sd_term(&sd);
+ smbsr_raise_nt_error(sr, NT_STATUS_INVALID_SECURITY_DESCR);
+ /* NOTREACHED */
+ }
+
+ if (sdlen > xa->smb_mdrcnt) {
+ /*
+ * The maximum data return count specified by the
+ * client is not big enough to hold the security
+ * descriptor. We have to return an error but we
+ * should provide a buffer size hint for the client.
+ */
+ (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen);
+ smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR,
+ NT_STATUS_BUFFER_TOO_SMALL);
+ smb_sd_term(&sd);
+ return (SDRC_NORMAL_REPLY);
+ }
- kmem_free(sr_sd, sr_sdlen);
+ smb_encode_sd(xa, &sd, secinfo);
+ (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen);
+ smb_sd_term(&sd);
return (SDRC_NORMAL_REPLY);
}
@@ -152,12 +160,12 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
int
smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
{
- smb_sdbuf_t *sd_buf;
- uint32_t sec_info;
+ smb_sd_t sd;
+ uint32_t secinfo;
uint32_t status;
if (smb_decode_mbc(&xa->req_param_mb, "w2.l",
- &sr->smb_fid, &sec_info) != 0) {
+ &sr->smb_fid, &secinfo) != 0) {
smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER);
/* NOTREACHED */
}
@@ -185,25 +193,27 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
* If target filesystem doesn't support ACE_T acls then
* don't process SACL
*/
- sec_info &= ~SMB_SACL_SECINFO;
+ secinfo &= ~SMB_SACL_SECINFO;
}
- if ((sec_info & SMB_ALL_SECINFO) == 0) {
+ if ((secinfo & SMB_ALL_SECINFO) == 0) {
return (NT_STATUS_SUCCESS);
}
- sd_buf = kmem_alloc(xa->smb_tdscnt, KM_SLEEP);
-
- if ((smb_decode_mbc(&xa->req_data_mb, "#c",
- xa->smb_tdscnt, (char *)sd_buf)) != 0) {
- kmem_free(sd_buf, xa->smb_tdscnt);
- smbsr_raise_nt_error(sr, NT_STATUS_BUFFER_TOO_SMALL);
+ status = smb_decode_sd(xa, &sd);
+ if (status != NT_STATUS_SUCCESS) {
+ smbsr_raise_nt_error(sr, status);
/* NOTREACHED */
}
- status = smb_sd_write(sr, sd_buf, sec_info);
- kmem_free(sd_buf, xa->smb_tdscnt);
+ if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) ||
+ ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) {
+ smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER);
+ /* NOTREACHED */
+ }
+ status = smb_sd_write(sr, &sd, secinfo);
+ smb_sd_term(&sd);
if (status != NT_STATUS_SUCCESS) {
smbsr_raise_nt_error(sr, status);
/* NOTREACHED */
@@ -211,3 +221,331 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
return (SDRC_NORMAL_REPLY);
}
+
+/*
+ * smb_encode_sd
+ *
+ * Encodes given security descriptor in the reply buffer.
+ */
+static void
+smb_encode_sd(struct smb_xa *xa, smb_sd_t *sd, uint32_t secinfo)
+{
+ uint32_t offset = SMB_SD_HDRSIZE;
+
+ /* encode header */
+ (void) smb_encode_mbc(&xa->rep_data_mb, "b.w",
+ sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE);
+
+ /* owner offset */
+ if (secinfo & SMB_OWNER_SECINFO) {
+ ASSERT(sd->sd_owner);
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset);
+ offset += nt_sid_length(sd->sd_owner);
+ } else {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0);
+ }
+
+ /* group offset */
+ if (secinfo & SMB_GROUP_SECINFO) {
+ ASSERT(sd->sd_group);
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset);
+ offset += nt_sid_length(sd->sd_group);
+ } else {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0);
+ }
+
+ /* SACL offset */
+ if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset);
+ offset += smb_acl_len(sd->sd_sacl);
+ } else {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0);
+ }
+
+ /* DACL offset */
+ if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl))
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", offset);
+ else
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l", 0);
+
+ if (secinfo & SMB_OWNER_SECINFO)
+ smb_encode_sid(xa, sd->sd_owner);
+
+ if (secinfo & SMB_GROUP_SECINFO)
+ smb_encode_sid(xa, sd->sd_group);
+
+ if (secinfo & SMB_SACL_SECINFO)
+ smb_encode_sacl(xa, sd->sd_sacl);
+
+ if (secinfo & SMB_DACL_SECINFO)
+ smb_encode_dacl(xa, sd->sd_dacl);
+}
+
+/*
+ * smb_encode_sid
+ *
+ * Encodes given SID in the reply buffer.
+ */
+static void
+smb_encode_sid(struct smb_xa *xa, nt_sid_t *sid)
+{
+ int i;
+
+ (void) smb_encode_mbc(&xa->rep_data_mb, "bb",
+ sid->Revision, sid->SubAuthCount);
+
+ for (i = 0; i < NT_SID_AUTH_MAX; i++) {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "b",
+ sid->Authority[i]);
+ }
+
+ for (i = 0; i < sid->SubAuthCount; i++) {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "l",
+ sid->SubAuthority[i]);
+ }
+}
+
+/*
+ * smb_encode_sacl
+ *
+ * Encodes given SACL in the reply buffer.
+ */
+static void
+smb_encode_sacl(struct smb_xa *xa, smb_acl_t *acl)
+{
+ smb_ace_t *ace;
+ int i;
+
+ if (acl == NULL)
+ return;
+
+ /* encode header */
+ (void) smb_encode_mbc(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
+ acl->sl_bsize, acl->sl_acecnt);
+
+ for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "bbwl",
+ ace->se_hdr.se_type, ace->se_hdr.se_flags,
+ ace->se_hdr.se_bsize, ace->se_mask);
+
+ smb_encode_sid(xa, ace->se_sid);
+ }
+}
+
+/*
+ * smb_encode_dacl
+ *
+ * Encodes given DACL in the reply buffer.
+ */
+static void
+smb_encode_dacl(struct smb_xa *xa, smb_acl_t *acl)
+{
+ smb_ace_t *ace;
+
+ if (acl == NULL)
+ return;
+
+ /* encode header */
+ (void) smb_encode_mbc(&xa->rep_data_mb, "b.ww2.", acl->sl_revision,
+ acl->sl_bsize, acl->sl_acecnt);
+
+ ace = list_head(&acl->sl_sorted);
+ while (ace) {
+ (void) smb_encode_mbc(&xa->rep_data_mb, "bbwl",
+ ace->se_hdr.se_type, ace->se_hdr.se_flags,
+ ace->se_hdr.se_bsize, ace->se_mask);
+
+ smb_encode_sid(xa, ace->se_sid);
+ ace = list_next(&acl->sl_sorted, ace);
+ }
+}
+
+/*
+ * smb_decode_sd
+ *
+ * Decodes the security descriptor in the request buffer
+ * and set the fields of 'sd' appropraitely. Upon successful
+ * return, caller must free allocated memories by calling
+ * smb_sd_term().
+ */
+uint32_t
+smb_decode_sd(struct smb_xa *xa, smb_sd_t *sd)
+{
+ struct mbuf_chain sdbuf;
+ uint32_t owner_offs;
+ uint32_t group_offs;
+ uint32_t sacl_offs;
+ uint32_t dacl_offs;
+
+ smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
+
+ (void) MBC_SHADOW_CHAIN(&sdbuf, &xa->req_data_mb,
+ xa->req_data_mb.chain_offset,
+ xa->req_data_mb.max_bytes - xa->req_data_mb.chain_offset);
+
+ if (smb_decode_mbc(&sdbuf, "b.wllll",
+ &sd->sd_revision, &sd->sd_control,
+ &owner_offs, &group_offs, &sacl_offs, &dacl_offs))
+ goto decode_error;
+
+ sd->sd_control &= ~SE_SELF_RELATIVE;
+
+ if (owner_offs != 0) {
+ if (owner_offs < SMB_SD_HDRSIZE)
+ goto decode_error;
+
+ sd->sd_owner = smb_decode_sid(xa, owner_offs);
+ if (sd->sd_owner == NULL)
+ goto decode_error;
+ }
+
+ if (group_offs != 0) {
+ if (group_offs < SMB_SD_HDRSIZE)
+ goto decode_error;
+
+ sd->sd_group = smb_decode_sid(xa, group_offs);
+ if (sd->sd_group == NULL)
+ goto decode_error;
+ }
+
+ if (sacl_offs != 0) {
+ if ((sd->sd_control & SE_SACL_PRESENT) == 0)
+ goto decode_error;
+
+ if (sacl_offs < SMB_SD_HDRSIZE)
+ goto decode_error;
+
+ sd->sd_sacl = smb_decode_acl(xa, sacl_offs);
+ if (sd->sd_sacl == NULL)
+ goto decode_error;
+ }
+
+ if (dacl_offs != 0) {
+ if ((sd->sd_control & SE_DACL_PRESENT) == 0)
+ goto decode_error;
+
+ if (dacl_offs < SMB_SD_HDRSIZE)
+ goto decode_error;
+
+ sd->sd_dacl = smb_decode_acl(xa, dacl_offs);
+ if (sd->sd_dacl == NULL)
+ goto decode_error;
+ }
+
+ return (NT_STATUS_SUCCESS);
+
+decode_error:
+ smb_sd_term(sd);
+ return (NT_STATUS_INVALID_SECURITY_DESCR);
+}
+
+/*
+ * smb_decode_sid
+ *
+ * Allocates memory and decodes the SID in the request buffer
+ * Upon successful return, caller must free the allocated memory
+ * by calling MEM_FREE()
+ */
+static nt_sid_t *
+smb_decode_sid(struct smb_xa *xa, uint32_t offset)
+{
+ uint8_t revision;
+ uint8_t subauth_cnt;
+ struct mbuf_chain sidbuf;
+ nt_sid_t *sid;
+ int sidlen;
+ int bytes_left;
+ int i;
+
+ offset += xa->req_data_mb.chain_offset;
+ bytes_left = xa->req_data_mb.max_bytes - offset;
+ if (bytes_left < sizeof (nt_sid_t))
+ return (NULL);
+
+ (void) MBC_SHADOW_CHAIN(&sidbuf, &xa->req_data_mb, offset, bytes_left);
+
+ if (smb_decode_mbc(&sidbuf, "bb", &revision, &subauth_cnt))
+ return (NULL);
+
+ sidlen = sizeof (nt_sid_t) - sizeof (uint32_t) +
+ (subauth_cnt * sizeof (uint32_t));
+ sid = MEM_MALLOC("smbsrv", sidlen);
+
+ sid->Revision = revision;
+ sid->SubAuthCount = subauth_cnt;
+
+ for (i = 0; i < NT_SID_AUTH_MAX; i++) {
+ if (smb_decode_mbc(&sidbuf, "b", &sid->Authority[i]))
+ goto decode_err;
+ }
+
+ for (i = 0; i < sid->SubAuthCount; i++) {
+ if (smb_decode_mbc(&sidbuf, "l", &sid->SubAuthority[i]))
+ goto decode_err;
+ }
+
+ return (sid);
+
+decode_err:
+ MEM_FREE("smbsrv", sid);
+ return (NULL);
+}
+
+/*
+ * smb_decode_acl
+ *
+ * Allocates memory and decodes the ACL in the request buffer
+ * Upon successful return, caller must free the allocated memory
+ * by calling smb_acl_free().
+ */
+static smb_acl_t *
+smb_decode_acl(struct smb_xa *xa, uint32_t offset)
+{
+ struct mbuf_chain aclbuf;
+ smb_acl_t *acl;
+ smb_ace_t *ace;
+ uint8_t revision;
+ uint16_t size;
+ uint16_t acecnt;
+ int bytes_left;
+ uint32_t sid_offs = offset;
+ int sidlen;
+ int i;
+
+ offset += xa->req_data_mb.chain_offset;
+ bytes_left = xa->req_data_mb.max_bytes - offset;
+ if (bytes_left < SMB_ACL_HDRSIZE)
+ return (NULL);
+
+ (void) MBC_SHADOW_CHAIN(&aclbuf, &xa->req_data_mb, offset, bytes_left);
+
+ if (smb_decode_mbc(&aclbuf, "b.ww2.", &revision, &size, &acecnt))
+ return (NULL);
+
+ if (size == 0)
+ return (NULL);
+
+ acl = smb_acl_alloc(revision, size, acecnt);
+
+ sid_offs += SMB_ACL_HDRSIZE;
+ for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
+ if (smb_decode_mbc(&aclbuf, "bbwl",
+ &ace->se_hdr.se_type, &ace->se_hdr.se_flags,
+ &ace->se_hdr.se_bsize, &ace->se_mask))
+ goto decode_error;
+
+ sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask);
+ ace->se_sid = smb_decode_sid(xa, sid_offs);
+ if (ace->se_sid == NULL)
+ goto decode_error;
+ sidlen = nt_sid_length(ace->se_sid);
+ aclbuf.chain_offset += sidlen;
+ sid_offs += sidlen;
+ }
+
+ return (acl);
+
+decode_error:
+ smb_acl_free(acl);
+ return (NULL);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index 150262e28b..e8eb106291 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -498,7 +498,7 @@ smb_ofile_seek(
int32_t off,
uint32_t *retoff)
{
- off_t newoff = 0;
+ u_offset_t newoff = 0;
int rc = 0;
ASSERT(of);
@@ -511,21 +511,22 @@ smb_ofile_seek(
if (off < 0)
newoff = 0;
else
- newoff = (off_t)off;
+ newoff = (u_offset_t)off;
break;
case SMB_SEEK_CUR:
if (off < 0 && (-off) > of->f_seek_pos)
newoff = 0;
else
- newoff = of->f_seek_pos + (off_t)off;
+ newoff = of->f_seek_pos + (u_offset_t)off;
break;
case SMB_SEEK_END:
if (off < 0 && (-off) > of->f_node->attr.sa_vattr.va_size)
newoff = 0;
else
- newoff = of->f_node->attr.sa_vattr.va_size + (off_t)off;
+ newoff = of->f_node->attr.sa_vattr.va_size +
+ (u_offset_t)off;
break;
default:
@@ -533,7 +534,12 @@ smb_ofile_seek(
return (EINVAL);
}
- if (newoff > ULONG_MAX) {
+ /*
+ * See comments at the beginning of smb_seek.c.
+ * If the offset is greater than UINT_MAX, we will return an error.
+ */
+
+ if (newoff > UINT_MAX) {
rc = EOVERFLOW;
} else {
of->f_seek_pos = newoff;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
index aa02274224..b195ed6353 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c
@@ -280,7 +280,7 @@ smb_com_open(struct smb_request *sr)
~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
}
- if (op->dsize > 0xffffffff)
+ if (op->dsize > UINT_MAX)
smbsr_raise_error(sr, ERRDOS, ERRbadfunc);
file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
@@ -350,7 +350,7 @@ smb_com_open_andx(struct smb_request *sr)
else if (flags & 4)
op->my_flags = MYF_BATCH_OPLOCK;
- if ((CreationTime != 0) && (CreationTime != 0xffffffff))
+ if ((CreationTime != 0) && (CreationTime != UINT_MAX))
op->utime.tv_sec = smb_local_time_to_gmt(CreationTime);
op->utime.tv_nsec = 0;
@@ -385,7 +385,7 @@ smb_com_open_andx(struct smb_request *sr)
/* NOTREACHED */
}
- if (op->dsize > 0xffffffff)
+ if (op->dsize > UINT_MAX)
smbsr_raise_error(sr, ERRDOS, ERRbadfunc);
if (MYF_OPLOCK_TYPE(op->my_flags) != MYF_OPLOCK_NONE) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
index cacbbb3e9d..cc203a7315 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c
@@ -391,19 +391,17 @@ smb_pathname(
rootvp = (vnode_t *)root_node->vp;
/*
- * Instead of passing the FOLLOW flag to lookuppnvp(), process links in
- * this routine. This allows smb_nodes to be created for each component
- * of a link.
- */
- local_flags = flags & FIGNORECASE;
-
- /*
* Path components are processed one at a time so that smb_nodes
* can be created for each component. This allows the dir_snode
* field in the smb_node to be properly populated.
*
- * Mangle checking is also done on each component.
+ * Because of the above, links are also processed in this routine
+ * (i.e., we do not pass the FOLLOW flag to lookuppnvp()). This
+ * will allow smb_nodes to be created for each component of a link.
+ *
+ * Mangle checking is per component.
*/
+
while ((pathleft = pn_pathleft(&upn)) != 0) {
if (fnode) {
smb_node_release(dnode);
@@ -419,10 +417,24 @@ smb_pathname(
component, real_name, MAXNAMELEN, 0, 0,
1)) != 0)
break;
+ /*
+ * Do not pass FIGNORECASE to lookuppnvp().
+ * This is because we would like to do a lookup
+ * on the real name just obtained (which
+ * corresponds to the mangled name).
+ */
namep = real_name;
+ local_flags = 0;
} else {
+ /*
+ * Pass FIGNORECASE to lookuppnvp().
+ * This will cause the file system to
+ * return "first match" in the event of
+ * a case collision.
+ */
namep = component;
+ local_flags = flags & FIGNORECASE;
}
if ((err = pn_set(&pn, namep)) != 0)
diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c
index 6554c07014..8542a1a1f9 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_read.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_read.c
@@ -145,7 +145,7 @@ smb_com_lock_and_read(struct smb_request *sr)
}
result = smb_lock_range(sr, sr->fid_ofile, param.r_offset,
- (uint64_t)param.r_count, 0xffffffff, SMB_LOCK_TYPE_READWRITE);
+ (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE);
if (result != NT_STATUS_SUCCESS) {
smb_lock_range_raise_error(sr, result);
}
@@ -370,7 +370,7 @@ smb_common_read(struct smb_request *sr, smb_read_param_t *param)
vdb->uio.uio_iov = &vdb->iovec[0];
vdb->uio.uio_iovcnt = MAX_IOVEC;
vdb->uio.uio_resid = param->r_count;
- vdb->uio.uio_offset = param->r_offset;
+ vdb->uio.uio_loffset = (offset_t)param->r_offset;
vdb->uio.uio_segflg = UIO_SYSSPACE;
switch (sr->tid_tree->t_res_type & STYPE_MASK) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_rpc.c b/usr/src/uts/common/fs/smbsrv/smb_rpc.c
index 394c5addbe..5059c909b4 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_rpc.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_rpc.c
@@ -171,9 +171,6 @@ smb_rpc_open(struct smb_request *sr)
char *pipe_name;
int status;
- if (smb_winpipe_open() != 0)
- return (NT_STATUS_INTERNAL_ERROR);
-
op = &sr->arg.open;
if ((pipe_name = smb_rpc_lookup(op->fqi.path)) != 0) {
@@ -278,7 +275,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio)
streamin = &pipe_info->input;
streamin->uio.uio_iov = uio->uio_iov;
streamin->uio.uio_iovcnt = uio->uio_iovcnt;
- streamin->uio.uio_offset = 0;
+ streamin->uio.uio_loffset = 0;
streamin->uio.uio_resid = uio->uio_resid;
streamin->uio.uio_segflg = UIO_SYSSPACE;
@@ -446,7 +443,7 @@ smb_rpc_write(struct smb_request *sr, struct uio *uio)
streamin = &pipe_info->input;
streamin->uio.uio_iov = uio->uio_iov;
streamin->uio.uio_iovcnt = uio->uio_iovcnt;
- streamin->uio.uio_offset = 0;
+ streamin->uio.uio_loffset = 0;
streamin->uio.uio_resid = uio->uio_resid;
streamin->uio.uio_segflg = UIO_SYSSPACE;
mdrcnt = (uint32_t)uio->uio_resid;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_sd.c b/usr/src/uts/common/fs/smbsrv/smb_sd.c
index 4afa258b9a..fa2bf223d7 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_sd.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_sd.c
@@ -29,20 +29,21 @@
* This module provides Security Descriptor handling functions.
*/
-#include <smbsrv/smb_incl.h>
+#include <smbsrv/smbvar.h>
+#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_idmap.h>
+#include <smbsrv/ntstatus.h>
-#define AS_DWORD(X) (*(uint32_t *)&(X))
-#define SELF_REL(P, M, T) (T *)(((char *)(P)) + AS_DWORD((P)->M))
-
-void smb_fmt_sid(char *buf, nt_sid_t *sid);
+static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
+static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int);
+static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *);
void
smb_sd_init(smb_sd_t *sd, uint8_t revision)
{
bzero(sd, sizeof (smb_sd_t));
- sd->sd_hdr.sd_revision = revision;
+ sd->sd_revision = revision;
}
/*
@@ -55,7 +56,7 @@ void
smb_sd_term(smb_sd_t *sd)
{
ASSERT(sd);
- ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0);
+ ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0);
if (sd->sd_owner)
MEM_FREE("libnt", sd->sd_owner);
@@ -63,219 +64,28 @@ smb_sd_term(smb_sd_t *sd)
if (sd->sd_group)
MEM_FREE("libnt", sd->sd_group);
- if (sd->sd_dacl)
- kmem_free(sd->sd_dacl, sd->sd_dacl->sl_size);
-
- if (sd->sd_sacl)
- kmem_free(sd->sd_sacl, sd->sd_sacl->sl_size);
+ smb_acl_free(sd->sd_dacl);
+ smb_acl_free(sd->sd_sacl);
bzero(sd, sizeof (smb_sd_t));
}
-/*
- * Hmmm. For all of these smb_sd_set_xxx() functions,
- * what do we do if the affected member is already set?
- * Should we free() it? For now, punt and risk a memory leak.
- */
-
-void
-smb_sd_set_owner(smb_sd_t *sd, nt_sid_t *owner, int defaulted)
-{
- ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0);
-
- sd->sd_owner = owner;
- if (defaulted)
- sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED;
- else
- sd->sd_hdr.sd_control &= ~SE_OWNER_DEFAULTED;
-}
-
-void
-smb_sd_set_group(smb_sd_t *sd, nt_sid_t *group, int defaulted)
-{
- ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0);
-
- sd->sd_group = group;
- if (defaulted)
- sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED;
- else
- sd->sd_hdr.sd_control &= ~SE_GROUP_DEFAULTED;
-}
-
-void
-smb_sd_set_dacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags)
-{
- ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0);
-
- sd->sd_dacl = acl;
-
- if (flags & ACL_DEFAULTED)
- sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED;
- if (flags & ACL_AUTO_INHERIT)
- sd->sd_hdr.sd_control |= SE_DACL_AUTO_INHERITED;
- if (flags & ACL_PROTECTED)
- sd->sd_hdr.sd_control |= SE_DACL_PROTECTED;
-
- if (present)
- sd->sd_hdr.sd_control |= SE_DACL_PRESENT;
-}
-
-void
-smb_sd_set_sacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags)
-{
- ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0);
-
- sd->sd_sacl = acl;
-
- if (flags & ACL_DEFAULTED)
- sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED;
- if (flags & ACL_AUTO_INHERIT)
- sd->sd_hdr.sd_control |= SE_SACL_AUTO_INHERITED;
- if (flags & ACL_PROTECTED)
- sd->sd_hdr.sd_control |= SE_SACL_PROTECTED;
-
- if (present)
- sd->sd_hdr.sd_control |= SE_SACL_PRESENT;
-}
-
-nt_sid_t *
-smb_sd_get_owner(void *sd, int *defaulted)
-{
- smb_sdbuf_t *sr_sd;
- smb_sd_hdr_t *sd_hdr;
- nt_sid_t *sid;
-
- sd_hdr = (smb_sd_hdr_t *)sd;
- if (defaulted != NULL)
- *defaulted = (sd_hdr->sd_control & SE_OWNER_DEFAULTED) ? 1 : 0;
-
- if (sd_hdr->sd_control & SE_SELF_RELATIVE) {
- sr_sd = ((smb_sdbuf_t *)sd);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- sid = SELF_REL(sr_sd, sd_owner_offs, nt_sid_t);
- }
- else
- sid = ((smb_sd_t *)sd)->sd_owner;
-
- return (sid);
-}
-
-nt_sid_t *
-smb_sd_get_group(void *sd, int *defaulted)
-{
- smb_sdbuf_t *sr_sd;
- smb_sd_hdr_t *sd_hdr;
- nt_sid_t *sid;
-
- sd_hdr = (smb_sd_hdr_t *)sd;
- if (defaulted != NULL)
- *defaulted = (sd_hdr->sd_control & SE_GROUP_DEFAULTED) ? 1 : 0;
-
- if (sd_hdr->sd_control & SE_SELF_RELATIVE) {
- sr_sd = ((smb_sdbuf_t *)sd);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- sid = SELF_REL(sr_sd, sd_group_offs, nt_sid_t);
- }
- else
- sid = ((smb_sd_t *)sd)->sd_group;
-
- return (sid);
-}
-
-smb_acl_t *
-smb_sd_get_dacl(void *sd, int *present, int *defaulted)
-{
- smb_sdbuf_t *sr_sd;
- smb_sd_hdr_t *sd_hdr;
- smb_acl_t *acl = NULL;
-
- sd_hdr = (smb_sd_hdr_t *)sd;
- if (present != NULL)
- *present = (sd_hdr->sd_control & SE_DACL_PRESENT) ? 1 : 0;
-
- if (defaulted != NULL)
- *defaulted = (sd_hdr->sd_control & SE_DACL_DEFAULTED) ? 1 : 0;
-
- if (sd_hdr->sd_control & SE_SELF_RELATIVE) {
- sr_sd = ((smb_sdbuf_t *)sd);
- if (sr_sd->sd_dacl_offs) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- acl = SELF_REL(sr_sd, sd_dacl_offs, smb_acl_t);
- }
- }
- else
- acl = ((smb_sd_t *)sd)->sd_dacl;
-
- return (acl);
-}
-
-smb_acl_t *
-smb_sd_get_sacl(void *sd, int *present, int *defaulted)
-{
- smb_sdbuf_t *sr_sd;
- smb_sd_hdr_t *sd_hdr;
- smb_acl_t *acl = NULL;
-
- sd_hdr = (smb_sd_hdr_t *)sd;
- if (present != NULL)
- *present = (sd_hdr->sd_control & SE_SACL_PRESENT) ? 1 : 0;
-
- if (defaulted != NULL)
- *defaulted = (sd_hdr->sd_control & SE_SACL_DEFAULTED) ? 1 : 0;
-
- if (sd_hdr->sd_control & SE_SELF_RELATIVE) {
- sr_sd = ((smb_sdbuf_t *)sd);
- if (sr_sd->sd_sacl_offs) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- acl = SELF_REL(sr_sd, sd_sacl_offs, smb_acl_t);
- }
- }
- else
- acl = ((smb_sd_t *)sd)->sd_sacl;
-
- return (acl);
-}
-
uint32_t
-smb_sd_len(void *sd, uint32_t secinfo)
+smb_sd_len(smb_sd_t *sd, uint32_t secinfo)
{
- uint32_t length = 0;
- nt_sid_t *sid;
- smb_acl_t *acl;
- int present;
-
- /* SD Header */
- length += sizeof (smb_sdbuf_t);
+ uint32_t length = SMB_SD_HDRSIZE;
- /* Owner */
- if (secinfo & SMB_OWNER_SECINFO) {
- sid = smb_sd_get_owner(sd, NULL);
- if (sid)
- length += nt_sid_length(sid);
- }
+ if (secinfo & SMB_OWNER_SECINFO)
+ length += nt_sid_length(sd->sd_owner);
+ if (secinfo & SMB_GROUP_SECINFO)
+ length += nt_sid_length(sd->sd_group);
- /* Group */
- if (secinfo & SMB_GROUP_SECINFO) {
- sid = smb_sd_get_group(sd, NULL);
- if (sid)
- length += nt_sid_length(sid);
- }
+ if (secinfo & SMB_DACL_SECINFO)
+ length += smb_acl_len(sd->sd_dacl);
-
- /* DACL */
- if (secinfo & SMB_DACL_SECINFO) {
- acl = smb_sd_get_dacl(sd, &present, NULL);
- if (present && acl)
- length += smb_acl_len(acl);
- }
-
- /* SACL */
- if (secinfo & SMB_SACL_SECINFO) {
- acl = smb_sd_get_sacl(sd, &present, NULL);
- if (present && acl)
- length += smb_acl_len(acl);
- }
+ if (secinfo & SMB_SACL_SECINFO)
+ length += smb_acl_len(sd->sd_sacl);
return (length);
}
@@ -287,273 +97,103 @@ smb_sd_len(void *sd, uint32_t secinfo)
* descriptor.
*/
uint32_t
-smb_sd_get_secinfo(void *sd)
+smb_sd_get_secinfo(smb_sd_t *sd)
{
uint32_t sec_info = 0;
- smb_acl_t *acl;
- int present;
- if (sd == 0)
+ if (sd == NULL)
return (0);
- if (smb_sd_get_owner(sd, NULL) != 0)
+ if (sd->sd_owner)
sec_info |= SMB_OWNER_SECINFO;
- if (smb_sd_get_group(sd, NULL) != 0)
+ if (sd->sd_group)
sec_info |= SMB_GROUP_SECINFO;
- acl = smb_sd_get_dacl(sd, &present, NULL);
- if (acl && present)
+ if (sd->sd_dacl)
sec_info |= SMB_DACL_SECINFO;
- acl = smb_sd_get_sacl(sd, &present, NULL);
- if (acl && present)
+ if (sd->sd_sacl)
sec_info |= SMB_SACL_SECINFO;
return (sec_info);
}
/*
- * smb_sd_abs2selfrel
- *
- * This function takes an absolute SD (sd) and make a self relative
- * SD which will be returned in srel_sd.
- *
- * srel_sdsz contains the size of buffer which srel_sd points to.
+ * smb_sd_read
*
- * Do not add new error codes here without checking the impact on
- * all callers of this function.
+ * Read uid, gid and ACL from filesystem. The returned ACL from read
+ * routine is always in ZFS format. Convert the ZFS acl to a Win acl
+ * and return the Win SD in absolute form.
*
- * Returns NT status codes:
- * NT_STATUS_SUCCESS
- * NT_STATUS_BUFFER_TOO_SMALL
- * NT_STATUS_INVALID_SECURITY_DESCR
+ * NOTE: upon successful return caller MUST free the memory allocated
+ * for the returned SD by calling smb_sd_term().
*/
-static uint32_t
-smb_sd_abs2selfrel(
- smb_sd_t *sd,
- uint32_t secinfo,
- smb_sdbuf_t *srel_sd,
- uint32_t srel_sdsz)
+uint32_t
+smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo)
{
- uint32_t avail_len = srel_sdsz;
- uint32_t length = 0;
- unsigned char *scan_beg = (unsigned char *) srel_sd;
- unsigned char *scan = scan_beg;
- unsigned char *scan_end;
- nt_sid_t *sid;
- smb_acl_t *acl;
- int present, defaulted;
-
- length = smb_sd_len(sd, secinfo);
-
- if (length == 0)
- return (NT_STATUS_INVALID_SECURITY_DESCR);
-
- if (avail_len < length)
- return (NT_STATUS_BUFFER_TOO_SMALL);
-
- bzero(srel_sd, length);
- scan_end = scan_beg + length;
-
- /* SD Header */
- length = sizeof (smb_sdbuf_t);
- srel_sd->sd_hdr.sd_revision = sd->sd_hdr.sd_revision;
- srel_sd->sd_hdr.sd_control = SE_SELF_RELATIVE;
- scan += length;
-
- if (secinfo & SMB_OWNER_SECINFO) {
- /* Owner */
- sid = smb_sd_get_owner(sd, &defaulted);
-
- if (defaulted)
- srel_sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED;
-
- if (sid) {
- /*LINTED E_PTRDIFF_OVERFLOW*/
- length = nt_sid_copy((void*)scan, sid, scan_end - scan);
- if (length == 0)
- goto fail;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- srel_sd->sd_owner_offs = scan - scan_beg;
- scan += length;
- }
- }
-
- if (secinfo & SMB_GROUP_SECINFO) {
- /* Group */
- sid = smb_sd_get_group(sd, &defaulted);
-
- if (defaulted)
- srel_sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED;
-
- if (sid) {
- /*LINTED E_PTRDIFF_OVERFLOW*/
- length = nt_sid_copy((void*)scan, sid, scan_end - scan);
- if (length == 0)
- goto fail;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- srel_sd->sd_group_offs = scan - scan_beg;
- scan += length;
- }
- }
-
-
- if (secinfo & SMB_DACL_SECINFO) {
- /* Dacl */
- acl = smb_sd_get_dacl(sd, &present, &defaulted);
-
- srel_sd->sd_hdr.sd_control |=
- (sd->sd_hdr.sd_control & SE_DACL_INHERITANCE_MASK);
-
- if (defaulted)
- srel_sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED;
+ smb_fssd_t fs_sd;
+ smb_error_t smb_err;
+ smb_node_t *node;
+ uint32_t status = NT_STATUS_SUCCESS;
+ uint32_t sd_flags;
+ int error;
- if (present)
- srel_sd->sd_hdr.sd_control |= SE_DACL_PRESENT;
+ node = sr->fid_ofile->f_node;
+ sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0;
+ smb_fssd_init(&fs_sd, secinfo, sd_flags);
- if (present && acl) {
- /*LINTED E_PTRDIFF_OVERFLOW*/
- length = smb_acl_copy(scan_end - scan,
- (void*) scan, acl);
- if (length == 0)
- goto fail;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- srel_sd->sd_dacl_offs = scan - scan_beg;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- acl = (smb_acl_t *)scan;
- acl->sl_size = (WORD)length; /* set the size */
- scan += length;
- }
+ error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd);
+ if (error) {
+ smb_errmap_unix2smb(error, &smb_err);
+ return (smb_err.status);
}
- if (secinfo & SMB_SACL_SECINFO) {
- /* Sacl */
- acl = smb_sd_get_sacl(sd, &present, &defaulted);
-
- srel_sd->sd_hdr.sd_control |=
- (sd->sd_hdr.sd_control & SE_SACL_INHERITANCE_MASK);
-
- if (defaulted)
- srel_sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED;
-
- if (present)
- srel_sd->sd_hdr.sd_control |= SE_SACL_PRESENT;
-
- if (present && acl) {
- /*LINTED E_PTRDIFF_OVERFLOW*/
- length = smb_acl_copy(scan_end - scan,
- (void*) scan, acl);
- if (length == 0)
- goto fail;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- srel_sd->sd_sacl_offs = scan - scan_beg;
- /*LINTED E_PTRDIFF_OVERFLOW*/
- acl = (smb_acl_t *)scan;
- acl->sl_size = (WORD)length; /* set the size */
- scan += length;
- }
- }
+ status = smb_sd_fromfs(&fs_sd, sd);
+ smb_fssd_term(&fs_sd);
- return (NT_STATUS_SUCCESS);
-
-fail:
- return (NT_STATUS_INVALID_SECURITY_DESCR);
+ return (status);
}
/*
- * smb_sd_fromfs
- *
- * Makes an Windows style security descriptor in absolute form
- * based on the given filesystem security information.
+ * smb_sd_write
*
- * Should call smb_sd_term() for the returned sd to free allocated
- * members.
+ * Takes a Win SD in absolute form, converts it to
+ * ZFS format and write it to filesystem. The write routine
+ * converts ZFS acl to Posix acl if required.
*/
-static uint32_t
-smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd)
+uint32_t
+smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo)
{
- uint32_t status = NT_STATUS_SUCCESS;
- smb_acl_t *acl = NULL;
- smb_acl_t *sorted_acl;
- nt_sid_t *sid;
- idmap_stat idm_stat;
-
- ASSERT(fs_sd);
- ASSERT(sd);
-
- smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
-
- /* Owner */
- if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
- idm_stat = smb_idmap_getsid(fs_sd->sd_uid,
- SMB_IDMAP_USER, &sid);
-
- if (idm_stat != IDMAP_SUCCESS) {
- return (NT_STATUS_NONE_MAPPED);
- }
-
- smb_sd_set_owner(sd, sid, 0);
- }
-
- /* Group */
- if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
- idm_stat = smb_idmap_getsid(fs_sd->sd_gid,
- SMB_IDMAP_GROUP, &sid);
-
- if (idm_stat != IDMAP_SUCCESS) {
- smb_sd_term(sd);
- return (NT_STATUS_NONE_MAPPED);
- }
-
- smb_sd_set_group(sd, sid, 0);
- }
+ smb_node_t *node;
+ smb_fssd_t fs_sd;
+ smb_error_t smb_err;
+ uint32_t status;
+ uint32_t sd_flags;
+ int error;
- /* DACL */
- if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) {
- if (fs_sd->sd_zdacl != NULL) {
- acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid,
- fs_sd->sd_gid);
- if (acl == NULL) {
- smb_sd_term(sd);
- return (NT_STATUS_INTERNAL_ERROR);
- }
+ node = sr->fid_ofile->f_node;
+ sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0;
+ smb_fssd_init(&fs_sd, secinfo, sd_flags);
- /*
- * Need to sort the ACL before send it to Windows
- * clients. Winodws GUI is sensitive about the order
- * of ACEs.
- */
- sorted_acl = smb_acl_sort(acl);
- if (sorted_acl && (sorted_acl != acl)) {
- kmem_free(acl, acl->sl_size);
- acl = sorted_acl;
- }
- smb_sd_set_dacl(sd, 1, acl, fs_sd->sd_zdacl->acl_flags);
- } else {
- smb_sd_set_dacl(sd, 0, NULL, 0);
- }
+ status = smb_sd_tofs(sd, &fs_sd);
+ if (status != NT_STATUS_SUCCESS) {
+ smb_fssd_term(&fs_sd);
+ return (status);
}
- /* SACL */
- if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) {
- if (fs_sd->sd_zsacl != NULL) {
- acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid,
- fs_sd->sd_gid);
- if (acl == NULL) {
- smb_sd_term(sd);
- return (NT_STATUS_INTERNAL_ERROR);
- }
+ error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0);
+ smb_fssd_term(&fs_sd);
- smb_sd_set_sacl(sd, 1, acl, fs_sd->sd_zsacl->acl_flags);
- } else {
- smb_sd_set_sacl(sd, 0, NULL, 0);
- }
+ if (error) {
+ smb_errmap_unix2smb(error, &smb_err);
+ return (smb_err.status);
}
- return (status);
+ return (NT_STATUS_SUCCESS);
}
+
/*
* smb_sd_tofs
*
@@ -561,18 +201,16 @@ smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd)
* Windows security descriptor.
*/
uint32_t
-smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
+smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd)
{
nt_sid_t *sid;
- smb_acl_t *acl;
uint32_t status = NT_STATUS_SUCCESS;
uint16_t sd_control;
idmap_stat idm_stat;
- int present;
int idtype;
int flags = 0;
- sd_control = sr_sd->sd_hdr.sd_control;
+ sd_control = sd->sd_control;
/*
* ZFS only has one set of flags so for now only
@@ -590,7 +228,7 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
/* Owner */
if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
- sid = smb_sd_get_owner(sr_sd, NULL);
+ sid = sd->sd_owner;
if (nt_sid_is_valid(sid) == 0) {
return (NT_STATUS_INVALID_SID);
}
@@ -604,7 +242,7 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
/* Group */
if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
- sid = smb_sd_get_group(sr_sd, NULL);
+ sid = sd->sd_group;
if (nt_sid_is_valid(sid) == 0) {
return (NT_STATUS_INVALID_SID);
}
@@ -618,9 +256,8 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
/* DACL */
if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) {
- acl = smb_sd_get_dacl(sr_sd, &present, NULL);
- if (present) {
- status = smb_acl_to_zfs(acl, flags,
+ if (sd->sd_control & SE_DACL_PRESENT) {
+ status = smb_acl_to_zfs(sd->sd_dacl, flags,
SMB_DACL_SECINFO, &fs_sd->sd_zdacl);
if (status != NT_STATUS_SUCCESS)
return (status);
@@ -631,9 +268,8 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
/* SACL */
if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) {
- acl = smb_sd_get_sacl(sr_sd, &present, NULL);
- if (present) {
- status = smb_acl_to_zfs(acl, flags,
+ if (sd->sd_control & SE_SACL_PRESENT) {
+ status = smb_acl_to_zfs(sd->sd_sacl, flags,
SMB_SACL_SECINFO, &fs_sd->sd_zsacl);
if (status != NT_STATUS_SUCCESS) {
return (status);
@@ -647,216 +283,156 @@ smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd)
}
/*
- * smb_sd_read
+ * smb_sd_fromfs
*
- * Read uid, gid and ACL from filesystem. The returned ACL from read
- * routine is always in ZFS format. Convert the ZFS acl to a Win acl
- * and return the Win SD in relative form.
+ * Makes an Windows style security descriptor in absolute form
+ * based on the given filesystem security information.
*
- * NOTE: upon successful return caller MUST free the memory allocated
- * for the returned SD by calling kmem_free(). The length of the allocated
- * buffer is returned in 'buflen'.
+ * Should call smb_sd_term() for the returned sd to free allocated
+ * members.
*/
-uint32_t
-smb_sd_read(smb_request_t *sr, smb_sdbuf_t **sr_sd,
- uint32_t secinfo, uint32_t *buflen)
+static uint32_t
+smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd)
{
- smb_sd_t sd;
- smb_fssd_t fs_sd;
- smb_error_t smb_err;
- smb_sdbuf_t *sdbuf;
- smb_node_t *node;
- uint32_t sdlen;
uint32_t status = NT_STATUS_SUCCESS;
- uint32_t sd_flags;
- int error;
+ smb_acl_t *acl = NULL;
+ nt_sid_t *sid;
+ idmap_stat idm_stat;
- *sr_sd = NULL;
+ ASSERT(fs_sd);
+ ASSERT(sd);
- node = sr->fid_ofile->f_node;
- sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0;
- smb_fsop_sdinit(&fs_sd, secinfo, sd_flags);
+ smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
- error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd);
- if (error) {
- smb_errmap_unix2smb(error, &smb_err);
- return (smb_err.status);
+ /* Owner */
+ if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
+ idm_stat = smb_idmap_getsid(fs_sd->sd_uid,
+ SMB_IDMAP_USER, &sid);
+
+ if (idm_stat != IDMAP_SUCCESS) {
+ smb_sd_term(sd);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ sd->sd_owner = sid;
}
- status = smb_sd_fromfs(&fs_sd, &sd);
- smb_fsop_sdterm(&fs_sd);
+ /* Group */
+ if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
+ idm_stat = smb_idmap_getsid(fs_sd->sd_gid,
+ SMB_IDMAP_GROUP, &sid);
- if (status != NT_STATUS_SUCCESS)
- return (status);
+ if (idm_stat != IDMAP_SUCCESS) {
+ smb_sd_term(sd);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- sdlen = smb_sd_len(&sd, secinfo);
+ sd->sd_group = sid;
+ }
- if (*buflen < sdlen) {
- /* return the required size */
- *buflen = sdlen;
- smb_sd_term(&sd);
- return (NT_STATUS_BUFFER_TOO_SMALL);
+ /* DACL */
+ if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) {
+ if (fs_sd->sd_zdacl != NULL) {
+ acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid,
+ fs_sd->sd_gid);
+ if (acl == NULL) {
+ smb_sd_term(sd);
+ return (NT_STATUS_INTERNAL_ERROR);
+ }
+
+ /*
+ * Need to sort the ACL before send it to Windows
+ * clients. Winodws GUI is sensitive about the order
+ * of ACEs.
+ */
+ smb_acl_sort(acl);
+ smb_sd_set_dacl(sd, acl, B_TRUE,
+ fs_sd->sd_zdacl->acl_flags);
+ } else {
+ smb_sd_set_dacl(sd, NULL, B_FALSE, 0);
+ }
}
- sdbuf = kmem_alloc(sdlen, KM_SLEEP);
- status = smb_sd_abs2selfrel(&sd, secinfo, sdbuf, sdlen);
- smb_sd_term(&sd);
+ /* SACL */
+ if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) {
+ if (fs_sd->sd_zsacl != NULL) {
+ acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid,
+ fs_sd->sd_gid);
+ if (acl == NULL) {
+ smb_sd_term(sd);
+ return (NT_STATUS_INTERNAL_ERROR);
+ }
- if (status == NT_STATUS_SUCCESS) {
- *sr_sd = sdbuf;
- *buflen = sdlen;
+ smb_sd_set_sacl(sd, acl, B_TRUE,
+ fs_sd->sd_zsacl->acl_flags);
+ } else {
+ smb_sd_set_sacl(sd, NULL, B_FALSE, 0);
+ }
}
- else
- kmem_free(sdbuf, sdlen);
return (status);
}
-/*
- * smb_sd_write
- *
- * Takes a Win SD in self-relative form, convert it to
- * ZFS format and write it to filesystem. The write routine
- * converts ZFS acl to Posix acl if required.
- */
-uint32_t
-smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, uint32_t secinfo)
+static void
+smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags)
{
- smb_node_t *node;
- smb_fssd_t fs_sd;
- smb_error_t smb_err;
- uint32_t status;
- uint32_t sd_flags;
- int error;
+ ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0);
- node = sr->fid_ofile->f_node;
- sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0;
- smb_fsop_sdinit(&fs_sd, secinfo, sd_flags);
+ sd->sd_dacl = acl;
- status = smb_sd_tofs(sr_sd, &fs_sd);
- if (status != NT_STATUS_SUCCESS) {
- smb_fsop_sdterm(&fs_sd);
- return (status);
- }
+ if (flags & ACL_DEFAULTED)
+ sd->sd_control |= SE_DACL_DEFAULTED;
+ if (flags & ACL_AUTO_INHERIT)
+ sd->sd_control |= SE_DACL_AUTO_INHERITED;
+ if (flags & ACL_PROTECTED)
+ sd->sd_control |= SE_DACL_PROTECTED;
- error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0);
- smb_fsop_sdterm(&fs_sd);
+ if (present)
+ sd->sd_control |= SE_DACL_PRESENT;
+}
- if (error) {
- smb_errmap_unix2smb(error, &smb_err);
- return (smb_err.status);
- }
+static void
+smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags)
+{
+ ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0);
- return (NT_STATUS_SUCCESS);
+ sd->sd_sacl = acl;
+
+ if (flags & ACL_DEFAULTED)
+ sd->sd_control |= SE_SACL_DEFAULTED;
+ if (flags & ACL_AUTO_INHERIT)
+ sd->sd_control |= SE_SACL_AUTO_INHERITED;
+ if (flags & ACL_PROTECTED)
+ sd->sd_control |= SE_SACL_PROTECTED;
+
+ if (present)
+ sd->sd_control |= SE_SACL_PRESENT;
}
/*
- * smb_fmt_sid
+ * smb_fssd_init
*
- * Make an string SID and copy the result into the specified buffer.
+ * Initializes the given FS SD structure.
*/
void
-smb_fmt_sid(char *buf, nt_sid_t *sid)
+smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags)
{
- char *sid_str;
-
- sid_str = nt_sid_format(sid);
- if (sid_str) {
- (void) strcpy(buf, sid_str);
- MEM_FREE("smb", sid_str);
- } else {
- (void) strcpy(buf, "<invalid SID>");
- }
+ bzero(fs_sd, sizeof (smb_fssd_t));
+ fs_sd->sd_secinfo = secinfo;
+ fs_sd->sd_flags = flags;
}
/*
- * smb_sd_log
+ * smb_fssd_term
*
- * log the given Windows style security descriptor information
- * in system log. This is for debugging purposes.
+ * Frees allocated memory for acl fields.
*/
void
-smb_sd_log(void *sd)
+smb_fssd_term(smb_fssd_t *fs_sd)
{
- smb_acl_t *acl;
- smb_ace_t *ace;
- nt_sid_t *sid;
- int present, defaulted;
- char entry[128];
- char *inherit;
- char *type;
- int ix_dacl;
-
- sid = smb_sd_get_owner(sd, &defaulted);
- if (sid)
- smb_fmt_sid(entry, sid);
- else
- (void) strcpy(entry, "NULL");
-
- cmn_err(CE_NOTE, " Owner: %s", entry);
-
- sid = smb_sd_get_group(sd, &defaulted);
- if (sid)
- smb_fmt_sid(entry, sid);
- else
- (void) strcpy(entry, "NULL");
-
- cmn_err(CE_NOTE, " Primary Group: %s", entry);
-
- acl = smb_sd_get_dacl(sd, &present, &defaulted);
-
- if (!present || !acl) {
- cmn_err(CE_NOTE, " No DACL");
- return;
- }
-
- for (ix_dacl = 0;
- ace = smb_ace_get(acl, ix_dacl);
- ix_dacl++) {
- /*
- * Make sure the ACE type is something we grok.
- * All ACE, now and in the future, have a valid
- * header. Can't access fields passed the Header
- * until we're sure it's right.
- */
- switch (ace->se_header.se_type) {
- case ACCESS_ALLOWED_ACE_TYPE:
- type = "(Allow)";
- break;
- case ACCESS_DENIED_ACE_TYPE:
- type = "(Deny)";
- break;
-
- case SYSTEM_AUDIT_ACE_TYPE:
- default:
- /* Ignore unrecognized/misplaced ACE */
- continue;
- }
-
- smb_fmt_sid(entry, &ace->se_sid);
-
- switch (ace->se_header.se_flags & INHERIT_MASK_ACE) {
- case OBJECT_INHERIT_ACE:
- inherit = "(OI)";
- break;
- case CONTAINER_INHERIT_ACE:
- inherit = "(CI)";
- break;
- case INHERIT_ONLY_ACE:
- inherit = "(IO)";
- break;
- case NO_PROPOGATE_INHERIT_ACE:
- inherit = "(NP)";
- break;
- default:
- inherit = "";
- }
-
- (void) snprintf(entry + strlen(entry), sizeof (entry),
- ":%s 0x%X %s", inherit, ace->se_mask, type);
-
- cmn_err(CE_NOTE, " %s", entry);
- }
+ ASSERT(fs_sd);
- cmn_err(CE_NOTE, " %d ACE(s)", ix_dacl);
+ smb_fsacl_free(fs_sd->sd_zdacl);
+ smb_fsacl_free(fs_sd->sd_zsacl);
+ bzero(fs_sd, sizeof (smb_fssd_t));
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index 3ab7076102..c92a248a93 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -637,7 +637,7 @@ int smb_trans2_find_get_dents(
ihdr->uio.uio_iovcnt = maxcount;
ihdr->uio.uio_resid = dent_buf_size;
ihdr->uio.uio_iov = ihdr->iov;
- ihdr->uio.uio_offset = 0;
+ ihdr->uio.uio_loffset = 0;
rc = smb_get_dents(sr, cookie, dir_snode, wildcards, ihdr, more);
if (rc != 0) {
@@ -839,9 +839,9 @@ smb_gather_dents_info(
* Each entry needs to be properly aligned or we may get an alignment
* fault on sparc.
*/
- ihdr->uio.uio_offset = (off_t)PTRALIGN(ihdr->uio.uio_offset);
+ ihdr->uio.uio_loffset = (offset_t)PTRALIGN(ihdr->uio.uio_loffset);
/*LINTED E_BAD_PTR_CAST_ALIGN*/
- ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_offset];
+ ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_loffset];
ient->cookie = cookie;
ient->attr = *attr;
@@ -856,7 +856,7 @@ smb_gather_dents_info(
ihdr->uio.uio_iov++;
ihdr->uio.uio_iovcnt--;
ihdr->uio.uio_resid -= reclen;
- ihdr->uio.uio_offset += reclen;
+ ihdr->uio.uio_loffset += reclen;
kmem_free(v5_name, MAXNAMELEN-1);
return (0);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c
index 2d488b7f2c..e6d4dbeccf 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c
@@ -78,7 +78,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
{
static smb_attr_t pipe_attr;
unsigned short infolev, dattr = 0;
- off_t dsize = 0, dused = 0;
+ u_offset_t dsize = 0, dused = 0;
smb_attr_t *ap = NULL;
char *namep = NULL;
char *filename = NULL, *alt_nm_ptr = NULL;
@@ -194,10 +194,10 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
break;
case SMB_INFO_STANDARD:
- if (dsize > 0xffffffff)
- dsize = 0xffffffff;
- if (dused > 0xffffffff)
- dused = 0xffffffff;
+ if (dsize > UINT_MAX)
+ dsize = UINT_MAX;
+ if (dused > UINT_MAX)
+ dused = UINT_MAX;
(void) smb_encode_mbc(&xa->rep_param_mb, "w", 0);
(void) smb_encode_mbc(&xa->rep_data_mb,
@@ -212,10 +212,10 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
break;
case SMB_INFO_QUERY_EA_SIZE:
- if (dsize > 0xffffffff)
- dsize = 0xffffffff;
- if (dused > 0xffffffff)
- dused = 0xffffffff;
+ if (dsize > UINT_MAX)
+ dsize = UINT_MAX;
+ if (dused > UINT_MAX)
+ dused = UINT_MAX;
(void) smb_encode_mbc(&xa->rep_param_mb, "w", 0);
(void) smb_encode_mbc(&xa->rep_data_mb,
@@ -449,7 +449,7 @@ smb_encode_stream_info(
uint32_t next_offset;
uint32_t stream_nlen;
uint32_t pad;
- off_t dsize;
+ u_offset_t dsize;
int is_dir;
uint32_t cookie = 0;
struct fs_stream_info *stream_info;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
index aa7cc15343..509c4094f0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c
@@ -294,7 +294,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa)
/* NOTREACHED */
}
- max_int = 0xffffffffLL;
+ max_int = (uint64_t)UINT_MAX;
if (df.f_blocks > max_int)
df.f_blocks = max_int;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c
index 1a80d6a2c4..374a6de2bd 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c
@@ -329,7 +329,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa)
{
char *path, *alt_nm_ptr;
int rc;
- off_t dsize, dused;
+ u_offset_t dsize, dused;
unsigned short infolev, dattr;
smb_attr_t *ap, ret_attr;
struct smb_node *dir_node;
@@ -415,10 +415,10 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa)
switch (infolev) {
case SMB_INFO_STANDARD:
- if (dsize > 0xffffffff)
- dsize = 0xffffffff;
- if (dused > 0xffffffff)
- dused = 0xffffffff;
+ if (dsize > UINT_MAX)
+ dsize = UINT_MAX;
+ if (dused > UINT_MAX)
+ dused = UINT_MAX;
(void) smb_encode_mbc(&xa->rep_param_mb, "w", 0);
(void) smb_encode_mbc(&xa->rep_data_mb,
@@ -433,10 +433,10 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa)
break;
case SMB_INFO_QUERY_EA_SIZE:
- if (dsize > 0xffffffff)
- dsize = 0xffffffff;
- if (dused > 0xffffffff)
- dused = 0xffffffff;
+ if (dsize > UINT_MAX)
+ dsize = UINT_MAX;
+ if (dused > UINT_MAX)
+ dused = UINT_MAX;
(void) smb_encode_mbc(&xa->rep_param_mb, "w", 0);
(void) smb_encode_mbc(&xa->rep_data_mb,
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c
index b41e1c426d..8c4368f93f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c
@@ -197,7 +197,7 @@ smb_set_standard_info(
if (DataSize != 0) {
node->flags |= NODE_FLAGS_SET_SIZE;
- node->n_size = DataSize;
+ node->n_size = (u_offset_t)DataSize;
}
/*
@@ -331,7 +331,7 @@ smb_set_alloc_info(
if (node->attr.sa_vattr.va_size != DataSize) {
node->flags |= NODE_FLAGS_SET_SIZE;
- node->n_size = (off_t)DataSize;
+ node->n_size = (u_offset_t)DataSize;
/*
* Ensure that the FS is consistent with the node cache
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 85d663c88c..d17c7dfade 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -164,6 +164,7 @@
* being queued in that list is NOT registered by incrementing the
* reference count.
*/
+#include <sys/fsid.h>
#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_fsops.h>
@@ -243,17 +244,21 @@ smb_tree_connect(
tree->t_acltype = smb_fsop_acltype(snode);
- if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACLONCREATE)) {
+ if (strncasecmp(tree->t_typename, NFS, sizeof (NFS)) == 0)
+ tree->t_flags |= SMB_TREE_FLAG_NFS_MOUNTED;
+
+ if (strncasecmp(tree->t_typename, "UFS", sizeof ("UFS")) == 0)
+ tree->t_flags |= SMB_TREE_FLAG_UFS;
+
+ if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACLONCREATE))
tree->t_flags |= SMB_TREE_FLAG_ACLONCREATE;
- }
- if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACEMASKONACCESS)) {
+ if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_ACEMASKONACCESS))
tree->t_flags |= SMB_TREE_FLAG_ACEMASKONACCESS;
- }
- if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_CASEINSENSITIVE)) {
+ if (vfs_has_feature(snode->vp->v_vfsp, VFSFT_CASEINSENSITIVE))
tree->t_flags |= SMB_TREE_FLAG_IGNORE_CASE;
- }
+
break;
case STYPE_IPC:
diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c
index 420c26a250..fef432d9fc 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c
@@ -75,7 +75,7 @@ smb_com_unlock_byte_range(struct smb_request *sr)
}
result = smb_unlock_range(sr, sr->fid_ofile->f_node,
- (off_t)Offset, (uint64_t)Length);
+ (u_offset_t)Offset, (uint64_t)Length);
if (result != NT_STATUS_SUCCESS) {
smb_unlock_range_raise_error(sr, result);
/* NOT REACHED */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index b71174e9d5..538c9cfc91 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -34,13 +34,15 @@
#include <sys/pathname.h>
#include <sys/cred.h>
#include <sys/extdirent.h>
-#include <acl/acl_common.h>
+
#include <smbsrv/smb_vops.h>
#include <smbsrv/string.h>
-#include <smbsrv/lmshare.h>
+
#include <smbsrv/smbtrans.h>
-#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_fsops.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_incl.h>
+
static int
smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count,
@@ -324,7 +326,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
int
smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
- int flags, cred_t *cr, caller_context_t *ct)
+ int flags, cred_t *cr, boolean_t no_xvattr, caller_context_t *ct)
{
int error = 0;
int at_size = 0;
@@ -350,7 +352,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
set_attr->sa_vattr.va_mask = 0;
- if (vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) {
+ if ((no_xvattr == B_FALSE) &&
+ vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) {
/*
* Initialize xvattr, including bzero
*/
@@ -361,8 +364,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
/*
* Copy caller-specified classic attributes to tmp_xvattr.
- * First save tmp_xvattr's mask (set in xva_init()).
- * This is |'d in later.
+ * First save tmp_xvattr's mask (set in xva_init()), which
+ * contains AT_XVATTR. This is |'d in later if needed.
*/
xva_mask = tmp_xvattr.xva_vattr.va_mask;
@@ -372,12 +375,20 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
&tmp_xvattr.xva_vattr.va_mask);
/*
- * "|" in the original xva_mask.
+ * Do not set ctime (only the file system can do it)
*/
- tmp_xvattr.xva_vattr.va_mask |= xva_mask;
+ tmp_xvattr.xva_vattr.va_mask &= ~AT_CTIME;
if (set_attr->sa_mask & SMB_AT_DOSATTR) {
+
+ /*
+ * "|" in the original xva_mask, which contains
+ * AT_XVATTR
+ */
+
+ tmp_xvattr.xva_vattr.va_mask |= xva_mask;
+
XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE);
XVA_SET_REQ(&tmp_xvattr, XAT_SYSTEM);
XVA_SET_REQ(&tmp_xvattr, XAT_READONLY);
@@ -404,6 +415,12 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
}
if (set_attr->sa_mask & SMB_AT_CRTIME) {
+ /*
+ * "|" in the original xva_mask, which contains
+ * AT_XVATTR
+ */
+
+ tmp_xvattr.xva_vattr.va_mask |= xva_mask;
XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME);
xoap->xoa_createtime = set_attr->sa_crtime;
}
@@ -431,16 +448,12 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags,
cr, ct);
}
-
return (error);
}
-
/*
- * Support for file systems without VFSFT_XVATTR
+ * Support for file systems without VFSFT_XVATTR or no_xvattr == B_TRUE
*/
-
smb_sa_to_va_mask(set_attr->sa_mask, &set_attr->sa_vattr.va_mask);
-
/*
* set_attr->sa_vattr already contains new values
* as set by the caller
@@ -463,7 +476,6 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr,
set_attr->sa_vattr.va_mask = AT_SIZE;
error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, ct);
}
-
return (error);
}
@@ -1538,181 +1550,6 @@ smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr)
}
/*
- * smb_vop_acl_from_vsa
- *
- * Converts given vsecattr_t structure to a acl_t structure.
- *
- * The allocated memory for retuned acl_t should be freed by
- * calling acl_free().
- */
-static acl_t *
-smb_vop_acl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type)
-{
- int aclbsize = 0; /* size of acl list in bytes */
- int dfaclbsize = 0; /* size of default acl list in bytes */
- int numacls;
- acl_t *acl_info;
-
- ASSERT(vsecattr);
-
- acl_info = acl_alloc(acl_type);
- if (acl_info == NULL)
- return (NULL);
-
- acl_info->acl_flags = 0;
-
- switch (acl_type) {
-
- case ACLENT_T:
- numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt;
- aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t);
- dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t);
-
- acl_info->acl_cnt = numacls;
- acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize,
- KM_SLEEP);
- (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
- aclbsize);
- (void) memcpy((char *)acl_info->acl_aclp + aclbsize,
- vsecattr->vsa_dfaclentp, dfaclbsize);
-
- if (acl_info->acl_cnt <= MIN_ACL_ENTRIES)
- acl_info->acl_flags |= ACL_IS_TRIVIAL;
-
- break;
-
- case ACE_T:
- aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
- acl_info->acl_cnt = vsecattr->vsa_aclcnt;
- acl_info->acl_flags = vsecattr->vsa_aclflags;
- acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP);
- (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp,
- aclbsize);
- if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0)
- acl_info->acl_flags |= ACL_IS_TRIVIAL;
-
- break;
-
- default:
- acl_free(acl_info);
- return (NULL);
- }
-
- if (aclbsize && vsecattr->vsa_aclentp)
- kmem_free(vsecattr->vsa_aclentp, aclbsize);
- if (dfaclbsize && vsecattr->vsa_dfaclentp)
- kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize);
-
- return (acl_info);
-}
-
-/*
- * smb_vop_acl_to_vsa
- *
- * Converts given acl_t structure to a vsecattr_t structure.
- *
- * IMPORTANT:
- * Upon successful return the memory allocated for vsa_aclentp
- * should be freed by calling kmem_free(). The size is returned
- * in aclbsize.
- */
-int
-smb_vop_acl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
-{
- int error = 0;
- int numacls;
- aclent_t *aclp;
-
- ASSERT(acl_info);
- ASSERT(vsecattr);
- ASSERT(aclbsize);
-
- bzero(vsecattr, sizeof (vsecattr_t));
- *aclbsize = 0;
-
- switch (acl_info->acl_type) {
- case ACLENT_T:
- numacls = acl_info->acl_cnt;
- /*
- * Minimum ACL size is three entries so might as well
- * bail out here. Also limit request size to prevent user
- * from allocating too much kernel memory. Maximum size
- * is MAX_ACL_ENTRIES for the ACL part and MAX_ACL_ENTRIES
- * for the default ACL part.
- */
- if (numacls < 3 || numacls > (MAX_ACL_ENTRIES * 2)) {
- error = EINVAL;
- break;
- }
-
- vsecattr->vsa_mask = VSA_ACL;
-
- vsecattr->vsa_aclcnt = numacls;
- *aclbsize = numacls * sizeof (aclent_t);
- vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
- (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
- *aclbsize);
-
- /* Sort the acl list */
- ksort((caddr_t)vsecattr->vsa_aclentp,
- vsecattr->vsa_aclcnt, sizeof (aclent_t), cmp2acls);
-
- /* Break into acl and default acl lists */
- for (numacls = 0, aclp = vsecattr->vsa_aclentp;
- numacls < vsecattr->vsa_aclcnt;
- aclp++, numacls++) {
- if (aclp->a_type & ACL_DEFAULT)
- break;
- }
-
- /* Find where defaults start (if any) */
- if (numacls < vsecattr->vsa_aclcnt) {
- vsecattr->vsa_mask |= VSA_DFACL;
- vsecattr->vsa_dfaclcnt = vsecattr->vsa_aclcnt - numacls;
- vsecattr->vsa_dfaclentp = aclp;
- vsecattr->vsa_aclcnt = numacls;
- }
-
- /* Adjust if they're all defaults */
- if (vsecattr->vsa_aclcnt == 0) {
- vsecattr->vsa_mask &= ~VSA_ACL;
- vsecattr->vsa_aclentp = NULL;
- }
-
- /* Only directories can have defaults */
- if (vsecattr->vsa_dfaclcnt &&
- (acl_info->acl_flags & ACL_IS_DIR)) {
- error = ENOTDIR;
- }
-
- break;
-
- case ACE_T:
- if (acl_info->acl_cnt < 1 ||
- acl_info->acl_cnt > MAX_ACL_ENTRIES) {
- error = EINVAL;
- break;
- }
-
- vsecattr->vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
- vsecattr->vsa_aclcnt = acl_info->acl_cnt;
- vsecattr->vsa_aclflags = acl_info->acl_flags & ACL_FLAGS_ALL;
- *aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t);
- vsecattr->vsa_aclentsz = *aclbsize;
- vsecattr->vsa_aclentp = kmem_alloc(*aclbsize, KM_SLEEP);
- (void) memcpy(vsecattr->vsa_aclentp, acl_info->acl_aclp,
- *aclbsize);
-
- break;
-
- default:
- error = EINVAL;
- }
-
- return (error);
-}
-
-/*
* smb_vop_acl_read
*
* Reads the ACL of the specified file into 'aclp'.
@@ -1751,7 +1588,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type,
if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, ct))
return (error);
- *aclp = smb_vop_acl_from_vsa(&vsecattr, acl_type);
+ *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type);
if (vp->v_type == VDIR)
(*aclp)->acl_flags |= ACL_IS_DIR;
@@ -1774,7 +1611,7 @@ smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr,
ASSERT(vp);
ASSERT(aclp);
- error = smb_vop_acl_to_vsa(aclp, &vsecattr, &aclbsize);
+ error = smb_fsacl_to_vsa(aclp, &vsecattr, &aclbsize);
if (error == 0) {
(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_winpipe.c b/usr/src/uts/common/fs/smbsrv/smb_winpipe.c
index 361485783c..cf4c3beda0 100755
--- a/usr/src/uts/common/fs/smbsrv/smb_winpipe.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_winpipe.c
@@ -26,8 +26,7 @@
#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * This file contain routines to initialize the doors interfaces for
- * CIFS winpipe calls.
+ * Winpipe door interface to MSRPC services.
*/
#define START_UPDOOR_SIZE 16384
@@ -46,7 +45,8 @@
#include <sys/uio.h>
-static door_handle_t *smb_winpipe_dh = NULL;
+static door_handle_t smb_winpipe_dh = NULL;
+static int smb_winpipe_door_id = -1;
static uint64_t smb_winpipe_ncall = 0;
static kmutex_t smb_winpipe_mutex;
static kcondvar_t smb_winpipe_cv;
@@ -74,43 +74,41 @@ smb_winpipe_fini(void)
mutex_destroy(&smb_winpipe_mutex);
}
+/*
+ * Open the winpipe (user space) door. If the door is already
+ * open, close it because the door-id has probably changed.
+ * Returns 0 on success. Otherwise -1 to indicate a lookup failure.
+ */
int
-smb_winpipe_open(void)
+smb_winpipe_open(int door_id)
{
- door_handle_t *dh;
- int rc;
+ smb_winpipe_close();
mutex_enter(&smb_winpipe_mutex);
+ smb_winpipe_ncall = 0;
if (smb_winpipe_dh == NULL) {
- dh = kmem_zalloc(sizeof (door_handle_t), KM_SLEEP);
-
- rc = door_ki_open(SMB_WINPIPE_DOOR_UP_PATH, dh);
- if (rc) {
- kmem_free(dh, sizeof (door_handle_t));
- mutex_exit(&smb_winpipe_mutex);
- cmn_err(CE_WARN, "smb_winpipe_open: rc=%d", rc);
- return (-1);
- }
-
- smb_winpipe_ncall = 0;
- smb_winpipe_dh = dh;
+ smb_winpipe_door_id = door_id;
+ smb_winpipe_dh = door_ki_lookup(door_id);
}
mutex_exit(&smb_winpipe_mutex);
- return (0);
+ return ((smb_winpipe_dh == NULL) ? -1 : 0);
}
+/*
+ * Close the winpipe (user space) door.
+ */
void
smb_winpipe_close(void)
{
mutex_enter(&smb_winpipe_mutex);
- while (smb_winpipe_ncall > 0)
- cv_wait(&smb_winpipe_cv, &smb_winpipe_mutex);
+ if (smb_winpipe_dh != NULL) {
+ while (smb_winpipe_ncall > 0)
+ cv_wait(&smb_winpipe_cv, &smb_winpipe_mutex);
- if (smb_winpipe_dh) {
- kmem_free(smb_winpipe_dh, sizeof (door_handle_t));
+ door_ki_rele(smb_winpipe_dh);
smb_winpipe_dh = NULL;
}
@@ -140,7 +138,9 @@ smb_winpipe_call(struct smb_request *sr,
if (smb_winpipe_dh == NULL) {
mutex_exit(&smb_winpipe_mutex);
- return (-1);
+
+ if (smb_winpipe_open(smb_winpipe_door_id) != 0)
+ return (-1);
}
++smb_winpipe_ncall;
@@ -284,7 +284,7 @@ smb_winpipe_upcall(mlsvc_pipe_t *pipe_info,
da.rbuf = (char *)lbuf;
da.rsize = START_UPDOOR_SIZE;
- if (door_ki_upcall(*smb_winpipe_dh, &da) != 0) {
+ if (door_ki_upcall(smb_winpipe_dh, &da) != 0) {
return (-1);
}
/* RPC_WRITE just queues the data and returns */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c
index e6874397b4..93b9f6e758 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_write.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_write.c
@@ -84,7 +84,7 @@ smb_com_write(struct smb_request *sr)
}
param->w_offset = (uint64_t)off;
- param->w_vdb.uio.uio_offset = param->w_offset;
+ param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset;
if (param->w_count == 0) {
rc = smb_write_truncate(sr, param);
@@ -97,7 +97,7 @@ smb_com_write(struct smb_request *sr)
/* NOTREACHED */
}
- param->w_vdb.uio.uio_offset = param->w_offset;
+ param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset;
rc = smb_write_common(sr, param);
}
@@ -173,7 +173,7 @@ smb_com_write_and_close(struct smb_request *sr)
/* NOTREACHED */
}
- param->w_vdb.uio.uio_offset = param->w_offset;
+ param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset;
rc = smb_write_common(sr, param);
}
@@ -255,7 +255,7 @@ smb_com_write_and_unlock(struct smb_request *sr)
}
param->w_offset = (uint64_t)off;
- param->w_vdb.uio.uio_offset = (off_t)param->w_offset;
+ param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset;
if ((rc = smb_write_common(sr, param)) != 0) {
kmem_free(param, sizeof (smb_write_param_t));
@@ -344,7 +344,7 @@ smb_com_write_andx(struct smb_request *sr)
/* NOTREACHED */
}
- param->w_vdb.uio.uio_offset = param->w_offset;
+ param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset;
if (param->w_count != 0) {
if ((rc = smb_write_common(sr, param)) != 0) {