/* * smb_pathname_validate * * Perform basic validation of pn: * - If first component of pn->path is ".." -> PATH_SYNTAX_BAD * - If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID * - If fname is "." -> INVALID_OBJECT_NAME * * On unix .. at the root of a file system links to the root. Thus * an attempt to lookup "/../../.." will be the same as looking up "/" * CIFs clients expect the above to result in * NT_STATUS_OBJECT_PATH_SYNTAX_BAD. It is currently not possible * (and questionable if it's desirable) to deal with all cases * but paths beginning with \\.. are handled. * * Returns: B_TRUE if pn is valid, * otherwise returns B_FALSE and sets error status in sr. */ boolean_t smb_pathname_validate(smb_request_t *sr, smb_pathname_t *pn) { char *path = pn->pn_path; /* ignore any initial "\\" */ path += strspn(path, "\\"); /* If first component of path is ".." -> PATH_SYNTAX_BAD */ if ((strcmp(path, "..") == 0) || (strncmp(path, "..\\", 3) == 0)) { smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD, ERRDOS, ERROR_BAD_PATHNAME); return (B_FALSE); } /* If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID */ if (pn->pn_pname && smb_contains_wildcards(pn->pn_pname)) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, ERRDOS, ERROR_INVALID_NAME); return (B_FALSE); } /* If fname is "." -> INVALID_OBJECT_NAME */ if (pn->pn_fname && (strcmp(pn->pn_fname, ".") == 0)) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, ERRDOS, ERROR_PATH_NOT_FOUND); return (B_FALSE); } return (B_TRUE); }
/* * smb_odir_create * Allocate and populate an odir obect and add it to the tree's list. */ static uint16_t smb_odir_create(smb_request_t *sr, smb_node_t *dnode, char *pattern, uint16_t sattr, cred_t *cr) { smb_odir_t *od; smb_tree_t *tree; uint16_t odid; ASSERT(sr); ASSERT(sr->sr_magic == SMB_REQ_MAGIC); ASSERT(sr->tid_tree); ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC); ASSERT(dnode); ASSERT(dnode->n_magic == SMB_NODE_MAGIC); tree = sr->tid_tree; if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) { smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, ERRDOS, ERROR_TOO_MANY_OPEN_FILES); return (0); } od = kmem_cache_alloc(smb_cache_odir, KM_SLEEP); bzero(od, sizeof (smb_odir_t)); mutex_init(&od->d_mutex, NULL, MUTEX_DEFAULT, NULL); od->d_refcnt = 0; od->d_state = SMB_ODIR_STATE_OPEN; od->d_magic = SMB_ODIR_MAGIC; 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); od->d_odid = odid; od->d_sattr = sattr; (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern)); od->d_flags = 0; if (smb_contains_wildcards(od->d_pattern)) od->d_flags |= SMB_ODIR_FLAG_WILDCARDS; if (vfs_has_feature(dnode->vp->v_vfsp, VFSFT_DIRENTFLAGS)) od->d_flags |= SMB_ODIR_FLAG_EDIRENT; if (smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE)) od->d_flags |= SMB_ODIR_FLAG_IGNORE_CASE; if (smb_tree_has_feature(tree, SMB_TREE_SHORTNAMES)) od->d_flags |= SMB_ODIR_FLAG_SHORTNAMES; if (SMB_TREE_SUPPORTS_CATIA(sr)) od->d_flags |= SMB_ODIR_FLAG_CATIA; if (SMB_TREE_SUPPORTS_ABE(sr)) od->d_flags |= SMB_ODIR_FLAG_ABE; if (dnode->flags & NODE_XATTR_DIR) od->d_flags |= SMB_ODIR_FLAG_XATTR; od->d_eof = B_FALSE; smb_llist_enter(&tree->t_odir_list, RW_WRITER); smb_llist_insert_tail(&tree->t_odir_list, od); smb_llist_exit(&tree->t_odir_list); atomic_inc_32(&tree->t_session->s_dir_cnt); return (odid); }