1 /* $NetBSD: smb_conn.c,v 1.24 2008/04/28 20:24:10 martin Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 2000-2001 Boris Popov
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by Boris Popov.
44 * 4. Neither the name of the author nor the names of any co-contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * FreeBSD: src/sys/netsmb/smb_conn.c,v 1.3 2001/12/02 08:47:29 bp Exp
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: smb_conn.c,v 1.24 2008/04/28 20:24:10 martin Exp $");
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/kernel.h>
73 #include <sys/malloc.h>
76 #include <sys/sysctl.h>
77 #include <sys/mbuf.h> /* for M_SONAME */
78 #include <sys/kauth.h>
80 #include <netsmb/iconv.h>
82 #include <netsmb/smb.h>
83 #include <netsmb/smb_subr.h>
84 #include <netsmb/smb_conn.h>
85 #include <netsmb/smb_tran.h>
86 #include <netsmb/smb_trantcp.h>
88 static struct smb_connobj smb_vclist
;
89 static int smb_vcnext
= 1; /* next unique id for VC */
92 SYSCTL_NODE(_net
, OID_AUTO
, smb
, CTLFLAG_RW
, NULL
, "SMB protocol");
95 MALLOC_DEFINE(M_SMBCONN
, "SMB conn", "SMB connection");
97 static void smb_co_init(struct smb_connobj
*cp
, int level
, const char *objname
);
98 static void smb_co_done(struct smb_connobj
*cp
);
100 static int smb_vc_disconnect(struct smb_vc
*vcp
);
101 static void smb_vc_free(struct smb_connobj
*cp
);
102 static void smb_vc_gone(struct smb_connobj
*cp
, struct smb_cred
*scred
);
103 static smb_co_free_t smb_share_free
;
104 static smb_co_gone_t smb_share_gone
;
107 static int smb_sysctl_treedump(SYSCTL_HANDLER_ARGS
);
109 SYSCTL_PROC(_net_smb
, OID_AUTO
, treedump
, CTLFLAG_RD
| CTLTYPE_OPAQUE
,
110 NULL
, 0, smb_sysctl_treedump
, "S,treedump", "Requester tree");
117 smb_co_init(&smb_vclist
, SMBL_SM
, "smbsm");
118 mutex_enter(&smb_vclist
.co_interlock
);
119 smb_co_unlock(&smb_vclist
);
120 mutex_exit(&smb_vclist
.co_interlock
);
128 /* XXX: hold the mutex */
130 if (smb_vclist
.co_usecount
> 1)
131 panic("%d connections still active", smb_vclist
.co_usecount
- 1);
133 smb_co_done(&smb_vclist
);
138 smb_sm_lockvclist(int flags
)
142 mutex_enter(&smb_vclist
.co_interlock
);
143 error
= smb_co_lock(&smb_vclist
);
144 mutex_exit(&smb_vclist
.co_interlock
);
150 smb_sm_unlockvclist(void)
153 mutex_enter(&smb_vclist
.co_interlock
);
154 smb_co_unlock(&smb_vclist
);
155 mutex_exit(&smb_vclist
.co_interlock
);
159 smb_sm_lookupint(struct smb_vcspec
*vcspec
, struct smb_sharespec
*shspec
,
160 struct smb_cred
*scred
, struct smb_vc
**vcpp
)
162 struct smb_connobj
*ocp
;
166 vcspec
->shspec
= shspec
;
167 SMBCO_FOREACH(ocp
, &smb_vclist
) {
168 struct smb_vc
*vcp
= (struct smb_vc
*)ocp
;
170 if (smb_vc_lock(vcp
) != 0)
174 if ((ocp
->co_flags
& SMBV_PRIVATE
) ||
175 !CONNADDREQ(vcp
->vc_paddr
, vcspec
->sap
) ||
176 strcmp(vcp
->vc_username
, vcspec
->username
) != 0)
179 if (vcspec
->owner
!= SMBM_ANY_OWNER
) {
180 if (vcp
->vc_uid
!= vcspec
->owner
)
184 if (vcspec
->group
!= SMBM_ANY_GROUP
) {
185 if (vcp
->vc_grp
!= vcspec
->group
)
190 if (vcspec
->mode
& SMBM_EXACT
) {
192 (vcspec
->mode
& SMBM_MASK
) != vcp
->vc_mode
)
195 if (smb_vc_access(vcp
, scred
, vcspec
->mode
) != 0)
199 &&smb_vc_lookupshare(vcp
, shspec
, scred
, &vcspec
->ssp
) != 0)
202 /* if we get here, all checks succeeded */
217 smb_sm_lookup(struct smb_vcspec
*vcspec
, struct smb_sharespec
*shspec
,
218 struct smb_cred
*scred
, struct smb_vc
**vcpp
)
221 struct smb_share
*ssp
= NULL
;
226 error
= smb_sm_lockvclist(LK_EXCLUSIVE
);
229 fail
= smb_sm_lookupint(vcspec
, shspec
, scred
, vcpp
);
230 if (!fail
|| (vcspec
->flags
& SMBV_CREATE
) == 0) {
231 smb_sm_unlockvclist();
234 fail
= smb_sm_lookupint(vcspec
, NULL
, scred
, &vcp
);
236 error
= smb_vc_create(vcspec
, scred
, &vcp
);
239 error
= smb_vc_connect(vcp
, scred
);
245 error
= smb_share_create(vcp
, shspec
, scred
, &ssp
);
248 error
= smb_smb_treeconnect(ssp
, scred
);
252 smb_share_put(ssp
, scred
);
254 smb_sm_unlockvclist();
258 smb_vc_put(vcp
, scred
);
263 * Common code for connection object
266 smb_co_init(struct smb_connobj
*cp
, int level
, const char *objname
)
268 SLIST_INIT(&cp
->co_children
);
269 smb_sl_init(&cp
->co_interlock
, objname
);
270 cv_init(&cp
->co_lock
, "smblock");
272 cp
->co_locker
= NULL
;
273 cp
->co_level
= level
;
275 mutex_enter(&cp
->co_interlock
);
277 mutex_exit(&cp
->co_interlock
);
281 smb_co_done(struct smb_connobj
*cp
)
283 smb_sl_destroy(&cp
->co_interlock
);
284 cv_destroy(&cp
->co_lock
);
288 smb_co_gone(struct smb_connobj
*cp
, struct smb_cred
*scred
)
290 struct smb_connobj
*parent
;
293 cp
->co_gone(cp
, scred
);
294 parent
= cp
->co_parent
;
296 mutex_enter(&parent
->co_interlock
);
298 mutex_exit(&parent
->co_interlock
);
299 SLIST_REMOVE(&parent
->co_children
, cp
, smb_connobj
, co_next
);
300 smb_co_put(parent
, scred
);
307 smb_co_ref(struct smb_connobj
*cp
)
310 mutex_enter(&cp
->co_interlock
);
312 mutex_exit(&cp
->co_interlock
);
316 smb_co_rele(struct smb_connobj
*cp
, struct smb_cred
*scred
)
318 mutex_enter(&cp
->co_interlock
);
320 if (cp
->co_usecount
> 1) {
322 mutex_exit(&cp
->co_interlock
);
326 if (cp
->co_usecount
== 0)
327 panic("negative use_count for object %d", cp
->co_level
);
330 cp
->co_flags
|= SMBO_GONE
;
331 mutex_exit(&cp
->co_interlock
);
333 smb_co_gone(cp
, scred
);
337 smb_co_get(struct smb_connobj
*cp
, struct smb_cred
*scred
)
341 KASSERT(mutex_owned(&cp
->co_interlock
));
343 error
= smb_co_lock(cp
);
350 smb_co_put(struct smb_connobj
*cp
, struct smb_cred
*scred
)
353 mutex_enter(&cp
->co_interlock
);
354 if (cp
->co_usecount
> 1) {
356 } else if (cp
->co_usecount
== 1) {
358 cp
->co_flags
|= SMBO_GONE
;
362 panic("smb_co_put: negative usecount");
365 mutex_exit(&cp
->co_interlock
);
366 if ((cp
->co_flags
& SMBO_GONE
) == 0)
368 smb_co_gone(cp
, scred
);
372 smb_co_lock(struct smb_connobj
*cp
)
375 KASSERT(mutex_owned(&cp
->co_interlock
));
378 if (cp
->co_flags
& SMBO_GONE
)
380 if (cp
->co_locker
== NULL
) {
381 cp
->co_locker
= curlwp
;
384 if (cp
->co_locker
== curlwp
) {
388 cv_wait(&cp
->co_lock
, &cp
->co_interlock
);
393 smb_co_unlock(struct smb_connobj
*cp
)
396 KASSERT(mutex_owned(&cp
->co_interlock
));
397 KASSERT(cp
->co_locker
== curlwp
);
399 if (cp
->co_lockcnt
!= 0) {
403 cp
->co_locker
= NULL
;
404 cv_signal(&cp
->co_lock
);
408 smb_co_addchild(struct smb_connobj
*parent
, struct smb_connobj
*child
)
412 SLIST_INSERT_HEAD(&parent
->co_children
, child
, co_next
);
413 child
->co_parent
= parent
;
417 * Session implementation
421 smb_vc_create(struct smb_vcspec
*vcspec
,
422 struct smb_cred
*scred
, struct smb_vc
**vcpp
)
425 kauth_cred_t cred
= scred
->scr_cred
;
426 uid_t uid
= vcspec
->owner
;
427 gid_t gid
= vcspec
->group
;
429 char *domain
= vcspec
->domain
;
430 int error
, isroot
, ismember
= 0;
432 realuid
= kauth_cred_geteuid(cred
);
433 isroot
= (smb_suser(cred
) == 0);
435 * Only superuser can create VCs with different uid and gid
437 if (uid
!= SMBM_ANY_OWNER
&& uid
!= realuid
&& !isroot
)
440 if (gid
!= SMBM_ANY_GROUP
&&
441 (kauth_cred_ismember_gid(cred
, gid
, &ismember
) != 0 || !ismember
) &&
445 vcp
= smb_zmalloc(sizeof(*vcp
), M_SMBCONN
, M_WAITOK
);
446 smb_co_init(VCTOCP(vcp
), SMBL_VC
, "smb_vc");
447 vcp
->obj
.co_free
= smb_vc_free
;
448 vcp
->obj
.co_gone
= smb_vc_gone
;
449 vcp
->vc_number
= smb_vcnext
++;
450 vcp
->vc_smbuid
= SMB_UID_UNKNOWN
;
451 vcp
->vc_mode
= vcspec
->rights
& SMBM_MASK
;
452 vcp
->obj
.co_flags
= vcspec
->flags
& (SMBV_PRIVATE
| SMBV_SINGLESHARE
);
453 vcp
->vc_tdesc
= &smb_tran_nbtcp_desc
;
455 if (uid
== SMBM_ANY_OWNER
)
457 if (gid
== SMBM_ANY_GROUP
)
458 gid
= kauth_cred_group(cred
, 0);
462 smb_sl_init(&vcp
->vc_stlock
, "vcstlock");
464 if ((vcp
->vc_paddr
= dup_sockaddr(vcspec
->sap
, 1)) == NULL
)
467 if ((vcp
->vc_laddr
= dup_sockaddr(vcspec
->lap
, 1)) == NULL
)
470 if ((vcp
->vc_pass
= smb_strdup(vcspec
->pass
)) == NULL
)
473 vcp
->vc_domain
= smb_strdup((domain
&& domain
[0]) ? domain
: "NODOMAIN");
474 if (vcp
->vc_domain
== NULL
)
477 if ((vcp
->vc_srvname
= smb_strdup(vcspec
->srvname
)) == NULL
)
480 if ((vcp
->vc_username
= smb_strdup(vcspec
->username
)) == NULL
)
483 #define ithrow(cmd) \
487 ithrow(iconv_open("tolower", vcspec
->localcs
, &vcp
->vc_tolower
));
488 ithrow(iconv_open("toupper", vcspec
->localcs
, &vcp
->vc_toupper
));
489 if (vcspec
->servercs
[0]) {
490 ithrow(iconv_open(vcspec
->servercs
, vcspec
->localcs
,
492 ithrow(iconv_open(vcspec
->localcs
, vcspec
->servercs
,
496 ithrow(smb_iod_create(vcp
));
500 /* all is well, return success */
502 smb_co_addchild(&smb_vclist
, VCTOCP(vcp
));
507 smb_vc_put(vcp
, scred
);
513 smb_vc_free(struct smb_connobj
*cp
)
515 struct smb_vc
*vcp
= CPTOVC(cp
);
518 smb_iod_destroy(vcp
->vc_iod
);
519 SMB_STRFREE(vcp
->vc_username
);
520 SMB_STRFREE(vcp
->vc_srvname
);
521 SMB_STRFREE(vcp
->vc_pass
);
522 SMB_STRFREE(vcp
->vc_domain
);
524 free(vcp
->vc_paddr
, M_SONAME
);
526 free(vcp
->vc_laddr
, M_SONAME
);
528 iconv_close(vcp
->vc_tolower
);
530 iconv_close(vcp
->vc_toupper
);
532 iconv_close(vcp
->vc_tolocal
);
533 if (vcp
->vc_toserver
)
534 iconv_close(vcp
->vc_toserver
);
535 smb_co_done(VCTOCP(vcp
));
536 smb_sl_destroy(&vcp
->vc_stlock
);
537 free(vcp
, M_SMBCONN
);
541 * Called when use count of VC dropped to zero.
542 * VC should be locked on enter with LK_DRAIN.
545 smb_vc_gone(struct smb_connobj
*cp
, struct smb_cred
*scred
)
547 struct smb_vc
*vcp
= CPTOVC(cp
);
549 smb_vc_disconnect(vcp
);
553 smb_vc_ref(struct smb_vc
*vcp
)
555 smb_co_ref(VCTOCP(vcp
));
559 smb_vc_rele(struct smb_vc
*vcp
, struct smb_cred
*scred
)
561 smb_co_rele(VCTOCP(vcp
), scred
);
565 smb_vc_get(struct smb_vc
*vcp
, struct smb_cred
*scred
)
567 struct smb_connobj
*cp
= VCTOCP(vcp
);
570 mutex_enter(&cp
->co_interlock
);
571 error
= smb_co_get(cp
, scred
);
572 mutex_exit(&cp
->co_interlock
);
578 smb_vc_put(struct smb_vc
*vcp
, struct smb_cred
*scred
)
580 smb_co_put(VCTOCP(vcp
), scred
);
584 smb_vc_lock(struct smb_vc
*vcp
)
586 struct smb_connobj
*cp
= VCTOCP(vcp
);
589 mutex_enter(&cp
->co_interlock
);
590 error
= smb_co_lock(cp
);
591 mutex_exit(&cp
->co_interlock
);
597 smb_vc_unlock(struct smb_vc
*vcp
)
599 struct smb_connobj
*cp
= VCTOCP(vcp
);
601 mutex_enter(&cp
->co_interlock
);
603 mutex_exit(&cp
->co_interlock
);
608 smb_vc_access(struct smb_vc
*vcp
, struct smb_cred
*scred
, mode_t mode
)
610 kauth_cred_t cred
= scred
->scr_cred
;
613 if (smb_suser(cred
) == 0 || kauth_cred_geteuid(cred
) == vcp
->vc_uid
)
616 if (kauth_cred_ismember_gid(cred
, vcp
->vc_grp
, &ismember
) != 0 ||
619 return (vcp
->vc_mode
& mode
) == mode
? 0 : EACCES
;
623 smb_vc_cmpshare(struct smb_share
*ssp
, struct smb_sharespec
*dp
)
627 if (strcmp(ssp
->ss_name
, dp
->name
) != 0)
629 if (dp
->owner
!= SMBM_ANY_OWNER
) {
630 if (ssp
->ss_uid
!= dp
->owner
)
634 if (dp
->group
!= SMBM_ANY_GROUP
) {
635 if (ssp
->ss_grp
!= dp
->group
)
640 if (dp
->mode
& SMBM_EXACT
) {
643 return (dp
->mode
& SMBM_MASK
) == ssp
->ss_mode
? 0 : 1;
645 if (smb_share_access(ssp
, dp
->scred
, dp
->mode
) != 0)
651 * Lookup share in the given VC. Share referenced and locked on return.
652 * VC expected to be locked on entry and will be left locked on exit.
655 smb_vc_lookupshare(struct smb_vc
*vcp
, struct smb_sharespec
*dp
,
656 struct smb_cred
*scred
, struct smb_share
**sspp
)
658 struct smb_connobj
*osp
;
659 struct smb_share
*ssp
= NULL
;
664 SMBCO_FOREACH(osp
, VCTOCP(vcp
)) {
665 ssp
= (struct smb_share
*)osp
;
666 error
= smb_share_lock(ssp
);
669 if (smb_vc_cmpshare(ssp
, dp
) == 0)
671 smb_share_unlock(ssp
);
683 smb_vc_connect(struct smb_vc
*vcp
, struct smb_cred
*scred
)
686 return smb_iod_request(vcp
->vc_iod
, SMBIOD_EV_CONNECT
| SMBIOD_EV_SYNC
, NULL
);
690 * Destroy VC to server, invalidate shares linked with it.
691 * Transport should be locked on entry.
694 smb_vc_disconnect(struct smb_vc
*vcp
)
697 smb_iod_request(vcp
->vc_iod
, SMBIOD_EV_DISCONNECT
| SMBIOD_EV_SYNC
, NULL
);
701 static const char * const smb_emptypass
= "";
704 smb_vc_getpass(struct smb_vc
*vcp
)
708 return smb_emptypass
;
713 smb_vc_getinfo(struct smb_vc
*vcp
, struct smb_vc_info
*vip
)
715 memset(vip
, 0, sizeof(struct smb_vc_info
));
716 vip
->itype
= SMB_INFO_VC
;
717 vip
->usecount
= vcp
->obj
.co_usecount
;
718 vip
->uid
= vcp
->vc_uid
;
719 vip
->gid
= vcp
->vc_grp
;
720 vip
->mode
= vcp
->vc_mode
;
721 vip
->flags
= vcp
->obj
.co_flags
;
722 vip
->sopt
= vcp
->vc_sopt
;
723 vip
->iodstate
= vcp
->vc_iod
->iod_state
;
724 memset(&vip
->sopt
.sv_skey
, 0, sizeof(vip
->sopt
.sv_skey
));
725 snprintf(vip
->srvname
, sizeof(vip
->srvname
), "%s", vcp
->vc_srvname
);
726 snprintf(vip
->vcname
, sizeof(vip
->vcname
), "%s", vcp
->vc_username
);
732 smb_vc_nextmid(struct smb_vc
*vcp
)
736 mutex_enter(&vcp
->obj
.co_interlock
);
738 mutex_exit(&vcp
->obj
.co_interlock
);
743 * Share implementation
746 * Allocate share structure and attach it to the given VC
747 * Connection expected to be locked on entry. Share will be returned
751 smb_share_create(struct smb_vc
*vcp
, struct smb_sharespec
*shspec
,
752 struct smb_cred
*scred
, struct smb_share
**sspp
)
754 struct smb_share
*ssp
;
755 kauth_cred_t cred
= scred
->scr_cred
;
757 uid_t uid
= shspec
->owner
;
758 gid_t gid
= shspec
->group
;
759 int error
, isroot
, ismember
= 0;
761 realuid
= kauth_cred_geteuid(cred
);
762 isroot
= smb_suser(cred
) == 0;
764 * Only superuser can create shares with different uid and gid
766 if (uid
!= SMBM_ANY_OWNER
&& uid
!= realuid
&& !isroot
)
768 if (gid
!= SMBM_ANY_GROUP
&&
769 (kauth_cred_ismember_gid(cred
, gid
, &ismember
) != 0 || !ismember
) &&
772 error
= smb_vc_lookupshare(vcp
, shspec
, scred
, &ssp
);
774 smb_share_put(ssp
, scred
);
777 if (uid
== SMBM_ANY_OWNER
)
779 if (gid
== SMBM_ANY_GROUP
)
780 gid
= kauth_cred_group(cred
, 0);
781 ssp
= smb_zmalloc(sizeof(*ssp
), M_SMBCONN
, M_WAITOK
);
782 smb_co_init(SSTOCP(ssp
), SMBL_SHARE
, "smbss");
783 ssp
->obj
.co_free
= smb_share_free
;
784 ssp
->obj
.co_gone
= smb_share_gone
;
785 smb_sl_init(&ssp
->ss_stlock
, "ssstlock");
786 ssp
->ss_name
= smb_strdup(shspec
->name
);
787 if (shspec
->pass
&& shspec
->pass
[0])
788 ssp
->ss_pass
= smb_strdup(shspec
->pass
);
789 ssp
->ss_type
= shspec
->stype
;
790 ssp
->ss_tid
= SMB_TID_UNKNOWN
;
793 ssp
->ss_mode
= shspec
->rights
& SMBM_MASK
;
794 smb_co_addchild(VCTOCP(vcp
), SSTOCP(ssp
));
800 smb_share_free(struct smb_connobj
*cp
)
802 struct smb_share
*ssp
= CPTOSS(cp
);
804 SMB_STRFREE(ssp
->ss_name
);
805 SMB_STRFREE(ssp
->ss_pass
);
806 smb_sl_destroy(&ssp
->ss_stlock
);
807 smb_co_done(SSTOCP(ssp
));
808 free(ssp
, M_SMBCONN
);
812 smb_share_gone(struct smb_connobj
*cp
, struct smb_cred
*scred
)
814 struct smb_share
*ssp
= CPTOSS(cp
);
816 smb_smb_treedisconnect(ssp
, scred
);
820 smb_share_ref(struct smb_share
*ssp
)
822 smb_co_ref(SSTOCP(ssp
));
826 smb_share_rele(struct smb_share
*ssp
, struct smb_cred
*scred
)
828 smb_co_rele(SSTOCP(ssp
), scred
);
832 smb_share_get(struct smb_share
*ssp
, struct smb_cred
*scred
)
834 struct smb_connobj
*cp
= SSTOCP(ssp
);
837 mutex_enter(&cp
->co_interlock
);
838 error
= smb_co_get(cp
, scred
);
839 mutex_exit(&cp
->co_interlock
);
845 smb_share_put(struct smb_share
*ssp
, struct smb_cred
*scred
)
847 smb_co_put(SSTOCP(ssp
), scred
);
851 smb_share_lock(struct smb_share
*ssp
)
853 struct smb_connobj
*cp
= SSTOCP(ssp
);
856 mutex_enter(&cp
->co_interlock
);
857 error
= smb_co_lock(cp
);
858 mutex_exit(&cp
->co_interlock
);
864 smb_share_unlock(struct smb_share
*ssp
)
866 struct smb_connobj
*cp
= SSTOCP(ssp
);
868 mutex_enter(&cp
->co_interlock
);
870 mutex_exit(&cp
->co_interlock
);
874 smb_share_access(struct smb_share
*ssp
, struct smb_cred
*scred
, mode_t mode
)
876 kauth_cred_t cred
= scred
->scr_cred
;
879 if (smb_suser(cred
) == 0 || kauth_cred_geteuid(cred
) == ssp
->ss_uid
)
882 if (kauth_cred_ismember_gid(cred
, ssp
->ss_grp
, &ismember
) != 0 ||
885 return (ssp
->ss_mode
& mode
) == mode
? 0 : EACCES
;
889 smb_share_valid(struct smb_share
*ssp
)
891 return ssp
->ss_tid
!= SMB_TID_UNKNOWN
&&
892 ssp
->ss_vcgenid
== SSTOVC(ssp
)->vc_genid
;
896 smb_share_getpass(struct smb_share
*ssp
)
905 return smb_emptypass
;
910 smb_share_getinfo(struct smb_share
*ssp
, struct smb_share_info
*sip
)
912 memset(sip
, 0, sizeof(struct smb_share_info
));
913 sip
->itype
= SMB_INFO_SHARE
;
914 sip
->usecount
= ssp
->obj
.co_usecount
;
915 sip
->tid
= ssp
->ss_tid
;
916 sip
->type
= ssp
->ss_type
;
917 sip
->uid
= ssp
->ss_uid
;
918 sip
->gid
= ssp
->ss_grp
;
919 sip
->mode
= ssp
->ss_mode
;
920 sip
->flags
= ssp
->obj
.co_flags
;
921 snprintf(sip
->sname
, sizeof(sip
->sname
), "%s", ssp
->ss_name
);
928 * Dump an entire tree into sysctl call
931 smb_sysctl_treedump(SYSCTL_HANDLER_ARGS
)
933 struct smb_cred scred
;
935 struct smb_share
*ssp
;
936 struct smb_vc_info vci
;
937 struct smb_share_info ssi
;
940 smb_makescred(&scred
, td
, td
->td_proc
->p_cred
);
941 error
= smb_sm_lockvclist(LK_SHARED
);
944 SMBCO_FOREACH((struct smb_connobj
*)vcp
, &smb_vclist
) {
945 error
= smb_vc_lock(vcp
, LK_SHARED
);
948 smb_vc_getinfo(vcp
, &vci
);
949 error
= SYSCTL_OUT(req
, &vci
, sizeof(struct smb_vc_info
));
951 smb_vc_unlock(vcp
, 0);
954 SMBCO_FOREACH((struct smb_connobj
*)ssp
, VCTOCP(vcp
)) {
955 error
= smb_share_lock(ssp
, LK_SHARED
);
960 smb_share_getinfo(ssp
, &ssi
);
961 smb_share_unlock(ssp
, 0);
962 error
= SYSCTL_OUT(req
, &ssi
, sizeof(struct smb_share_info
));
966 smb_vc_unlock(vcp
, 0);
971 itype
= SMB_INFO_NONE
;
972 error
= SYSCTL_OUT(req
, &itype
, sizeof(itype
));
974 smb_sm_unlockvclist();