summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Barden <matt.barden@nexenta.com>2019-12-16 17:26:34 -0500
committerGordon Ross <gordon.ross@tintri.com>2021-01-30 14:02:54 -0500
commit9e3ab9e9117808af4e738ea3ac45888be11e4045 (patch)
treef0bdc9fcc8ec00a108d592d479624d0707e3ee54
parent0a73e6f973645e207d33a7012fed997991b4e531 (diff)
downloadillumos-joyent-9e3ab9e9117808af4e738ea3ac45888be11e4045.tar.gz
13442 SMB server should try harder to protect SACLs
Reviewed by: Evan Layton <elayton@tintri.com> Reviewed by: Gordon Ross <gordon.ross@tintri.com> Reviewed by: Roman Strashkin <rstrashkin@tintri.com> Reviewed by: Andy Fiddaman <andy@omnios.org> Approved by: Robert Mustacchi <rm@fingolfin.org>
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c13
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_user.c41
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h1
4 files changed, 58 insertions, 5 deletions
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 24dda9a79d..454d48364c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
*/
/*
@@ -938,6 +938,12 @@ create:
goto errout;
}
+ if ((op->desired_access & ACCESS_SYSTEM_SECURITY) != 0 &&
+ !smb_user_has_security_priv(sr->uid_user, sr->user_cr)) {
+ status = NT_STATUS_ACCESS_DENIED;
+ goto errout;
+ }
+
if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
status = NT_STATUS_OBJECT_NAME_INVALID;
goto errout;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 148f4ed6f9..4325d75282 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -506,6 +506,10 @@ smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
*/
secinfo = smb_sd_get_secinfo(op->sd);
+ if ((secinfo & SMB_SACL_SECINFO) != 0 &&
+ !smb_user_has_security_priv(sr->uid_user, cr))
+ return (EPERM);
+
smb_fssd_init(&fs_sd, secinfo, 0);
status = smb_sd_tofs(op->sd, &fs_sd);
@@ -652,6 +656,10 @@ smb_fsop_mkdir(
*/
secinfo = smb_sd_get_secinfo(op->sd);
+ if ((secinfo & SMB_SACL_SECINFO) != 0 &&
+ !smb_user_has_security_priv(sr->uid_user, cr))
+ return (EPERM);
+
smb_fssd_init(&fs_sd, secinfo, SMB_FSSD_FLAGS_DIR);
status = smb_sd_tofs(op->sd, &fs_sd);
@@ -1735,10 +1743,7 @@ smb_fsop_access(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
* it's not part of DACL. It's only granted via proper
* privileges.
*/
- if ((sr->uid_user->u_privileges &
- (SMB_USER_PRIV_BACKUP |
- SMB_USER_PRIV_RESTORE |
- SMB_USER_PRIV_SECURITY)) == 0)
+ if (!smb_user_has_security_priv(sr->uid_user, cr))
return (NT_STATUS_PRIVILEGE_NOT_HELD);
faccess &= ~ACCESS_SYSTEM_SECURITY;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c
index b46cad1b6f..332c6bc67d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_user.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_user.c
@@ -205,6 +205,8 @@
#include <sys/types.h>
#include <sys/sid.h>
#include <sys/priv_names.h>
+#include <sys/priv.h>
+#include <sys/policy.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_door.h>
@@ -831,6 +833,45 @@ smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
#endif /* _KERNEL */
/*
+ * Determines whether a user can be granted ACCESS_SYSTEM_SECURITY
+ */
+boolean_t
+smb_user_has_security_priv(smb_user_t *user, cred_t *cr)
+{
+ /* Need SeSecurityPrivilege to get/set SACL */
+ if ((user->u_privileges & SMB_USER_PRIV_SECURITY) != 0)
+ return (B_TRUE);
+
+#ifdef _KERNEL
+ /*
+ * ACCESS_SYSTEM_SECURITY is also granted if the file is opened with
+ * BACKUP/RESTORE intent by a user with BACKUP/RESTORE privilege,
+ * which means we'll be using u_privcred.
+ *
+ * We translate BACKUP as DAC_READ and RESTORE as DAC_WRITE,
+ * to account for our various SMB_USER_* privileges.
+ */
+ if (PRIV_POLICY_ONLY(cr,
+ priv_getbyname(PRIV_FILE_DAC_READ, 0), B_FALSE) ||
+ PRIV_POLICY_ONLY(cr,
+ priv_getbyname(PRIV_FILE_DAC_WRITE, 0), B_FALSE))
+ return (B_TRUE);
+#else
+ /*
+ * No "real" privileges in fksmbsrv, so use the SMB privs instead.
+ */
+ if ((user->u_privileges &
+ (SMB_USER_PRIV_BACKUP |
+ SMB_USER_PRIV_RESTORE |
+ SMB_USER_PRIV_READ_FILE |
+ SMB_USER_PRIV_WRITE_FILE)) != 0)
+ return (B_TRUE);
+#endif
+
+ return (B_FALSE);
+}
+
+/*
* Private function to support smb_user_enum.
*/
static int
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index 504cfc1ade..8bffe1b36a 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -739,6 +739,7 @@ cred_t *smb_cred_create(smb_token_t *);
cred_t *smb_kcred_create(void);
void smb_user_setcred(smb_user_t *, cred_t *, uint32_t);
boolean_t smb_is_same_user(cred_t *, cred_t *);
+boolean_t smb_user_has_security_priv(smb_user_t *, cred_t *);
/*
* SMB tree functions (file smb_tree.c)