diff options
Diffstat (limited to 'usr/src')
21 files changed, 648 insertions, 561 deletions
diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c index 83ffae0634..eaa381cc47 100644 --- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c +++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c @@ -688,9 +688,12 @@ static const smb_exp_t smb_session_exp[] = { SMB_OPT_REQUEST, offsetof(smb_session_t, s_req_list.sl_list), "smbreq", "smb_request"}, - { SMB_OPT_USER | SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, + { SMB_OPT_USER, offsetof(smb_session_t, s_user_list.ll_list), "smbuser", "smb_user"}, + { SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, + offsetof(smb_session_t, s_tree_list.ll_list), + "smbtree", "smb_tree"}, { 0, 0, NULL, NULL} }; @@ -963,17 +966,6 @@ static const char *smb_user_state[SMB_USER_STATE_SENTINEL] = "LOGGED_OFF" }; -/* - * List of objects that can be expanded under a user structure. - */ -static const smb_exp_t smb_user_exp[] = -{ - { SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR, - offsetof(smb_user_t, u_tree_list.ll_list), - "smbtree", "smb_tree"}, - { 0, 0, NULL, NULL} -}; - static void smb_dcmd_user_help(void) { @@ -983,17 +975,13 @@ smb_dcmd_user_help(void) mdb_printf("%<b>OPTIONS%</b>\n"); (void) mdb_inc_indent(2); mdb_printf( - "-v\tDisplay verbose smb_user information\n" - "-d\tDisplay the list of smb_odirs attached\n" - "-f\tDisplay the list of smb_ofiles attached\n" - "-t\tDisplay the list of smb_trees attached\n"); + "-v\tDisplay verbose smb_user information\n"); } static int smb_dcmd_user(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { uint_t opts; - ulong_t indent = 0; if (smb_dcmd_getopt(&opts, argc, argv)) return (DCMD_USAGE); @@ -1009,8 +997,6 @@ smb_dcmd_user(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) smb_user_t *user; char *account; - indent = SMB_DCMD_INDENT; - user = mdb_alloc(sizeof (*user), UM_SLEEP | UM_GC); if (mdb_vread(user, sizeof (*user), addr) == -1) { mdb_warn("failed to read smb_user at %p", addr); @@ -1058,8 +1044,6 @@ smb_dcmd_user(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) account); } } - if (smb_obj_expand(addr, opts, smb_user_exp, indent)) - return (DCMD_ERR); return (DCMD_OK); } @@ -1217,6 +1201,8 @@ smb_dcmd_odir(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) addr); mdb_printf("State: %d (%s)\n", od->d_state, state); mdb_printf("SID: %u\n", od->d_odid); + mdb_printf("User: %p\n", od->d_user); + mdb_printf("Tree: %p\n", od->d_tree); mdb_printf("Reference Count: %d\n", od->d_refcnt); mdb_printf("Pattern: %s\n", od->d_pattern); mdb_printf("SMB Node: %p\n\n", od->d_dnode); @@ -1292,6 +1278,8 @@ smb_dcmd_ofile(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) ((of->f_flags & SMB_OFLAGS_LLF_POS_VALID) ? "Valid" : "Invalid")); mdb_printf("Flags: 0x%08x\n", of->f_flags); + mdb_printf("User: %p\n", of->f_user); + mdb_printf("Tree: %p\n", of->f_tree); mdb_printf("Credential: %p\n\n", of->f_cr); } else { if (DCMD_HDRSPEC(flags)) 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 3fa43d43cb..5eaa5865c6 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c @@ -820,8 +820,8 @@ smb_open_subr(smb_request_t *sr) status = NT_STATUS_SUCCESS; - of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK, - uniq_fid, &err); + of = smb_ofile_open(sr, node, sr->smb_pid, op, SMB_FTYPE_DISK, uniq_fid, + &err); if (of == NULL) { smbsr_error(sr, err.status, err.errcls, err.errcode); status = err.status; diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c index 4930f741ef..14eff73896 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c @@ -297,7 +297,7 @@ smb_delete_multiple_files(smb_request_t *sr, smb_error_t *err) if (odid == 0) return (-1); - if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL) + if ((od = smb_tree_lookup_odir(sr, odid)) == NULL) return (-1); for (;;) { diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c index 1afcf18b28..9b1fed6f9a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c @@ -20,8 +20,8 @@ */ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -694,16 +694,13 @@ andx_more: } sr->user_cr = smb_user_getcred(sr->uid_user); - - if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) && - (sr->tid_tree == NULL)) { - sr->tid_tree = smb_user_lookup_tree( - sr->uid_user, sr->smb_tid); - if (sr->tid_tree == NULL) { - smbsr_error(sr, 0, ERRSRV, ERRinvnid); - smbsr_cleanup(sr); - goto report_error; - } + } + if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) && (sr->tid_tree == NULL)) { + sr->tid_tree = smb_session_lookup_tree(session, sr->smb_tid); + if (sr->tid_tree == NULL) { + smbsr_error(sr, 0, ERRSRV, ERRinvnid); + smbsr_cleanup(sr); + goto report_error; } } @@ -1116,8 +1113,7 @@ void smbsr_lookup_file(smb_request_t *sr) { if (sr->fid_ofile == NULL) - sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, - sr->smb_fid); + sr->fid_ofile = smb_ofile_lookup_by_fid(sr, sr->smb_fid); } static int diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c index 1dae4e8cb5..eecbeff4df 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find.c @@ -306,7 +306,7 @@ smb_com_search(smb_request_t *sr) } } - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); @@ -452,7 +452,7 @@ smb_com_find(smb_request_t *sr) } } - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); @@ -575,7 +575,7 @@ smb_com_find_close(smb_request_t *sr) return (SDRC_ERROR); } - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); @@ -649,7 +649,7 @@ smb_com_find_unique(struct smb_request *sr) odid = smb_odir_open(sr, pn->pn_path, sattr, 0); if (odid == 0) return (SDRC_ERROR); - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) return (SDRC_ERROR); diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index 2f4545e966..c64313fdbf 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -805,7 +805,7 @@ smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode) return (-1); } - if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL) { + if ((od = smb_tree_lookup_odir(sr, odid)) == NULL) { smbsr_errno(sr, ENOENT); return (-1); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c index c77c175fc1..037c1373b5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c @@ -264,8 +264,7 @@ smb_com_nt_create_andx(struct smb_request *sr) if (op->rootdirfid == 0) { op->fqi.fq_dnode = sr->tid_tree->t_snode; } else { - op->dir = smb_ofile_lookup_by_fid(sr->tid_tree, - (uint16_t)op->rootdirfid); + op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid); if (op->dir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 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 fcc12f2fc8..dcfa469617 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 @@ -173,8 +173,7 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) if (op->rootdirfid == 0) { op->fqi.fq_dnode = sr->tid_tree->t_snode; } else { - op->dir = smb_ofile_lookup_by_fid(sr->tid_tree, - (uint16_t)op->rootdirfid); + op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid); if (op->dir == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c index b8435d191a..16fffa6692 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_odir.c +++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c @@ -39,15 +39,15 @@ * +-------------------+ +-------------------+ +-------------------+ * | SESSION |<----->| SESSION |......| SESSION | * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v - * +-------------------+ +-------------------+ +-------------------+ - * | USER |<----->| USER |......| USER | - * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v + * | | + * | | + * | v + * | +-------------------+ +-------------------+ +-------------------+ + * | | USER |<--->| USER |...| USER | + * | +-------------------+ +-------------------+ +-------------------+ + * | + * | + * v * +-------------------+ +-------------------+ +-------------------+ * | TREE |<----->| TREE |......| TREE | * +-------------------+ +-------------------+ +-------------------+ @@ -153,7 +153,7 @@ * and add it into the tree's list of odirs. * Return an identifier (odid) uniquely identifying the created odir. * - * smb_odir_t *odir = smb_tree_lookup_odir(odid) + * smb_odir_t *odir = smb_tree_lookup_odir(..., odid) * Find the odir corresponding to the specified odid in the tree's * list of odirs. Place a hold on the odir. * @@ -312,9 +312,9 @@ smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags) } if (flags & SMB_ODIR_OPENF_BACKUP_INTENT) - cr = smb_user_getprivcred(tree->t_user); + cr = smb_user_getprivcred(sr->uid_user); else - cr = tree->t_user->u_cred; + cr = sr->uid_user->u_cred; odid = smb_odir_create(sr, dnode, pattern, sattr, cr); smb_node_release(dnode); @@ -888,6 +888,12 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode, od->d_opened_by_pid = sr->smb_pid; od->d_session = tree->t_session; od->d_cred = cr; + /* + * grab a ref for od->d_user + * released in smb_odir_delete() + */ + smb_user_hold_internal(sr->uid_user); + od->d_user = sr->uid_user; od->d_tree = tree; od->d_dnode = dnode; smb_node_ref(dnode); @@ -947,6 +953,7 @@ smb_odir_delete(void *arg) od->d_magic = 0; smb_node_release(od->d_dnode); + smb_user_release(od->d_user); mutex_destroy(&od->d_mutex); kmem_cache_free(od->d_tree->t_server->si_cache_odir, od); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index 8987da2950..ee45f13c8b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -39,15 +39,15 @@ * +-------------------+ +-------------------+ +-------------------+ * | SESSION |<----->| SESSION |......| SESSION | * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v - * +-------------------+ +-------------------+ +-------------------+ - * | USER |<----->| USER |......| USER | - * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v + * | | + * | | + * | v + * | +-------------------+ +-------------------+ +-------------------+ + * | | USER |<--->| USER |...| USER | + * | +-------------------+ +-------------------+ +-------------------+ + * | + * | + * v * +-------------------+ +-------------------+ +-------------------+ * | TREE |<----->| TREE |......| TREE | * +-------------------+ +-------------------+ +-------------------+ @@ -175,7 +175,7 @@ static void smb_ofile_netinfo_fini(smb_netfileinfo_t *); */ smb_ofile_t * smb_ofile_open( - smb_tree_t *tree, + smb_request_t *sr, smb_node_t *node, uint16_t pid, struct open_param *op, @@ -183,10 +183,13 @@ smb_ofile_open( uint32_t uniqid, smb_error_t *err) { + smb_tree_t *tree = sr->tid_tree; smb_ofile_t *of; uint16_t fid; smb_attr_t attr; int rc; + enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT }; + enum errstates state = EMPTY; if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) { err->status = NT_STATUS_TOO_MANY_OPENED_FILES; @@ -194,6 +197,7 @@ smb_ofile_open( err->errcode = ERROR_TOO_MANY_OPEN_FILES; return (NULL); } + state = FIDALLOC; of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP); bzero(of, sizeof (smb_ofile_t)); @@ -206,16 +210,23 @@ smb_ofile_open( of->f_share_access = op->share_access; of->f_create_options = op->create_options; of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ? - smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred; + smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred; crhold(of->f_cr); + state = CRHELD; of->f_ftype = ftype; of->f_server = tree->t_server; - of->f_session = tree->t_user->u_session; - of->f_user = tree->t_user; + of->f_session = tree->t_session; + /* + * grab a ref for of->f_user + * released in smb_ofile_delete() + */ + smb_user_hold_internal(sr->uid_user); + of->f_user = sr->uid_user; of->f_tree = tree; of->f_node = node; mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL); + state = MUTEXINIT; of->f_state = SMB_OFILE_STATE_OPEN; if (ftype == SMB_FTYPE_MESG_PIPE) { @@ -232,15 +243,10 @@ smb_ofile_open( attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR; rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr); if (rc != 0) { - of->f_magic = 0; - mutex_destroy(&of->f_mutex); - crfree(of->f_cr); - smb_idpool_free(&tree->t_fid_pool, of->f_fid); - kmem_cache_free(tree->t_server->si_cache_ofile, of); err->status = NT_STATUS_INTERNAL_ERROR; err->errcls = ERRDOS; err->errcode = ERROR_INTERNAL_ERROR; - return (NULL); + goto errout; } if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) { /* @@ -254,16 +260,10 @@ smb_ofile_open( of->f_mode = smb_fsop_amask_to_omode(of->f_granted_access); if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { - of->f_magic = 0; - mutex_destroy(&of->f_mutex); - crfree(of->f_cr); - smb_idpool_free(&tree->t_fid_pool, of->f_fid); - kmem_cache_free(tree->t_server->si_cache_ofile, - of); err->status = NT_STATUS_ACCESS_DENIED; err->errcls = ERRDOS; err->errcode = ERROR_ACCESS_DENIED; - return (NULL); + goto errout; } } @@ -290,6 +290,25 @@ smb_ofile_open( atomic_inc_32(&tree->t_open_files); atomic_inc_32(&of->f_session->s_file_cnt); return (of); + +errout: + switch (state) { + case MUTEXINIT: + mutex_destroy(&of->f_mutex); + smb_user_release(of->f_user); + /*FALLTHROUGH*/ + case CRHELD: + crfree(of->f_cr); + of->f_magic = 0; + kmem_cache_free(tree->t_server->si_cache_ofile, of); + /*FALLTHROUGH*/ + case FIDALLOC: + smb_idpool_free(&tree->t_fid_pool, fid); + /*FALLTHROUGH*/ + case EMPTY: + break; + } + return (NULL); } /* @@ -601,9 +620,10 @@ smb_ofile_request_complete(smb_ofile_t *of) */ smb_ofile_t * smb_ofile_lookup_by_fid( - smb_tree_t *tree, + smb_request_t *sr, uint16_t fid) { + smb_tree_t *tree = sr->tid_tree; smb_llist_t *of_list; smb_ofile_t *of; @@ -616,19 +636,32 @@ smb_ofile_lookup_by_fid( while (of) { ASSERT(of->f_magic == SMB_OFILE_MAGIC); ASSERT(of->f_tree == tree); - if (of->f_fid == fid) { - mutex_enter(&of->f_mutex); - if (of->f_state != SMB_OFILE_STATE_OPEN) { - mutex_exit(&of->f_mutex); - smb_llist_exit(of_list); - return (NULL); - } - of->f_refcnt++; - mutex_exit(&of->f_mutex); + if (of->f_fid == fid) break; - } of = smb_llist_next(of_list, of); } + if (of == NULL) + goto out; + + /* + * Only allow use of a given FID with the same UID that + * was used to open it. MS-CIFS 3.3.5.14 + */ + if (of->f_user != sr->uid_user) { + of = NULL; + goto out; + } + + mutex_enter(&of->f_mutex); + if (of->f_state != SMB_OFILE_STATE_OPEN) { + mutex_exit(&of->f_mutex); + of = NULL; + goto out; + } + of->f_refcnt++; + mutex_exit(&of->f_mutex); + +out: smb_llist_exit(of_list); return (of); } @@ -921,6 +954,7 @@ smb_ofile_delete(void *arg) of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; mutex_destroy(&of->f_mutex); crfree(of->f_cr); + smb_user_release(of->f_user); kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe.c b/usr/src/uts/common/fs/smbsrv/smb_opipe.c index bb178f3952..90cb25aaa0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c +++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c @@ -130,8 +130,8 @@ smb_opipe_open(smb_request_t *sr) op->create_options = 0; - of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op, - SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err); + of = smb_ofile_open(sr, NULL, sr->smb_pid, op, SMB_FTYPE_MESG_PIPE, + SMB_UNIQ_FID(), &err); if (of == NULL) return (err.status); diff --git a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c index b8c835cd57..2839ca2807 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c +++ b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c @@ -85,11 +85,11 @@ smb_com_process_exit(smb_request_t *sr) * to be the only thing that sends this request these days and * it doesn't provide a TID. */ - sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid); + sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid); if (sr->tid_tree != NULL) smb_tree_close_pid(sr->tid_tree, sr->smb_pid); else - smb_user_close_pid(sr->uid_user, sr->smb_pid); + smb_session_close_pid(sr->session, sr->smb_pid); rc = smbsr_encode_empty_result(sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c index bef69e7f61..70ac2e7b24 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c @@ -662,7 +662,7 @@ smb_encode_stream_info(smb_request_t *sr, smb_xa_t *xa, smb_queryinfo_t *qinfo) odid = smb_odir_openat(sr, fnode); if (odid != 0) - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od != NULL) rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos); diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c index 3654744569..8687d42b18 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_server.c +++ b/usr/src/uts/common/fs/smbsrv/smb_server.c @@ -240,7 +240,8 @@ static void smb_event_cancel(smb_server_t *, uint32_t); static uint32_t smb_event_alloc_txid(void); static void smb_server_disconnect_share(smb_llist_t *, const char *); -static void smb_server_enum_private(smb_llist_t *, smb_svcenum_t *); +static void smb_server_enum_users(smb_llist_t *, smb_svcenum_t *); +static void smb_server_enum_trees(smb_llist_t *, smb_svcenum_t *); static int smb_server_session_disconnect(smb_llist_t *, const char *, const char *); static int smb_server_fclose(smb_llist_t *, uint32_t); @@ -833,15 +834,6 @@ smb_server_enum(smb_ioc_svcenum_t *ioc) smb_server_t *sv; int rc; - switch (svcenum->se_type) { - case SMB_SVCENUM_TYPE_USER: - case SMB_SVCENUM_TYPE_TREE: - case SMB_SVCENUM_TYPE_FILE: - break; - default: - return (EINVAL); - } - if ((rc = smb_server_lookup(&sv)) != 0) return (rc); @@ -849,11 +841,26 @@ smb_server_enum(smb_ioc_svcenum_t *ioc) svcenum->se_bused = 0; svcenum->se_nitems = 0; - smb_server_enum_private(&sv->sv_nbt_daemon.ld_session_list, svcenum); - smb_server_enum_private(&sv->sv_tcp_daemon.ld_session_list, svcenum); + switch (svcenum->se_type) { + case SMB_SVCENUM_TYPE_USER: + smb_server_enum_users(&sv->sv_nbt_daemon.ld_session_list, + svcenum); + smb_server_enum_users(&sv->sv_tcp_daemon.ld_session_list, + svcenum); + break; + case SMB_SVCENUM_TYPE_TREE: + case SMB_SVCENUM_TYPE_FILE: + smb_server_enum_trees(&sv->sv_nbt_daemon.ld_session_list, + svcenum); + smb_server_enum_trees(&sv->sv_tcp_daemon.ld_session_list, + svcenum); + break; + default: + rc = EINVAL; + } smb_server_release(sv); - return (0); + return (rc); } /* @@ -1694,7 +1701,7 @@ smb_server_release(smb_server_t *sv) * Enumerate the users associated with a session list. */ static void -smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum) +smb_server_enum_users(smb_llist_t *ll, smb_svcenum_t *svcenum) { smb_session_t *sn; smb_llist_t *ulist; @@ -1714,6 +1721,8 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum) if (smb_user_hold(user)) { rc = smb_user_enum(user, svcenum); smb_user_release(user); + if (rc != 0) + break; } user = smb_llist_next(ulist, user); @@ -1731,6 +1740,48 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum) } /* + * Enumerate the trees/files associated with a session list. + */ +static void +smb_server_enum_trees(smb_llist_t *ll, smb_svcenum_t *svcenum) +{ + smb_session_t *sn; + smb_llist_t *tlist; + smb_tree_t *tree; + int rc = 0; + + smb_llist_enter(ll, RW_READER); + sn = smb_llist_head(ll); + + while (sn != NULL) { + SMB_SESSION_VALID(sn); + tlist = &sn->s_tree_list; + smb_llist_enter(tlist, RW_READER); + tree = smb_llist_head(tlist); + + while (tree != NULL) { + if (smb_tree_hold(tree)) { + rc = smb_tree_enum(tree, svcenum); + smb_tree_release(tree); + if (rc != 0) + break; + } + + tree = smb_llist_next(tlist, tree); + } + + smb_llist_exit(tlist); + + if (rc != 0) + break; + + sn = smb_llist_next(ll, sn); + } + + smb_llist_exit(ll); +} + +/* * Disconnect sessions associated with the specified client and username. * Empty strings are treated as wildcards. */ @@ -1796,8 +1847,8 @@ static int smb_server_fclose(smb_llist_t *ll, uint32_t uniqid) { smb_session_t *sn; - smb_llist_t *ulist; - smb_user_t *user; + smb_llist_t *tlist; + smb_tree_t *tree; int rc = ENOENT; smb_llist_enter(ll, RW_READER); @@ -1805,20 +1856,20 @@ smb_server_fclose(smb_llist_t *ll, uint32_t uniqid) while ((sn != NULL) && (rc == ENOENT)) { SMB_SESSION_VALID(sn); - ulist = &sn->s_user_list; - smb_llist_enter(ulist, RW_READER); - user = smb_llist_head(ulist); - - while ((user != NULL) && (rc == ENOENT)) { - if (smb_user_hold(user)) { - rc = smb_user_fclose(user, uniqid); - smb_user_release(user); + tlist = &sn->s_tree_list; + smb_llist_enter(tlist, RW_READER); + tree = smb_llist_head(tlist); + + while ((tree != NULL) && (rc == ENOENT)) { + if (smb_tree_hold(tree)) { + rc = smb_tree_fclose(tree, uniqid); + smb_tree_release(tree); } - user = smb_llist_next(ulist, user); + tree = smb_llist_next(tlist, tree); } - smb_llist_exit(ulist); + smb_llist_exit(tlist); sn = smb_llist_next(ll, sn); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c index 0fdac10ca6..b8284b372f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session.c @@ -43,6 +43,7 @@ static int smb_session_message(smb_session_t *); static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *, uint8_t *, size_t); static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *); +static smb_tree_t *smb_session_get_tree(smb_session_t *, smb_tree_t *); static void smb_session_logoff(smb_session_t *); static void smb_request_init_command_mbuf(smb_request_t *sr); void dump_smb_inaddr(smb_inaddr_t *ipaddr); @@ -624,6 +625,11 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv, kmem_cache_free(sv->si_cache_session, session); return (NULL); } + if (smb_idpool_constructor(&session->s_tid_pool)) { + smb_idpool_destructor(&session->s_uid_pool); + kmem_cache_free(sv->si_cache_session, session); + return (NULL); + } now = ddi_get_lbolt64(); @@ -642,6 +648,9 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv, smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t), offsetof(smb_user_t, u_lnd)); + smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t), + offsetof(smb_tree_t, t_lnd)); + smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t), offsetof(smb_xa_t, xa_lnd)); @@ -719,6 +728,7 @@ smb_session_delete(smb_session_t *session) list_destroy(&session->s_oplock_brkreqs); smb_slist_destructor(&session->s_req_list); + smb_llist_destructor(&session->s_tree_list); smb_llist_destructor(&session->s_user_list); smb_llist_destructor(&session->s_xa_list); @@ -726,6 +736,7 @@ smb_session_delete(smb_session_t *session) ASSERT(session->s_file_cnt == 0); ASSERT(session->s_dir_cnt == 0); + smb_idpool_destructor(&session->s_tid_pool); smb_idpool_destructor(&session->s_uid_pool); if (session->sock != NULL) { if (session->s_local_port == IPPORT_NETBIOS_SSN) @@ -928,45 +939,306 @@ smb_session_post_user(smb_session_t *session, smb_user_t *user) } /* - * Logoff all users associated with the specified session. + * Find a tree by tree-id. */ -static void -smb_session_logoff(smb_session_t *session) +smb_tree_t * +smb_session_lookup_tree( + smb_session_t *session, + uint16_t tid) + { - smb_user_t *user; + smb_tree_t *tree; SMB_SESSION_VALID(session); - smb_llist_enter(&session->s_user_list, RW_READER); + smb_llist_enter(&session->s_tree_list, RW_READER); + tree = smb_llist_head(&session->s_tree_list); - user = smb_llist_head(&session->s_user_list); - while (user) { - SMB_USER_VALID(user); - ASSERT(user->u_session == session); + while (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); - if (smb_user_hold(user)) { - smb_user_logoff(user); - smb_user_release(user); + if (tree->t_tid == tid) { + if (smb_tree_hold(tree)) { + smb_llist_exit(&session->s_tree_list); + return (tree); + } else { + smb_llist_exit(&session->s_tree_list); + return (NULL); + } } - user = smb_llist_next(&session->s_user_list, user); + tree = smb_llist_next(&session->s_tree_list, tree); } - smb_llist_exit(&session->s_user_list); + smb_llist_exit(&session->s_tree_list); + return (NULL); +} + +/* + * Find the first connected tree that matches the specified sharename. + * If the specified tree is NULL the search starts from the beginning of + * the user's tree list. If a tree is provided the search starts just + * after that tree. + */ +smb_tree_t * +smb_session_lookup_share( + smb_session_t *session, + const char *sharename, + smb_tree_t *tree) +{ + SMB_SESSION_VALID(session); + ASSERT(sharename); + + smb_llist_enter(&session->s_tree_list, RW_READER); + + if (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + tree = smb_llist_next(&session->s_tree_list, tree); + } else { + tree = smb_llist_head(&session->s_tree_list); + } + + while (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) { + if (smb_tree_hold(tree)) { + smb_llist_exit(&session->s_tree_list); + return (tree); + } + } + tree = smb_llist_next(&session->s_tree_list, tree); + } + + smb_llist_exit(&session->s_tree_list); + return (NULL); +} + +/* + * Find the first connected tree that matches the specified volume name. + * If the specified tree is NULL the search starts from the beginning of + * the user's tree list. If a tree is provided the search starts just + * after that tree. + */ +smb_tree_t * +smb_session_lookup_volume( + smb_session_t *session, + const char *name, + smb_tree_t *tree) +{ + SMB_SESSION_VALID(session); + ASSERT(name); + + smb_llist_enter(&session->s_tree_list, RW_READER); + + if (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + tree = smb_llist_next(&session->s_tree_list, tree); + } else { + tree = smb_llist_head(&session->s_tree_list); + } + + while (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + + if (smb_strcasecmp(tree->t_volume, name, 0) == 0) { + if (smb_tree_hold(tree)) { + smb_llist_exit(&session->s_tree_list); + return (tree); + } + } + + tree = smb_llist_next(&session->s_tree_list, tree); + } + + smb_llist_exit(&session->s_tree_list); + return (NULL); +} + +/* + * Disconnect all trees that match the specified client process-id. + */ +void +smb_session_close_pid( + smb_session_t *session, + uint16_t pid) +{ + smb_tree_t *tree; + + SMB_SESSION_VALID(session); + + tree = smb_session_get_tree(session, NULL); + while (tree) { + smb_tree_t *next; + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + smb_tree_close_pid(tree, pid); + next = smb_session_get_tree(session, tree); + smb_tree_release(tree); + tree = next; + } +} + +static void +smb_session_tree_dtor(void *t) +{ + smb_tree_t *tree = (smb_tree_t *)t; + + smb_tree_disconnect(tree, B_TRUE); + /* release the ref acquired during the traversal loop */ + smb_tree_release(tree); } + /* - * Disconnect any trees associated with the specified share. - * Iterate through the users on this session and tell each user - * to disconnect from the share. + * Disconnect all trees that this user has connected. */ void -smb_session_disconnect_share(smb_session_t *session, const char *sharename) +smb_session_disconnect_owned_trees( + smb_session_t *session, + smb_user_t *owner) +{ + smb_tree_t *tree; + smb_llist_t *tree_list = &session->s_tree_list; + + SMB_SESSION_VALID(session); + SMB_USER_VALID(owner); + + smb_llist_enter(tree_list, RW_READER); + + tree = smb_llist_head(tree_list); + while (tree) { + if ((tree->t_owner == owner) && + smb_tree_hold(tree)) { + /* + * smb_tree_hold() succeeded, hence we are in state + * SMB_TREE_STATE_CONNECTED; schedule this tree + * for asynchronous disconnect, which will fire + * after we drop the llist traversal lock. + */ + smb_llist_post(tree_list, tree, smb_session_tree_dtor); + } + tree = smb_llist_next(tree_list, tree); + } + + /* drop the lock and flush the dtor queue */ + smb_llist_exit(tree_list); +} + +/* + * Disconnect all trees that this user has connected. + */ +void +smb_session_disconnect_trees( + smb_session_t *session) +{ + smb_tree_t *tree; + + SMB_SESSION_VALID(session); + + tree = smb_session_get_tree(session, NULL); + while (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + smb_tree_disconnect(tree, B_TRUE); + smb_tree_release(tree); + tree = smb_session_get_tree(session, NULL); + } +} + +/* + * Disconnect all trees that match the specified share name. + */ +void +smb_session_disconnect_share( + smb_session_t *session, + const char *sharename) +{ + smb_tree_t *tree; + smb_tree_t *next; + + SMB_SESSION_VALID(session); + + tree = smb_session_lookup_share(session, sharename, NULL); + while (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + ASSERT(tree->t_session == session); + smb_session_cancel_requests(session, tree, NULL); + smb_tree_disconnect(tree, B_TRUE); + next = smb_session_lookup_share(session, sharename, tree); + smb_tree_release(tree); + tree = next; + } +} + +void +smb_session_post_tree(smb_session_t *session, smb_tree_t *tree) +{ + SMB_SESSION_VALID(session); + SMB_TREE_VALID(tree); + ASSERT0(tree->t_refcnt); + ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); + ASSERT(tree->t_session == session); + + smb_llist_post(&session->s_tree_list, tree, smb_tree_dealloc); +} + +/* + * Get the next connected tree in the list. A reference is taken on + * the tree, which can be released later with smb_tree_release(). + * + * If the specified tree is NULL the search starts from the beginning of + * the tree list. If a tree is provided the search starts just after + * that tree. + * + * Returns NULL if there are no connected trees in the list. + */ +static smb_tree_t * +smb_session_get_tree( + smb_session_t *session, + smb_tree_t *tree) +{ + smb_llist_t *tree_list; + + SMB_SESSION_VALID(session); + tree_list = &session->s_tree_list; + + smb_llist_enter(tree_list, RW_READER); + + if (tree) { + ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC); + tree = smb_llist_next(tree_list, tree); + } else { + tree = smb_llist_head(tree_list); + } + + while (tree) { + if (smb_tree_hold(tree)) + break; + + tree = smb_llist_next(tree_list, tree); + } + + smb_llist_exit(tree_list); + return (tree); +} + +/* + * Logoff all users associated with the specified session. + */ +static void +smb_session_logoff(smb_session_t *session) { smb_user_t *user; SMB_SESSION_VALID(session); + smb_session_disconnect_trees(session); + smb_llist_enter(&session->s_user_list, RW_READER); user = smb_llist_head(&session->s_user_list); @@ -975,7 +1247,7 @@ smb_session_disconnect_share(smb_session_t *session, const char *sharename) ASSERT(user->u_session == session); if (smb_user_hold(user)) { - smb_user_disconnect_share(user, sharename); + smb_user_logoff(user); smb_user_release(user); } 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 037b2a3b36..d0d60cea5d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -332,7 +332,7 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) return (SDRC_ERROR); } - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) return (SDRC_ERROR); @@ -463,7 +463,7 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) if (args.fa_maxdata == 0) return (SDRC_ERROR); - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); @@ -943,7 +943,7 @@ smb_com_find_close2(smb_request_t *sr) if (smbsr_decode_vwv(sr, "w", &odid) != 0) return (SDRC_ERROR); - od = smb_tree_lookup_odir(sr->tid_tree, odid); + od = smb_tree_lookup_odir(sr, odid); if (od == NULL) { smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c index 13adc2d803..b225c67623 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -40,15 +40,15 @@ * +-------------------+ +-------------------+ +-------------------+ * | SESSION |<----->| SESSION |......| SESSION | * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v - * +-------------------+ +-------------------+ +-------------------+ - * | USER |<----->| USER |......| USER | - * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v + * | | + * | | + * | v + * | +-------------------+ +-------------------+ +-------------------+ + * | | USER |<--->| USER |...| USER | + * | +-------------------+ +-------------------+ +-------------------+ + * | + * | + * v * +-------------------+ +-------------------+ +-------------------+ * | TREE |<----->| TREE |......| TREE | * +-------------------+ +-------------------+ +-------------------+ @@ -175,7 +175,7 @@ static smb_tree_t *smb_tree_connect_core(smb_request_t *); static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *); static smb_tree_t *smb_tree_connect_printq(smb_request_t *, const char *); static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *); -static smb_tree_t *smb_tree_alloc(smb_user_t *, const smb_kshare_t *, +static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *, smb_node_t *, uint32_t, uint32_t); static boolean_t smb_tree_is_connected_locked(smb_tree_t *); static boolean_t smb_tree_is_disconnected(smb_tree_t *); @@ -269,6 +269,7 @@ smb_tree_connect_core(smb_request_t *sr) } smb_kshare_release(si); + return (tree); } @@ -361,7 +362,7 @@ smb_tree_release( smb_llist_flush(&tree->t_odir_list); if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0)) - smb_user_post_tree(tree->t_user, tree); + smb_session_post_tree(tree->t_session, tree); mutex_exit(&tree->t_mutex); } @@ -428,7 +429,7 @@ smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) { smb_ofile_t *of; smb_ofile_t *next; - int rc; + int rc = 0; ASSERT(tree); ASSERT(tree->t_magic == SMB_TREE_MAGIC); @@ -712,8 +713,7 @@ smb_tree_connect_disk(smb_request_t *sr, const char *sharename) if (!smb_shortnames) sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME; - tree = smb_tree_alloc(user, si, snode, access, - sr->sr_cfg->skc_execflags); + tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); smb_node_release(snode); @@ -805,8 +805,7 @@ smb_tree_connect_printq(smb_request_t *sr, const char *sharename) sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; - tree = smb_tree_alloc(user, si, snode, access, - sr->sr_cfg->skc_execflags); + tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); smb_node_release(snode); @@ -846,7 +845,7 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name) sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; - tree = smb_tree_alloc(user, si, NULL, ACE_ALL_PERMS, 0); + tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0); if (tree == NULL) { smb_tree_log(sr, name, "access denied"); smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); @@ -859,41 +858,45 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name) * Allocate a tree. */ static smb_tree_t * -smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode, - uint32_t access, uint32_t execflags) +smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si, + smb_node_t *snode, uint32_t access, uint32_t execflags) { + smb_session_t *session = sr->session; smb_tree_t *tree; uint32_t stype = si->shr_type; uint16_t tid; - if (smb_idpool_alloc(&user->u_tid_pool, &tid)) + if (smb_idpool_alloc(&session->s_tid_pool, &tid)) return (NULL); - tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP); + tree = kmem_cache_alloc(session->s_server->si_cache_tree, KM_SLEEP); bzero(tree, sizeof (smb_tree_t)); - tree->t_user = user; - tree->t_session = user->u_session; - tree->t_server = user->u_server; + tree->t_session = session; + tree->t_server = session->s_server; + + /* grab a ref for tree->t_owner */ + smb_user_hold_internal(sr->uid_user); + tree->t_owner = sr->uid_user; if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { if (smb_tree_getattr(si, snode, tree) != 0) { - smb_idpool_free(&user->u_tid_pool, tid); - kmem_cache_free(user->u_server->si_cache_tree, tree); + smb_idpool_free(&session->s_tid_pool, tid); + kmem_cache_free(session->s_server->si_cache_tree, tree); return (NULL); } } if (smb_idpool_constructor(&tree->t_fid_pool)) { - smb_idpool_free(&user->u_tid_pool, tid); - kmem_cache_free(user->u_server->si_cache_tree, tree); + smb_idpool_free(&session->s_tid_pool, tid); + kmem_cache_free(session->s_server->si_cache_tree, tree); return (NULL); } if (smb_idpool_constructor(&tree->t_odid_pool)) { smb_idpool_destructor(&tree->t_fid_pool); - smb_idpool_free(&user->u_tid_pool, tid); - kmem_cache_free(user->u_server->si_cache_tree, tree); + smb_idpool_free(&session->s_tid_pool, tid); + kmem_cache_free(session->s_server->si_cache_tree, tree); return (NULL); } @@ -929,11 +932,11 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode, tree->t_acltype = smb_fsop_acltype(snode); } - smb_llist_enter(&user->u_tree_list, RW_WRITER); - smb_llist_insert_head(&user->u_tree_list, tree); - smb_llist_exit(&user->u_tree_list); - atomic_inc_32(&user->u_session->s_tree_cnt); - smb_server_inc_trees(user->u_server); + smb_llist_enter(&session->s_tree_list, RW_WRITER); + smb_llist_insert_head(&session->s_tree_list, tree); + smb_llist_exit(&session->s_tree_list); + atomic_inc_32(&session->s_tree_cnt); + smb_server_inc_trees(session->s_server); return (tree); } @@ -947,19 +950,19 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode, void smb_tree_dealloc(void *arg) { - smb_user_t *user; + smb_session_t *session; smb_tree_t *tree = (smb_tree_t *)arg; SMB_TREE_VALID(tree); ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); ASSERT(tree->t_refcnt == 0); - user = tree->t_user; - smb_llist_enter(&user->u_tree_list, RW_WRITER); - smb_llist_remove(&user->u_tree_list, tree); - smb_idpool_free(&user->u_tid_pool, tree->t_tid); - atomic_dec_32(&tree->t_session->s_tree_cnt); - smb_llist_exit(&user->u_tree_list); + session = tree->t_session; + smb_llist_enter(&session->s_tree_list, RW_WRITER); + smb_llist_remove(&session->s_tree_list, tree); + smb_idpool_free(&session->s_tid_pool, tree->t_tid); + atomic_dec_32(&session->s_tree_cnt); + smb_llist_exit(&session->s_tree_list); mutex_enter(&tree->t_mutex); mutex_exit(&tree->t_mutex); @@ -974,6 +977,10 @@ smb_tree_dealloc(void *arg) smb_llist_destructor(&tree->t_odir_list); smb_idpool_destructor(&tree->t_fid_pool); smb_idpool_destructor(&tree->t_odid_pool); + + SMB_USER_VALID(tree->t_owner); + smb_user_release(tree->t_owner); + kmem_cache_free(tree->t_server->si_cache_tree, tree); } @@ -1234,27 +1241,38 @@ smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) * Returns NULL if odir not found or a hold cannot be obtained. */ smb_odir_t * -smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid) +smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid) { smb_odir_t *od; smb_llist_t *od_list; + smb_tree_t *tree = sr->tid_tree; - ASSERT(tree); ASSERT(tree->t_magic == SMB_TREE_MAGIC); od_list = &tree->t_odir_list; - smb_llist_enter(od_list, RW_READER); + smb_llist_enter(od_list, RW_READER); od = smb_llist_head(od_list); while (od) { - if (od->d_odid == odid) { - if (!smb_odir_hold(od)) - od = NULL; + if (od->d_odid == odid) break; - } od = smb_llist_next(od_list, od); } + if (od == NULL) + goto out; + + /* + * Only allow use of a given Search ID with the same UID that + * was used to create it. MS-CIFS 3.3.5.14 + */ + if (od->d_user != sr->uid_user) { + od = NULL; + goto out; + } + if (!smb_odir_hold(od)) + od = NULL; +out: smb_llist_exit(od_list); return (od); } @@ -1377,15 +1395,16 @@ smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid) } static void -smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, int exec_type) +smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, + int exec_type) { exec->e_sharename = tree->t_sharename; - exec->e_winname = tree->t_user->u_name; - exec->e_userdom = tree->t_user->u_domain; + exec->e_winname = tree->t_owner->u_name; + exec->e_userdom = tree->t_owner->u_domain; exec->e_srv_ipaddr = tree->t_session->local_ipaddr; exec->e_cli_ipaddr = tree->t_session->ipaddr; exec->e_cli_netbiosname = tree->t_session->workstation; - exec->e_uid = crgetuid(tree->t_user->u_cred); + exec->e_uid = crgetuid(tree->t_owner->u_cred); exec->e_type = exec_type; } @@ -1438,6 +1457,26 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, return (rc); } +static void +smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen) +{ + smb_user_t *user = tree->t_owner; + + /* + * u_domain_len and u_name_len include the '\0' in their + * lengths, hence the sum of the two lengths gives us room + * for both the '\\' and '\0' chars. + */ + ASSERT(namestr); + ASSERT(namelen); + ASSERT(user->u_domain_len > 0); + ASSERT(user->u_name_len > 0); + *namelen = user->u_domain_len + user->u_name_len; + *namestr = kmem_alloc(*namelen, KM_SLEEP); + (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain, + user->u_name); +} + /* * Note: ci_numusers should be the number of users connected to * the share rather than the number of references on the tree but @@ -1446,8 +1485,6 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) { - smb_user_t *user; - ASSERT(tree); info->ci_id = tree->t_tid; @@ -1459,13 +1496,7 @@ smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) info->ci_sharelen = strlen(tree->t_sharename) + 1; info->ci_share = smb_mem_strdup(tree->t_sharename); - user = tree->t_user; - ASSERT(user); - - info->ci_namelen = user->u_domain_len + user->u_name_len + 2; - info->ci_username = kmem_alloc(info->ci_namelen, KM_SLEEP); - (void) snprintf(info->ci_username, info->ci_namelen, "%s\\%s", - user->u_domain, user->u_name); + smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen); } static void diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c index 1ce9720f5d..19b857e834 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -362,8 +363,7 @@ smb_sdrc_t smb_pre_tree_disconnect(smb_request_t *sr) { sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid); - if (sr->uid_user != NULL) - sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid); + sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid); DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr); return (SDRC_SUCCESS); diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c index cc3fde7f38..09eaba699c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_user.c +++ b/usr/src/uts/common/fs/smbsrv/smb_user.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -38,15 +39,15 @@ * +-------------------+ +-------------------+ +-------------------+ * | SESSION |<----->| SESSION |......| SESSION | * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v - * +-------------------+ +-------------------+ +-------------------+ - * | USER |<----->| USER |......| USER | - * +-------------------+ +-------------------+ +-------------------+ - * | - * | - * v + * | | + * | | + * | v + * | +-------------------+ +-------------------+ +-------------------+ + * | | USER |<--->| USER |...| USER | + * | +-------------------+ +-------------------+ +-------------------+ + * | + * | + * v * +-------------------+ +-------------------+ +-------------------+ * | TREE |<----->| TREE |......| TREE | * +-------------------+ +-------------------+ +-------------------+ @@ -170,7 +171,6 @@ static boolean_t smb_user_is_logged_in(smb_user_t *); static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *); -static smb_tree_t *smb_user_get_tree(smb_llist_t *, smb_tree_t *); static void smb_user_setcred(smb_user_t *, cred_t *, uint32_t); static void smb_user_nonauth_logon(uint32_t); static void smb_user_auth_logoff(uint32_t); @@ -210,20 +210,15 @@ smb_user_login( user->u_audit_sid = audit_sid; if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) { - if (!smb_idpool_constructor(&user->u_tid_pool)) { - smb_llist_constructor(&user->u_tree_list, - sizeof (smb_tree_t), offsetof(smb_tree_t, t_lnd)); - mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL); - smb_user_setcred(user, cr, privileges); - user->u_state = SMB_USER_STATE_LOGGED_IN; - user->u_magic = SMB_USER_MAGIC; - smb_llist_enter(&session->s_user_list, RW_WRITER); - smb_llist_insert_tail(&session->s_user_list, user); - smb_llist_exit(&session->s_user_list); - smb_server_inc_users(session->s_server); - return (user); - } - smb_idpool_free(&session->s_uid_pool, user->u_uid); + mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL); + smb_user_setcred(user, cr, privileges); + user->u_state = SMB_USER_STATE_LOGGED_IN; + user->u_magic = SMB_USER_MAGIC; + smb_llist_enter(&session->s_user_list, RW_WRITER); + smb_llist_insert_tail(&session->s_user_list, user); + smb_llist_exit(&session->s_user_list); + smb_server_inc_users(session->s_server); + return (user); } smb_mem_free(user->u_name); smb_mem_free(user->u_domain); @@ -279,10 +274,7 @@ smb_user_logoff( */ user->u_state = SMB_USER_STATE_LOGGING_OFF; mutex_exit(&user->u_mutex); - /* - * All the trees hanging off of this user are disconnected. - */ - smb_user_disconnect_trees(user); + smb_session_disconnect_owned_trees(user->u_session, user); smb_user_auth_logoff(user->u_audit_sid); mutex_enter(&user->u_mutex); user->u_state = SMB_USER_STATE_LOGGED_OFF; @@ -301,13 +293,13 @@ smb_user_logoff( } /* - * Take a reference on a user. + * Take a reference on a user. Do not return a reference unless the user is in + * the logged-in state. */ boolean_t smb_user_hold(smb_user_t *user) { - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); + SMB_USER_VALID(user); mutex_enter(&user->u_mutex); @@ -322,6 +314,19 @@ smb_user_hold(smb_user_t *user) } /* + * Unconditionally take a reference on a user. + */ +void +smb_user_hold_internal(smb_user_t *user) +{ + SMB_USER_VALID(user); + + mutex_enter(&user->u_mutex); + user->u_refcnt++; + mutex_exit(&user->u_mutex); +} + +/* * Release a reference on a user. If the reference count falls to * zero and the user has logged off, post the object for deletion. * Object deletion is deferred to avoid modifying a list while an @@ -337,9 +342,6 @@ smb_user_release( ASSERT(user->u_refcnt); user->u_refcnt--; - /* flush the tree list's delete queue */ - smb_llist_flush(&user->u_tree_list); - switch (user->u_state) { case SMB_USER_STATE_LOGGED_OFF: if (user->u_refcnt == 0) @@ -357,248 +359,6 @@ smb_user_release( mutex_exit(&user->u_mutex); } -void -smb_user_post_tree(smb_user_t *user, smb_tree_t *tree) -{ - SMB_USER_VALID(user); - SMB_TREE_VALID(tree); - ASSERT(tree->t_refcnt == 0); - ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); - ASSERT(tree->t_user == user); - - smb_llist_post(&user->u_tree_list, tree, smb_tree_dealloc); -} - - -/* - * Find a tree by tree-id. - */ -smb_tree_t * -smb_user_lookup_tree( - smb_user_t *user, - uint16_t tid) - -{ - smb_tree_t *tree; - - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - - smb_llist_enter(&user->u_tree_list, RW_READER); - tree = smb_llist_head(&user->u_tree_list); - - while (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - ASSERT(tree->t_user == user); - - if (tree->t_tid == tid) { - if (smb_tree_hold(tree)) { - smb_llist_exit(&user->u_tree_list); - return (tree); - } else { - smb_llist_exit(&user->u_tree_list); - return (NULL); - } - } - - tree = smb_llist_next(&user->u_tree_list, tree); - } - - smb_llist_exit(&user->u_tree_list); - return (NULL); -} - -/* - * Find the first connected tree that matches the specified sharename. - * If the specified tree is NULL the search starts from the beginning of - * the user's tree list. If a tree is provided the search starts just - * after that tree. - */ -smb_tree_t * -smb_user_lookup_share( - smb_user_t *user, - const char *sharename, - smb_tree_t *tree) -{ - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - ASSERT(sharename); - - smb_llist_enter(&user->u_tree_list, RW_READER); - - if (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - ASSERT(tree->t_user == user); - tree = smb_llist_next(&user->u_tree_list, tree); - } else { - tree = smb_llist_head(&user->u_tree_list); - } - - while (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - ASSERT(tree->t_user == user); - if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) { - if (smb_tree_hold(tree)) { - smb_llist_exit(&user->u_tree_list); - return (tree); - } - } - tree = smb_llist_next(&user->u_tree_list, tree); - } - - smb_llist_exit(&user->u_tree_list); - return (NULL); -} - -/* - * Find the first connected tree that matches the specified volume name. - * If the specified tree is NULL the search starts from the beginning of - * the user's tree list. If a tree is provided the search starts just - * after that tree. - */ -smb_tree_t * -smb_user_lookup_volume( - smb_user_t *user, - const char *name, - smb_tree_t *tree) -{ - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - ASSERT(name); - - smb_llist_enter(&user->u_tree_list, RW_READER); - - if (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - ASSERT(tree->t_user == user); - tree = smb_llist_next(&user->u_tree_list, tree); - } else { - tree = smb_llist_head(&user->u_tree_list); - } - - while (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - ASSERT(tree->t_user == user); - - if (smb_strcasecmp(tree->t_volume, name, 0) == 0) { - if (smb_tree_hold(tree)) { - smb_llist_exit(&user->u_tree_list); - return (tree); - } - } - - tree = smb_llist_next(&user->u_tree_list, tree); - } - - smb_llist_exit(&user->u_tree_list); - return (NULL); -} - -/* - * Disconnect all trees that match the specified client process-id. - */ -void -smb_user_close_pid( - smb_user_t *user, - uint16_t pid) -{ - smb_tree_t *tree; - - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - - tree = smb_user_get_tree(&user->u_tree_list, NULL); - while (tree) { - smb_tree_t *next; - ASSERT(tree->t_user == user); - smb_tree_close_pid(tree, pid); - next = smb_user_get_tree(&user->u_tree_list, tree); - smb_tree_release(tree); - tree = next; - } -} - -/* - * Disconnect all trees that this user has connected. - */ -void -smb_user_disconnect_trees( - smb_user_t *user) -{ - smb_tree_t *tree; - - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - - tree = smb_user_get_tree(&user->u_tree_list, NULL); - while (tree) { - ASSERT(tree->t_user == user); - smb_tree_disconnect(tree, B_TRUE); - smb_tree_release(tree); - tree = smb_user_get_tree(&user->u_tree_list, NULL); - } -} - -/* - * Disconnect all trees that match the specified share name. - */ -void -smb_user_disconnect_share( - smb_user_t *user, - const char *sharename) -{ - smb_tree_t *tree; - smb_tree_t *next; - - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - ASSERT(user->u_refcnt); - - tree = smb_user_lookup_share(user, sharename, NULL); - while (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - smb_session_cancel_requests(user->u_session, tree, NULL); - smb_tree_disconnect(tree, B_TRUE); - next = smb_user_lookup_share(user, sharename, tree); - smb_tree_release(tree); - tree = next; - } -} - -/* - * Close a file by its unique id. - */ -int -smb_user_fclose(smb_user_t *user, uint32_t uniqid) -{ - smb_llist_t *tree_list; - smb_tree_t *tree; - int rc = ENOENT; - - ASSERT(user); - ASSERT(user->u_magic == SMB_USER_MAGIC); - - tree_list = &user->u_tree_list; - ASSERT(tree_list); - - smb_llist_enter(tree_list, RW_READER); - tree = smb_llist_head(tree_list); - - while ((tree != NULL) && (rc == ENOENT)) { - ASSERT(tree->t_user == user); - - if (smb_tree_hold(tree)) { - rc = smb_tree_fclose(tree, uniqid); - smb_tree_release(tree); - } - - tree = smb_llist_next(tree_list, tree); - } - - smb_llist_exit(tree_list); - return (rc); -} - /* * Determine whether or not the user is an administrator. * Members of the administrators group have administrative rights. @@ -688,9 +448,7 @@ smb_user_namecmp(smb_user_t *user, const char *name) int smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum) { - smb_tree_t *tree; - smb_tree_t *next; - int rc; + int rc = 0; ASSERT(user); ASSERT(user->u_magic == SMB_USER_MAGIC); @@ -698,21 +456,6 @@ smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum) if (svcenum->se_type == SMB_SVCENUM_TYPE_USER) return (smb_user_enum_private(user, svcenum)); - tree = smb_user_get_tree(&user->u_tree_list, NULL); - while (tree) { - ASSERT(tree->t_user == user); - - rc = smb_tree_enum(tree, svcenum); - if (rc != 0) { - smb_tree_release(tree); - break; - } - - next = smb_user_get_tree(&user->u_tree_list, tree); - smb_tree_release(tree); - tree = next; - } - return (rc); } @@ -769,8 +512,6 @@ smb_user_delete(void *arg) user->u_magic = (uint32_t)~SMB_USER_MAGIC; mutex_destroy(&user->u_mutex); - smb_llist_destructor(&user->u_tree_list); - smb_idpool_destructor(&user->u_tid_pool); if (user->u_cred) crfree(user->u_cred); if (user->u_privcred) @@ -780,43 +521,6 @@ smb_user_delete(void *arg) kmem_cache_free(user->u_server->si_cache_user, user); } -/* - * Get the next connected tree in the list. A reference is taken on - * the tree, which can be released later with smb_tree_release(). - * - * If the specified tree is NULL the search starts from the beginning of - * the tree list. If a tree is provided the search starts just after - * that tree. - * - * Returns NULL if there are no connected trees in the list. - */ -static smb_tree_t * -smb_user_get_tree( - smb_llist_t *tree_list, - smb_tree_t *tree) -{ - ASSERT(tree_list); - - smb_llist_enter(tree_list, RW_READER); - - if (tree) { - ASSERT(tree->t_magic == SMB_TREE_MAGIC); - tree = smb_llist_next(tree_list, tree); - } else { - tree = smb_llist_head(tree_list); - } - - while (tree) { - if (smb_tree_hold(tree)) - break; - - tree = smb_llist_next(tree_list, tree); - } - - smb_llist_exit(tree_list); - return (tree); -} - cred_t * smb_user_getcred(smb_user_t *user) { diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index f2de265176..ad7402fd80 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -521,6 +521,15 @@ void smb_session_disconnect_from_share(smb_llist_t *, char *); smb_user_t *smb_session_dup_user(smb_session_t *, char *, char *); smb_user_t *smb_session_lookup_uid(smb_session_t *, uint16_t); void smb_session_post_user(smb_session_t *, smb_user_t *); +void smb_session_post_tree(smb_session_t *, smb_tree_t *); +smb_tree_t *smb_session_lookup_tree(smb_session_t *, uint16_t); +smb_tree_t *smb_session_lookup_share(smb_session_t *, const char *, + smb_tree_t *); +smb_tree_t *smb_session_lookup_volume(smb_session_t *, const char *, + smb_tree_t *); +void smb_session_close_pid(smb_session_t *, uint16_t); +void smb_session_disconnect_owned_trees(smb_session_t *, smb_user_t *); +void smb_session_disconnect_trees(smb_session_t *); void smb_session_disconnect_share(smb_session_t *, const char *); void smb_session_getclient(smb_session_t *, char *, size_t); boolean_t smb_session_isclient(smb_session_t *, const char *); @@ -539,10 +548,10 @@ void smb_request_free(smb_request_t *); /* * ofile functions (file smb_ofile.c) */ -smb_ofile_t *smb_ofile_lookup_by_fid(smb_tree_t *, uint16_t); +smb_ofile_t *smb_ofile_lookup_by_fid(smb_request_t *, uint16_t); smb_ofile_t *smb_ofile_lookup_by_uniqid(smb_tree_t *, uint32_t); boolean_t smb_ofile_disallow_fclose(smb_ofile_t *); -smb_ofile_t *smb_ofile_open(smb_tree_t *, smb_node_t *, uint16_t, +smb_ofile_t *smb_ofile_open(smb_request_t *, smb_node_t *, uint16_t, smb_arg_open_t *, uint16_t, uint32_t, smb_error_t *); void smb_ofile_close(smb_ofile_t *, int32_t); void smb_ofile_delete(void *); @@ -603,18 +612,11 @@ smb_user_t *smb_user_login(smb_session_t *, cred_t *, smb_user_t *smb_user_dup(smb_user_t *); void smb_user_logoff(smb_user_t *); void smb_user_delete(void *); -void smb_user_post_tree(smb_user_t *, smb_tree_t *); -smb_tree_t *smb_user_lookup_tree(smb_user_t *, uint16_t); -smb_tree_t *smb_user_lookup_share(smb_user_t *, const char *, smb_tree_t *); -smb_tree_t *smb_user_lookup_volume(smb_user_t *, const char *, smb_tree_t *); boolean_t smb_user_is_admin(smb_user_t *); boolean_t smb_user_namecmp(smb_user_t *, const char *); int smb_user_enum(smb_user_t *, smb_svcenum_t *); -void smb_user_close_pid(smb_user_t *, uint16_t); -void smb_user_disconnect_trees(smb_user_t *user); -void smb_user_disconnect_share(smb_user_t *, const char *); -int smb_user_fclose(smb_user_t *, uint32_t); boolean_t smb_user_hold(smb_user_t *); +void smb_user_hold_internal(smb_user_t *); void smb_user_release(smb_user_t *); cred_t *smb_user_getcred(smb_user_t *); cred_t *smb_user_getprivcred(smb_user_t *); @@ -637,7 +639,7 @@ int smb_tree_enum(smb_tree_t *, smb_svcenum_t *); int smb_tree_fclose(smb_tree_t *, uint32_t); boolean_t smb_tree_hold(smb_tree_t *); void smb_tree_release(smb_tree_t *); -smb_odir_t *smb_tree_lookup_odir(smb_tree_t *, uint16_t); +smb_odir_t *smb_tree_lookup_odir(smb_request_t *, uint16_t); boolean_t smb_tree_is_connected(smb_tree_t *); #define SMB_TREE_GET_TID(tree) ((tree)->t_tid) diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 493e7130a7..2c5d102f62 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -908,7 +908,9 @@ typedef struct smb_session { smb_slist_t s_req_list; smb_llist_t s_xa_list; smb_llist_t s_user_list; + smb_llist_t s_tree_list; smb_idpool_t s_uid_pool; + smb_idpool_t s_tid_pool; smb_txlst_t s_txlst; volatile uint32_t s_tree_cnt; @@ -975,9 +977,6 @@ typedef struct smb_user { cred_t *u_cred; cred_t *u_privcred; - smb_llist_t u_tree_list; - smb_idpool_t u_tid_pool; - uint32_t u_refcnt; uint32_t u_flags; uint32_t u_privileges; @@ -1028,7 +1027,11 @@ typedef struct smb_tree { struct smb_server *t_server; smb_session_t *t_session; - smb_user_t *t_user; + /* + * user whose uid was in the tree connect message + * ("owner" in MS-CIFS parlance, see section 2.2.1.6 definition of FID) + */ + smb_user_t *t_owner; smb_node_t *t_snode; smb_llist_t t_ofile_list; @@ -1259,6 +1262,7 @@ typedef struct smb_odir { list_node_t d_lnd; smb_odir_state_t d_state; smb_session_t *d_session; + smb_user_t *d_user; smb_tree_t *d_tree; smb_node_t *d_dnode; cred_t *d_cred; |