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 52421264e71e..d6625ed58a1d 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 d7ea83166390..5368aa7fcc03 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 e04a6e30e693..b54549eebbeb 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 ac93f2f70e88..fa2ee7fdd44e 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'/> + 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 56cab5ca8a10..8d6eb04683c2 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 cfecd0e944a5..45b0e79c44e8 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 99404484e661..c593a5217830 100644 --- a/usr/src/man/man4/smb.4 +++ b/usr/src/man/man4/smb.4 @@ -56,6 +56,22 @@ Specifies the full path for the SMD autohome map file, \fBsmbautohome\fR. The default path is \fB/etc\fR. .RE +.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 diff --git a/usr/src/uts/common/fs/smbsrv/smb_authenticate.c b/usr/src/uts/common/fs/smbsrv/smb_authenticate.c index a5d0bad335ae..af9f5d271f7d 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 c6956518fc05..f47f5e72a5b2 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 7011ac6dbebb..09e52b70f75c 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