1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23b819cea2SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24*b6b7639aSGordon Ross  * Copyright 2022 RackTop Systems, Inc.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw /*
28da6c28aaSamw  * LanMan share door server
29da6c28aaSamw  */
30da6c28aaSamw 
31da6c28aaSamw #include <door.h>
32da6c28aaSamw #include <unistd.h>
33da6c28aaSamw #include <sys/types.h>
34da6c28aaSamw #include <sys/stat.h>
35da6c28aaSamw #include <fcntl.h>
36da6c28aaSamw #include <errno.h>
37da6c28aaSamw #include <syslog.h>
38da6c28aaSamw #include <string.h>
393ad684d6Sjb #include <strings.h>
40da6c28aaSamw #include <pthread.h>
41*b6b7639aSGordon Ross #include <priv.h>
42*b6b7639aSGordon Ross 
43da6c28aaSamw #include <smbsrv/libsmb.h>
443db3f65cSamw #include <smbsrv/smb_share.h>
45da6c28aaSamw #include <smbsrv/smbinfo.h>
469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include "smbd.h"
47da6c28aaSamw 
483db3f65cSamw #define	SMB_SHARE_DSRV_VERSION	1
493db3f65cSamw #define	SMB_SHARE_DSRV_COOKIE	((void*)(0xdeadbeef^SMB_SHARE_DSRV_VERSION))
503db3f65cSamw 
513ad684d6Sjb static int smb_share_dsrv_fd = -1;
523ad684d6Sjb static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smbd_door_t smb_share_sdh;
54da6c28aaSamw 
559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
56da6c28aaSamw 
57da6c28aaSamw /*
58da6c28aaSamw  * Start the LanMan share door service.
59da6c28aaSamw  * Returns 0 on success. Otherwise, -1.
60da6c28aaSamw  */
61da6c28aaSamw int
smbd_share_start(void)629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbd_share_start(void)
63da6c28aaSamw {
64b819cea2SGordon Ross 	int		newfd;
65b819cea2SGordon Ross 	const char	*door_name;
66da6c28aaSamw 
673ad684d6Sjb 	(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
68da6c28aaSamw 
693ad684d6Sjb 	if (smb_share_dsrv_fd != -1) {
709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		syslog(LOG_ERR, "smbd_share_start: duplicate");
713ad684d6Sjb 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
723ad684d6Sjb 		return (smb_share_dsrv_fd);
73da6c28aaSamw 	}
74da6c28aaSamw 
759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smbd_door_init(&smb_share_sdh, "share");
769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((smb_share_dsrv_fd = door_create(smbd_share_dispatch,
783db3f65cSamw 	    SMB_SHARE_DSRV_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		syslog(LOG_ERR, "smbd_share_start: door_create: %s",
80da6c28aaSamw 		    strerror(errno));
813ad684d6Sjb 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
82da6c28aaSamw 		return (-1);
83da6c28aaSamw 	}
84da6c28aaSamw 
85b819cea2SGordon Ross 	door_name = getenv("SMB_SHARE_DNAME");
86b819cea2SGordon Ross 	if (door_name == NULL)
87b819cea2SGordon Ross 		door_name = SMB_SHARE_DNAME;
88da6c28aaSamw 
89b819cea2SGordon Ross 	(void) unlink(door_name);
90b819cea2SGordon Ross 
91b819cea2SGordon Ross 	if ((newfd = creat(door_name, 0644)) < 0) {
929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		syslog(LOG_ERR, "smbd_share_start: open: %s",
93da6c28aaSamw 		    strerror(errno));
943ad684d6Sjb 		(void) door_revoke(smb_share_dsrv_fd);
953ad684d6Sjb 		smb_share_dsrv_fd = -1;
963ad684d6Sjb 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
97da6c28aaSamw 		return (-1);
98da6c28aaSamw 	}
99da6c28aaSamw 
100da6c28aaSamw 	(void) close(newfd);
101b819cea2SGordon Ross 	(void) fdetach(door_name);
102da6c28aaSamw 
103b819cea2SGordon Ross 	if (fattach(smb_share_dsrv_fd, door_name) < 0) {
1049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		syslog(LOG_ERR, "smbd_share_start: fattach: %s",
105da6c28aaSamw 		    strerror(errno));
1063ad684d6Sjb 		(void) door_revoke(smb_share_dsrv_fd);
1073ad684d6Sjb 		smb_share_dsrv_fd = -1;
1083ad684d6Sjb 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
109da6c28aaSamw 		return (-1);
110da6c28aaSamw 	}
111da6c28aaSamw 
1123ad684d6Sjb 	(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
1133ad684d6Sjb 	return (smb_share_dsrv_fd);
114da6c28aaSamw }
115da6c28aaSamw 
116da6c28aaSamw /*
117da6c28aaSamw  * Stop the LanMan share door service.
118da6c28aaSamw  */
119da6c28aaSamw void
smbd_share_stop(void)1209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbd_share_stop(void)
121da6c28aaSamw {
1223ad684d6Sjb 	(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
123da6c28aaSamw 
1249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smbd_door_fini(&smb_share_sdh);
1259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1263ad684d6Sjb 	if (smb_share_dsrv_fd != -1) {
127b819cea2SGordon Ross 		const char *door_name;
128b819cea2SGordon Ross 
129b819cea2SGordon Ross 		door_name = getenv("SMB_SHARE_DNAME");
130b819cea2SGordon Ross 		if (door_name == NULL)
131b819cea2SGordon Ross 			door_name = SMB_SHARE_DNAME;
132b819cea2SGordon Ross 		(void) fdetach(door_name);
1333ad684d6Sjb 		(void) door_revoke(smb_share_dsrv_fd);
1343ad684d6Sjb 		smb_share_dsrv_fd = -1;
135da6c28aaSamw 	}
136da6c28aaSamw 
1373ad684d6Sjb 	(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
138da6c28aaSamw }
139da6c28aaSamw 
140*b6b7639aSGordon Ross static boolean_t
have_priv_sys_smb(void)141*b6b7639aSGordon Ross have_priv_sys_smb(void)
142*b6b7639aSGordon Ross {
143*b6b7639aSGordon Ross 	ucred_t *uc = NULL;
144*b6b7639aSGordon Ross 	const priv_set_t *ps = NULL;
145*b6b7639aSGordon Ross 	boolean_t ret = B_FALSE;
146*b6b7639aSGordon Ross 	pid_t pid;
147*b6b7639aSGordon Ross 
148*b6b7639aSGordon Ross 	if (door_ucred(&uc) != 0) {
149*b6b7639aSGordon Ross 		syslog(LOG_DEBUG, "%s: door_ucred failed", __func__);
150*b6b7639aSGordon Ross 		goto out;
151*b6b7639aSGordon Ross 	}
152*b6b7639aSGordon Ross 
153*b6b7639aSGordon Ross 	/*
154*b6b7639aSGordon Ross 	 * in-kernel callers have pid==0
155*b6b7639aSGordon Ross 	 * If we have pid zero, that's sufficient.
156*b6b7639aSGordon Ross 	 * If not, allow with sys_smb priv (below)
157*b6b7639aSGordon Ross 	 */
158*b6b7639aSGordon Ross 	pid = ucred_getpid(uc);
159*b6b7639aSGordon Ross 	if (pid == 0) {
160*b6b7639aSGordon Ross 		ret = B_TRUE;
161*b6b7639aSGordon Ross 		goto out;
162*b6b7639aSGordon Ross 	}
163*b6b7639aSGordon Ross 
164*b6b7639aSGordon Ross 	ps = ucred_getprivset(uc, PRIV_EFFECTIVE);
165*b6b7639aSGordon Ross 	if (ps == NULL) {
166*b6b7639aSGordon Ross 		syslog(LOG_DEBUG, "%s: ucred_getprivset failed", __func__);
167*b6b7639aSGordon Ross 		goto out;
168*b6b7639aSGordon Ross 	}
169*b6b7639aSGordon Ross 	if (priv_ismember(ps, PRIV_SYS_SMB)) {
170*b6b7639aSGordon Ross 		ret = B_TRUE;
171*b6b7639aSGordon Ross 		goto out;
172*b6b7639aSGordon Ross 	}
173*b6b7639aSGordon Ross 
174*b6b7639aSGordon Ross 	syslog(LOG_DEBUG, "smbd_share_dispatch: missing privilege, "
175*b6b7639aSGordon Ross 	    "PID = %d UID = %d", (int)pid, ucred_getruid(uc));
176*b6b7639aSGordon Ross 
177*b6b7639aSGordon Ross out:
178*b6b7639aSGordon Ross 	/* ps is free'd with the ucred */
179*b6b7639aSGordon Ross 	if (uc != NULL)
180*b6b7639aSGordon Ross 		ucred_free(uc);
181*b6b7639aSGordon Ross 
182*b6b7639aSGordon Ross 	return (ret);
183*b6b7639aSGordon Ross }
184*b6b7639aSGordon Ross 
185da6c28aaSamw /*
186da6c28aaSamw  * This function with which the LMSHARE door is associated
187da6c28aaSamw  * will invoke the appropriate CIFS share management function
188da6c28aaSamw  * based on the request type of the door call.
189da6c28aaSamw  */
190da6c28aaSamw /*ARGSUSED*/
1913ad684d6Sjb static void
smbd_share_dispatch(void * cookie,char * ptr,size_t size,door_desc_t * dp,uint_t n_desc)1929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
193da6c28aaSamw     uint_t n_desc)
194da6c28aaSamw {
1953db3f65cSamw 	uint32_t rc;
1963db3f65cSamw 	int req_type;
1973db3f65cSamw 	char buf[SMB_SHARE_DSIZE];
198da6c28aaSamw 	unsigned int used;
1993ad684d6Sjb 	smb_dr_ctx_t *dec_ctx;
2003ad684d6Sjb 	smb_dr_ctx_t *enc_ctx;
201da6c28aaSamw 	unsigned int dec_status;
202da6c28aaSamw 	unsigned int enc_status;
203da6c28aaSamw 	char *sharename, *sharename2;
2043db3f65cSamw 	smb_share_t lmshr_info;
2053db3f65cSamw 	smb_shrlist_t lmshr_list;
2063ad684d6Sjb 	int offset;
2073ad684d6Sjb 
2089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smbd_door_enter(&smb_share_sdh);
2099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
2103db3f65cSamw 	if ((cookie != SMB_SHARE_DSRV_COOKIE) || (ptr == NULL) ||
2113ad684d6Sjb 	    (size < sizeof (uint32_t))) {
2129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smbd_door_return(&smb_share_sdh, NULL, 0, NULL, 0);
2133ad684d6Sjb 	}
214da6c28aaSamw 
2153ad684d6Sjb 	dec_ctx = smb_dr_decode_start(ptr, size);
2163ad684d6Sjb 	enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
217da6c28aaSamw 	req_type = smb_dr_get_uint32(dec_ctx);
218da6c28aaSamw 
219*b6b7639aSGordon Ross 	if (req_type != SMB_SHROP_NUM_SHARES &&
220*b6b7639aSGordon Ross 	    req_type != SMB_SHROP_LIST &&
221*b6b7639aSGordon Ross 	    !have_priv_sys_smb()) {
222*b6b7639aSGordon Ross 		dec_status = EPERM;
223*b6b7639aSGordon Ross 		goto decode_error;
224*b6b7639aSGordon Ross 	}
225*b6b7639aSGordon Ross 
226da6c28aaSamw 	switch (req_type) {
2273db3f65cSamw 	case SMB_SHROP_NUM_SHARES:
228da6c28aaSamw 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
229da6c28aaSamw 			goto decode_error;
230da6c28aaSamw 
2313db3f65cSamw 		rc = smb_shr_count();
2323db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
233da6c28aaSamw 		smb_dr_put_uint32(enc_ctx, rc);
234da6c28aaSamw 		break;
235da6c28aaSamw 
2363db3f65cSamw 	case SMB_SHROP_DELETE:
237da6c28aaSamw 		sharename = smb_dr_get_string(dec_ctx);
238da6c28aaSamw 
239da6c28aaSamw 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
240da6c28aaSamw 			smb_dr_free_string(sharename);
241da6c28aaSamw 			goto decode_error;
242da6c28aaSamw 		}
243da6c28aaSamw 
244b89a8333Snatalie li - Sun Microsystems - Irvine United States 		rc = smb_shr_remove(sharename);
2453db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
246da6c28aaSamw 		smb_dr_put_uint32(enc_ctx, rc);
247da6c28aaSamw 		smb_dr_free_string(sharename);
248da6c28aaSamw 		break;
249da6c28aaSamw 
2503db3f65cSamw 	case SMB_SHROP_RENAME:
251da6c28aaSamw 		sharename = smb_dr_get_string(dec_ctx);
252da6c28aaSamw 		sharename2 = smb_dr_get_string(dec_ctx);
253da6c28aaSamw 
254da6c28aaSamw 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
255da6c28aaSamw 			smb_dr_free_string(sharename);
256da6c28aaSamw 			smb_dr_free_string(sharename2);
257da6c28aaSamw 			goto decode_error;
258da6c28aaSamw 		}
259da6c28aaSamw 
260c8ec8eeaSjose borrego 		rc = smb_shr_rename(sharename, sharename2);
2613db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
262da6c28aaSamw 		smb_dr_put_uint32(enc_ctx, rc);
263da6c28aaSamw 		smb_dr_free_string(sharename);
264da6c28aaSamw 		smb_dr_free_string(sharename2);
265da6c28aaSamw 		break;
266da6c28aaSamw 
2673db3f65cSamw 	case SMB_SHROP_ADD:
2683db3f65cSamw 		smb_dr_get_share(dec_ctx, &lmshr_info);
269da6c28aaSamw 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
270da6c28aaSamw 			goto decode_error;
271da6c28aaSamw 
272b89a8333Snatalie li - Sun Microsystems - Irvine United States 		rc = smb_shr_add(&lmshr_info);
2733db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
274da6c28aaSamw 		smb_dr_put_uint32(enc_ctx, rc);
2753db3f65cSamw 		smb_dr_put_share(enc_ctx, &lmshr_info);
276da6c28aaSamw 		break;
277da6c28aaSamw 
278c8ec8eeaSjose borrego 	case SMB_SHROP_MODIFY:
279b89a8333Snatalie li - Sun Microsystems - Irvine United States 		smb_dr_get_share(dec_ctx, &lmshr_info);
280c8ec8eeaSjose borrego 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
281da6c28aaSamw 			goto decode_error;
282c8ec8eeaSjose borrego 		}
283da6c28aaSamw 
284b89a8333Snatalie li - Sun Microsystems - Irvine United States 		rc = smb_shr_modify(&lmshr_info);
2853db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
286da6c28aaSamw 		smb_dr_put_uint32(enc_ctx, rc);
287c8ec8eeaSjose borrego 
288da6c28aaSamw 		break;
289da6c28aaSamw 
2903db3f65cSamw 	case SMB_SHROP_LIST:
291da6c28aaSamw 		offset = smb_dr_get_int32(dec_ctx);
292da6c28aaSamw 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
293da6c28aaSamw 			goto decode_error;
294da6c28aaSamw 
2953db3f65cSamw 		smb_shr_list(offset, &lmshr_list);
2963db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
297c8ec8eeaSjose borrego 		smb_dr_put_buf(enc_ctx, (unsigned char *)&lmshr_list,
298c8ec8eeaSjose borrego 		    sizeof (smb_shrlist_t));
299da6c28aaSamw 		break;
300da6c28aaSamw 
301da6c28aaSamw 	default:
302cbfb650aScp 		dec_status = smb_dr_decode_finish(dec_ctx);
303da6c28aaSamw 		goto decode_error;
304da6c28aaSamw 	}
305da6c28aaSamw 
3063ad684d6Sjb 	if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
3073ad684d6Sjb 		enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
3083db3f65cSamw 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
3093ad684d6Sjb 		smb_dr_put_uint32(enc_ctx, enc_status);
3103ad684d6Sjb 		(void) smb_dr_encode_finish(enc_ctx, &used);
3113ad684d6Sjb 	}
312da6c28aaSamw 
3139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
314da6c28aaSamw 	return;
315da6c28aaSamw 
316da6c28aaSamw decode_error:
3173db3f65cSamw 	smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
318da6c28aaSamw 	smb_dr_put_uint32(enc_ctx, dec_status);
319da6c28aaSamw 	(void) smb_dr_encode_finish(enc_ctx, &used);
3209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
321da6c28aaSamw }
322