xref: /illumos-gate/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 /*
27  * LanMan share door server
28  */
29 
30 #include <door.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <syslog.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <pthread.h>
40 #include <smbsrv/libsmb.h>
41 #include <smbsrv/smb_share.h>
42 #include <smbsrv/smbinfo.h>
43 #include "smbd.h"
44 
45 #define	SMB_SHARE_DSRV_VERSION	1
46 #define	SMB_SHARE_DSRV_COOKIE	((void*)(0xdeadbeef^SMB_SHARE_DSRV_VERSION))
47 
48 static int smb_share_dsrv_fd = -1;
49 static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
50 static smbd_door_t smb_share_sdh;
51 
52 static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
53 
54 /*
55  * Start the LanMan share door service.
56  * Returns 0 on success. Otherwise, -1.
57  */
58 int
59 smbd_share_start(void)
60 {
61 	int		newfd;
62 	const char	*door_name;
63 
64 	(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
65 
66 	if (smb_share_dsrv_fd != -1) {
67 		syslog(LOG_ERR, "smbd_share_start: duplicate");
68 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
69 		return (smb_share_dsrv_fd);
70 	}
71 
72 	smbd_door_init(&smb_share_sdh, "share");
73 
74 	if ((smb_share_dsrv_fd = door_create(smbd_share_dispatch,
75 	    SMB_SHARE_DSRV_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
76 		syslog(LOG_ERR, "smbd_share_start: door_create: %s",
77 		    strerror(errno));
78 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
79 		return (-1);
80 	}
81 
82 	door_name = getenv("SMB_SHARE_DNAME");
83 	if (door_name == NULL)
84 		door_name = SMB_SHARE_DNAME;
85 
86 	(void) unlink(door_name);
87 
88 	if ((newfd = creat(door_name, 0644)) < 0) {
89 		syslog(LOG_ERR, "smbd_share_start: open: %s",
90 		    strerror(errno));
91 		(void) door_revoke(smb_share_dsrv_fd);
92 		smb_share_dsrv_fd = -1;
93 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
94 		return (-1);
95 	}
96 
97 	(void) close(newfd);
98 	(void) fdetach(door_name);
99 
100 	if (fattach(smb_share_dsrv_fd, door_name) < 0) {
101 		syslog(LOG_ERR, "smbd_share_start: fattach: %s",
102 		    strerror(errno));
103 		(void) door_revoke(smb_share_dsrv_fd);
104 		smb_share_dsrv_fd = -1;
105 		(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
106 		return (-1);
107 	}
108 
109 	(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
110 	return (smb_share_dsrv_fd);
111 }
112 
113 /*
114  * Stop the LanMan share door service.
115  */
116 void
117 smbd_share_stop(void)
118 {
119 	(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
120 
121 	smbd_door_fini(&smb_share_sdh);
122 
123 	if (smb_share_dsrv_fd != -1) {
124 		const char *door_name;
125 
126 		door_name = getenv("SMB_SHARE_DNAME");
127 		if (door_name == NULL)
128 			door_name = SMB_SHARE_DNAME;
129 		(void) fdetach(door_name);
130 		(void) door_revoke(smb_share_dsrv_fd);
131 		smb_share_dsrv_fd = -1;
132 	}
133 
134 	(void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
135 }
136 
137 /*
138  * This function with which the LMSHARE door is associated
139  * will invoke the appropriate CIFS share management function
140  * based on the request type of the door call.
141  */
142 /*ARGSUSED*/
143 static void
144 smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
145     uint_t n_desc)
146 {
147 	uint32_t rc;
148 	int req_type;
149 	char buf[SMB_SHARE_DSIZE];
150 	unsigned int used;
151 	smb_dr_ctx_t *dec_ctx;
152 	smb_dr_ctx_t *enc_ctx;
153 	unsigned int dec_status;
154 	unsigned int enc_status;
155 	char *sharename, *sharename2;
156 	smb_share_t lmshr_info;
157 	smb_shrlist_t lmshr_list;
158 	int offset;
159 
160 	smbd_door_enter(&smb_share_sdh);
161 
162 	if ((cookie != SMB_SHARE_DSRV_COOKIE) || (ptr == NULL) ||
163 	    (size < sizeof (uint32_t))) {
164 		smbd_door_return(&smb_share_sdh, NULL, 0, NULL, 0);
165 	}
166 
167 	dec_ctx = smb_dr_decode_start(ptr, size);
168 	enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
169 	req_type = smb_dr_get_uint32(dec_ctx);
170 
171 	switch (req_type) {
172 	case SMB_SHROP_NUM_SHARES:
173 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
174 			goto decode_error;
175 
176 		rc = smb_shr_count();
177 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
178 		smb_dr_put_uint32(enc_ctx, rc);
179 		break;
180 
181 	case SMB_SHROP_DELETE:
182 		sharename = smb_dr_get_string(dec_ctx);
183 
184 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
185 			smb_dr_free_string(sharename);
186 			goto decode_error;
187 		}
188 
189 		rc = smb_shr_remove(sharename);
190 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
191 		smb_dr_put_uint32(enc_ctx, rc);
192 		smb_dr_free_string(sharename);
193 		break;
194 
195 	case SMB_SHROP_RENAME:
196 		sharename = smb_dr_get_string(dec_ctx);
197 		sharename2 = smb_dr_get_string(dec_ctx);
198 
199 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
200 			smb_dr_free_string(sharename);
201 			smb_dr_free_string(sharename2);
202 			goto decode_error;
203 		}
204 
205 		rc = smb_shr_rename(sharename, sharename2);
206 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
207 		smb_dr_put_uint32(enc_ctx, rc);
208 		smb_dr_free_string(sharename);
209 		smb_dr_free_string(sharename2);
210 		break;
211 
212 	case SMB_SHROP_ADD:
213 		smb_dr_get_share(dec_ctx, &lmshr_info);
214 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
215 			goto decode_error;
216 
217 		rc = smb_shr_add(&lmshr_info);
218 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
219 		smb_dr_put_uint32(enc_ctx, rc);
220 		smb_dr_put_share(enc_ctx, &lmshr_info);
221 		break;
222 
223 	case SMB_SHROP_MODIFY:
224 		smb_dr_get_share(dec_ctx, &lmshr_info);
225 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
226 			goto decode_error;
227 		}
228 
229 		rc = smb_shr_modify(&lmshr_info);
230 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
231 		smb_dr_put_uint32(enc_ctx, rc);
232 
233 		break;
234 
235 	case SMB_SHROP_LIST:
236 		offset = smb_dr_get_int32(dec_ctx);
237 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
238 			goto decode_error;
239 
240 		smb_shr_list(offset, &lmshr_list);
241 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
242 		smb_dr_put_buf(enc_ctx, (unsigned char *)&lmshr_list,
243 		    sizeof (smb_shrlist_t));
244 		break;
245 
246 	default:
247 		dec_status = smb_dr_decode_finish(dec_ctx);
248 		goto decode_error;
249 	}
250 
251 	if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
252 		enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
253 		smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
254 		smb_dr_put_uint32(enc_ctx, enc_status);
255 		(void) smb_dr_encode_finish(enc_ctx, &used);
256 	}
257 
258 	smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
259 	return;
260 
261 decode_error:
262 	smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
263 	smb_dr_put_uint32(enc_ctx, dec_status);
264 	(void) smb_dr_encode_finish(enc_ctx, &used);
265 	smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
266 }
267