xref: /illumos-gate/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c (revision ca9327a6de44d69ddab3668cc1e143ce781387a3)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * LanMan share door server
30  */
31 
32 #include <door.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <syslog.h>
39 #include <string.h>
40 #include <pthread.h>
41 
42 #include <smbsrv/libsmb.h>
43 
44 #include <smbsrv/lmshare.h>
45 #include <smbsrv/lmshare_door.h>
46 #include <smbsrv/smbinfo.h>
47 
48 static smb_kmod_cfg_t smb_kcfg;
49 
50 static int smb_lmshrd_fildes = -1;
51 static pthread_mutex_t smb_lmshrd_srv_mutex = PTHREAD_MUTEX_INITIALIZER;
52 
53 /* forward declaration */
54 static void smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size,
55     door_desc_t *dp, uint_t n_desc);
56 static int smb_lmshrd_srv_check(int opcode, char *sharename);
57 
58 /*
59  * smb_lmshrd_srv_start
60  *
61  * Start the LanMan share door service.
62  * Returns 0 on success. Otherwise, -1.
63  */
64 int
65 smb_lmshrd_srv_start(void)
66 {
67 	int	newfd;
68 
69 	(void) pthread_mutex_lock(&smb_lmshrd_srv_mutex);
70 
71 	if (smb_lmshrd_fildes != -1) {
72 		syslog(LOG_ERR, "smb_lmshrd_srv_start: duplicate");
73 		(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
74 		return (smb_lmshrd_fildes);
75 	}
76 
77 	if ((smb_lmshrd_fildes = door_create(smb_lmshrd_srv_door,
78 	    LMSHR_DOOR_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
79 		syslog(LOG_ERR, "smb_lmshrd_srv_start: door_create: %s",
80 		    strerror(errno));
81 		(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
82 		return (-1);
83 	}
84 
85 	(void) unlink(LMSHR_DOOR_NAME);
86 
87 	if ((newfd = creat(LMSHR_DOOR_NAME, 0644)) < 0) {
88 		syslog(LOG_ERR, "smb_lmshrd_srv_start: open: %s",
89 		    strerror(errno));
90 		(void) door_revoke(smb_lmshrd_fildes);
91 		smb_lmshrd_fildes = -1;
92 		(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
93 		return (-1);
94 	}
95 
96 	(void) close(newfd);
97 	(void) fdetach(LMSHR_DOOR_NAME);
98 
99 	if (fattach(smb_lmshrd_fildes, LMSHR_DOOR_NAME) < 0) {
100 		syslog(LOG_ERR, "smb_lmshrd_srv_start: fattach: %s",
101 		    strerror(errno));
102 		(void) door_revoke(smb_lmshrd_fildes);
103 		smb_lmshrd_fildes = -1;
104 		(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
105 		return (-1);
106 	}
107 
108 	(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
109 	return (smb_lmshrd_fildes);
110 }
111 
112 
113 /*
114  * smb_lmshrd_srv_stop
115  *
116  * Stop the LanMan share door service.
117  */
118 void
119 smb_lmshrd_srv_stop(void)
120 {
121 	(void) pthread_mutex_lock(&smb_lmshrd_srv_mutex);
122 
123 	if (smb_lmshrd_fildes != -1) {
124 		(void) fdetach(LMSHR_DOOR_NAME);
125 		(void) door_revoke(smb_lmshrd_fildes);
126 		smb_lmshrd_fildes = -1;
127 	}
128 
129 	(void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex);
130 }
131 
132 
133 /*
134  * smb_lmshrd_srv_door
135  *
136  * This function with which the LMSHARE door is associated
137  * will invoke the appropriate CIFS share management function
138  * based on the request type of the door call.
139  */
140 /*ARGSUSED*/
141 void
142 smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp,
143     uint_t n_desc)
144 {
145 	DWORD rc;
146 	int req_type, mode, rc2;
147 	char buf[LMSHR_DOOR_SIZE];
148 	unsigned int used;
149 	smb_dr_ctx_t *dec_ctx = smb_dr_decode_start(ptr, size);
150 	smb_dr_ctx_t *enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
151 	unsigned int dec_status;
152 	unsigned int enc_status;
153 	char *sharename, *sharename2;
154 	lmshare_info_t lmshr_info;
155 	lmshare_info_t *lmshr_infop;
156 	lmshare_iterator_t *lmshr_iter;
157 	int offset;
158 	lmshare_list_t lmshr_list;
159 
160 	req_type = smb_dr_get_uint32(dec_ctx);
161 
162 	switch (req_type) {
163 	case LMSHR_DOOR_OPEN_ITERATOR:
164 		mode = smb_dr_get_int32(dec_ctx);
165 
166 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
167 			goto decode_error;
168 
169 		lmshr_iter = lmshare_open_iterator(mode);
170 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
171 		smb_dr_put_lmshr_iterator(enc_ctx,
172 		    (uint64_t)(uintptr_t)lmshr_iter);
173 
174 		break;
175 
176 	case LMSHR_DOOR_CLOSE_ITERATOR:
177 		lmshr_iter = (lmshare_iterator_t *)(uintptr_t)
178 		    smb_dr_get_lmshr_iterator(dec_ctx);
179 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
180 			goto decode_error;
181 
182 		lmshare_close_iterator(lmshr_iter);
183 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
184 		break;
185 
186 	case LMSHR_DOOR_ITERATE:
187 		lmshr_iter = (lmshare_iterator_t *)(uintptr_t)
188 		    smb_dr_get_lmshr_iterator(dec_ctx);
189 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
190 			goto decode_error;
191 
192 		lmshr_infop = lmshare_iterate(lmshr_iter);
193 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
194 		smb_dr_put_lmshare(enc_ctx, lmshr_infop);
195 		break;
196 
197 	case LMSHR_DOOR_NUM_SHARES:
198 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
199 			goto decode_error;
200 
201 		rc = lmshare_num_shares();
202 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
203 		smb_dr_put_uint32(enc_ctx, rc);
204 		break;
205 
206 	case LMSHR_DOOR_DELETE:
207 		sharename = smb_dr_get_string(dec_ctx);
208 
209 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
210 			smb_dr_free_string(sharename);
211 			goto decode_error;
212 		}
213 
214 		rc = lmshare_delete(sharename, 0);
215 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
216 		smb_dr_put_uint32(enc_ctx, rc);
217 		smb_dr_free_string(sharename);
218 		break;
219 
220 	case LMSHR_DOOR_RENAME:
221 		sharename = smb_dr_get_string(dec_ctx);
222 		sharename2 = smb_dr_get_string(dec_ctx);
223 
224 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
225 			smb_dr_free_string(sharename);
226 			smb_dr_free_string(sharename2);
227 			goto decode_error;
228 		}
229 
230 		rc = lmshare_rename(sharename, sharename2, 0);
231 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
232 		smb_dr_put_uint32(enc_ctx, rc);
233 		smb_dr_free_string(sharename);
234 		smb_dr_free_string(sharename2);
235 		break;
236 
237 	case LMSHR_DOOR_GETINFO:
238 		sharename = smb_dr_get_string(dec_ctx);
239 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
240 			smb_dr_free_string(sharename);
241 			goto decode_error;
242 		}
243 
244 		rc = lmshare_getinfo(sharename, &lmshr_info);
245 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
246 		smb_dr_put_uint32(enc_ctx, rc);
247 		smb_dr_put_lmshare(enc_ctx, &lmshr_info);
248 		smb_dr_free_string(sharename);
249 		break;
250 
251 	case LMSHR_DOOR_ADD:
252 		smb_dr_get_lmshare(dec_ctx, &lmshr_info);
253 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
254 			goto decode_error;
255 
256 		rc = lmshare_add(&lmshr_info, 0);
257 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
258 		smb_dr_put_uint32(enc_ctx, rc);
259 		smb_dr_put_lmshare(enc_ctx, &lmshr_info);
260 		break;
261 
262 	case LMSHR_DOOR_SETINFO:
263 		smb_dr_get_lmshare(dec_ctx, &lmshr_info);
264 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
265 			goto decode_error;
266 
267 		rc = lmshare_setinfo(&lmshr_info, 0);
268 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
269 		smb_dr_put_uint32(enc_ctx, rc);
270 		break;
271 
272 	case LMSHR_DOOR_EXISTS:
273 	case LMSHR_DOOR_IS_SPECIAL:
274 	case LMSHR_DOOR_IS_RESTRICTED:
275 	case LMSHR_DOOR_IS_ADMIN:
276 	case LMSHR_DOOR_IS_VALID:
277 	case LMSHR_DOOR_IS_DIR:
278 		sharename = smb_dr_get_string(dec_ctx);
279 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
280 			smb_dr_free_string(sharename);
281 			goto decode_error;
282 		}
283 
284 		rc2 = smb_lmshrd_srv_check(req_type, sharename);
285 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
286 		smb_dr_put_uint32(enc_ctx, rc2);
287 		smb_dr_free_string(sharename);
288 		break;
289 
290 	case LMSHR_DOOR_LIST:
291 		offset = smb_dr_get_int32(dec_ctx);
292 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
293 			goto decode_error;
294 
295 		rc = lmshare_list(offset, &lmshr_list);
296 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
297 		smb_dr_put_uint32(enc_ctx, rc);
298 		smb_dr_put_lmshr_list(enc_ctx, &lmshr_list);
299 		break;
300 
301 	case SMB_GET_KCONFIG:
302 		if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
303 			goto decode_error;
304 
305 		smb_load_kconfig(&smb_kcfg);
306 		smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS);
307 		smb_dr_put_kconfig(enc_ctx, &smb_kcfg);
308 		break;
309 
310 	default:
311 		dec_status = smb_dr_decode_finish(dec_ctx);
312 		goto decode_error;
313 	}
314 
315 	if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0)
316 		goto encode_error;
317 
318 	(void) door_return(buf, used, NULL, 0);
319 
320 	return;
321 
322 decode_error:
323 	smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR);
324 	smb_dr_put_uint32(enc_ctx, dec_status);
325 	(void) smb_dr_encode_finish(enc_ctx, &used);
326 	(void) door_return(buf, used, NULL, 0);
327 	return;
328 
329 encode_error:
330 	enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
331 	smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR);
332 	smb_dr_put_uint32(enc_ctx, enc_status);
333 	(void) smb_dr_encode_finish(enc_ctx, &used);
334 	(void) door_return(buf, used, NULL, 0);
335 }
336 
337 /*
338  * smb_lmshrd_srv_check
339  *
340  * Depending upon the opcode, this function will
341  * either check the existence of a share/dir or
342  * the the type of the specified share.
343  */
344 static int
345 smb_lmshrd_srv_check(int opcode, char *sharename)
346 {
347 	int rc;
348 
349 	switch (opcode) {
350 	case LMSHR_DOOR_EXISTS:
351 		rc = lmshare_exists(sharename);
352 		break;
353 
354 	case LMSHR_DOOR_IS_SPECIAL:
355 		rc = lmshare_is_special(sharename);
356 		break;
357 
358 	case LMSHR_DOOR_IS_RESTRICTED:
359 		rc = lmshare_is_restricted(sharename);
360 		break;
361 
362 	case LMSHR_DOOR_IS_ADMIN:
363 		rc = lmshare_is_admin(sharename);
364 		break;
365 
366 	case LMSHR_DOOR_IS_VALID:
367 		rc = lmshare_is_valid(sharename);
368 		break;
369 
370 	case LMSHR_DOOR_IS_DIR:
371 		rc = lmshare_is_dir(sharename);
372 	}
373 
374 	return (rc);
375 }
376