/* * smb_pathname_preprocess * * Perform common pre-processing of pn->pn_path: * - if the pn_path is blank, set it to '\\' * - perform unicode wildcard converstion. * - convert any '/' to '\\' * - eliminate duplicate slashes * - remove trailing slashes * - quota directory specific pre-processing */ static void smb_pathname_preprocess(smb_request_t *sr, smb_pathname_t *pn) { char *p; /* treat empty path as "\\" */ if (strlen(pn->pn_path) == 0) { pn->pn_path = smb_pathname_strdup(sr, "\\"); return; } if (sr->session->dialect < NT_LM_0_12) smb_convert_wildcards(pn->pn_path); /* treat '/' as '\\' */ (void) strsubst(pn->pn_path, '/', '\\'); (void) strcanon(pn->pn_path, "\\"); /* remove trailing '\\' */ p = pn->pn_path + strlen(pn->pn_path) - 1; if ((p != pn->pn_path) && (*p == '\\')) *p = '\0'; smb_pathname_preprocess_quota(sr, pn); smb_pathname_preprocess_adminshare(sr, pn); }
/* * smb_odir_open * * Create an odir representing the directory specified in pathname. * * Returns: * odid - Unique identifier of newly created odir. * 0 - error, error details set in sr. */ uint16_t smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags) { int rc; smb_tree_t *tree; smb_node_t *dnode; char pattern[MAXNAMELEN]; uint16_t odid; cred_t *cr; ASSERT(sr); ASSERT(sr->sr_magic == SMB_REQ_MAGIC); ASSERT(sr->tid_tree); ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC); tree = sr->tid_tree; if (sr->session->dialect < NT_LM_0_12) smb_convert_wildcards(path); rc = smb_pathname_reduce(sr, sr->user_cr, path, tree->t_snode, tree->t_snode, &dnode, pattern); if (rc != 0) { smbsr_errno(sr, rc); return (0); } if (!smb_node_is_dir(dnode)) { smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, ERRDOS, ERROR_PATH_NOT_FOUND); smb_node_release(dnode); return (0); } if (smb_fsop_access(sr, sr->user_cr, dnode, FILE_LIST_DIRECTORY) != 0) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); smb_node_release(dnode); return (0); } if (flags & SMB_ODIR_OPENF_BACKUP_INTENT) cr = smb_user_getprivcred(sr->uid_user); else cr = sr->uid_user->u_cred; odid = smb_odir_create(sr, dnode, pattern, sattr, cr); smb_node_release(dnode); return (odid); }
/* * smb_com_trans2_find_first2 * * Client Request Value * ============================ ================================== * * UCHAR WordCount 15 * UCHAR TotalDataCount Total size of extended attribute list * UCHAR SetupCount 1 * UCHAR Setup[0] TRANS2_FIND_FIRST2 * * Parameter Block Encoding Description * ============================ ================================== * USHORT SearchAttributes; * USHORT SearchCount; Maximum number of entries to return * USHORT Flags; Additional information: * Bit 0 - close search after this request * Bit 1 - close search if end of search * reached * Bit 2 - return resume keys for each * entry found * Bit 3 - continue search from previous * ending place * Bit 4 - find with backup intent * USHORT InformationLevel; See below * ULONG SearchStorageType; * STRING FileName; Pattern for the search * UCHAR Data[ TotalDataCount ] FEAList if InformationLevel is * QUERY_EAS_FROM_LIST * * Response Parameter Block Description * ============================ ================================== * * USHORT Sid; Search handle * USHORT SearchCount; Number of entries returned * USHORT EndOfSearch; Was last entry returned? * USHORT EaErrorOffset; Offset into EA list if EA error * USHORT LastNameOffset; Offset into data to file name of last * entry, if server needs it to resume * search; else 0 * UCHAR Data[ TotalDataCount ] Level dependent info about the matches * found in the search */ smb_sdrc_t smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) { int count; uint16_t sattr, odid; char *path; smb_odir_t *od; smb_find_args_t args; boolean_t eos; uint32_t odir_flags = 0; bzero(&args, sizeof (smb_find_args_t)); if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); return (SDRC_ERROR); } if (smb_mbc_decodef(&xa->req_param_mb, "%wwww4.u", sr, &sattr, &args.fa_maxcount, &args.fa_fflag, &args.fa_infolev, &path) != 0) { return (SDRC_ERROR); } if (smb_is_stream_name(path)) { smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, ERRDOS, ERROR_INVALID_NAME); return (SDRC_ERROR); } if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT) { sr->user_cr = smb_user_getprivcred(sr->uid_user); odir_flags = SMB_ODIR_OPENF_BACKUP_INTENT; } args.fa_maxdata = smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag); if (args.fa_maxdata == 0) return (SDRC_ERROR); if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) (void) smb_convert_wildcards(path); odid = smb_odir_open(sr, path, sattr, odir_flags); if (odid == 0) return (SDRC_ERROR); od = smb_tree_lookup_odir(sr->tid_tree, odid); if (od == NULL) return (SDRC_ERROR); count = smb_trans2_find_entries(sr, xa, od, &args, &eos); if (count == -1) { smb_odir_close(od); smb_odir_release(od); return (SDRC_ERROR); } if (count == 0) { smb_odir_close(od); smb_odir_release(od); smbsr_errno(sr, ENOENT); return (SDRC_ERROR); } if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) || (eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) { smb_odir_close(od); } /* else leave odir open for trans2_find_next2 */ smb_odir_release(od); (void) smb_mbc_encodef(&xa->rep_param_mb, "wwwww", odid, count, (eos) ? 1 : 0, 0, 0); return (SDRC_SUCCESS); }