PageRenderTime 62ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c

https://bitbucket.org/osunix/osunix-gate
C | 2831 lines | 2119 code | 255 blank | 457 comment | 371 complexity | 3b8c9685fb05652d92bc904bc48edff4 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, BSD-3-Clause, BSD-2-Clause, LGPL-3.0, 0BSD, GPL-2.0, LGPL-2.0, AGPL-1.0, AGPL-3.0, GPL-3.0, LGPL-2.1
  1. /*
  2. * Copyright (c) 2000-2001 Boris Popov
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by Boris Popov.
  16. * 4. Neither the name of the author nor the names of any co-contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * $Id: smbfs_smb.c,v 1.73.38.1 2005/05/27 02:35:28 lindak Exp $
  33. */
  34. /*
  35. * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
  36. * Use is subject to license terms.
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/time.h>
  41. #include <sys/vnode.h>
  42. #include <sys/sunddi.h>
  43. #include <sys/cmn_err.h>
  44. #include <netsmb/smb_osdep.h>
  45. #include <netsmb/smb.h>
  46. #include <netsmb/smb_conn.h>
  47. #include <netsmb/smb_subr.h>
  48. #include <netsmb/smb_rq.h>
  49. #include <smbfs/smbfs.h>
  50. #include <smbfs/smbfs_node.h>
  51. #include <smbfs/smbfs_subr.h>
  52. /*
  53. * Jan 1 1980 as 64 bit NT time.
  54. * (tenths of microseconds since 1601)
  55. */
  56. const uint64_t NT1980 = 11960035200ULL*10000000ULL;
  57. /*
  58. * Local functions.
  59. * Not static, to aid debugging.
  60. */
  61. int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
  62. struct smbfattr *fap, struct smb_cred *scrp);
  63. int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
  64. struct smb_cred *scrp, uint16_t infolevel);
  65. int smbfs_smb_statfsLM1(struct smb_share *ssp,
  66. statvfs64_t *sbp, struct smb_cred *scrp);
  67. int smbfs_smb_statfsLM2(struct smb_share *ssp,
  68. statvfs64_t *sbp, struct smb_cred *scrp);
  69. int smbfs_smb_setfattrNT(struct smbnode *np, int fid,
  70. uint32_t attr, struct timespec *mtime, struct timespec *atime,
  71. struct smb_cred *scrp);
  72. int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid,
  73. struct timespec *mtime, struct timespec *atime,
  74. struct smb_cred *scrp);
  75. int smbfs_smb_setpattr1(struct smbnode *np,
  76. const char *name, int len, uint32_t attr,
  77. struct timespec *mtime, struct smb_cred *scrp);
  78. /*
  79. * Todo: locking over-the-wire
  80. */
  81. #ifdef APPLE
  82. static int
  83. smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid,
  84. offset_t start, uint64_t len, int largelock,
  85. struct smb_cred *scrp, uint32_t timeout)
  86. {
  87. struct smb_share *ssp = np->n_mount->smi_share;
  88. struct smb_rq rq, *rqp = &rq;
  89. struct mbchain *mbp;
  90. uint8_t ltype = 0;
  91. int error;
  92. /* Shared lock for n_fid use below. */
  93. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  94. /* After reconnect, n_fid is invalid */
  95. if (np->n_vcgenid != ssp->ss_vcgenid)
  96. return (ESTALE);
  97. if (op == SMB_LOCK_SHARED)
  98. ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
  99. /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
  100. if (largelock)
  101. ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
  102. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
  103. if (error)
  104. return (error);
  105. smb_rq_getrequest(rqp, &mbp);
  106. smb_rq_wstart(rqp);
  107. mb_put_uint8(mbp, 0xff); /* secondary command */
  108. mb_put_uint8(mbp, 0); /* MBZ */
  109. mb_put_uint16le(mbp, 0);
  110. mb_put_uint16le(mbp, np->n_fid);
  111. mb_put_uint8(mbp, ltype); /* locktype */
  112. mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */
  113. mb_put_uint32le(mbp, timeout); /* 0 nowait, -1 infinite wait */
  114. mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0);
  115. mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1);
  116. smb_rq_wend(rqp);
  117. smb_rq_bstart(rqp);
  118. mb_put_uint16le(mbp, pid);
  119. if (!largelock) {
  120. mb_put_uint32le(mbp, start);
  121. mb_put_uint32le(mbp, len);
  122. } else {
  123. mb_put_uint16le(mbp, 0); /* pad */
  124. mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
  125. mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
  126. mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
  127. mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
  128. }
  129. smb_rq_bend(rqp);
  130. /*
  131. * Don't want to risk missing a successful
  132. * unlock send or lock response, or we could
  133. * lose track of an outstanding lock.
  134. */
  135. if (op == SMB_LOCK_RELEASE)
  136. rqp->sr_flags |= SMBR_NOINTR_SEND;
  137. else
  138. rqp->sr_flags |= SMBR_NOINTR_RECV;
  139. error = smb_rq_simple(rqp);
  140. smb_rq_done(rqp);
  141. return (error);
  142. }
  143. int
  144. smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
  145. offset_t start, uint64_t len, int largelock,
  146. struct smb_cred *scrp, uint32_t timeout)
  147. {
  148. struct smb_share *ssp = np->n_mount->smi_share;
  149. if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0)
  150. /*
  151. * TODO: use LOCK_BYTE_RANGE here.
  152. */
  153. return (EINVAL);
  154. /*
  155. * XXX: compute largelock via:
  156. * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)?
  157. */
  158. return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
  159. largelock, scrp, timeout));
  160. }
  161. #endif /* APPLE */
  162. /*
  163. * Helper for smbfs_getattr
  164. * Something like nfs_getattr_otw
  165. */
  166. int
  167. smbfs_smb_getfattr(
  168. struct smbnode *np,
  169. struct smbfattr *fap,
  170. struct smb_cred *scrp)
  171. {
  172. int error;
  173. /*
  174. * This lock is necessary for FID-based calls.
  175. * Lock may be writer (via open) or reader.
  176. */
  177. ASSERT(np->r_lkserlock.count != 0);
  178. /*
  179. * Extended attribute directory or file.
  180. */
  181. if (np->n_flag & N_XATTR) {
  182. error = smbfs_xa_getfattr(np, fap, scrp);
  183. return (error);
  184. }
  185. error = smbfs_smb_trans2_query(np, fap, scrp, 0);
  186. if (error != EINVAL)
  187. return (error);
  188. /* fallback */
  189. error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
  190. return (error);
  191. }
  192. /*
  193. * Common function for QueryFileInfo, QueryPathInfo.
  194. */
  195. int
  196. smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
  197. struct smb_cred *scrp, uint16_t infolevel)
  198. {
  199. struct smb_share *ssp = np->n_mount->smi_share;
  200. struct smb_vc *vcp = SSTOVC(ssp);
  201. struct smb_t2rq *t2p;
  202. int error, svtz, timesok = 1;
  203. struct mbchain *mbp;
  204. struct mdchain *mdp;
  205. uint16_t cmd, date, time, wattr;
  206. uint64_t llongint, lsize;
  207. uint32_t size, dattr;
  208. /*
  209. * Shared lock for n_fid use below.
  210. * See smbfs_smb_getfattr()
  211. */
  212. ASSERT(np->r_lkserlock.count != 0);
  213. /*
  214. * If we have a valid open FID, use it.
  215. */
  216. if ((np->n_fidrefs > 0) &&
  217. (np->n_fid != SMB_FID_UNUSED) &&
  218. (np->n_vcgenid == ssp->ss_vcgenid))
  219. cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
  220. else
  221. cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
  222. top:
  223. error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
  224. if (error)
  225. return (error);
  226. mbp = &t2p->t2_tparam;
  227. mb_init(mbp);
  228. if (!infolevel) {
  229. if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12)
  230. infolevel = SMB_QFILEINFO_STANDARD;
  231. else
  232. infolevel = SMB_QFILEINFO_ALL_INFO;
  233. }
  234. if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
  235. mb_put_uint16le(mbp, np->n_fid);
  236. mb_put_uint16le(mbp, infolevel);
  237. if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
  238. mb_put_uint32le(mbp, 0);
  239. /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
  240. error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
  241. if (error) {
  242. smb_t2_done(t2p);
  243. return (error);
  244. }
  245. }
  246. t2p->t2_maxpcount = 2;
  247. t2p->t2_maxdcount = vcp->vc_txmax;
  248. error = smb_t2_request(t2p);
  249. if (error) {
  250. smb_t2_done(t2p);
  251. /* Invalid info level? Try fallback. */
  252. if (error == EINVAL &&
  253. infolevel == SMB_QFILEINFO_ALL_INFO) {
  254. infolevel = SMB_QFILEINFO_STANDARD;
  255. goto top;
  256. }
  257. return (error);
  258. }
  259. mdp = &t2p->t2_rdata;
  260. svtz = vcp->vc_sopt.sv_tz;
  261. switch (infolevel) {
  262. case SMB_QFILEINFO_STANDARD:
  263. md_get_uint16le(mdp, &date);
  264. md_get_uint16le(mdp, &time); /* creation time */
  265. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime);
  266. md_get_uint16le(mdp, &date);
  267. md_get_uint16le(mdp, &time); /* access time */
  268. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
  269. md_get_uint16le(mdp, &date);
  270. md_get_uint16le(mdp, &time); /* modify time */
  271. smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
  272. md_get_uint32le(mdp, &size); /* EOF position */
  273. fap->fa_size = size;
  274. md_get_uint32le(mdp, &size); /* allocation size */
  275. fap->fa_allocsz = size;
  276. error = md_get_uint16le(mdp, &wattr);
  277. fap->fa_attr = wattr;
  278. timesok = 1;
  279. break;
  280. case SMB_QFILEINFO_ALL_INFO:
  281. timesok = 0;
  282. /* creation time */
  283. md_get_uint64le(mdp, &llongint);
  284. if (llongint)
  285. timesok++;
  286. smb_time_NT2local(llongint, &fap->fa_createtime);
  287. /* last access time */
  288. md_get_uint64le(mdp, &llongint);
  289. if (llongint)
  290. timesok++;
  291. smb_time_NT2local(llongint, &fap->fa_atime);
  292. /* last write time */
  293. md_get_uint64le(mdp, &llongint);
  294. if (llongint)
  295. timesok++;
  296. smb_time_NT2local(llongint, &fap->fa_mtime);
  297. /* last change time */
  298. md_get_uint64le(mdp, &llongint);
  299. if (llongint)
  300. timesok++;
  301. smb_time_NT2local(llongint, &fap->fa_ctime);
  302. /* attributes */
  303. md_get_uint32le(mdp, &dattr);
  304. fap->fa_attr = dattr;
  305. /*
  306. * 4-Byte alignment - discard
  307. * Specs don't talk about this.
  308. */
  309. md_get_uint32le(mdp, NULL);
  310. /* allocation size */
  311. md_get_uint64le(mdp, &lsize);
  312. fap->fa_allocsz = lsize;
  313. /* File size */
  314. error = md_get_uint64le(mdp, &lsize);
  315. fap->fa_size = lsize;
  316. break;
  317. default:
  318. SMBVDEBUG("unexpected info level %d\n", infolevel);
  319. error = EINVAL;
  320. }
  321. smb_t2_done(t2p);
  322. /*
  323. * if all times are zero (observed with FAT on NT4SP6)
  324. * then fall back to older info level
  325. */
  326. if (!timesok) {
  327. if (infolevel == SMB_QFILEINFO_ALL_INFO) {
  328. infolevel = SMB_QFILEINFO_STANDARD;
  329. goto top;
  330. }
  331. error = EINVAL;
  332. }
  333. return (error);
  334. }
  335. /*
  336. * Support functions for _qstreaminfo
  337. * Moved to smbfs_xattr.c
  338. */
  339. int
  340. smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
  341. struct smb_cred *scrp)
  342. {
  343. struct smb_t2rq *t2p;
  344. struct mbchain *mbp;
  345. struct mdchain *mdp;
  346. int error;
  347. uint32_t nlen;
  348. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
  349. scrp, &t2p);
  350. if (error)
  351. return (error);
  352. mbp = &t2p->t2_tparam;
  353. mb_init(mbp);
  354. mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO);
  355. t2p->t2_maxpcount = 4;
  356. t2p->t2_maxdcount = 4 * 3 + 512;
  357. error = smb_t2_request(t2p);
  358. if (error)
  359. goto out;
  360. mdp = &t2p->t2_rdata;
  361. md_get_uint32le(mdp, &fsa->fsa_aflags);
  362. md_get_uint32le(mdp, &fsa->fsa_maxname);
  363. error = md_get_uint32le(mdp, &nlen); /* fs name length */
  364. if (error)
  365. goto out;
  366. /*
  367. * Get the FS type name.
  368. */
  369. bzero(fsa->fsa_tname, FSTYPSZ);
  370. if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
  371. uint16_t tmpbuf[FSTYPSZ];
  372. size_t tmplen, outlen;
  373. if (nlen > sizeof (tmpbuf))
  374. nlen = sizeof (tmpbuf);
  375. error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
  376. tmplen = nlen / 2; /* UCS-2 chars */
  377. outlen = FSTYPSZ - 1;
  378. (void) uconv_u16tou8(tmpbuf, &tmplen,
  379. (uchar_t *)fsa->fsa_tname, &outlen,
  380. UCONV_IN_LITTLE_ENDIAN);
  381. } else {
  382. if (nlen > (FSTYPSZ - 1))
  383. nlen = FSTYPSZ - 1;
  384. error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
  385. }
  386. /*
  387. * If fs_name starts with FAT, we can't set dates before 1980
  388. */
  389. if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
  390. SMB_SS_LOCK(ssp);
  391. ssp->ss_flags |= SMBS_FST_FAT;
  392. SMB_SS_UNLOCK(ssp);
  393. }
  394. out:
  395. smb_t2_done(t2p);
  396. return (0);
  397. }
  398. int
  399. smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
  400. struct smb_cred *scp)
  401. {
  402. int error;
  403. if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
  404. error = smbfs_smb_statfsLM2(ssp, sbp, scp);
  405. else
  406. error = smbfs_smb_statfsLM1(ssp, sbp, scp);
  407. return (error);
  408. }
  409. int
  410. smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
  411. struct smb_cred *scrp)
  412. {
  413. struct smb_t2rq *t2p;
  414. struct mbchain *mbp;
  415. struct mdchain *mdp;
  416. uint16_t bsize;
  417. uint32_t units, bpu, funits;
  418. uint64_t s, t, f;
  419. int error;
  420. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
  421. scrp, &t2p);
  422. if (error)
  423. return (error);
  424. mbp = &t2p->t2_tparam;
  425. mb_init(mbp);
  426. mb_put_uint16le(mbp, SMB_QFS_ALLOCATION);
  427. t2p->t2_maxpcount = 4;
  428. t2p->t2_maxdcount = 4 * 4 + 2;
  429. error = smb_t2_request(t2p);
  430. if (error)
  431. goto out;
  432. mdp = &t2p->t2_rdata;
  433. md_get_uint32le(mdp, NULL); /* fs id */
  434. md_get_uint32le(mdp, &bpu);
  435. md_get_uint32le(mdp, &units);
  436. md_get_uint32le(mdp, &funits);
  437. error = md_get_uint16le(mdp, &bsize);
  438. if (error)
  439. goto out;
  440. s = bsize;
  441. s *= bpu;
  442. t = units;
  443. f = funits;
  444. /*
  445. * Don't allow over-large blocksizes as they determine
  446. * Finder List-view size granularities. On the other
  447. * hand, we mustn't let the block count overflow the
  448. * 31 bits available.
  449. */
  450. while (s > 16 * 1024) {
  451. if (t > LONG_MAX)
  452. break;
  453. s /= 2;
  454. t *= 2;
  455. f *= 2;
  456. }
  457. while (t > LONG_MAX) {
  458. t /= 2;
  459. f /= 2;
  460. s *= 2;
  461. }
  462. sbp->f_bsize = (ulong_t)s; /* file system block size */
  463. sbp->f_blocks = t; /* total data blocks in file system */
  464. sbp->f_bfree = f; /* free blocks in fs */
  465. sbp->f_bavail = f; /* free blocks avail to non-superuser */
  466. sbp->f_files = (-1); /* total file nodes in file system */
  467. sbp->f_ffree = (-1); /* free file nodes in fs */
  468. out:
  469. smb_t2_done(t2p);
  470. return (0);
  471. }
  472. int
  473. smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
  474. struct smb_cred *scrp)
  475. {
  476. struct smb_rq rq, *rqp = &rq;
  477. struct mdchain *mdp;
  478. uint16_t units, bpu, bsize, funits;
  479. uint64_t s, t, f;
  480. int error;
  481. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
  482. scrp);
  483. if (error)
  484. return (error);
  485. smb_rq_wstart(rqp);
  486. smb_rq_wend(rqp);
  487. smb_rq_bstart(rqp);
  488. smb_rq_bend(rqp);
  489. error = smb_rq_simple(rqp);
  490. if (error)
  491. goto out;
  492. smb_rq_getreply(rqp, &mdp);
  493. md_get_uint16le(mdp, &units);
  494. md_get_uint16le(mdp, &bpu);
  495. md_get_uint16le(mdp, &bsize);
  496. error = md_get_uint16le(mdp, &funits);
  497. if (error)
  498. goto out;
  499. s = bsize;
  500. s *= bpu;
  501. t = units;
  502. f = funits;
  503. /*
  504. * Don't allow over-large blocksizes as they determine
  505. * Finder List-view size granularities. On the other
  506. * hand, we mustn't let the block count overflow the
  507. * 31 bits available.
  508. */
  509. while (s > 16 * 1024) {
  510. if (t > LONG_MAX)
  511. break;
  512. s /= 2;
  513. t *= 2;
  514. f *= 2;
  515. }
  516. while (t > LONG_MAX) {
  517. t /= 2;
  518. f /= 2;
  519. s *= 2;
  520. }
  521. sbp->f_bsize = (ulong_t)s; /* file system block size */
  522. sbp->f_blocks = t; /* total data blocks in file system */
  523. sbp->f_bfree = f; /* free blocks in fs */
  524. sbp->f_bavail = f; /* free blocks avail to non-superuser */
  525. sbp->f_files = (-1); /* total file nodes in file system */
  526. sbp->f_ffree = (-1); /* free file nodes in fs */
  527. out:
  528. smb_rq_done(rqp);
  529. return (0);
  530. }
  531. int
  532. smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize,
  533. struct smb_cred *scrp)
  534. {
  535. struct smb_t2rq *t2p;
  536. struct smb_vc *vcp = SSTOVC(ssp);
  537. struct mbchain *mbp;
  538. int error;
  539. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
  540. scrp, &t2p);
  541. if (error)
  542. return (error);
  543. mbp = &t2p->t2_tparam;
  544. mb_init(mbp);
  545. mb_put_uint16le(mbp, fid);
  546. if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
  547. mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION);
  548. else
  549. mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO);
  550. mb_put_uint16le(mbp, 0); /* pad */
  551. mbp = &t2p->t2_tdata;
  552. mb_init(mbp);
  553. mb_put_uint64le(mbp, newsize);
  554. t2p->t2_maxpcount = 2;
  555. t2p->t2_maxdcount = 0;
  556. error = smb_t2_request(t2p);
  557. smb_t2_done(t2p);
  558. return (error);
  559. }
  560. /*ARGSUSED*/
  561. int
  562. smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp,
  563. const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite)
  564. {
  565. struct smb_t2rq *t2p;
  566. struct smb_share *ssp = np->n_mount->smi_share;
  567. struct smb_vc *vcp = SSTOVC(ssp);
  568. struct mbchain *mbp;
  569. int32_t *ucslenp;
  570. int error, cerror;
  571. uint16_t fid = 0;
  572. /* Shared lock for n_fid use below. */
  573. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  574. /* After reconnect, n_fid is invalid */
  575. if (np->n_vcgenid != ssp->ss_vcgenid)
  576. return (ESTALE);
  577. if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU))
  578. return (ENOTSUP);
  579. error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
  580. scrp, &t2p);
  581. if (error)
  582. return (error);
  583. if (tdnp) {
  584. error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp,
  585. &fid);
  586. if (error)
  587. goto exit;
  588. }
  589. mbp = &t2p->t2_tparam;
  590. mb_init(mbp);
  591. mb_put_uint16le(mbp, np->n_fid);
  592. mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION);
  593. mb_put_uint16le(mbp, 0); /* reserved, nowadays */
  594. mbp = &t2p->t2_tdata;
  595. mb_init(mbp);
  596. mb_put_uint32le(mbp, overwrite);
  597. mb_put_uint16le(mbp, fid); /* base for tname */
  598. mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */
  599. ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t));
  600. mbp->mb_count = 0;
  601. error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE);
  602. if (error)
  603. goto exit;
  604. mbp->mb_count--; /* don't count the null */
  605. *ucslenp = htolel(mbp->mb_count);
  606. t2p->t2_maxpcount = 2;
  607. t2p->t2_maxdcount = 0;
  608. error = smb_t2_request(t2p);
  609. exit:
  610. if (fid) {
  611. cerror = smbfs_smb_tmpclose(tdnp, fid, scrp);
  612. if (cerror)
  613. SMBVDEBUG("error %d closing %s\n",
  614. cerror, tdnp->n_rpath);
  615. }
  616. smb_t2_done(t2p);
  617. return (error);
  618. }
  619. int
  620. smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp)
  621. {
  622. struct smb_share *ssp = np->n_mount->smi_share;
  623. struct smb_rq rq, *rqp = &rq;
  624. struct mbchain *mbp;
  625. int error;
  626. /* Shared lock for n_fid use below. */
  627. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  628. if (!(np->n_flag & NFLUSHWIRE))
  629. return (0);
  630. if (np->n_fidrefs == 0)
  631. return (0); /* not open */
  632. /* After reconnect, n_fid is invalid */
  633. if (np->n_vcgenid != ssp->ss_vcgenid)
  634. return (ESTALE);
  635. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
  636. if (error)
  637. return (error);
  638. smb_rq_getrequest(rqp, &mbp);
  639. smb_rq_wstart(rqp);
  640. mb_put_uint16le(mbp, np->n_fid);
  641. smb_rq_wend(rqp);
  642. smb_rq_bstart(rqp);
  643. smb_rq_bend(rqp);
  644. error = smb_rq_simple(rqp);
  645. smb_rq_done(rqp);
  646. if (!error) {
  647. mutex_enter(&np->r_statelock);
  648. np->n_flag &= ~NFLUSHWIRE;
  649. mutex_exit(&np->r_statelock);
  650. }
  651. return (error);
  652. }
  653. int
  654. smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
  655. struct smb_cred *scrp)
  656. {
  657. struct smb_share *ssp = np->n_mount->smi_share;
  658. struct smb_rq rq, *rqp = &rq;
  659. struct mbchain *mbp;
  660. int error;
  661. if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  662. /*
  663. * This call knows about 64-bit offsets.
  664. */
  665. error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
  666. if (!error) {
  667. mutex_enter(&np->r_statelock);
  668. np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
  669. mutex_exit(&np->r_statelock);
  670. return (0);
  671. }
  672. }
  673. /*
  674. * OK, so fallback to SMB_COM_WRITE, but note:
  675. * it only supports 32-bit file offsets.
  676. */
  677. if (newsize > UINT32_MAX)
  678. return (EFBIG);
  679. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp);
  680. if (error)
  681. return (error);
  682. smb_rq_getrequest(rqp, &mbp);
  683. smb_rq_wstart(rqp);
  684. mb_put_uint16le(mbp, fid);
  685. mb_put_uint16le(mbp, 0);
  686. mb_put_uint32le(mbp, newsize);
  687. mb_put_uint16le(mbp, 0);
  688. smb_rq_wend(rqp);
  689. smb_rq_bstart(rqp);
  690. mb_put_uint8(mbp, SMB_DT_DATA);
  691. mb_put_uint16le(mbp, 0);
  692. smb_rq_bend(rqp);
  693. error = smb_rq_simple(rqp);
  694. smb_rq_done(rqp);
  695. mutex_enter(&np->r_statelock);
  696. np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
  697. mutex_exit(&np->r_statelock);
  698. return (error);
  699. }
  700. /*
  701. * Old method for getting file attributes.
  702. */
  703. int
  704. smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
  705. struct smbfattr *fap, struct smb_cred *scrp)
  706. {
  707. struct smb_rq rq, *rqp = &rq;
  708. struct smb_share *ssp = np->n_mount->smi_share;
  709. struct mbchain *mbp;
  710. struct mdchain *mdp;
  711. uint8_t wc;
  712. int error;
  713. uint16_t wattr;
  714. uint32_t longint;
  715. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp);
  716. if (error)
  717. return (error);
  718. smb_rq_getrequest(rqp, &mbp);
  719. smb_rq_wstart(rqp);
  720. smb_rq_wend(rqp);
  721. smb_rq_bstart(rqp);
  722. mb_put_uint8(mbp, SMB_DT_ASCII);
  723. error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
  724. name, &nmlen, '\\');
  725. if (error)
  726. goto out;
  727. smb_rq_bend(rqp);
  728. error = smb_rq_simple(rqp);
  729. if (error)
  730. goto out;
  731. smb_rq_getreply(rqp, &mdp);
  732. error = md_get_uint8(mdp, &wc);
  733. if (error)
  734. goto out;
  735. if (wc != 10) {
  736. error = EBADRPC;
  737. goto out;
  738. }
  739. md_get_uint16le(mdp, &wattr);
  740. fap->fa_attr = wattr;
  741. /*
  742. * Be careful using the time returned here, as
  743. * with FAT on NT4SP6, at least, the time returned is low
  744. * 32 bits of 100s of nanoseconds (since 1601) so it rolls
  745. * over about every seven minutes!
  746. */
  747. md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
  748. smb_time_server2local(longint,
  749. SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
  750. error = md_get_uint32le(mdp, &longint);
  751. fap->fa_size = longint;
  752. out:
  753. smb_rq_done(rqp);
  754. return (error);
  755. }
  756. /*
  757. * Set DOS file attributes. mtime should be NULL for dialects above lm10
  758. */
  759. int
  760. smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len,
  761. uint32_t attr, struct timespec *mtime,
  762. struct smb_cred *scrp)
  763. {
  764. struct smb_rq rq, *rqp = &rq;
  765. struct smb_share *ssp = np->n_mount->smi_share;
  766. struct mbchain *mbp;
  767. long time;
  768. int error, svtz;
  769. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp);
  770. if (error)
  771. return (error);
  772. svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
  773. smb_rq_getrequest(rqp, &mbp);
  774. smb_rq_wstart(rqp);
  775. mb_put_uint16le(mbp, (uint16_t)attr);
  776. if (mtime) {
  777. smb_time_local2server(mtime, svtz, &time);
  778. } else
  779. time = 0;
  780. mb_put_uint32le(mbp, time); /* mtime */
  781. mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO);
  782. smb_rq_wend(rqp);
  783. smb_rq_bstart(rqp);
  784. mb_put_uint8(mbp, SMB_DT_ASCII);
  785. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
  786. if (error)
  787. goto out;
  788. mb_put_uint8(mbp, SMB_DT_ASCII);
  789. if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
  790. mb_put_padbyte(mbp);
  791. mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
  792. }
  793. mb_put_uint8(mbp, 0);
  794. smb_rq_bend(rqp);
  795. error = smb_rq_simple(rqp);
  796. out:
  797. smb_rq_done(rqp);
  798. return (error);
  799. }
  800. int
  801. smbfs_smb_hideit(struct smbnode *np, const char *name, int len,
  802. struct smb_cred *scrp)
  803. {
  804. struct smbfattr fa;
  805. int error;
  806. uint32_t attr;
  807. error = smbfs_smb_query_info(np, name, len, &fa, scrp);
  808. attr = fa.fa_attr;
  809. if (!error && !(attr & SMB_FA_HIDDEN)) {
  810. attr |= SMB_FA_HIDDEN;
  811. error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
  812. }
  813. return (error);
  814. }
  815. int
  816. smbfs_smb_unhideit(struct smbnode *np, const char *name, int len,
  817. struct smb_cred *scrp)
  818. {
  819. struct smbfattr fa;
  820. uint32_t attr;
  821. int error;
  822. error = smbfs_smb_query_info(np, name, len, &fa, scrp);
  823. attr = fa.fa_attr;
  824. if (!error && (attr & SMB_FA_HIDDEN)) {
  825. attr &= ~SMB_FA_HIDDEN;
  826. error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
  827. }
  828. return (error);
  829. }
  830. /*
  831. * Set file attributes (optionally: DOS attr, atime, mtime)
  832. * either by open FID or by path name (FID == -1).
  833. */
  834. int
  835. smbfs_smb_setfattr(
  836. struct smbnode *np,
  837. int fid,
  838. uint32_t attr,
  839. struct timespec *mtime,
  840. struct timespec *atime,
  841. struct smb_cred *scrp)
  842. {
  843. struct smb_share *ssp = np->n_mount->smi_share;
  844. struct smb_vc *vcp = SSTOVC(ssp);
  845. int error;
  846. /*
  847. * Normally can use the trans2 call.
  848. */
  849. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  850. error = smbfs_smb_setfattrNT(np, fid,
  851. attr, mtime, atime, scrp);
  852. return (error);
  853. }
  854. /*
  855. * Fall-back for older protocols.
  856. */
  857. if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
  858. error = smbfs_smb_setftime1(np, fid,
  859. mtime, atime, scrp);
  860. return (error);
  861. }
  862. error = smbfs_smb_setpattr1(np, NULL, 0,
  863. attr, mtime, scrp);
  864. return (error);
  865. }
  866. /*
  867. * Set file atime and mtime. Isn't supported by core dialect.
  868. */
  869. int
  870. smbfs_smb_setftime1(
  871. struct smbnode *np,
  872. uint16_t fid,
  873. struct timespec *mtime,
  874. struct timespec *atime,
  875. struct smb_cred *scrp)
  876. {
  877. struct smb_rq rq, *rqp = &rq;
  878. struct smb_share *ssp = np->n_mount->smi_share;
  879. struct mbchain *mbp;
  880. uint16_t date, time;
  881. int error, tzoff;
  882. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp);
  883. if (error)
  884. return (error);
  885. tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
  886. smb_rq_getrequest(rqp, &mbp);
  887. smb_rq_wstart(rqp);
  888. mb_put_uint16le(mbp, fid);
  889. mb_put_uint32le(mbp, 0); /* creation time */
  890. if (atime)
  891. smb_time_unix2dos(atime, tzoff, &date, &time, NULL);
  892. else
  893. time = date = 0;
  894. mb_put_uint16le(mbp, date);
  895. mb_put_uint16le(mbp, time);
  896. if (mtime)
  897. smb_time_unix2dos(mtime, tzoff, &date, &time, NULL);
  898. else
  899. time = date = 0;
  900. mb_put_uint16le(mbp, date);
  901. mb_put_uint16le(mbp, time);
  902. smb_rq_wend(rqp);
  903. smb_rq_bstart(rqp);
  904. smb_rq_bend(rqp);
  905. error = smb_rq_simple(rqp);
  906. SMBVDEBUG("%d\n", error);
  907. smb_rq_done(rqp);
  908. return (error);
  909. }
  910. /*
  911. * Set DOS file attributes, either via open FID or by path name.
  912. * Looks like this call can be used only if CAP_NT_SMBS bit is on.
  913. *
  914. * When setting via path (fid == -1):
  915. * *BASIC_INFO works with Samba, but Win2K servers say it is an
  916. * invalid information level on a SET_PATH_INFO. Note Win2K does
  917. * support *BASIC_INFO on a SET_FILE_INFO, and they support the
  918. * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure.
  919. */
  920. int
  921. smbfs_smb_setfattrNT(
  922. struct smbnode *np,
  923. int fid, /* if fid == -1, set by path */
  924. uint32_t attr,
  925. struct timespec *mtime,
  926. struct timespec *atime,
  927. struct smb_cred *scrp)
  928. {
  929. struct smb_t2rq *t2p;
  930. struct smb_share *ssp = np->n_mount->smi_share;
  931. struct smb_vc *vcp = SSTOVC(ssp);
  932. struct mbchain *mbp;
  933. uint64_t tm;
  934. int error;
  935. uint16_t cmd, level;
  936. if (fid == -1) {
  937. cmd = SMB_TRANS2_SET_PATH_INFORMATION;
  938. } else {
  939. if (fid > UINT16_MAX)
  940. return (EINVAL);
  941. cmd = SMB_TRANS2_SET_FILE_INFORMATION;
  942. }
  943. if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
  944. level = SMB_SFILEINFO_BASIC_INFORMATION;
  945. else
  946. level = SMB_SFILEINFO_BASIC_INFO;
  947. error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
  948. if (error)
  949. return (error);
  950. mbp = &t2p->t2_tparam;
  951. mb_init(mbp);
  952. if (cmd == SMB_TRANS2_SET_FILE_INFORMATION)
  953. mb_put_uint16le(mbp, fid);
  954. mb_put_uint16le(mbp, level);
  955. mb_put_uint32le(mbp, 0); /* MBZ */
  956. if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
  957. error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
  958. if (error != 0)
  959. goto out;
  960. }
  961. /* FAT file systems don't support dates earlier than 1980. */
  962. mbp = &t2p->t2_tdata;
  963. mb_init(mbp);
  964. mb_put_uint64le(mbp, 0); /* creation time */
  965. if (atime) {
  966. smb_time_local2NT(atime, &tm);
  967. if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
  968. tm < NT1980)
  969. tm = NT1980;
  970. } else
  971. tm = 0;
  972. mb_put_uint64le(mbp, tm); /* access time */
  973. if (mtime) {
  974. smb_time_local2NT(mtime, &tm);
  975. if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
  976. tm < NT1980)
  977. tm = NT1980;
  978. } else
  979. tm = 0;
  980. mb_put_uint64le(mbp, tm); /* last write time */
  981. mb_put_uint64le(mbp, 0); /* ctime (no change) */
  982. mb_put_uint32le(mbp, attr);
  983. mb_put_uint32le(mbp, 0); /* padding */
  984. t2p->t2_maxpcount = 2;
  985. t2p->t2_maxdcount = 0;
  986. error = smb_t2_request(t2p);
  987. out:
  988. smb_t2_done(t2p);
  989. return (error);
  990. }
  991. /*
  992. * Modern create/open of file or directory.
  993. *
  994. * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or...
  995. * then this is an open attempt, and:
  996. * If xattr then name is the stream to be opened at np,
  997. * Else np should be opened.
  998. * ...we won't touch *fidp,
  999. * ...we will set or clear *attrcacheupdated.
  1000. * Else this is a creation attempt, and:
  1001. * If xattr then name is the stream to create at np,
  1002. * Else name is the thing to create under directory np.
  1003. * ...we will return *fidp,
  1004. * ...we won't touch *attrcacheupdated.
  1005. *
  1006. * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc.
  1007. * now too, which may or may not create a new object.
  1008. */
  1009. int
  1010. smbfs_smb_ntcreatex(
  1011. struct smbnode *np,
  1012. const char *name,
  1013. int nmlen,
  1014. int xattr, /* is named stream? */
  1015. uint32_t req_acc, /* requested access */
  1016. uint32_t efa, /* ext. file attrs (DOS attr +) */
  1017. uint32_t share_acc,
  1018. uint32_t disp, /* open disposition */
  1019. uint32_t createopt, /* NTCREATEX_OPTIONS_ */
  1020. struct smb_cred *scrp,
  1021. uint16_t *fidp,
  1022. uint32_t *cr_act_p, /* create action */
  1023. struct smbfattr *fap) /* optional */
  1024. {
  1025. struct smb_rq rq, *rqp = &rq;
  1026. struct smb_share *ssp = np->n_mount->smi_share;
  1027. struct smb_vc *vcp = SSTOVC(ssp);
  1028. struct mbchain *mbp;
  1029. struct mdchain *mdp;
  1030. struct smbfattr fa;
  1031. uint8_t wc;
  1032. uint32_t longint, createact;
  1033. uint64_t llongint;
  1034. int error;
  1035. uint16_t fid, *namelenp;
  1036. bzero(&fa, sizeof (fa));
  1037. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
  1038. if (error)
  1039. return (error);
  1040. smb_rq_getrequest(rqp, &mbp);
  1041. smb_rq_wstart(rqp);
  1042. mb_put_uint8(mbp, 0xff); /* secondary command */
  1043. mb_put_uint8(mbp, 0); /* MBZ */
  1044. mb_put_uint16le(mbp, 0); /* offset to next command (none) */
  1045. mb_put_uint8(mbp, 0); /* MBZ */
  1046. namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t));
  1047. /*
  1048. * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY
  1049. * for creating nor for opening a directory. Samba ignores the bit.
  1050. */
  1051. mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */
  1052. mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
  1053. mb_put_uint32le(mbp, req_acc);
  1054. mb_put_uint64le(mbp, 0); /* "initial allocation size" */
  1055. mb_put_uint32le(mbp, efa);
  1056. mb_put_uint32le(mbp, share_acc);
  1057. mb_put_uint32le(mbp, disp);
  1058. mb_put_uint32le(mbp, createopt);
  1059. mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
  1060. mb_put_uint8(mbp, 0); /* security flags (?) */
  1061. smb_rq_wend(rqp);
  1062. smb_rq_bstart(rqp);
  1063. if (name == NULL)
  1064. nmlen = 0;
  1065. error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
  1066. xattr ? ':' : '\\');
  1067. if (error)
  1068. goto done;
  1069. *namelenp = htoles(nmlen); /* includes null */
  1070. smb_rq_bend(rqp);
  1071. /*
  1072. * Don't want to risk missing a successful
  1073. * open response, or we could "leak" FIDs.
  1074. */
  1075. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1076. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1077. if (error)
  1078. goto done;
  1079. smb_rq_getreply(rqp, &mdp);
  1080. /*
  1081. * spec says 26 for word count, but 34 words are defined
  1082. * and observed from win2000
  1083. */
  1084. error = md_get_uint8(mdp, &wc);
  1085. if (error)
  1086. goto done;
  1087. if (wc != 26 && wc != 34 && wc != 42) {
  1088. error = EBADRPC;
  1089. goto done;
  1090. }
  1091. md_get_uint8(mdp, NULL); /* secondary cmd */
  1092. md_get_uint8(mdp, NULL); /* mbz */
  1093. md_get_uint16le(mdp, NULL); /* andxoffset */
  1094. md_get_uint8(mdp, NULL); /* oplock lvl granted */
  1095. md_get_uint16le(mdp, &fid); /* file ID */
  1096. md_get_uint32le(mdp, &createact); /* create_action */
  1097. md_get_uint64le(mdp, &llongint); /* creation time */
  1098. smb_time_NT2local(llongint, &fa.fa_createtime);
  1099. md_get_uint64le(mdp, &llongint); /* access time */
  1100. smb_time_NT2local(llongint, &fa.fa_atime);
  1101. md_get_uint64le(mdp, &llongint); /* write time */
  1102. smb_time_NT2local(llongint, &fa.fa_mtime);
  1103. md_get_uint64le(mdp, &llongint); /* change time */
  1104. smb_time_NT2local(llongint, &fa.fa_ctime);
  1105. md_get_uint32le(mdp, &longint); /* attributes */
  1106. fa.fa_attr = longint;
  1107. md_get_uint64le(mdp, &llongint); /* allocation size */
  1108. fa.fa_allocsz = llongint;
  1109. md_get_uint64le(mdp, &llongint); /* EOF position */
  1110. fa.fa_size = llongint;
  1111. error = md_get_uint16le(mdp, NULL); /* file type */
  1112. /* other stuff we don't care about */
  1113. done:
  1114. smb_rq_done(rqp);
  1115. if (error)
  1116. return (error);
  1117. if (fidp)
  1118. *fidp = fid;
  1119. if (cr_act_p)
  1120. *cr_act_p = createact;
  1121. if (fap)
  1122. *fap = fa; /* struct copy */
  1123. return (0);
  1124. }
  1125. static uint32_t
  1126. smb_mode2rights(int mode)
  1127. {
  1128. mode = mode & SMB_AM_OPENMODE;
  1129. uint32_t rights =
  1130. STD_RIGHT_SYNCHRONIZE_ACCESS |
  1131. STD_RIGHT_READ_CONTROL_ACCESS;
  1132. if ((mode == SMB_AM_OPENREAD) ||
  1133. (mode == SMB_AM_OPENRW)) {
  1134. rights |=
  1135. SA_RIGHT_FILE_READ_ATTRIBUTES |
  1136. SA_RIGHT_FILE_READ_DATA;
  1137. }
  1138. if ((mode == SMB_AM_OPENWRITE) ||
  1139. (mode == SMB_AM_OPENRW)) {
  1140. rights |=
  1141. SA_RIGHT_FILE_WRITE_ATTRIBUTES |
  1142. SA_RIGHT_FILE_APPEND_DATA |
  1143. SA_RIGHT_FILE_WRITE_DATA;
  1144. }
  1145. if (mode == SMB_AM_OPENEXEC) {
  1146. rights |=
  1147. SA_RIGHT_FILE_READ_ATTRIBUTES |
  1148. SA_RIGHT_FILE_EXECUTE;
  1149. }
  1150. return (rights);
  1151. }
  1152. static int
  1153. smb_rights2mode(uint32_t rights)
  1154. {
  1155. int accmode = SMB_AM_OPENEXEC; /* our fallback */
  1156. if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD |
  1157. SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES |
  1158. SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS |
  1159. STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS))
  1160. accmode = SMB_AM_OPENWRITE;
  1161. if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES |
  1162. SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS))
  1163. accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD
  1164. : SMB_AM_OPENRW;
  1165. return (accmode);
  1166. }
  1167. static int
  1168. smbfs_smb_oldopen(
  1169. struct smbnode *np,
  1170. const char *name,
  1171. int nmlen,
  1172. int xattr,
  1173. int accmode,
  1174. struct smb_cred *scrp,
  1175. uint16_t *fidp,
  1176. uint16_t *granted_mode_p,
  1177. smbfattr_t *fap)
  1178. {
  1179. struct smb_rq rq, *rqp = &rq;
  1180. struct smb_share *ssp = np->n_mount->smi_share;
  1181. struct smb_vc *vcp = SSTOVC(ssp);
  1182. struct mbchain *mbp;
  1183. struct mdchain *mdp;
  1184. struct smbfattr fa;
  1185. uint8_t wc;
  1186. uint16_t wattr;
  1187. uint32_t longint;
  1188. int error;
  1189. bzero(&fa, sizeof (fa));
  1190. /*
  1191. * XXX: move to callers...
  1192. *
  1193. * Use DENYNONE to give unixy semantics of permitting
  1194. * everything not forbidden by permissions. Ie denial
  1195. * is up to server with clients/openers needing to use
  1196. * advisory locks for further control.
  1197. */
  1198. accmode |= SMB_SM_DENYNONE;
  1199. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp);
  1200. if (error)
  1201. return (error);
  1202. smb_rq_getrequest(rqp, &mbp);
  1203. smb_rq_wstart(rqp);
  1204. mb_put_uint16le(mbp, accmode);
  1205. mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY |
  1206. SMB_FA_DIR);
  1207. smb_rq_wend(rqp);
  1208. smb_rq_bstart(rqp);
  1209. mb_put_uint8(mbp, SMB_DT_ASCII);
  1210. error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
  1211. xattr ? ':' : '\\');
  1212. if (error)
  1213. goto done;
  1214. smb_rq_bend(rqp);
  1215. /*
  1216. * Don't want to risk missing a successful
  1217. * open response, or we could "leak" FIDs.
  1218. */
  1219. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1220. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1221. if (error)
  1222. goto done;
  1223. smb_rq_getreply(rqp, &mdp);
  1224. /*
  1225. * 8/2002 a DAVE server returned wc of 15 so we ignore that.
  1226. * (the actual packet length and data was correct)
  1227. */
  1228. error = md_get_uint8(mdp, &wc);
  1229. if (error)
  1230. goto done;
  1231. if (wc != 7 && wc != 15) {
  1232. error = EBADRPC;
  1233. goto done;
  1234. }
  1235. md_get_uint16le(mdp, fidp);
  1236. md_get_uint16le(mdp, &wattr);
  1237. fa.fa_attr = wattr;
  1238. /*
  1239. * Be careful using the time returned here, as
  1240. * with FAT on NT4SP6, at least, the time returned is low
  1241. * 32 bits of 100s of nanoseconds (since 1601) so it rolls
  1242. * over about every seven minutes!
  1243. */
  1244. md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
  1245. smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime);
  1246. md_get_uint32le(mdp, &longint);
  1247. fa.fa_size = longint;
  1248. error = md_get_uint16le(mdp, granted_mode_p);
  1249. done:
  1250. smb_rq_done(rqp);
  1251. if (error)
  1252. return (error);
  1253. if (fap)
  1254. *fap = fa; /* struct copy */
  1255. return (0);
  1256. }
  1257. int
  1258. smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
  1259. uint16_t *fidp)
  1260. {
  1261. struct smb_share *ssp = np->n_mount->smi_share;
  1262. struct smb_vc *vcp = SSTOVC(ssp);
  1263. int accmode, error;
  1264. /* Shared lock for n_fid use below. */
  1265. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  1266. /* Can we re-use n_fid? or must we open anew? */
  1267. mutex_enter(&np->r_statelock);
  1268. if (np->n_fidrefs > 0 &&
  1269. np->n_vcgenid == ssp->ss_vcgenid &&
  1270. (rights & np->n_rights) == rights) {
  1271. np->n_fidrefs++;
  1272. *fidp = np->n_fid;
  1273. mutex_exit(&np->r_statelock);
  1274. return (0);
  1275. }
  1276. mutex_exit(&np->r_statelock);
  1277. /* re-open an existing file. */
  1278. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1279. error = smbfs_smb_ntcreatex(np,
  1280. NULL, 0, 0, /* name nmlen xattr */
  1281. rights, SMB_EFA_NORMAL,
  1282. NTCREATEX_SHARE_ACCESS_ALL,
  1283. NTCREATEX_DISP_OPEN,
  1284. 0, /* create options */
  1285. scrp, fidp,
  1286. NULL, NULL); /* cr_act_p fa_p */
  1287. return (error);
  1288. }
  1289. accmode = smb_rights2mode(rights);
  1290. error = smbfs_smb_oldopen(np,
  1291. NULL, 0, 0, /* name nmlen xattr */
  1292. accmode, scrp,
  1293. fidp,
  1294. NULL, /* granted mode p */
  1295. NULL); /* fa p */
  1296. return (error);
  1297. }
  1298. int
  1299. smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp)
  1300. {
  1301. struct smb_share *ssp = np->n_mount->smi_share;
  1302. int error = 0;
  1303. uint16_t oldfid = SMB_FID_UNUSED;
  1304. /* Shared lock for n_fid use below. */
  1305. ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  1306. mutex_enter(&np->r_statelock);
  1307. if (fid == np->n_fid) {
  1308. ASSERT(np->n_fidrefs > 0);
  1309. if (--np->n_fidrefs == 0) {
  1310. /*
  1311. * Don't expect to find the last reference
  1312. * here in tmpclose. Hard to deal with as
  1313. * we don't have r_lkserlock exclusive.
  1314. * Will close oldfid below.
  1315. */
  1316. oldfid = np->n_fid;
  1317. np->n_fid = SMB_FID_UNUSED;
  1318. }
  1319. } else {
  1320. /* Will close the passed fid. */
  1321. oldfid = fid;
  1322. }
  1323. mutex_exit(&np->r_statelock);
  1324. if (oldfid != SMB_FID_UNUSED)
  1325. error = smbfs_smb_close(ssp, oldfid, NULL, scrp);
  1326. return (error);
  1327. }
  1328. int
  1329. smbfs_smb_open(
  1330. struct smbnode *np,
  1331. const char *name,
  1332. int nmlen,
  1333. int xattr,
  1334. uint32_t rights,
  1335. struct smb_cred *scrp,
  1336. uint16_t *fidp,
  1337. uint32_t *rightsp,
  1338. smbfattr_t *fap)
  1339. {
  1340. struct smb_share *ssp = np->n_mount->smi_share;
  1341. struct smb_vc *vcp = SSTOVC(ssp);
  1342. int accmode, error;
  1343. uint16_t grantedmode;
  1344. /* open an existing file */
  1345. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1346. error = smbfs_smb_ntcreatex(np,
  1347. name, nmlen, xattr,
  1348. rights, SMB_EFA_NORMAL,
  1349. NTCREATEX_SHARE_ACCESS_ALL,
  1350. NTCREATEX_DISP_OPEN,
  1351. 0, /* create options */
  1352. scrp, fidp,
  1353. NULL, fap); /* cr_act_p fa_p */
  1354. if (error != 0)
  1355. return (error);
  1356. *rightsp = rights;
  1357. return (0);
  1358. }
  1359. accmode = smb_rights2mode(rights);
  1360. error = smbfs_smb_oldopen(np,
  1361. name, nmlen, xattr, accmode, scrp,
  1362. fidp, &grantedmode, fap);
  1363. if (error != 0)
  1364. return (error);
  1365. *rightsp = smb_mode2rights(grantedmode);
  1366. (void) smbfs_smb_getfattr(np, fap, scrp);
  1367. return (0);
  1368. }
  1369. int
  1370. smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
  1371. struct smb_cred *scrp)
  1372. {
  1373. struct smb_rq rq, *rqp = &rq;
  1374. struct mbchain *mbp;
  1375. long time;
  1376. int error;
  1377. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
  1378. if (error)
  1379. return (error);
  1380. smb_rq_getrequest(rqp, &mbp);
  1381. smb_rq_wstart(rqp);
  1382. mb_put_uint16le(mbp, fid);
  1383. if (mtime) {
  1384. int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
  1385. smb_time_local2server(mtime, sv_tz, &time);
  1386. } else
  1387. time = 0;
  1388. mb_put_uint32le(mbp, time);
  1389. smb_rq_wend(rqp);
  1390. smb_rq_bstart(rqp);
  1391. smb_rq_bend(rqp);
  1392. /*
  1393. * We don't really care about the result here, but we
  1394. * do need to make sure we send this out, or we could
  1395. * "leak" open file handles on interrupt or timeout.
  1396. * The NOINTR_SEND flag makes this request immune to
  1397. * interrupt or timeout until the send is done.
  1398. */
  1399. rqp->sr_flags |= SMBR_NOINTR_SEND;
  1400. error = smb_rq_simple(rqp);
  1401. smb_rq_done(rqp);
  1402. /*
  1403. * ENOTCONN isn't interesting - if the connection is closed,
  1404. * so are all our FIDs - and EIO is also not interesting,
  1405. * as it means a forced unmount was done. (was ENXIO)
  1406. * Also ETIME, which means we sent the request but gave up
  1407. * waiting before the response came back.
  1408. *
  1409. * Don't clog up the system log with warnings about these
  1410. * uninteresting failures on closes.
  1411. */
  1412. switch (error) {
  1413. case ENOTCONN:
  1414. case ENXIO:
  1415. case EIO:
  1416. case ETIME:
  1417. error = 0;
  1418. }
  1419. return (error);
  1420. }
  1421. static int
  1422. smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
  1423. int xattr, struct smb_cred *scrp, uint16_t *fidp)
  1424. {
  1425. struct smb_rq rq, *rqp = &rq;
  1426. struct smb_share *ssp = dnp->n_mount->smi_share;
  1427. struct mbchain *mbp;
  1428. struct mdchain *mdp;
  1429. struct timespec ctime;
  1430. uint8_t wc;
  1431. long tm;
  1432. int error;
  1433. uint16_t attr = SMB_FA_ARCHIVE;
  1434. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp);
  1435. if (error)
  1436. return (error);
  1437. smb_rq_getrequest(rqp, &mbp);
  1438. smb_rq_wstart(rqp);
  1439. if (name && *name == '.')
  1440. attr |= SMB_FA_HIDDEN;
  1441. mb_put_uint16le(mbp, attr); /* attributes */
  1442. gethrestime(&ctime);
  1443. smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm);
  1444. mb_put_uint32le(mbp, tm);
  1445. smb_rq_wend(rqp);
  1446. smb_rq_bstart(rqp);
  1447. mb_put_uint8(mbp, SMB_DT_ASCII);
  1448. error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen,
  1449. xattr ? ':' : '\\');
  1450. if (error)
  1451. goto out;
  1452. smb_rq_bend(rqp);
  1453. /*
  1454. * Don't want to risk missing a successful
  1455. * open response, or we could "leak" FIDs.
  1456. */
  1457. rqp->sr_flags |= SMBR_NOINTR_RECV;
  1458. error = smb_rq_simple_timed(rqp, smb_timo_open);
  1459. if (error)
  1460. goto out;
  1461. smb_rq_getreply(rqp, &mdp);
  1462. md_get_uint8(mdp, &wc);
  1463. if (wc != 1) {
  1464. error = EBADRPC;
  1465. goto out;
  1466. }
  1467. error = md_get_uint16le(mdp, fidp);
  1468. out:
  1469. smb_rq_done(rqp);
  1470. return (error);
  1471. }
  1472. int
  1473. smbfs_smb_create(
  1474. struct smbnode *dnp,
  1475. const char *name,
  1476. int nmlen,
  1477. int xattr,
  1478. uint32_t disp,
  1479. struct smb_cred *scrp,
  1480. uint16_t *fidp)
  1481. {
  1482. struct smb_share *ssp = dnp->n_mount->smi_share;
  1483. struct smb_vc *vcp = SSTOVC(ssp);
  1484. uint32_t efa, rights;
  1485. int error;
  1486. /*
  1487. * At present the only access we might need is to WRITE data,
  1488. * and that only if we are creating a "symlink". When/if the
  1489. * access needed gets more complex it should made a parameter
  1490. * and be set upstream.
  1491. */
  1492. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1493. rights = SA_RIGHT_FILE_WRITE_DATA;
  1494. efa = SMB_EFA_NORMAL;
  1495. if (!xattr && name && *name == '.')
  1496. efa = SMB_EFA_HIDDEN;
  1497. error = smbfs_smb_ntcreatex(dnp,
  1498. name, nmlen, xattr, rights, efa,
  1499. NTCREATEX_SHARE_ACCESS_ALL,
  1500. disp, /* != NTCREATEX_DISP_OPEN */
  1501. NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
  1502. scrp, fidp, NULL, NULL); /* cr_act_p fa_p */
  1503. return (error);
  1504. }
  1505. error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp);
  1506. return (error);
  1507. }
  1508. int
  1509. smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name,
  1510. int nmlen, int xattr)
  1511. {
  1512. struct smb_rq rq, *rqp = &rq;
  1513. struct smb_share *ssp = np->n_mount->smi_share;
  1514. struct mbchain *mbp;
  1515. int error;
  1516. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp);
  1517. if (error)
  1518. return (error);
  1519. smb_rq_getrequest(rqp, &mbp);
  1520. smb_rq_wstart(rqp);
  1521. mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
  1522. smb_rq_wend(rqp);
  1523. smb_rq_bstart(rqp);
  1524. mb_put_uint8(mbp, SMB_DT_ASCII);
  1525. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen,
  1526. xattr ? ':' : '\\');
  1527. if (!error) {
  1528. smb_rq_bend(rqp);
  1529. error = smb_rq_simple(rqp);
  1530. }
  1531. smb_rq_done(rqp);
  1532. return (error);
  1533. }
  1534. int
  1535. smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
  1536. const char *tname, int tnmlen, struct smb_cred *scrp)
  1537. {
  1538. struct smb_rq rq, *rqp = &rq;
  1539. struct smb_share *ssp = src->n_mount->smi_share;
  1540. struct mbchain *mbp;
  1541. int error;
  1542. uint16_t fa;
  1543. char sep;
  1544. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
  1545. if (error)
  1546. return (error);
  1547. smb_rq_getrequest(rqp, &mbp);
  1548. smb_rq_wstart(rqp);
  1549. /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
  1550. fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
  1551. fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
  1552. mb_put_uint16le(mbp, fa);
  1553. smb_rq_wend(rqp);
  1554. smb_rq_bstart(rqp);
  1555. /*
  1556. * When we're not adding any component name, the
  1557. * passed sep is ignored, so just pass sep=0.
  1558. */
  1559. mb_put_uint8(mbp, SMB_DT_ASCII);
  1560. error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0);
  1561. if (error)
  1562. goto out;
  1563. /*
  1564. * After XATTR directories, separator is ":"
  1565. */
  1566. sep = (src->n_flag & N_XATTR) ? ':' : '\\';
  1567. mb_put_uint8(mbp, SMB_DT_ASCII);
  1568. error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep);
  1569. if (error)
  1570. goto out;
  1571. smb_rq_bend(rqp);
  1572. error = smb_rq_simple(rqp);
  1573. out:
  1574. smb_rq_done(rqp);
  1575. return (error);
  1576. }
  1577. int
  1578. smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
  1579. const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp)
  1580. {
  1581. struct smb_rq rq, *rqp = &rq;
  1582. struct smb_share *ssp = src->n_mount->smi_share;
  1583. struct mbchain *mbp;
  1584. int error;
  1585. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp);
  1586. if (error)
  1587. return (error);
  1588. smb_rq_getrequest(rqp, &mbp);
  1589. smb_rq_wstart(rqp);
  1590. mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
  1591. mb_put_uint16le(mbp, 0x20); /* delete target file */
  1592. mb_put_uint16le(mbp, flags);
  1593. smb_rq_wend(rqp);
  1594. smb_rq_bstart(rqp);
  1595. mb_put_uint8(mbp, SMB_DT_ASCII);
  1596. error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
  1597. if (error)
  1598. goto out;
  1599. mb_put_uint8(mbp, SMB_DT_ASCII);
  1600. error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\');
  1601. if (error)
  1602. goto out;
  1603. smb_rq_bend(rqp);
  1604. error = smb_rq_simple(rqp);
  1605. out:
  1606. smb_rq_done(rqp);
  1607. return (error);
  1608. }
  1609. static int
  1610. smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len,
  1611. struct smb_cred *scrp)
  1612. {
  1613. struct smb_rq rq, *rqp = &rq;
  1614. struct smb_share *ssp = dnp->n_mount->smi_share;
  1615. struct mbchain *mbp;
  1616. int error;
  1617. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp);
  1618. if (error)
  1619. return (error);
  1620. smb_rq_getrequest(rqp, &mbp);
  1621. smb_rq_wstart(rqp);
  1622. smb_rq_wend(rqp);
  1623. smb_rq_bstart(rqp);
  1624. mb_put_uint8(mbp, SMB_DT_ASCII);
  1625. error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\');
  1626. if (!error) {
  1627. smb_rq_bend(rqp);
  1628. error = smb_rq_simple(rqp);
  1629. }
  1630. smb_rq_done(rqp);
  1631. return (error);
  1632. }
  1633. int
  1634. smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
  1635. struct smb_cred *scrp)
  1636. {
  1637. struct smb_share *ssp = dnp->n_mount->smi_share;
  1638. struct smb_vc *vcp = SSTOVC(ssp);
  1639. uint32_t rights;
  1640. uint16_t fid;
  1641. int error;
  1642. /*
  1643. * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
  1644. * just to be asking for something. The rights==0 case could
  1645. * easily be broken on some old or unusual servers.
  1646. */
  1647. if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
  1648. rights = SA_RIGHT_FILE_READ_DATA;
  1649. error = smbfs_smb_ntcreatex(dnp,
  1650. name, nmlen, 0, /* xattr */
  1651. rights, SMB_EFA_DIRECTORY,
  1652. NTCREATEX_SHARE_ACCESS_ALL,
  1653. NTCREATEX_DISP_CREATE,
  1654. NTCREATEX_OPTIONS_DIRECTORY,
  1655. scrp, &fid, NULL, NULL); /* cr_act_p fa_p */
  1656. if (error)
  1657. return (error);
  1658. (void) smbfs_smb_close(ssp, fid, NULL, scrp);
  1659. return (0);
  1660. }
  1661. error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp);
  1662. return (error);
  1663. }
  1664. int
  1665. smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp)
  1666. {
  1667. struct smb_rq rq, *rqp = &rq;
  1668. struct smb_share *ssp = np->n_mount->smi_share;
  1669. struct mbchain *mbp;
  1670. int error;
  1671. error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp);
  1672. if (error)
  1673. return (error);
  1674. smb_rq_getrequest(rqp, &mbp);
  1675. smb_rq_wstart(rqp);
  1676. smb_rq_wend(rqp);
  1677. smb_rq_bstart(rqp);
  1678. mb_put_uint8(mbp, SMB_DT_ASCII);
  1679. error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\');
  1680. if (!error) {
  1681. smb_rq_bend(rqp);
  1682. error = smb_rq_simple(rqp);
  1683. }
  1684. smb_rq_done(rqp);
  1685. return (error);
  1686. }
  1687. static int
  1688. smbfs_smb_search(struct smbfs_fctx *ctx)
  1689. {
  1690. struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
  1691. struct smb_rq *rqp;
  1692. struct mbchain *mbp;
  1693. struct mdchain *mdp;
  1694. uint8_t wc, bt;
  1695. uint16_t ec, dlen, bc;
  1696. int len, maxent, error, iseof = 0;
  1697. maxent = min(ctx->f_left,
  1698. (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN);
  1699. if (ctx->f_rq) {
  1700. smb_rq_done(ctx->f_rq);
  1701. ctx->f_rq = NULL;
  1702. }
  1703. error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH,
  1704. ctx->f_scred, &rqp);
  1705. if (error)
  1706. return (error);
  1707. ctx->f_rq = rqp;
  1708. smb_rq_getrequest(rqp, &mbp);
  1709. smb_rq_wstart(rqp);
  1710. mb_put_uint16le(mbp, maxent); /* max entries to return */
  1711. mb_put_uint16le(mbp, ctx->f_attrmask);
  1712. smb_rq_wend(rqp);
  1713. smb_rq_bstart(rqp);
  1714. mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */
  1715. if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
  1716. len = ctx->f_wclen;
  1717. error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
  1718. &len, '\\');
  1719. if (error)
  1720. return (error);
  1721. mb_put_uint8(mbp, SMB_DT_VARIABLE);
  1722. mb_put_uint16le(mbp, 0); /* context length */
  1723. ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
  1724. } else {
  1725. if (SMB_UNICODE_STRINGS(vcp)) {
  1726. mb_put_padbyte(mbp);
  1727. mb_put_uint8(mbp, 0);
  1728. }
  1729. mb_put_uint8(mbp, 0);
  1730. mb_put_uint8(mbp, SMB_DT_VARIABLE);
  1731. mb_put_uint16le(mbp, SMB_SKEYLEN);
  1732. mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
  1733. }
  1734. smb_rq_bend(rqp);
  1735. error = smb_rq_simple(rqp);
  1736. if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) {
  1737. error = 0;
  1738. iseof = 1;
  1739. ctx->f_flags |= SMBFS_RDD_EOF;
  1740. } else if (error)
  1741. return (error);
  1742. smb_rq_getreply(rqp, &mdp);
  1743. error = md_get_uint8(mdp, &wc);
  1744. if (error)
  1745. return (error);
  1746. if (wc != 1)
  1747. return (iseof ? ENOENT : EBADRPC);
  1748. md_get_uint16le(mdp, &ec);
  1749. md_get_uint16le(mdp, &bc);
  1750. md_get_uint8(mdp, &bt);
  1751. error = md_get_uint16le(mdp, &dlen);
  1752. if (error)
  1753. return (error);
  1754. if (ec == 0)
  1755. return (ENOENT);
  1756. ctx->f_ecnt = ec;
  1757. if (bc < 3)
  1758. return (EBADRPC);
  1759. bc -= 3;
  1760. if (bt != SMB_DT_VARIABLE)
  1761. return (EBADRPC);
  1762. if (dlen != bc || dlen % SMB_DENTRYLEN != 0)
  1763. return (EBADRPC);
  1764. return (0);
  1765. }
  1766. /*ARGSUSED*/
  1767. static int
  1768. smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp,
  1769. const char *wildcard, int wclen, uint16_t attr)
  1770. {
  1771. ctx->f_type = ft_LM1;
  1772. ctx->f_attrmask = attr;
  1773. if (wildcard) {
  1774. if (wclen == 1 && wildcard[0] == '*') {
  1775. ctx->f_wildcard = "*.*";
  1776. ctx->f_wclen = 3;
  1777. } else {
  1778. ctx->f_wildcard = wildcard;
  1779. ctx->f_wclen = wclen;
  1780. }
  1781. } else {
  1782. ctx->f_wildcard = NULL;
  1783. ctx->f_wclen = 0;
  1784. }
  1785. ctx->f_name = (char *)ctx->f_fname;
  1786. ctx->f_namesz = 0;
  1787. return (0);
  1788. }
  1789. static int
  1790. smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
  1791. {
  1792. struct mdchain *mdp;
  1793. struct smb_rq *rqp;
  1794. char *cp;
  1795. uint8_t battr;
  1796. uint16_t date, time;
  1797. uint32_t size;
  1798. int error;
  1799. struct timespec ts;
  1800. if (ctx->f_ecnt == 0) {
  1801. if (ctx->f_flags & SMBFS_RDD_EOF)
  1802. return (ENOENT);
  1803. ctx->f_left = ctx->f_limit = limit;
  1804. gethrestime(&ts);
  1805. error = smbfs_smb_search(ctx);
  1806. if (error)
  1807. return (error);
  1808. }
  1809. rqp = ctx->f_rq;
  1810. smb_rq_getreply(rqp, &mdp);
  1811. md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
  1812. md_get_uint8(mdp, &battr);
  1813. md_get_uint16le(mdp, &time);
  1814. md_get_uint16le(mdp, &date);
  1815. md_get_uint32le(mdp, &size);
  1816. cp = ctx->f_name;
  1817. error = md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM);
  1818. cp[sizeof (ctx->f_fname) - 1] = 0;
  1819. cp += strlen(cp) - 1;
  1820. while (*cp == ' ' && cp >= ctx->f_name)
  1821. *cp-- = 0;
  1822. ctx->f_attr.fa_attr = battr;
  1823. smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz,
  1824. &ctx->f_attr.fa_mtime);
  1825. ctx->f_attr.fa_size = size;
  1826. ctx->f_nmlen = strlen(ctx->f_name);
  1827. ctx->f_ecnt--;
  1828. ctx->f_left--;
  1829. return (0);
  1830. }
  1831. static int
  1832. smbfs_smb_findcloseLM1(struct smbfs_fctx *ctx)
  1833. {
  1834. if (ctx->f_rq)
  1835. smb_rq_done(ctx->f_rq);
  1836. return (0);
  1837. }
  1838. /*
  1839. * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
  1840. */
  1841. static int
  1842. smbfs_smb_trans2find2(struct smbfs_fctx *ctx)
  1843. {
  1844. struct smb_t2rq *t2p;
  1845. struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
  1846. struct mbchain *mbp;
  1847. struct mdchain *mdp;
  1848. uint16_t ecnt, eos, lno, flags;
  1849. int len, error;
  1850. if (ctx->f_t2) {
  1851. smb_t2_done(ctx->f_t2);
  1852. ctx->f_t2 = NULL;
  1853. }
  1854. flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS;
  1855. if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
  1856. flags |= FIND2_CLOSE_AFTER_REQUEST;
  1857. ctx->f_flags |= SMBFS_RDD_NOCLOSE;
  1858. }
  1859. if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
  1860. error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2,
  1861. ctx->f_scred, &t2p);
  1862. if (error)
  1863. return (error);
  1864. ctx->f_t2 = t2p;
  1865. mbp = &t2p->t2_tparam;
  1866. mb_init(mbp);
  1867. mb_put_uint16le(mbp, ctx->f_attrmask);
  1868. mb_put_uint16le(mbp, ctx->f_limit);
  1869. mb_put_uint16le(mbp, flags);
  1870. mb_put_uint16le(mbp, ctx->f_infolevel);
  1871. mb_put_uint32le(mbp, 0);
  1872. len = ctx->f_wclen;
  1873. error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard,
  1874. &len, '\\');
  1875. if (error)
  1876. return (error);
  1877. } else {
  1878. error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2,
  1879. ctx->f_scred, &t2p);
  1880. if (error)
  1881. return (error);
  1882. ctx->f_t2 = t2p;
  1883. mbp = &t2p->t2_tparam;
  1884. mb_init(mbp);
  1885. mb_put_uint16le(mbp, ctx->f_Sid);
  1886. mb_put_uint16le(mbp, ctx->f_limit);
  1887. mb_put_uint16le(mbp, ctx->f_infolevel);
  1888. /* Send whatever resume key we received... */
  1889. mb_put_uint32le(mbp, ctx->f_rkey);
  1890. mb_put_uint16le(mbp, flags);
  1891. /* ... and the resume name if we have one. */
  1892. if (ctx->f_rname) {
  1893. /* resume file name */
  1894. mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen,
  1895. MB_MSYSTEM);
  1896. }
  1897. /* Add trailing null - 1 byte if ASCII, 2 if Unicode */
  1898. if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
  1899. mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
  1900. mb_put_uint8(mbp, 0);
  1901. }
  1902. t2p->t2_maxpcount = 5 * 2;
  1903. t2p->t2_maxdcount = 0xF000; /* 64K less some overhead */
  1904. error = smb_t2_request(t2p);
  1905. if (error)
  1906. return (error);
  1907. /*
  1908. * This is the "resume name" we just sent.
  1909. * We want the new one (if any) that may be
  1910. * found in the response we just received and
  1911. * will now begin parsing. Free the old one
  1912. * now so we'll know if we found a new one.
  1913. */
  1914. if (ctx->f_rname) {
  1915. kmem_free(ctx->f_rname, ctx->f_rnamelen);
  1916. ctx->f_rname = NULL;
  1917. ctx->f_rnamelen = 0;
  1918. }
  1919. mdp = &t2p->t2_rparam;
  1920. if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
  1921. if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0)
  1922. goto nodata;
  1923. ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
  1924. }
  1925. md_get_uint16le(mdp, &ecnt); /* entry count */
  1926. md_get_uint16le(mdp, &eos); /* end of search */
  1927. md_get_uint16le(mdp, NULL); /* EA err. off. */
  1928. error = md_get_uint16le(mdp, &lno); /* last name off. */
  1929. if (error != 0)
  1930. goto nodata;
  1931. /*
  1932. * The "end of search" flag from an XP server sometimes
  1933. * comes back zero when the prior find_next returned exactly
  1934. * the number of entries requested. in which case we'd try again
  1935. * but the search has in fact been closed so an EBADF results.
  1936. * our circumvention is to check here for a zero entry count.
  1937. */
  1938. ctx->f_ecnt = ecnt;
  1939. if (eos || ctx->f_ecnt == 0)
  1940. ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE;
  1941. if (ctx->f_ecnt == 0)
  1942. return (ENOENT);
  1943. /* Last Name Off (LNO) is the entry with the resume name. */
  1944. ctx->f_rnameofs = lno;
  1945. ctx->f_eofs = 0;
  1946. return (0);
  1947. nodata:
  1948. /*
  1949. * Failed parsing the FindFirst or FindNext response.
  1950. * Force this directory listing closed, otherwise the
  1951. * calling process may hang in an infinite loop.
  1952. */
  1953. ctx->f_ecnt = 0; /* Force closed. */
  1954. ctx->f_flags |= SMBFS_RDD_EOF;
  1955. return (EIO);
  1956. }
  1957. static int
  1958. smbfs_smb_findclose2(struct smbfs_fctx *ctx)
  1959. {
  1960. struct smb_rq rq, *rqp = &rq;
  1961. struct mbchain *mbp;
  1962. int error;
  1963. error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
  1964. ctx->f_scred);
  1965. if (error)
  1966. return (error);
  1967. smb_rq_getrequest(rqp, &mbp);
  1968. smb_rq_wstart(rqp);
  1969. mb_put_uint16le(mbp, ctx->f_Sid);
  1970. smb_rq_wend(rqp);
  1971. smb_rq_bstart(rqp);
  1972. smb_rq_bend(rqp);
  1973. /* Ditto comments at _smb_close */
  1974. rqp->sr_flags |= SMBR_NOINTR_SEND;
  1975. error = smb_rq_simple(rqp);
  1976. smb_rq_done(rqp);
  1977. return (error);
  1978. }
  1979. /*ARGSUSED*/
  1980. static int
  1981. smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp,
  1982. const char *wildcard, int wclen, uint16_t attr)
  1983. {
  1984. ctx->f_type = ft_LM2;
  1985. ctx->f_namesz = SMB_MAXFNAMELEN + 1;
  1986. if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
  1987. ctx->f_namesz *= 2;
  1988. ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
  1989. ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp))
  1990. < SMB_DIALECT_NTLM0_12 ? SMB_FIND_STANDARD :
  1991. SMB_FIND_BOTH_DIRECTORY_INFO;
  1992. ctx->f_attrmask = attr;
  1993. ctx->f_wildcard = wildcard;
  1994. ctx->f_wclen = wclen;
  1995. return (0);
  1996. }
  1997. static int
  1998. smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
  1999. {
  2000. struct mdchain *mdp;
  2001. struct smb_t2rq *t2p;
  2002. char *cp;
  2003. uint8_t tb;
  2004. uint16_t date, time, wattr;
  2005. uint32_t size, next, dattr, resumekey = 0;
  2006. uint64_t llongint;
  2007. int error, svtz, cnt, fxsz, nmlen, recsz;
  2008. struct timespec ts;
  2009. if (ctx->f_ecnt == 0) {
  2010. if (ctx->f_flags & SMBFS_RDD_EOF)
  2011. return (ENOENT);
  2012. ctx->f_left = ctx->f_limit = limit;
  2013. gethrestime(&ts);
  2014. error = smbfs_smb_trans2find2(ctx);
  2015. if (error)
  2016. return (error);
  2017. ctx->f_otws++;
  2018. }
  2019. t2p = ctx->f_t2;
  2020. mdp = &t2p->t2_rdata;
  2021. svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz;
  2022. switch (ctx->f_infolevel) {
  2023. case SMB_FIND_STANDARD:
  2024. next = 0;
  2025. fxsz = 0;
  2026. md_get_uint16le(mdp, &date);
  2027. md_get_uint16le(mdp, &time); /* creation time */
  2028. smb_dos2unixtime(date, time, 0, svtz,
  2029. &ctx->f_attr.fa_createtime);
  2030. md_get_uint16le(mdp, &date);
  2031. md_get_uint16le(mdp, &time); /* access time */
  2032. smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime);
  2033. md_get_uint16le(mdp, &date);
  2034. md_get_uint16le(mdp, &time); /* modify time */
  2035. smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime);
  2036. md_get_uint32le(mdp, &size);
  2037. ctx->f_attr.fa_size = size;
  2038. md_get_uint32le(mdp, &size); /* allocation size */
  2039. ctx->f_attr.fa_allocsz = size;
  2040. md_get_uint16le(mdp, &wattr);
  2041. ctx->f_attr.fa_attr = wattr;
  2042. error = md_get_uint8(mdp, &tb);
  2043. if (error)
  2044. goto nodata;
  2045. size = nmlen = tb;
  2046. fxsz = 23;
  2047. recsz = next = 24 + nmlen; /* docs misses zero byte @end */
  2048. break;
  2049. case SMB_FIND_DIRECTORY_INFO:
  2050. case SMB_FIND_BOTH_DIRECTORY_INFO:
  2051. md_get_uint32le(mdp, &next);
  2052. md_get_uint32le(mdp, &resumekey); /* file index (resume key) */
  2053. md_get_uint64le(mdp, &llongint); /* creation time */
  2054. smb_time_NT2local(llongint, &ctx->f_attr.fa_createtime);
  2055. md_get_uint64le(mdp, &llongint);
  2056. smb_time_NT2local(llongint, &ctx->f_attr.fa_atime);
  2057. md_get_uint64le(mdp, &llongint);
  2058. smb_time_NT2local(llongint, &ctx->f_attr.fa_mtime);
  2059. md_get_uint64le(mdp, &llongint);
  2060. smb_time_NT2local(llongint, &ctx->f_attr.fa_ctime);
  2061. md_get_uint64le(mdp, &llongint); /* file size */
  2062. ctx->f_attr.fa_size = llongint;
  2063. md_get_uint64le(mdp, &llongint); /* alloc. size */
  2064. ctx->f_attr.fa_allocsz = llongint;
  2065. md_get_uint32le(mdp, &dattr); /* ext. file attributes */
  2066. ctx->f_attr.fa_attr = dattr;
  2067. error = md_get_uint32le(mdp, &size); /* name len */
  2068. if (error)
  2069. goto nodata;
  2070. fxsz = 64; /* size ofinfo up to filename */
  2071. if (ctx->f_infolevel == SMB_FIND_BOTH_DIRECTORY_INFO) {
  2072. /*
  2073. * Skip EaSize(4 bytes), a byte of ShortNameLength,
  2074. * a reserved byte, and ShortName(8.3 means 24 bytes,
  2075. * as Leach defined it to always be Unicode)
  2076. */
  2077. error = md_get_mem(mdp, NULL, 30, MB_MSYSTEM);
  2078. if (error)
  2079. goto nodata;
  2080. fxsz += 30;
  2081. }
  2082. recsz = next ? next : fxsz + size;
  2083. break;
  2084. default:
  2085. SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel);
  2086. return (EINVAL);
  2087. }
  2088. if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
  2089. nmlen = min(size, SMB_MAXFNAMELEN * 2);
  2090. else
  2091. nmlen = min(size, SMB_MAXFNAMELEN);
  2092. /* Allocated f_name in findopen */
  2093. ASSERT(nmlen < ctx->f_namesz);
  2094. cp = ctx->f_name;
  2095. error = md_get_mem(mdp, cp, nmlen, MB_MSYSTEM);
  2096. if (error)
  2097. goto nodata;
  2098. if (next) {
  2099. /* How much data to skip? */
  2100. cnt = next - nmlen - fxsz;
  2101. if (cnt < 0) {
  2102. SMBVDEBUG("out of sync\n");
  2103. goto nodata;
  2104. }
  2105. if (cnt > 0)
  2106. md_get_mem(mdp, NULL, cnt, MB_MSYSTEM);
  2107. }
  2108. /* Don't count any trailing null in the name. */
  2109. if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) {
  2110. if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0)
  2111. nmlen -= 2;
  2112. } else {
  2113. if (nmlen && cp[nmlen - 1] == 0)
  2114. nmlen--;
  2115. }
  2116. if (nmlen == 0)
  2117. goto nodata;
  2118. /*
  2119. * On a find-next we expect that the server will:
  2120. * 1) if the continue bit is set, use the server's offset,
  2121. * 2) else if the resume key is non-zero, use that offset,
  2122. * 3) else if the resume name is set, use that offset,
  2123. * 4) else use the server's idea of current offset.
  2124. *
  2125. * We always set the resume key flag. If the server returns
  2126. * a resume key then we should always send it back to them.
  2127. */
  2128. ctx->f_rkey = resumekey;
  2129. next = ctx->f_eofs + recsz;
  2130. if (ctx->f_rnameofs &&
  2131. ctx->f_rnameofs >= ctx->f_eofs &&
  2132. ctx->f_rnameofs < (int)next) {
  2133. /*
  2134. * This entry is the "resume name".
  2135. * Save it for the next request.
  2136. */
  2137. if (ctx->f_rnamelen != nmlen) {
  2138. if (ctx->f_rname)
  2139. kmem_free(ctx->f_rname, ctx->f_rnamelen);
  2140. ctx->f_rname = kmem_alloc(nmlen, KM_SLEEP);
  2141. ctx->f_rnamelen = nmlen;
  2142. }
  2143. bcopy(ctx->f_name, ctx->f_rname, nmlen);
  2144. }
  2145. ctx->f_nmlen = nmlen;
  2146. ctx->f_eofs = next;
  2147. ctx->f_ecnt--;
  2148. ctx->f_left--;
  2149. smbfs_fname_tolocal(ctx);
  2150. return (0);
  2151. nodata:
  2152. /*
  2153. * Something bad has happened and we ran out of data
  2154. * before we could parse all f_ecnt entries expected.
  2155. * Force this directory listing closed, otherwise the
  2156. * calling process may hang in an infinite loop.
  2157. */
  2158. SMBVDEBUG("ran out of data\n");
  2159. ctx->f_ecnt = 0; /* Force closed. */
  2160. ctx->f_flags |= SMBFS_RDD_EOF;
  2161. return (EIO);
  2162. }
  2163. static int
  2164. smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
  2165. {
  2166. int error = 0;
  2167. if (ctx->f_name)
  2168. kmem_free(ctx->f_name, ctx->f_namesz);
  2169. if (ctx->f_t2)
  2170. smb_t2_done(ctx->f_t2);
  2171. /*
  2172. * If SMBFS_RDD_FINDFIRST is still set, we were opened
  2173. * but never saw a findfirst, so we don't have any
  2174. * search handle to close.
  2175. */
  2176. if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
  2177. error = smbfs_smb_findclose2(ctx);
  2178. return (error);
  2179. }
  2180. int
  2181. smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
  2182. int attr, struct smb_cred *scrp,
  2183. struct smbfs_fctx **ctxpp)
  2184. {
  2185. struct smbfs_fctx *ctx;
  2186. int error;
  2187. ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
  2188. ctx->f_flags = SMBFS_RDD_FINDFIRST;
  2189. ctx->f_dnp = dnp;
  2190. ctx->f_scred = scrp;
  2191. ctx->f_ssp = dnp->n_mount->smi_share;
  2192. if (dnp->n_flag & N_XATTR) {
  2193. error = smbfs_xa_findopen(ctx, dnp, wild, wlen);
  2194. goto out;
  2195. }
  2196. if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0) {
  2197. error = smbfs_smb_findopenLM1(ctx, dnp, wild, wlen, attr);
  2198. } else {
  2199. error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
  2200. }
  2201. out:
  2202. if (error)
  2203. (void) smbfs_smb_findclose(ctx, scrp);
  2204. else
  2205. *ctxpp = ctx;
  2206. return (error);
  2207. }
  2208. int
  2209. smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
  2210. {
  2211. int error;
  2212. /*
  2213. * Note: "limit" (maxcount) needs to fit in a short!
  2214. */
  2215. if (limit > 0xffff)
  2216. limit = 0xffff;
  2217. ctx->f_scred = scrp;
  2218. for (;;) {
  2219. bzero(&ctx->f_attr, sizeof (ctx->f_attr));
  2220. switch (ctx->f_type) {
  2221. case ft_LM1:
  2222. error = smbfs_smb_findnextLM1(ctx, (uint16_t)limit);
  2223. break;
  2224. case ft_LM2:
  2225. error = smbfs_smb_findnextLM2(ctx, (uint16_t)limit);
  2226. break;
  2227. case ft_XA:
  2228. error = smbfs_xa_findnext(ctx, (uint16_t)limit);
  2229. break;
  2230. default:
  2231. ASSERT(0);
  2232. error = EINVAL;
  2233. break;
  2234. }
  2235. if (error)
  2236. return (error);
  2237. /*
  2238. * Skip "." or ".." - easy now that ctx->f_name
  2239. * has already been converted to utf-8 format.
  2240. */
  2241. if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') ||
  2242. (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' &&
  2243. ctx->f_name[1] == '.'))
  2244. continue;
  2245. break;
  2246. }
  2247. /*
  2248. * Moved the smbfs_fname_tolocal(ctx) call into
  2249. * the ..._findnext functions above.
  2250. */
  2251. ctx->f_inum = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen);
  2252. return (0);
  2253. }
  2254. int
  2255. smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp)
  2256. {
  2257. int error;
  2258. ctx->f_scred = scrp;
  2259. switch (ctx->f_type) {
  2260. case ft_LM1:
  2261. error = smbfs_smb_findcloseLM1(ctx);
  2262. break;
  2263. case ft_LM2:
  2264. error = smbfs_smb_findcloseLM2(ctx);
  2265. break;
  2266. case ft_XA:
  2267. error = smbfs_xa_findclose(ctx);
  2268. break;
  2269. }
  2270. if (ctx->f_rname)
  2271. kmem_free(ctx->f_rname, ctx->f_rnamelen);
  2272. if (ctx->f_firstnm)
  2273. kmem_free(ctx->f_firstnm, ctx->f_firstnmlen);
  2274. kmem_free(ctx, sizeof (*ctx));
  2275. return (error);
  2276. }
  2277. int
  2278. smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
  2279. struct smbfattr *fap, struct smb_cred *scrp)
  2280. {
  2281. struct smbfs_fctx *ctx;
  2282. int error, intr;
  2283. const char *name = (namep ? *namep : NULL);
  2284. int nmlen = (nmlenp ? *nmlenp : 0);
  2285. /* This is no longer called with a null dnp */
  2286. ASSERT(dnp);
  2287. /*
  2288. * Should not get here with "" anymore.
  2289. */
  2290. if (!name || !nmlen) {
  2291. DEBUG_ENTER("smbfs_smb_lookup: name is NULL");
  2292. return (EINVAL);
  2293. }
  2294. /*
  2295. * Should not get here with "." or ".." anymore.
  2296. */
  2297. if ((nmlen == 1 && name[0] == '.') ||
  2298. (nmlen == 2 && name[0] == '.' && name[1] == '.')) {
  2299. DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'");
  2300. return (EINVAL);
  2301. }
  2302. /*
  2303. * XXX: Should use _qpathinfo here instead.
  2304. * (if SMB_CAP_NT_SMBS)
  2305. */
  2306. /*
  2307. * Shared lock for n_fid use (smb_flush).
  2308. */
  2309. intr = dnp->n_mount->smi_flags & SMI_INT;
  2310. if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr))
  2311. return (EINTR);
  2312. /*
  2313. * This hides a server bug observable in Win98:
  2314. * size changes may not show until a CLOSE or a FLUSH op
  2315. * XXX: Make this conditional on !NTSMBs
  2316. */
  2317. error = smbfs_smb_flush(dnp, scrp);
  2318. if (error)
  2319. goto out;
  2320. error = smbfs_smb_findopen(dnp, name, nmlen,
  2321. SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx);
  2322. if (error)
  2323. goto out;
  2324. ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
  2325. error = smbfs_smb_findnext(ctx, 1, scrp);
  2326. if (error == 0) {
  2327. *fap = ctx->f_attr;
  2328. /*
  2329. * Solaris smbfattr doesn't have fa_ino,
  2330. * and we don't allow name==NULL in this
  2331. * function anymore.
  2332. */
  2333. if (namep)
  2334. *namep = (const char *)smbfs_name_alloc(
  2335. ctx->f_name, ctx->f_nmlen);
  2336. if (nmlenp)
  2337. *nmlenp = ctx->f_nmlen;
  2338. }
  2339. (void) smbfs_smb_findclose(ctx, scrp);
  2340. out:
  2341. smbfs_rw_exit(&dnp->r_lkserlock);
  2342. return (error);
  2343. }
  2344. /*
  2345. * OTW function to Get a security descriptor (SD).
  2346. *
  2347. * Note: On success, this fills in mdp->md_top,
  2348. * which the caller should free.
  2349. */
  2350. int
  2351. smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid,
  2352. struct smb_cred *scrp, uint32_t selector,
  2353. mblk_t **res, uint32_t *reslen)
  2354. {
  2355. struct smb_ntrq *ntp;
  2356. struct mbchain *mbp;
  2357. struct mdchain *mdp;
  2358. int error, len;
  2359. error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC,
  2360. scrp, &ntp);
  2361. if (error)
  2362. return (error);
  2363. /* Parameters part */
  2364. mbp = &ntp->nt_tparam;
  2365. mb_init(mbp);
  2366. mb_put_uint16le(mbp, fid);
  2367. mb_put_uint16le(mbp, 0); /* reserved */
  2368. mb_put_uint32le(mbp, selector);
  2369. /* Data part (none) */
  2370. /* Max. returned parameters and data. */
  2371. ntp->nt_maxpcount = 4;
  2372. ntp->nt_maxdcount = *reslen;
  2373. error = smb_nt_request(ntp);
  2374. if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
  2375. goto done;
  2376. *res = NULL;
  2377. /*
  2378. * if there's more data than we said we could receive, here
  2379. * is where we pick up the length of it
  2380. */
  2381. mdp = &ntp->nt_rparam;
  2382. md_get_uint32le(mdp, reslen);
  2383. if (error)
  2384. goto done;
  2385. /*
  2386. * get the data part.
  2387. */
  2388. mdp = &ntp->nt_rdata;
  2389. if (mdp->md_top == NULL) {
  2390. SMBVDEBUG("null md_top? fid 0x%x\n", fid);
  2391. error = EBADRPC;
  2392. goto done;
  2393. }
  2394. /*
  2395. * The returned parameter SD_length should match
  2396. * the length of the returned data. Unfortunately,
  2397. * we have to work around server bugs here.
  2398. */
  2399. len = m_fixhdr(mdp->md_top);
  2400. if (len != *reslen) {
  2401. SMBVDEBUG("len %d *reslen %d fid 0x%x\n",
  2402. len, *reslen, fid);
  2403. }
  2404. /*
  2405. * Actual data provided is < returned SD_length.
  2406. *
  2407. * The following "if (len < *reslen)" handles a Windows bug
  2408. * observed when the underlying filesystem is FAT32. In that
  2409. * case a 32 byte security descriptor comes back (S-1-1-0, ie
  2410. * "Everyone") but the Parameter Block claims 44 is the length
  2411. * of the security descriptor. (The Data Block length
  2412. * claimed is 32. This server bug was reported against NT
  2413. * first and I've personally observed it with W2K.
  2414. */
  2415. if (len < *reslen)
  2416. *reslen = len;
  2417. /*
  2418. * Actual data provided is > returned SD_length.
  2419. * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0)
  2420. * Narrow work-around for returned SD_length==0.
  2421. */
  2422. if (len > *reslen) {
  2423. /*
  2424. * Increase *reslen, but carefully.
  2425. */
  2426. if (*reslen == 0 && len <= ntp->nt_maxdcount)
  2427. *reslen = len;
  2428. }
  2429. error = md_get_mbuf(mdp, len, res);
  2430. done:
  2431. if (error == 0 && *res == NULL) {
  2432. ASSERT(*res);
  2433. error = EBADRPC;
  2434. }
  2435. smb_nt_done(ntp);
  2436. return (error);
  2437. }
  2438. #ifdef APPLE
  2439. /*
  2440. * Wrapper for _getsd() compatible with darwin code.
  2441. */
  2442. int
  2443. smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
  2444. uint32_t selector, struct ntsecdesc **res)
  2445. {
  2446. int error;
  2447. uint32_t len, olen;
  2448. struct mdchain *mdp, md_store;
  2449. struct mbuf *m;
  2450. bzero(mdp, sizeof (*mdp));
  2451. len = 500; /* "overlarge" values => server errors */
  2452. again:
  2453. olen = len;
  2454. error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len);
  2455. /*
  2456. * Server may give us an error indicating that we
  2457. * need a larger data buffer to receive the SD,
  2458. * and the size we'll need. Use the given size,
  2459. * but only after a sanity check.
  2460. *
  2461. * XXX: Check for specific error values here?
  2462. * XXX: also ... && len <= MAX_RAW_SD_SIZE
  2463. */
  2464. if (error && len > olen)
  2465. goto again;
  2466. if (error)
  2467. return (error);
  2468. mdp = &md_store;
  2469. md_initm(mdp, m);
  2470. MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK);
  2471. error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM);
  2472. md_done(mdp);
  2473. return (error);
  2474. }
  2475. #endif /* APPLE */
  2476. /*
  2477. * OTW function to Set a security descriptor (SD).
  2478. * Caller data are carried in an mbchain_t.
  2479. *
  2480. * Note: This normally consumes mbp->mb_top, and clears
  2481. * that pointer when it does.
  2482. */
  2483. int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid,
  2484. struct smb_cred *scrp, uint32_t selector, mblk_t **mp)
  2485. {
  2486. struct smb_ntrq *ntp;
  2487. struct mbchain *mbp;
  2488. int error;
  2489. error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC,
  2490. scrp, &ntp);
  2491. if (error)
  2492. return (error);
  2493. /* Parameters part */
  2494. mbp = &ntp->nt_tparam;
  2495. mb_init(mbp);
  2496. mb_put_uint16le(mbp, fid);
  2497. mb_put_uint16le(mbp, 0); /* reserved */
  2498. mb_put_uint32le(mbp, selector);
  2499. /* Data part */
  2500. mbp = &ntp->nt_tdata;
  2501. mb_initm(mbp, *mp);
  2502. *mp = NULL; /* consumed */
  2503. /* No returned parameters or data. */
  2504. ntp->nt_maxpcount = 0;
  2505. ntp->nt_maxdcount = 0;
  2506. error = smb_nt_request(ntp);
  2507. smb_nt_done(ntp);
  2508. return (error);
  2509. }
  2510. #ifdef APPLE
  2511. /*
  2512. * This function builds the SD given the various parts.
  2513. */
  2514. int
  2515. smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
  2516. uint32_t selector, uint16_t flags, struct ntsid *owner,
  2517. struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl)
  2518. {
  2519. struct mbchain *mbp, mb_store;
  2520. struct ntsecdesc ntsd;
  2521. int error, off;
  2522. /*
  2523. * Build the SD as its own mbuf chain and pass it to
  2524. * smbfs_smb_setsec_m()
  2525. */
  2526. mbp = &mb_store;
  2527. mb_init(mbp);
  2528. bzero(&ntsd, sizeof (ntsd));
  2529. wset_sdrevision(&ntsd);
  2530. /*
  2531. * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN)
  2532. * We set here only those bits we can be sure must be set. The rest
  2533. * are up to the caller. In particular, the caller may intentionally
  2534. * set an acl PRESENT bit while giving us a null pointer for the
  2535. * acl - that sets a null acl, giving access to everyone. Note also
  2536. * that the AUTO_INHERITED bits should probably always be set unless
  2537. * the server is NT.
  2538. */
  2539. flags |= SD_SELF_RELATIVE;
  2540. off = sizeof (ntsd);
  2541. if (owner) {
  2542. wset_sdowneroff(&ntsd, off);
  2543. off += sidlen(owner);
  2544. }
  2545. if (group) {
  2546. wset_sdgroupoff(&ntsd, off);
  2547. off += sidlen(group);
  2548. }
  2549. if (sacl) {
  2550. flags |= SD_SACL_PRESENT;
  2551. wset_sdsacloff(&ntsd, off);
  2552. off += acllen(sacl);
  2553. }
  2554. if (dacl) {
  2555. flags |= SD_DACL_PRESENT;
  2556. wset_sddacloff(&ntsd, off);
  2557. }
  2558. wset_sdflags(&ntsd, flags);
  2559. mb_put_mem(mbp, (caddr_t)&ntsd, sizeof (ntsd), MB_MSYSTEM);
  2560. if (owner)
  2561. mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM);
  2562. if (group)
  2563. mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM);
  2564. if (sacl)
  2565. mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM);
  2566. if (dacl)
  2567. mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM);
  2568. /*
  2569. * Just pass the mbuf to _setsec_m
  2570. * It will clear mb_top if consumed.
  2571. */
  2572. error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top);
  2573. mb_done(mbp);
  2574. return (error);
  2575. }
  2576. #endif /* APPLE */