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
33 /*
34 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
35 * Use is subject to license terms.
36 *
37 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/inttypes.h>
43 #include <sys/time.h>
44 #include <sys/vnode.h>
45 #include <sys/sunddi.h>
46 #include <sys/cmn_err.h>
47
48 #include <netsmb/smb_osdep.h>
49
50 #include <netsmb/smb.h>
51 #include <netsmb/smb2.h>
52 #include <netsmb/smb_conn.h>
53 #include <netsmb/smb_subr.h>
54 #include <netsmb/smb_rq.h>
55
56 #include <smbfs/smbfs.h>
57 #include <smbfs/smbfs_node.h>
58 #include <smbfs/smbfs_subr.h>
59
60 /*
61 * Jan 1 1980 as 64 bit NT time.
62 * (tenths of microseconds since 1601)
63 */
64 const uint64_t NT1980 = 11960035200ULL*10000000ULL;
65
66
67 /*
68 * Helper for smbfs_getattr_otw
69 * used when we have an open FID
70 */
71 int
72 smbfs_smb_getfattr(
73 struct smbnode *np,
74 smb_fh_t *fhp,
75 struct smbfattr *fap,
76 struct smb_cred *scrp)
77 {
78 struct smb_share *ssp = np->n_mount->smi_share;
79 int error;
80
81 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
82 error = smbfs_smb2_qfileinfo(ssp, &fhp->fh_fid2, fap, scrp);
83 } else {
84 error = smbfs_smb1_trans2_query(np, fhp->fh_fid1, fap, scrp);
85 }
86
87 return (error);
88 }
89
90 /*
91 * Helper for smbfs_getattr_otw
92 * used when we don't have an open FID
93 *
94 * For SMB1 we can just use the path form of trans2 query.
95 * For SMB2 we need to do an attribute-only open.
96 * See smbfs_smb2_getpattr()
97 */
98 int
99 smbfs_smb_getpattr(
100 struct smbnode *np,
101 struct smbfattr *fap,
102 struct smb_cred *scrp)
103 {
104 struct smb_share *ssp = np->n_mount->smi_share;
105 int error;
106
107 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
108 error = smbfs_smb2_getpattr(np, fap, scrp);
109 } else {
110 uint16_t fid = SMB_FID_UNUSED;
111 error = smbfs_smb1_trans2_query(np, fid, fap, scrp);
112 }
113
114 return (error);
115 }
116
117 /*
118 * Get and parse FileFsAttributeInformation
119 */
120 int
121 smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
122 struct smb_cred *scrp)
123 {
124 int error;
125
126 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
127 error = smbfs_smb2_qfsattr(ssp, fsa, scrp);
128 } else {
129 error = smbfs_smb1_qfsattr(ssp, fsa, scrp);
130 }
131
132 /*
133 * If fs_name starts with FAT, we can't set dates before 1980
134 */
135 if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
136 SMB_SS_LOCK(ssp);
137 ssp->ss_flags |= SMBS_FST_FAT;
138 SMB_SS_UNLOCK(ssp);
139 }
140
141 return (error);
142 }
143
144 int
145 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
146 struct smb_cred *scp)
147 {
148 struct smb_fs_size_info info;
149 struct smb_vc *vcp = SSTOVC(ssp);
150 uint32_t bps, spu;
151 int error;
152
153 if (vcp->vc_flags & SMBV_SMB2) {
154 error = smbfs_smb2_statfs(ssp, &info, scp);
155 } else {
156 error = smbfs_smb1_statfs(ssp, &info, scp);
157 }
158 if (error)
159 return (error);
160
161 /* A bit of paranoia. */
162 bps = info.bytes_per_sect;
163 if (bps < DEV_BSIZE)
164 bps = DEV_BSIZE;
165 spu = info.sect_per_unit;
166 if (spu == 0)
167 spu = 1;
168
169 /* preferred file system block size */
170 sbp->f_bsize = bps * spu;
171
172 /* file system block size ("fragment size") */
173 sbp->f_frsize = bps;
174
175 /* total blocks of f_frsize */
176 sbp->f_blocks = info.total_units * spu;
177
178 /* free blocks of f_frsize */
179 sbp->f_bfree = info.actual_avail * spu;
180
181 /* free blocks avail to non-superuser */
182 sbp->f_bavail = info.caller_avail * spu;
183
184 sbp->f_files = (-1); /* total file nodes in file system */
185 sbp->f_ffree = (-1); /* free file nodes in fs */
186
187 return (error);
188 }
189
190 int
191 smbfs_smb_setdisp(struct smb_share *ssp, smb_fh_t *fhp,
192 uint8_t disp, struct smb_cred *scrp)
193 {
194 int err;
195
196 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
197 err = smbfs_smb2_setdisp(ssp, &fhp->fh_fid2, disp, scrp);
198 } else {
199 err = smbfs_smb1_setdisp(ssp, fhp->fh_fid1, disp, scrp);
200 }
201
202 return (err);
203 }
204
205 int
206 smbfs_smb_setfsize(struct smb_share *ssp, smb_fh_t *fhp,
207 uint64_t size, struct smb_cred *scrp)
208 {
209 int error;
210
211 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
212 error = smbfs_smb2_seteof(ssp, &fhp->fh_fid2, size, scrp);
213 } else {
214 error = smbfs_smb1_seteof(ssp, fhp->fh_fid1, size, scrp);
215 }
216
217 return (error);
218 }
219
220
221 /*
222 * Set file attributes (optionally: DOS attr, atime, mtime)
223 * Always have an open FID with set attr rights.
224 */
225 int
226 smbfs_smb_setfattr(
227 struct smb_share *ssp,
228 smb_fh_t *fhp,
229 uint32_t attr,
230 struct timespec *mtime,
231 struct timespec *atime,
232 struct smb_cred *scrp)
233 {
234 struct mbchain mb_info;
235 struct mbchain *mbp = &mb_info;
236 uint64_t tm;
237 int error;
238
239 /*
240 * Build a struct FILE_BASIC_INFORMATION in mbp
241 * LARGE_INTEGER CreationTime;
242 * LARGE_INTEGER LastAccessTime;
243 * LARGE_INTEGER LastWriteTime;
244 * LARGE_INTEGER ChangeTime;
245 * ULONG FileAttributes;
246 * Zero in times means "no change".
247 */
248 mb_init(mbp);
249 mb_put_uint64le(mbp, 0); /* creation time */
250 if (atime) {
251 smb_time_local2NT(atime, &tm);
252 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
253 tm < NT1980)
254 tm = NT1980;
255 } else
256 tm = 0;
257 mb_put_uint64le(mbp, tm); /* last access time */
258 if (mtime) {
259 smb_time_local2NT(mtime, &tm);
260 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
261 tm < NT1980)
262 tm = NT1980;
263 } else
264 tm = 0;
265 mb_put_uint64le(mbp, tm); /* last write time */
266 mb_put_uint64le(mbp, 0); /* change time */
267 mb_put_uint32le(mbp, attr);
268
269 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
270 error = smbfs_smb2_setfattr(ssp, &fhp->fh_fid2, mbp, scrp);
271 } else {
272 error = smbfs_smb1_setfattr(ssp, fhp->fh_fid1, mbp, scrp);
273 }
274
275 return (error);
276 }
277
278 int
279 smbfs_smb_flush(struct smb_share *ssp, smb_fh_t *fhp,
280 struct smb_cred *scrp)
281 {
282 int error;
283
284 if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
285 error = smbfs_smb2_flush(ssp, &fhp->fh_fid2, scrp);
286 } else {
287 error = smbfs_smb1_flush(ssp, fhp->fh_fid1, scrp);
288 }
289 return (error);
290 }
291
292 /*
293 * Modern create/open of file or directory.
294 * On success, fills in fhp->fh_fid* and fhp->fh_rights
295 */
296 int
297 smbfs_smb_ntcreatex(
298 struct smbnode *np,
299 const char *name,
300 int nmlen,
301 int xattr, /* is named stream? */
302 uint32_t req_acc, /* requested access */
303 uint32_t efa, /* ext. file attrs (DOS attr +) */
304 uint32_t share_acc,
305 uint32_t disp, /* open disposition */
306 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
307 struct smb_cred *scrp,
308 smb_fh_t *fhp, /* pre-made file handle to fill in */
309 uint32_t *cr_act_p, /* optional returned create action */
310 struct smbfattr *fap) /* optional returned attributes */
311 {
312 struct mbchain name_mb;
313 struct smb_share *ssp = np->n_mount->smi_share;
314 int err;
315
316 mb_init(&name_mb);
317
318 if (name == NULL)
319 nmlen = 0;
320 err = smbfs_fullpath(&name_mb, SSTOVC(ssp),
321 np, name, nmlen, xattr ? ':' : '\\');
322 if (err)
323 goto out;
324
325 err = smb_smb_ntcreate(ssp, &name_mb,
326 0, /* NTCREATEX_FLAGS... */
327 req_acc, efa, share_acc, disp, createopt,
328 NTCREATEX_IMPERSONATION_IMPERSONATION,
329 scrp, fhp, cr_act_p, fap);
330
331 out:
332 mb_done(&name_mb);
333
334 return (err);
335 }
336
337 /*
338 * Get a file handle with (at least) the specified rights.
339 *
340 * We'll try to borrow the node ->n_fid if we can. When we
341 * borrow n_fid, just take a hold on the smb_fh_t, and don't
342 * bump n_fidrefs as that tracks VFS-level opens. Similarly
343 * in _tmpclose we just release the smb_fh_t, not n_fidrefs.
344 */
345 int
346 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
347 smb_fh_t **fhpp)
348 {
349 struct smb_share *ssp = np->n_mount->smi_share;
350 smb_fh_t *fhp = NULL;
351 int error;
352
353 /* Can we re-use n_fid? or must we open anew? */
354 mutex_enter(&np->r_statelock);
355 if (np->n_fidrefs > 0 &&
356 (fhp = np->n_fid) != NULL &&
357 fhp->fh_vcgenid == ssp->ss_vcgenid &&
358 (fhp->fh_rights & rights) == rights) {
359 smb_fh_hold(fhp);
360 *fhpp = fhp;
361 mutex_exit(&np->r_statelock);
362 return (0);
363 }
364 mutex_exit(&np->r_statelock);
365
366 error = smb_fh_create(ssp, &fhp);
367 if (error != 0)
368 goto out;
369
370 /* re-open an existing file. */
371 error = smbfs_smb_ntcreatex(np,
372 NULL, 0, 0, /* name nmlen xattr */
373 rights, SMB_EFA_NORMAL,
374 NTCREATEX_SHARE_ACCESS_ALL,
375 NTCREATEX_DISP_OPEN,
376 0, /* create options */
377 scrp, fhp,
378 NULL, NULL); /* cr_act_p fa_p */
379 if (error != 0)
380 goto out;
381
382 fhp->fh_rights = rights;
383 smb_fh_opened(fhp);
384 *fhpp = fhp;
385 fhp = NULL;
386
387 out:
388 if (fhp != NULL)
389 smb_fh_rele(fhp);
390
391 return (error);
392 }
393
394 /* ARGSUSED */
395 void
396 smbfs_smb_tmpclose(struct smbnode *np, smb_fh_t *fhp)
397 {
398 smb_fh_rele(fhp);
399 }
400
401 int
402 smbfs_smb_open(
403 struct smbnode *np,
404 const char *name,
405 int nmlen,
406 int xattr,
407 uint32_t rights,
408 struct smb_cred *scrp,
409 smb_fh_t **fhpp,
410 smbfattr_t *fap)
411 {
412 struct smb_share *ssp = np->n_mount->smi_share;
413 // struct smb_vc *vcp = SSTOVC(ssp);
414 smb_fh_t *fhp = NULL;
415 int error;
416
417 error = smb_fh_create(ssp, &fhp);
418 if (error != 0)
419 goto out;
420
421 /* open an existing file */
422 error = smbfs_smb_ntcreatex(np,
423 name, nmlen, xattr,
424 rights, SMB_EFA_NORMAL,
425 NTCREATEX_SHARE_ACCESS_ALL,
426 NTCREATEX_DISP_OPEN,
427 0, /* create options */
428 scrp, fhp, NULL, fap);
429 if (error != 0)
430 goto out;
431
432 fhp->fh_rights = rights;
433 smb_fh_opened(fhp);
434 *fhpp = fhp;
435 fhp = NULL;
436
437 out:
438 if (fhp != NULL)
439 smb_fh_rele(fhp);
440
441 return (0);
442 }
443
444 void
445 smbfs_smb_close(smb_fh_t *fhp)
446 {
447
448 smb_fh_close(fhp);
449 smb_fh_rele(fhp);
450 }
451
452 int
453 smbfs_smb_create(
454 struct smbnode *dnp,
455 const char *name,
456 int nmlen,
457 int xattr,
458 uint32_t disp,
459 struct smb_cred *scrp,
460 smb_fh_t **fhpp)
461 {
462 struct smb_share *ssp = dnp->n_mount->smi_share;
463 // struct smb_vc *vcp = SSTOVC(ssp);
464 smb_fh_t *fhp = NULL;
465 uint32_t efa, rights;
466 int error;
467
468 error = smb_fh_create(ssp, &fhp);
469 if (error != 0)
470 goto out;
471
472 /*
473 * At present the only access we might need is to WRITE data,
474 * and that only if we are creating a "symlink". When/if the
475 * access needed gets more complex it should made a parameter
476 * and be set upstream.
477 */
478 rights = SA_RIGHT_FILE_WRITE_DATA;
479 efa = SMB_EFA_NORMAL;
480 if (!xattr && name && *name == '.')
481 efa = SMB_EFA_HIDDEN;
482 error = smbfs_smb_ntcreatex(dnp,
483 name, nmlen, xattr, rights, efa,
484 NTCREATEX_SHARE_ACCESS_ALL,
485 disp, /* != NTCREATEX_DISP_OPEN */
486 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
487 scrp, fhp, NULL, NULL);
488 if (error != 0)
489 goto out;
490
491 fhp->fh_rights = rights;
492 smb_fh_opened(fhp);
493 *fhpp = fhp;
494 fhp = NULL;
495
496 out:
497 if (fhp != NULL)
498 smb_fh_rele(fhp);
499
500 return (error);
501 }
502
503 int
504 smbfs_smb_rename(struct smbnode *sdnp, struct smbnode *np,
505 struct smbnode *tdnp, const char *tname, int tnlen,
506 smb_fh_t *fhp, struct smb_cred *scrp)
507 {
508 struct smb_share *ssp = np->n_mount->smi_share;
509 struct smb_vc *vcp = SSTOVC(ssp);
510 int err;
511
512 if (vcp->vc_flags & SMBV_SMB2) {
513 err = smbfs_smb2_rename(np, tdnp, tname, tnlen, 0,
514 &fhp->fh_fid2, scrp);
515 return (err);
516 }
517
518 /*
519 * SMB1 -- Want to use _t2rename if we can
520 * (rename in same dir and cap pass-through)
521 * Most SMB1 servers have cap pass-through.
522 */
523 if (sdnp == tdnp &&
524 (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) != 0) {
525 err = smbfs_smb1_t2rename(np, tname, tnlen, fhp->fh_fid1, scrp);
526 } else {
527 err = smbfs_smb1_oldrename(np, tdnp, tname, tnlen, scrp);
528 }
529
530 return (err);
531 }
532
533 int
534 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
535 struct smb_cred *scrp)
536 {
537 smb_fh_t tmp_fh;
538 struct smb_share *ssp = dnp->n_mount->smi_share;
539 uint32_t efa, rights;
540 int error;
541
542 /*
543 * Using a faked-up handle here to avoid the work of
544 * creating and destroying a real "conn obj".
545 */
546 bzero(&tmp_fh, sizeof (tmp_fh));
547
548 /*
549 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
550 * just to be asking for something. The rights==0 case could
551 * easily be broken on some old or unusual servers.
552 */
553 rights = SA_RIGHT_FILE_READ_DATA;
554 efa = SMB_EFA_NORMAL;
555 if (name && *name == '.')
556 efa |= SMB_EFA_HIDDEN;
557 error = smbfs_smb_ntcreatex(dnp,
558 name, nmlen, 0, /* xattr */
559 rights, SMB_EFA_DIRECTORY,
560 NTCREATEX_SHARE_ACCESS_ALL,
561 NTCREATEX_DISP_CREATE,
562 NTCREATEX_OPTIONS_DIRECTORY,
563 scrp, &tmp_fh, NULL, NULL);
564 if (error == 0) {
565 (void) smb_smb_close(ssp, &tmp_fh, scrp);
566 }
567
568 return (error);
569 }
570
571 /*
572 * Protocol-level directory open
573 */
574 int
575 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
576 int attr, struct smb_cred *scrp,
577 struct smbfs_fctx **ctxpp)
578 {
579 struct smb_share *ssp = dnp->n_mount->smi_share;
580 struct smb_vc *vcp = SSTOVC(ssp);
581 struct smbfs_fctx *ctx;
582 int error;
583
584 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
585
586 ctx->f_flags = SMBFS_RDD_FINDFIRST;
587 ctx->f_dnp = dnp;
588 ctx->f_scred = scrp;
589 ctx->f_ssp = ssp;
590
591 if (dnp->n_flag & N_XATTR) {
592 error = smbfs_xa_findopen(ctx, dnp, wild, wlen);
593 goto out;
594 }
595
596 if (vcp->vc_flags & SMBV_SMB2) {
597 error = smbfs_smb2_findopen(ctx, dnp, wild, wlen, attr);
598 } else {
599 error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
600 }
601
602 out:
603 ctx->f_scred = NULL;
604 if (error) {
605 kmem_free(ctx, sizeof (*ctx));
606 } else {
607 *ctxpp = ctx;
608 }
609
610 return (error);
611 }
612
613 int
614 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
615 {
616 int error = 0;
617 uint16_t lim;
618
619 /*
620 * Note: "limit" (maxcount) needs to fit in a short!
621 */
622 if (limit > 0xffff)
623 limit = 0xffff;
624 lim = (uint16_t)limit;
625
626 ctx->f_scred = scrp;
627 for (;;) {
628 bzero(&ctx->f_attr, sizeof (ctx->f_attr));
629 switch (ctx->f_type) {
630
631 case ft_SMB2:
632 error = smbfs_smb2_findnext(ctx, lim);
633 break;
634 case ft_LM2:
635 error = smbfs_smb_findnextLM2(ctx, lim);
636 break;
637 case ft_XA:
638 error = smbfs_xa_findnext(ctx, lim);
639 break;
640 default:
641 ASSERT(0);
642 error = EINVAL;
643 break;
644 }
645 if (error)
646 break;
647 /*
648 * Skip "." or ".." - easy now that ctx->f_name
649 * has already been converted to utf-8 format.
650 */
651 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') ||
652 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' &&
653 ctx->f_name[1] == '.'))
654 continue;
655 break;
656 }
657 ctx->f_scred = NULL;
658 if (error != 0)
659 return (error);
660
661 ctx->f_inum = smbfs_getino(ctx->f_dnp,
662 ctx->f_name, ctx->f_nmlen);
663
664 #ifdef DEBUG
665 SMBVDEBUG("findnext: (%s)\n", ctx->f_name);
666 #endif
667
668 return (error);
669 }
670
671
672 int
673 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp)
674 {
675 int error;
676
677 ctx->f_scred = scrp;
678 switch (ctx->f_type) {
679 case ft_SMB2:
680 error = smbfs_smb2_findclose(ctx);
681 break;
682 case ft_LM2:
683 error = smbfs_smb_findcloseLM2(ctx);
684 break;
685 case ft_XA:
686 error = smbfs_xa_findclose(ctx);
687 break;
688 default:
689 error = ENOSYS;
690 break;
691 }
692 ctx->f_scred = NULL;
693 if (ctx->f_rname)
694 kmem_free(ctx->f_rname, ctx->f_rnamelen);
695 if (ctx->f_firstnm)
696 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen);
697 kmem_free(ctx, sizeof (*ctx));
698 return (error);
699 }
700
701
702 int
703 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
704 struct smbfattr *fap, struct smb_cred *scrp)
705 {
706 struct smbfs_fctx *ctx;
707 int error, intr;
708 const char *name = (namep ? *namep : NULL);
709 int nmlen = (nmlenp ? *nmlenp : 0);
710
711 /* This is no longer called with a null dnp */
712 ASSERT(dnp);
713
714 /*
715 * Should not get here with "" anymore.
716 */
717 if (!name || !nmlen) {
718 DEBUG_ENTER("smbfs_smb_lookup: name is NULL");
719 return (EINVAL);
720 }
721
722 /*
723 * Should not get here with "." or ".." anymore.
724 */
725 if ((nmlen == 1 && name[0] == '.') ||
726 (nmlen == 2 && name[0] == '.' && name[1] == '.')) {
727 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'");
728 return (EINVAL);
729 }
730
731 /*
732 * Shared lock for n_fid use (smb_flush).
733 */
734 intr = dnp->n_mount->smi_flags & SMI_INT;
735 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr))
736 return (EINTR);
737
738 error = smbfs_smb_findopen(dnp, name, nmlen,
739 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx);
740 if (error)
741 goto out;
742 ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
743 error = smbfs_smb_findnext(ctx, 1, scrp);
744 if (error == 0) {
745 *fap = ctx->f_attr;
746 /*
747 * Solaris smbfattr doesn't have fa_ino,
748 * and we don't allow name==NULL in this
749 * function anymore.
750 */
751 if (namep)
752 *namep = (const char *)smbfs_name_alloc(
753 ctx->f_name, ctx->f_nmlen);
754 if (nmlenp)
755 *nmlenp = ctx->f_nmlen;
756 }
757 (void) smbfs_smb_findclose(ctx, scrp);
758
759 out:
760 smbfs_rw_exit(&dnp->r_lkserlock);
761 return (error);
762 }
763
764 /*
765 * OTW function to Get a security descriptor (SD).
766 *
767 * Note: On success, this fills in mdp->md_top,
768 * which the caller should free.
769 */
770 int
771 smbfs_smb_getsec(struct smb_share *ssp, smb_fh_t *fhp,
772 uint32_t selector, mblk_t **res, uint32_t *reslen,
773 struct smb_cred *scrp)
774 {
775 struct smb_vc *vcp = SSTOVC(ssp);
776 int error, len;
777
778 *res = NULL;
779
780 if (vcp->vc_flags & SMBV_SMB2) {
781 error = smbfs_smb2_getsec(ssp, &fhp->fh_fid2,
782 selector, res, reslen, scrp);
783 } else {
784 error = smbfs_smb1_getsec(ssp, fhp->fh_fid1,
785 selector, res, reslen, scrp);
786 }
787
788 /*
789 * get the data part.
790 */
791 if (*res == NULL) {
792 error = EBADRPC;
793 goto done;
794 }
795
796 /*
797 * If message length is < returned SD_length,
798 * correct *reslen (reduce it). It greater,
799 * just ignore the extra data.
800 */
801 len = m_fixhdr(*res);
802 if (len < *reslen)
803 *reslen = len;
804
805 done:
806 if (error == 0 && *res == NULL) {
807 ASSERT(*res);
808 error = EBADRPC;
809 }
810
811 return (error);
812 }
813
814 /*
815 * OTW function to Set a security descriptor (SD).
816 * Caller data are carried in an mbchain_t.
817 *
818 * Note: This normally consumes mbp->mb_top, and clears
819 * that pointer when it does.
820 */
821 int
822 smbfs_smb_setsec(struct smb_share *ssp, smb_fh_t *fhp,
823 uint32_t selector, mblk_t **mp,
824 struct smb_cred *scrp)
825 {
826 struct smb_vc *vcp = SSTOVC(ssp);
827 int error;
828
829 if (vcp->vc_flags & SMBV_SMB2) {
830 error = smbfs_smb2_setsec(ssp, &fhp->fh_fid2,
831 selector, mp, scrp);
832 } else {
833 error = smbfs_smb1_setsec(ssp, fhp->fh_fid1,
834 selector, mp, scrp);
835 }
836
837 return (error);
838 }