15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 225772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <smbsrv/smb_incl.h> 295331Samw 305331Samw 315331Samw /* 325331Samw * smb_com_find 335331Samw * 345331Samw * Request Format: (same as core Search Protocol - "Find First" form) 355331Samw * 365331Samw * Client Request Description 375331Samw * ================================== ================================= 385331Samw * 395331Samw * BYTE smb_wct; value = 2 405331Samw * WORD smb_count; max number of entries to find 415331Samw * WORD smb_attr; search attribute 425331Samw * WORD smb_bcc; minimum value = 5 435331Samw * BYTE smb_ident1; ASCII (04) 445331Samw * BYTE smb_pathname[]; filename (may contain global characters) 455331Samw * BYTE smb_ident2; Variable Block (05) 465331Samw * WORD smb_keylen; resume key length (zero if "Find First") 475331Samw * BYTE smb_resumekey[*]; "Find Next" key, * = value of smb_keylen 485331Samw * 495331Samw * Response Format: (same as core Search Protocol) 505331Samw * 515331Samw * Server Response Description 525331Samw * ================================== ================================= 535331Samw * BYTE smb_wct; value = 1 545331Samw * WORD smb_count; number of entries found 555331Samw * WORD smb_bcc; minimum value = 3 565331Samw * BYTE smb_ident; Variable Block (05) 575331Samw * WORD smb_datalen; data length 585331Samw * BYTE smb_data[*]; directory entries 595331Samw * 605331Samw * Directory Information Entry (dir_info) Format: (same as core Search Protocol) 615331Samw * 625331Samw * BYTE find_buf_reserved[21]; reserved (resume_key) 635331Samw * BYTE find_buf_attr; attribute 645331Samw * WORD find_buf_time; modification time (hhhhh mmmmmm xxxxx) 655331Samw * where 'xxxxx' is in 2 second increments 665331Samw * WORD find_buf_date; modification date (yyyyyyy mmmm ddddd) 675331Samw * DWORD find_buf_size; file size 685331Samw * STRING find_buf_pname[13]; file name -- ASCII (null terminated) 695331Samw * 705331Samw * The resume_key has the following format: 715331Samw * 725331Samw * BYTE sr_res; reserved: 735331Samw * bit 7 - reserved for consumer use 745331Samw * bit 5,6 - reserved for system use 755331Samw * (must be preserved) 765331Samw * bits 0-4 - reserved for server 775331Samw * (must be preserved) 785331Samw * BYTE sr_name[11]; pathname sought. 795331Samw * Format: 1-8 character file name, 805331Samw * left justified 0-3 character extension, 815331Samw * BYTE sr_findid[1]; uniquely identifies find through 825331Samw * find_close 835331Samw * BYTE sr_server[4]; available for server use 845331Samw * (must be non-zero) 855331Samw * BYTE sr_res[4]; reserved for consumer use 865331Samw * 875331Samw * Service: 885331Samw * 895331Samw * The Find protocol finds the directory entry or group of entries matching the 905331Samw * specified file pathname. The filename portion of the pathname may contain 915331Samw * global (wild card) characters. 925331Samw * 935331Samw * The Find protocol is used to match the find OS/2 system call. The protocols 945331Samw * "Find", "Find_Unique" and "Find_Close" are methods of reading (or searching) 955331Samw * a directory. These protocols may be used in place of the core "Search" 965331Samw * protocol when LANMAN 1.0 dialect has been negotiated. There may be cases 975331Samw * where the Search protocol will still be used. 985331Samw * 995331Samw * The format of the Find protocol is the same as the core "Search" protocol. 1005331Samw * The difference is that the directory is logically Opened with a Find protocol 1015331Samw * and logically closed with the Find Close protocol. This allows the Server to 1025331Samw * make better use of its resources. Search buffers are thus held (allowing 1035331Samw * search resumption via presenting a "resume_key") until a Find Close protocol 1045331Samw * is received. The sr_findid field of each resume key is a unique identifier 1055331Samw * (within the session) of the search from "Find" through "Find close". Thus if 1065331Samw * the consumer does "Find ahead", any find buffers containing resume keys with 1075331Samw * the matching find id may be released when the Find Close is requested. 1085331Samw * 1095331Samw * As is true of a failing open, if a Find request (Find "first" request where 1105331Samw * resume_key is null) fails (no entries are found), no find close protocol is 1115331Samw * expected. 1125331Samw * 1135331Samw * If no global characters are present, a "Find Unique" protocol should be used 1145331Samw * (only one entry is expected and find close need not be sent). 1155331Samw * 1165331Samw * The file path name in the request specifies the file to be sought. The 1175331Samw * attribute field indicates the attributes that the file must have. If the 1185331Samw * attribute is zero then only normal files are returned. If the system file, 1195331Samw * hidden or directory attributes are specified then the search is inclusive -- 1205331Samw * both the specified type(s) of files and normal files are returned. If the 1215331Samw * volume label attribute is specified then the search is exclusive, and only 1225331Samw * the volume label entry is returned 1235331Samw * 1245331Samw * The max-count field specifies the number of directory entries to be returned. 1255331Samw * The response will contain zero or more directory entries as determined by the 1265331Samw * count-returned field. No more than max-count entries will be returned. Only 1275331Samw * entries that match the sought filename/attribute will be returned. 1285331Samw * 1295331Samw * The resume_key field must be null (length = 0) on the initial ("Find First") 1305331Samw * find request. Subsequent find requests intended to continue a search must 1315331Samw * contain the resume_key field extracted from the last directory entry of the 1325331Samw * previous response. The resume_key field is self-contained, for on calls 1335331Samw * containing a resume_key neither the attribute or pathname fields will be 1345331Samw * valid in the request. A find request will terminate when either the 1355331Samw * requested maximum number of entries that match the named file are found, or 1365331Samw * the end of directory is reached without the maximum number of matches being 1375331Samw * found. A response containing no entries indicates that no matching entries 1385331Samw * were found between the starting point of the search and the end of directory. 1395331Samw * 1405331Samw * There may be multiple matching entries in response to a single request as 1415331Samw * Find supports "wild cards" in the file name (last component of the pathname). 1425331Samw * "?" is the wild single characters, "*" or "null" will match any number of 1435331Samw * filename characters within a single part of the filename component. The 1445331Samw * filename is divided into two parts -- an eight character name and a three 1455331Samw * character extension. The name and extension are divided by a ".". 1465331Samw * 1475331Samw * If a filename part commences with one or more "?"s then exactly that number 1485331Samw * of characters will be matched by the Wild Cards, e.g., "??x" will equal "abx" 1495331Samw * but not "abcx" or "ax". When a filename part has trailing "?"s then it will 1505331Samw * match the specified number of characters or less, e.g., "x??" will match 1515331Samw * "xab", "xa" and "x", but not "xabc". If only "?"s are present in the filename 1525331Samw * part, then it is handled as for trailing "?"s "*" or "null" match entire 1535331Samw * pathname parts, thus "*.abc" or ".abc" will match any file with an extension 1545331Samw * of "abc". "*.*", "*" or "null" will match all files in a directory. 1555331Samw * 1565331Samw * Unprotected servers require the requester to have read permission on the 1575331Samw * subtree containing the directory searched (the share specifies read 1585331Samw * permission). 1595331Samw * 1605331Samw * Protected servers require the requester to have permission to search the 1615331Samw * specified directory. 1625331Samw * 1635331Samw * If a Find requests more data than can be placed in a message of the 1645331Samw * max-xmit-size for the TID specified, the server will return only the number 1655331Samw * of entries which will fit. 1665331Samw * 1675331Samw * The number of entries returned will be the minimum of: 1685331Samw * 1. The number of entries requested. 1695331Samw * 2. The number of (complete) entries that will fit in the negotiated SMB 1705331Samw * buffer. 1715331Samw * 3. The number of entries that match the requested name pattern and 1725331Samw * attributes. 1735331Samw * 1745331Samw * The error ERRnofiles set in smb_err field of the response header or a zero 1755331Samw * value in smb_count of the response indicates no matching entry was found. 1765331Samw * 1775331Samw * The resume search key returned along with each directory entry is a server 1785331Samw * defined key which when returned in the Find Next protocol, allows the 1795331Samw * directory search to be resumed at the directory entry fol lowing the one 1805331Samw * denoted by the resume search key. 1815331Samw * 1825331Samw * The date is in the following format: 1835331Samw * bits: 1845331Samw * 1 1 1 1 1 1 1855331Samw * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 1865331Samw * y y y y y y y m m m m d d d d d 1875331Samw * where: 1885331Samw * y - bit of year 0-119 (1980-2099) 1895331Samw * m - bit of month 1-12 1905331Samw * d - bit of day 1-31 1915331Samw * 1925331Samw * The time is in the following format: 1935331Samw * bits: 1945331Samw * 1 1 1 1 1 1 1955331Samw * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 1965331Samw * h h h h h m m m m m m x x x x x 1975331Samw * where: 1985331Samw * h - bit of hour (0-23) 1995331Samw * m - bit of minute (0-59) 2005331Samw * x - bit of 2 second increment 2015331Samw * 2025331Samw * Find may generate the following errors. 2035331Samw * ERRDOS/ERRnofiles 2045331Samw * ERRDOS/ERRbadpath 2055331Samw * ERRDOS/ERRnoaccess 2065331Samw * ERRDOS/ERRbadaccess 2075331Samw * ERRDOS/ERRbadshare 2085331Samw * ERRSRV/ERRerror 2095331Samw * ERRSRV/ERRaccess 2105331Samw * ERRSRV/ERRinvnid 2115331Samw */ 212*6030Sjb150015 smb_sdrc_t 2135331Samw smb_com_find(struct smb_request *sr) 2145331Samw { 2155331Samw int rc; 2165331Samw unsigned short sattr, count, maxcount; 2175331Samw char *path; 2185331Samw char filename[14]; 2195331Samw uint32_t cookie; 2205331Samw struct smb_node *node; 2215331Samw unsigned char type; 2225331Samw unsigned short key_len; 2235331Samw smb_odir_context_t *pc; 2245331Samw 225*6030Sjb150015 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 226*6030Sjb150015 return (SDRC_ERROR_REPLY); 2275331Samw 228*6030Sjb150015 rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); 229*6030Sjb150015 if ((rc != 0) || (type != 0x05)) 230*6030Sjb150015 return (SDRC_ERROR_REPLY); 2315331Samw 2325331Samw if (key_len == 0) { /* begin search */ 233*6030Sjb150015 if (smb_rdir_open(sr, path, sattr) != 0) 234*6030Sjb150015 return (SDRC_ERROR_REPLY); 2355331Samw cookie = 0; 2365331Samw } else if (key_len == 21) { 2375331Samw sr->smb_sid = 0; 2385331Samw if (smb_decode_mbc(&sr->smb_data, SMB_RESUME_KEY_FMT, 2395331Samw filename, &sr->smb_sid, &cookie) != 0) { 2405331Samw /* We don't know which rdir to close */ 241*6030Sjb150015 return (SDRC_ERROR_REPLY); 2425331Samw } 2435331Samw 2445331Samw sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, 2455331Samw sr->smb_sid); 2465331Samw if (sr->sid_odir == NULL) { 2475772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 2485331Samw ERRDOS, ERRbadfid); 249*6030Sjb150015 return (SDRC_ERROR_REPLY); 2505331Samw } 2515331Samw 2525331Samw cookie--; /* +1 when returned */ 2535331Samw } else { 2545331Samw /* We don't know which rdir to close */ 255*6030Sjb150015 return (SDRC_ERROR_REPLY); 2565331Samw } 2575331Samw 2585331Samw (void) smb_encode_mbc(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); 2595331Samw 2605331Samw pc = MEM_ZALLOC("smb", sizeof (*pc)); 2615331Samw pc->dc_cookie = cookie; 2625331Samw count = 0; 2635331Samw node = (struct smb_node *)0; 2645331Samw rc = 0; 2655331Samw while (count < maxcount) { 2665331Samw if ((rc = smb_rdir_next(sr, &node, pc)) != 0) 2675331Samw break; 2685331Samw 2695331Samw (void) smb_encode_mbc(&sr->reply, ".8c3cbl4.bYl13c", 2705331Samw pc->dc_name83, pc->dc_name83+9, sr->smb_sid, 2715331Samw pc->dc_cookie+1, pc->dc_dattr, 2725331Samw smb_gmt_to_local_time(pc->dc_attr.sa_vattr.va_mtime.tv_sec), 2735331Samw (int32_t)smb_node_get_size(node, &pc->dc_attr), 2745331Samw (*pc->dc_shortname) ? pc->dc_shortname : pc->dc_name); 2755331Samw smb_node_release(node); 2765331Samw node = (struct smb_node *)0; 2775331Samw count++; 2785331Samw } 2795331Samw MEM_FREE("smb", pc); 2805331Samw 2815331Samw if ((rc != 0) && (rc != ENOENT)) { 2825331Samw /* returned error by smb_rdir_next() */ 2835331Samw smb_rdir_close(sr); 2845772Sas200622 smbsr_errno(sr, rc); 285*6030Sjb150015 return (SDRC_ERROR_REPLY); 2865331Samw } 2875331Samw 2885331Samw if (count == 0) { 2895331Samw smb_rdir_close(sr); 2905772Sas200622 smbsr_error(sr, 0, ERRDOS, ERRnofiles); 291*6030Sjb150015 return (SDRC_ERROR_REPLY); 2925331Samw } 2935331Samw 2945331Samw rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8; 295*6030Sjb150015 if (smb_poke_mbc(&sr->reply, sr->cur_reply_offset, "bwwbw", 296*6030Sjb150015 1, count, rc+3, 5, rc) < 0) { 2975331Samw smb_rdir_close(sr); 298*6030Sjb150015 return (SDRC_ERROR_REPLY); 2995331Samw } 3005331Samw 3015331Samw return (SDRC_NORMAL_REPLY); 3025331Samw } 3035331Samw 3045331Samw /* 3055331Samw * smb_com_find_close 3065331Samw * 3075331Samw * Request Format: (same as core Search Protocol - "Find Next" form) 3085331Samw * 3095331Samw * Client Request Description 3105331Samw * ================================== ================================= 3115331Samw * 3125331Samw * BYTE smb_wct; value = 2 3135331Samw * WORD smb_count; max number of entries to find 3145331Samw * WORD smb_attr; search attribute 3155331Samw * WORD smb_bcc; minimum value = 5 3165331Samw * BYTE smb_ident1; ASCII (04) 3175331Samw * BYTE smb_pathname[]; null (may contain only null) 3185331Samw * BYTE smb_ident2; Variable Block (05) 3195331Samw * WORD smb_keylen; resume (close) key length 3205331Samw * (may not be zero) 3215331Samw * BYTE smb_resumekey[*]; "Find Close" key 3225331Samw * (* = value of smb_keylen) 3235331Samw * 3245331Samw * Response Format: (same format as core Search Protocol) 3255331Samw * 3265331Samw * Server Response Description 3275331Samw * ================================== ================================= 3285331Samw * 3295331Samw * BYTE smb_wct; value = 1 3305331Samw * WORD smb_reserved; reserved 3315331Samw * WORD smb_bcc; value = 3 3325331Samw * BYTE smb_ident; Variable Block (05) 3335331Samw * WORD smb_datalen; data length (value = 0) 3345331Samw * 3355331Samw * The resume_key (or close key) has the following format: 3365331Samw * 3375331Samw * BYTE sr_res; reserved: 3385331Samw * bit 7 - reserved for consumer use 3395331Samw * bit 5,6 - reserved for system use 3405331Samw * (must be preserved) 3415331Samw * bits 0-4 - rsvd for server 3425331Samw * (must be preserved by consumer) 3435331Samw * BYTE sr_name[11]; pathname sought. 3445331Samw * Format: 1-8 character file name, 3455331Samw * left justified 0-3 character extension, 3465331Samw * left justified (in last 3 chars) 3475331Samw * BYTE sr_findid[1]; uniquely identifies find 3485331Samw * through find_close 3495331Samw * BYTE sr_server[4]; available for server use 3505331Samw * (must be non-zero) 3515331Samw * BYTE sr_res[4]; reserved for consumer use 3525331Samw * 3535331Samw * Service: 3545331Samw * 3555331Samw * The Find_Close protocol closes the association between a Find id 3565331Samw * returned (in the resume_key) by the Find protocol and the directory 3575331Samw * search. 3585331Samw * 3595331Samw * Whereas the First Find protocol logically opens the directory, 3605331Samw * subsequent find protocols presenting a resume_key further "read" the 3615331Samw * directory, the Find Close protocol "closes" the directory allowing the 3625331Samw * server to free any resources held in support of the directory search. 3635331Samw * 3645331Samw * The Find Close protocol is used to match the find Close OS/2 3655331Samw * system call. The protocols "Find", "Find Unique" and "Find Close" are 3665331Samw * methods of reading (or searching) a directory. These protocols may 3675331Samw * be used in place of the core "Search" protocol when LANMAN 1.0 dialect has 3685331Samw * been negotiated. There may be cases where the Search protocol will still be 3695331Samw * used. 3705331Samw * 3715331Samw * Although only the find id portion the resume key should be 3725331Samw * required to identify the search being ter minated, the entire 3735331Samw * resume_key as returned in the previous Find, either a "Find First" or "Find 3745331Samw * Next" is sent to the server in this protocol. 3755331Samw * 3765331Samw * Find Close may generate the following errors: 3775331Samw * 3785331Samw * ERRDOS/ERRbadfid 3795331Samw * ERRSRV/ERRerror 3805331Samw * ERRSRV/ERRinvnid 3815331Samw */ 382*6030Sjb150015 smb_sdrc_t 3835331Samw smb_com_find_close(struct smb_request *sr) 3845331Samw { 3855331Samw unsigned short sattr, maxcount; 3865331Samw char *path; 3875331Samw char filename[14]; 3885331Samw uint32_t cookie; 3895331Samw unsigned char type; 3905331Samw unsigned short key_len; 3915331Samw int rc; 3925331Samw 393*6030Sjb150015 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 394*6030Sjb150015 return (SDRC_ERROR_REPLY); 3955331Samw 3965331Samw rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); 397*6030Sjb150015 if ((rc != 0) || (type != 0x05)) 398*6030Sjb150015 return (SDRC_ERROR_REPLY); 3995331Samw 4005331Samw if (key_len == 0) { /* begin search */ 4015772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 402*6030Sjb150015 return (SDRC_ERROR_REPLY); 4035331Samw } 4045331Samw 4055331Samw if (key_len == 21) { 4065331Samw sr->smb_sid = 0; 4075331Samw if (smb_decode_mbc(&sr->smb_data, SMB_RESUME_KEY_FMT, 4085331Samw filename, &sr->smb_sid, &cookie) != 0) { 409*6030Sjb150015 return (SDRC_ERROR_REPLY); 4105331Samw } 4115331Samw 4125331Samw sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, 4135331Samw sr->smb_sid); 4145331Samw if (sr->sid_odir == NULL) { 4155772Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 4165331Samw ERRDOS, ERRbadfid); 417*6030Sjb150015 return (SDRC_ERROR_REPLY); 4185331Samw } 4195331Samw 4205331Samw cookie--; /* +1 when returned */ 4215331Samw } else { 422*6030Sjb150015 return (SDRC_ERROR_REPLY); 4235331Samw } 4245331Samw 4255331Samw smb_rdir_close(sr); 426*6030Sjb150015 if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0)) 427*6030Sjb150015 return (SDRC_ERROR_REPLY); 4285331Samw return (SDRC_NORMAL_REPLY); 4295331Samw } 430