diff options
author | Gordon Ross <gwr@nexenta.com> | 2017-01-21 18:02:35 -0500 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2019-08-10 10:05:21 -0400 |
commit | cc3780e66ce1eea52e650b27b7dc5ad62d24eec2 (patch) | |
tree | 5721eddec5921b9b7058cd8ceeb9c766fa4a263e /usr/src | |
parent | 3e2c0c0978d26f8b8020b49760008c6bb6e59221 (diff) | |
download | illumos-gate-cc3780e66ce1eea52e650b27b7dc5ad62d24eec2.tar.gz |
11024 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Approved by: Garrett D'Amore <garrett@damore.org>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/smbfs/smbfs.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c | 37 | ||||
-rw-r--r-- | usr/src/cmd/smbsrv/smbd/server.xml | 2 | ||||
-rw-r--r-- | usr/src/lib/libshare/smb/libshare_smb.c | 2 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c | 10 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/libsmb.h | 1 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/smb_cfg.c | 2 | ||||
-rw-r--r-- | usr/src/man/man4/smb.4 | 16 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_authenticate.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbsrv/smb_cred.c | 17 | ||||
-rw-r--r-- | usr/src/uts/common/smbsrv/smb_ktypes.h | 13 |
12 files changed, 97 insertions, 24 deletions
diff --git a/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c b/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c index 52421264e7..d6625ed58a 100644 --- a/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c +++ b/usr/src/cmd/mdb/common/modules/libmlsvc/smb_ht.c @@ -42,7 +42,7 @@ smb_ht_walk_init(mdb_walk_state_t *wsp) uintptr_t addr = wsp->walk_addr; HT_HANDLE *ht; - if (addr == (uintptr_t)NULL) { + if (addr == 0) { mdb_printf("require address of an HT_HANDLE\n"); return (WALK_ERR); } @@ -63,7 +63,7 @@ smb_ht_walk_init(mdb_walk_state_t *wsp) } hw->hw_idx = -1; - wsp->walk_addr = (uintptr_t)NULL; + wsp->walk_addr = 0; wsp->walk_data = hw; return (WALK_NEXT); @@ -78,7 +78,7 @@ smb_ht_walk_step(mdb_walk_state_t *wsp) uintptr_t he_addr; int rv; - while (wsp->walk_addr == (uintptr_t)NULL) { + while (wsp->walk_addr == 0) { if (++hw->hw_idx >= hw->hw_handle.ht_table_size) return (WALK_DONE); he_addr = (uintptr_t)hw->hw_handle.ht_table + diff --git a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c index d7ea831663..5368aa7fcc 100644 --- a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c +++ b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c @@ -281,7 +281,7 @@ static const mdb_dcmd_t dcmds[] = { int vfs_walk_init(mdb_walk_state_t *wsp) { - if (wsp->walk_addr == (uintptr_t)NULL && + if (wsp->walk_addr == 0 && mdb_readvar(&wsp->walk_addr, "rootvfs") == -1) { mdb_warn("failed to read 'rootvfs'"); return (WALK_ERR); diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c index e04a6e30e6..b54549eebb 100644 --- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c +++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c @@ -1382,6 +1382,21 @@ user_flag_bits[] = { static const mdb_bitmask_t user_priv_bits[] = { + /* + * Old definitions of these bits, for when we're + * looking at an older core file. These happen to + * have no overlap with the current definitions. + */ + { "TAKE_OWNER", 1, 1 }, + { "BACKUP", 2, 2 }, + { "RESTORE", 4, 4 }, + { "SECURITY", 8, 8 }, + /* + * Current definitions + */ + { "SECURITY", + SMB_USER_PRIV_SECURITY, + SMB_USER_PRIV_SECURITY }, { "TAKE_OWNER", SMB_USER_PRIV_TAKE_OWNERSHIP, SMB_USER_PRIV_TAKE_OWNERSHIP }, @@ -1391,9 +1406,9 @@ user_priv_bits[] = { { "RESTORE", SMB_USER_PRIV_RESTORE, SMB_USER_PRIV_RESTORE }, - { "SECURITY", - SMB_USER_PRIV_SECURITY, - SMB_USER_PRIV_SECURITY }, + { "CHANGE_NOTIFY", + SMB_USER_PRIV_CHANGE_NOTIFY, + SMB_USER_PRIV_CHANGE_NOTIFY }, { NULL, 0, 0 } }; @@ -1940,7 +1955,7 @@ smb_hash_walk_init(mdb_walk_state_t *wsp) int ll_off, sll_off, i; uintptr_t addr = wsp->walk_addr; - if (addr == (uintptr_t)NULL) { + if (addr == 0) { mdb_printf("require address of an smb_hash_t\n"); return (WALK_ERR); } @@ -2029,7 +2044,7 @@ smb_hashstat_walk_init(mdb_walk_state_t *wsp) uint32_t arr_sz; smb_hash_wd_t *wd; - if (addr == (uintptr_t)NULL) { + if (addr == 0) { mdb_printf("require address of an smb_hash_t\n"); return (WALK_ERR); } @@ -2284,7 +2299,7 @@ smb_kshare_walk_init(mdb_walk_state_t *wsp) { int sv_exp_off, ex_sha_off, avl_tr_off; - if (wsp->walk_addr == (uintptr_t)NULL) { + if (wsp->walk_addr == 0) { mdb_printf("require address of an smb_server_t\n"); return (WALK_ERR); } @@ -2417,7 +2432,7 @@ smb_vfs_walk_init(mdb_walk_state_t *wsp) { int sv_exp_off, ex_vfs_off, ll_off; - if (wsp->walk_addr == (uintptr_t)NULL) { + if (wsp->walk_addr == 0) { mdb_printf("require address of an smb_server_t\n"); return (WALK_ERR); } @@ -2751,7 +2766,7 @@ smb_node_walk_init(mdb_walk_state_t *wsp) int ll_off; int i; - if (wsp->walk_addr == (uintptr_t)NULL) { + if (wsp->walk_addr == 0) { if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_node_hash_table", &sym) == -1) { mdb_warn("failed to find 'smb_node_hash_table'"); @@ -3227,7 +3242,7 @@ smb_mbuf_walk_init(mdb_walk_state_t *wsp) { mbuf_t *m; - if (wsp->walk_addr == (uintptr_t)NULL) { + if (wsp->walk_addr == 0) { mdb_printf("require address of an mbuf_t\n"); return (WALK_ERR); } @@ -3243,7 +3258,7 @@ smb_mbuf_walk_step(mdb_walk_state_t *wsp) mbuf_t *m = wsp->walk_data; int rc; - if (wsp->walk_addr == (uintptr_t)NULL) + if (wsp->walk_addr == 0) return (WALK_DONE); if (mdb_vread(m, sizeof (*m), addr) == -1) { @@ -3369,7 +3384,7 @@ smb_ace_walk_init(mdb_walk_state_t *wsp) { int sal_off; - if (wsp->walk_addr == (uintptr_t)NULL) { + if (wsp->walk_addr == 0) { mdb_printf("smb_ace walk only supports local walks\n"); return (WALK_ERR); } diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml index ac93f2f70e..fa2ee7fdd4 100644 --- a/usr/src/cmd/smbsrv/smbd/server.xml +++ b/usr/src/cmd/smbsrv/smbd/server.xml @@ -157,6 +157,8 @@ file. value='true' override='true'/> <propval name='autohome_map' type='astring' value='/etc' override='true'/> + <propval name='bypass_traverse_checking' type='boolean' + value='true' override='true'/> <propval name='debug' type='integer' value='0' override='true'/> <propval name='domain_sid' type='astring' diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index 6a0ad97b7f..e15bb26d9a 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -924,6 +924,8 @@ struct smb_proto_option_defs { SMB_REFRESH_REFRESH }, { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator, SMB_REFRESH_REFRESH }, + { SMB_CI_BYPASS_TRAVERSE_CHECKING, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, { SMB_CI_OPLOCK_ENABLE, 0, 0, true_false_validator, SMB_REFRESH_REFRESH }, }; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c index 3902e58a46..ea9aca4733 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c @@ -328,6 +328,16 @@ smb_token_create_privs(smb_token_t *token) smb_privset_enable(privs, SE_SECURITY_LUID); } + /* + * Members of "Authenticated Users" (!anon) should normally get + * "Bypass traverse checking" privilege, though we allow this + * to be disabled (see smb.4). For historical reasons, the + * internal privilege name is "SeChangeNotifyPrivilege". + */ + if ((token->tkn_flags & SMB_ATF_ANON) == 0 && + smb_config_getbool(SMB_CI_BYPASS_TRAVERSE_CHECKING)) + smb_privset_enable(privs, SE_CHANGE_NOTIFY_LUID); + return (privs); } diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 56cab5ca8a..8d6eb04683 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -159,6 +159,7 @@ typedef enum { SMB_CI_MAX_PROTOCOL, SMB_CI_ENCRYPT, SMB_CI_MIN_PROTOCOL, + SMB_CI_BYPASS_TRAVERSE_CHECKING, SMB_CI_MAX } smb_cfg_id_t; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index cfecd0e944..45b0e79c44 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -148,6 +148,8 @@ static smb_cfg_param_t smb_cfg_table[] = {SMB_CI_MAX_PROTOCOL, "max_protocol", SCF_TYPE_ASTRING, 0}, {SMB_CI_ENCRYPT, "encrypt", SCF_TYPE_ASTRING, 0}, {SMB_CI_MIN_PROTOCOL, "min_protocol", SCF_TYPE_ASTRING, 0}, + {SMB_CI_BYPASS_TRAVERSE_CHECKING, + "bypass_traverse_checking", SCF_TYPE_BOOLEAN, 0}, /* SMB_CI_MAX */ }; diff --git a/usr/src/man/man4/smb.4 b/usr/src/man/man4/smb.4 index 99404484e6..c593a52178 100644 --- a/usr/src/man/man4/smb.4 +++ b/usr/src/man/man4/smb.4 @@ -59,6 +59,22 @@ default path is \fB/etc\fR. .sp .ne 2 .na +\fB\fBbypass_traverse_checking\fR\fR +.ad +.sp .6 +.RS 4n +When set, allows the SMB server to bypass ACL "traverse" checks. +The default value is \fBtrue\fR, for Windows compatibility. +If this parameter is \fBfalse\fR, ACL checks require that +"traverse" (directory execute) is granted on every directory +above the directory the SMB client tries to access. +Windows shares are normally setup with the higher level +directories not specifically granting such access. +.RE + +.sp +.ne 2 +.na \fB\fBdisposition\fR\fR .ad .sp .6 diff --git a/usr/src/uts/common/fs/smbsrv/smb_authenticate.c b/usr/src/uts/common/fs/smbsrv/smb_authenticate.c index a5d0bad335..af9f5d271f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_authenticate.c +++ b/usr/src/uts/common/fs/smbsrv/smb_authenticate.c @@ -529,17 +529,20 @@ smb_priv_xlate(smb_token_t *token) { uint32_t privileges = 0; + if (smb_token_query_privilege(token, SE_SECURITY_LUID)) + privileges |= SMB_USER_PRIV_SECURITY; + + if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) + privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; + if (smb_token_query_privilege(token, SE_BACKUP_LUID)) privileges |= SMB_USER_PRIV_BACKUP; if (smb_token_query_privilege(token, SE_RESTORE_LUID)) privileges |= SMB_USER_PRIV_RESTORE; - if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) - privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; - - if (smb_token_query_privilege(token, SE_SECURITY_LUID)) - privileges |= SMB_USER_PRIV_SECURITY; + if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID)) + privileges |= SMB_USER_PRIV_CHANGE_NOTIFY; return (privileges); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_cred.c b/usr/src/uts/common/fs/smbsrv/smb_cred.c index c6956518fc..f47f5e72a5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_cred.c +++ b/usr/src/uts/common/fs/smbsrv/smb_cred.c @@ -49,6 +49,11 @@ static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps); * If the mapped UID is ephemeral, or the primary group could not be * obtained, the cred gid is set to whatever Solaris group is mapped * to the token's primary group. + * + * Also add any privileges that should always be in effect for this user. + * Note that an SMB user object also gets a u_privcred which is used + * when the client opens an object with "backup/restore intent". + * That cred is setup later, in smb_user_setcred(). */ cred_t * smb_cred_create(smb_token_t *token) @@ -109,6 +114,18 @@ smb_cred_create(smb_token_t *token) NULL); } + /* + * See smb.4 bypass_traverse_checking + * + * For historical reasons, the Windows privilege is named + * SeChangeNotifyPrivilege, though the description is + * "Bypass traverse checking". + */ + if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID)) { + (void) crsetpriv(cr, PRIV_FILE_DAC_SEARCH, NULL); + } + + return (cr); } diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 7011ac6dbe..09e52b70f7 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -1008,10 +1008,15 @@ typedef struct smb_session { #define SMB_USER_IS_ADMIN(U) (((U)->u_flags & SMB_USER_FLAG_ADMIN) != 0) #define SMB_USER_IS_GUEST(U) (((U)->u_flags & SMB_USER_FLAG_GUEST) != 0) -#define SMB_USER_PRIV_TAKE_OWNERSHIP 0x00000001 -#define SMB_USER_PRIV_BACKUP 0x00000002 -#define SMB_USER_PRIV_RESTORE 0x00000004 -#define SMB_USER_PRIV_SECURITY 0x00000008 +/* + * Internal privilege flags derived from smb_privilege.h numbers + * Would rather not include that in this file. + */ +#define SMB_USER_PRIV_SECURITY (1<<8) /* SE_SECURITY_LUID */ +#define SMB_USER_PRIV_TAKE_OWNERSHIP (1<<9) /* SE_TAKE_OWNERSHIP_LUID */ +#define SMB_USER_PRIV_BACKUP (1<<17) /* SE_BACKUP_LUID */ +#define SMB_USER_PRIV_RESTORE (1<<18) /* SE_RESTORE_LUID */ +#define SMB_USER_PRIV_CHANGE_NOTIFY (1<<23) /* SE_CHANGE_NOTIFY_LUID */ /* * See the long "User State Machine" comment in smb_user.c |