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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * User-space door client for LanMan share management.
31  */
32 
33 #include <syslog.h>
34 #include <door.h>
35 #include <fcntl.h>
36 #include <stdarg.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <thread.h>
42 #include <synch.h>
43 
44 #include <smbsrv/libsmb.h>
45 #include <smbsrv/smb_share.h>
46 #include <smbsrv/lmerr.h>
47 #include <smbsrv/cifs.h>
48 
49 static int smb_share_dfd = -1;
50 static uint64_t smb_share_dncall = 0;
51 static mutex_t smb_share_dmtx;
52 static cond_t smb_share_dcv;
53 
54 /*
55  * Open the lmshrd door.  This is a private call for use by
56  * smb_share_denter() and must be called with smb_share_dmtx held.
57  *
58  * Returns the door fd on success.  Otherwise, -1.
59  */
60 static int
61 smb_share_dopen(void)
62 {
63 	if (smb_share_dfd == -1) {
64 		if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0)
65 			smb_share_dfd = -1;
66 		else
67 			smb_share_dncall = 0;
68 	}
69 
70 	return (smb_share_dfd);
71 }
72 
73 /*
74  * Close the lmshrd door.
75  */
76 void
77 smb_share_dclose(void)
78 {
79 	(void) mutex_lock(&smb_share_dmtx);
80 
81 	if (smb_share_dfd != -1) {
82 		while (smb_share_dncall > 0)
83 			(void) cond_wait(&smb_share_dcv, &smb_share_dmtx);
84 
85 		if (smb_share_dfd != -1) {
86 			(void) close(smb_share_dfd);
87 			smb_share_dfd = -1;
88 		}
89 	}
90 
91 	(void) mutex_unlock(&smb_share_dmtx);
92 }
93 
94 /*
95  * Entry handler for lmshrd door calls.
96  */
97 static door_arg_t *
98 smb_share_denter(void)
99 {
100 	door_arg_t *arg;
101 	char *buf;
102 
103 	(void) mutex_lock(&smb_share_dmtx);
104 
105 	if (smb_share_dopen() == -1) {
106 		(void) mutex_unlock(&smb_share_dmtx);
107 		return (NULL);
108 	}
109 
110 	if ((arg = malloc(sizeof (door_arg_t) + SMB_SHARE_DSIZE)) != NULL) {
111 		buf = ((char *)arg) + sizeof (door_arg_t);
112 		bzero(arg, sizeof (door_arg_t));
113 		arg->data_ptr = buf;
114 		arg->rbuf = buf;
115 		arg->rsize = SMB_SHARE_DSIZE;
116 
117 		++smb_share_dncall;
118 	}
119 
120 	(void) mutex_unlock(&smb_share_dmtx);
121 	return (arg);
122 }
123 
124 /*
125  * Exit handler for lmshrd door calls.
126  */
127 static void
128 smb_share_dexit(door_arg_t *arg, char *errmsg)
129 {
130 	if (errmsg)
131 		syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg);
132 
133 	(void) mutex_lock(&smb_share_dmtx);
134 	free(arg);
135 	--smb_share_dncall;
136 	(void) cond_signal(&smb_share_dcv);
137 	(void) mutex_unlock(&smb_share_dmtx);
138 }
139 
140 /*
141  * Return 0 upon success. Otherwise, -1.
142  */
143 static int
144 smb_share_dchk(smb_dr_ctx_t *dec_ctx)
145 {
146 	int status = smb_dr_get_int32(dec_ctx);
147 
148 	if (status != SMB_SHARE_DSUCCESS) {
149 		if (status == SMB_SHARE_DERROR)
150 			(void) smb_dr_get_uint32(dec_ctx);
151 		return (-1);
152 	}
153 
154 	return (0);
155 }
156 
157 uint32_t
158 smb_share_list(int offset, smb_shrlist_t *list)
159 {
160 	door_arg_t *arg;
161 	smb_dr_ctx_t *dec_ctx;
162 	smb_dr_ctx_t *enc_ctx;
163 	uint32_t rc;
164 
165 	if ((arg = smb_share_denter()) == NULL)
166 		return (NERR_InternalError);
167 
168 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
169 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST);
170 	smb_dr_put_int32(enc_ctx, offset);
171 
172 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
173 	if (rc != 0) {
174 		smb_share_dexit(arg, "encode error");
175 		return (NERR_InternalError);
176 	}
177 
178 	if (door_call(smb_share_dfd, arg) < 0) {
179 		smb_share_dexit(arg, "door call error");
180 		smb_share_dclose();
181 		return (NERR_InternalError);
182 	}
183 
184 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
185 	if (smb_share_dchk(dec_ctx) != 0) {
186 		(void) smb_dr_decode_finish(dec_ctx);
187 		smb_share_dexit(arg, "decode error");
188 		return (NERR_InternalError);
189 	}
190 
191 	smb_dr_get_shrlist(dec_ctx, list);
192 	if (smb_dr_decode_finish(dec_ctx) != 0) {
193 		smb_share_dexit(arg, "decode error");
194 		return (NERR_InternalError);
195 	}
196 
197 	smb_share_dexit(arg, NULL);
198 	return (NERR_Success);
199 }
200 
201 int
202 smb_share_count(void)
203 {
204 	door_arg_t *arg;
205 	smb_dr_ctx_t *dec_ctx;
206 	smb_dr_ctx_t *enc_ctx;
207 	uint32_t num_shares;
208 	int rc;
209 
210 	if ((arg = smb_share_denter()) == NULL)
211 		return (-1);
212 
213 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
214 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES);
215 
216 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
217 	if (rc != 0) {
218 		smb_share_dexit(arg, "encode error");
219 		return (-1);
220 	}
221 
222 	if (door_call(smb_share_dfd, arg) < 0) {
223 		smb_share_dexit(arg, "door call error");
224 		smb_share_dclose();
225 		return (-1);
226 	}
227 
228 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
229 	if (smb_share_dchk(dec_ctx) != 0) {
230 		(void) smb_dr_decode_finish(dec_ctx);
231 		smb_share_dexit(arg, "decode error");
232 		return (-1);
233 	}
234 
235 	num_shares = smb_dr_get_uint32(dec_ctx);
236 	if (smb_dr_decode_finish(dec_ctx) != 0) {
237 		smb_share_dexit(arg, "decode error");
238 		return (-1);
239 	}
240 
241 	smb_share_dexit(arg, NULL);
242 	return (num_shares);
243 }
244 
245 uint32_t
246 smb_share_del(char *share_name)
247 {
248 	door_arg_t *arg;
249 	smb_dr_ctx_t *dec_ctx;
250 	smb_dr_ctx_t *enc_ctx;
251 	uint32_t rc;
252 
253 	if ((arg = smb_share_denter()) == NULL)
254 		return (NERR_InternalError);
255 
256 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
257 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE);
258 	smb_dr_put_string(enc_ctx, share_name);
259 
260 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
261 	if (rc != 0) {
262 		smb_share_dexit(arg, "encode error");
263 		return (NERR_InternalError);
264 	}
265 
266 	if (door_call(smb_share_dfd, arg) < 0) {
267 		smb_share_dexit(arg, "door call error");
268 		smb_share_dclose();
269 		return (NERR_InternalError);
270 	}
271 
272 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
273 	if (smb_share_dchk(dec_ctx) != 0) {
274 		(void) smb_dr_decode_finish(dec_ctx);
275 		smb_share_dexit(arg, "decode error");
276 		return (NERR_InternalError);
277 	}
278 
279 	rc = smb_dr_get_uint32(dec_ctx);
280 	if (smb_dr_decode_finish(dec_ctx) != 0) {
281 		smb_share_dexit(arg, "decode error");
282 		return (NERR_InternalError);
283 	}
284 
285 	smb_share_dexit(arg, NULL);
286 	return (rc);
287 
288 }
289 
290 uint32_t
291 smb_share_ren(char *from, char *to)
292 {
293 	door_arg_t *arg;
294 	smb_dr_ctx_t *dec_ctx;
295 	smb_dr_ctx_t *enc_ctx;
296 	uint32_t rc;
297 
298 	if ((arg = smb_share_denter()) == NULL)
299 		return (NERR_InternalError);
300 
301 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
302 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME);
303 	smb_dr_put_string(enc_ctx, from);
304 	smb_dr_put_string(enc_ctx, to);
305 
306 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
307 	if (rc != 0) {
308 		smb_share_dexit(arg, "encode error");
309 		return (NERR_InternalError);
310 	}
311 
312 	if (door_call(smb_share_dfd, arg) < 0) {
313 		smb_share_dexit(arg, "door call error");
314 		smb_share_dclose();
315 		return (NERR_InternalError);
316 	}
317 
318 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
319 	if (smb_share_dchk(dec_ctx) != 0) {
320 		(void) smb_dr_decode_finish(dec_ctx);
321 		smb_share_dexit(arg, "decode error");
322 		return (NERR_InternalError);
323 	}
324 
325 	rc = smb_dr_get_uint32(dec_ctx);
326 	if (smb_dr_decode_finish(dec_ctx) != 0) {
327 		smb_share_dexit(arg, "decode error");
328 		return (NERR_InternalError);
329 	}
330 
331 	smb_share_dexit(arg, NULL);
332 	return (rc);
333 }
334 
335 uint32_t
336 smb_share_get(char *share_name, smb_share_t *si)
337 {
338 	door_arg_t *arg;
339 	smb_dr_ctx_t *dec_ctx;
340 	smb_dr_ctx_t *enc_ctx;
341 	uint32_t rc;
342 
343 	if ((arg = smb_share_denter()) == NULL)
344 		return (NERR_InternalError);
345 
346 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
347 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_GETINFO);
348 	smb_dr_put_string(enc_ctx, share_name);
349 
350 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
351 	if (rc != 0) {
352 		smb_share_dexit(arg, "encode error");
353 		return (NERR_InternalError);
354 	}
355 
356 	if (door_call(smb_share_dfd, arg) < 0) {
357 		smb_share_dexit(arg, "door call error");
358 		smb_share_dclose();
359 		return (NERR_InternalError);
360 	}
361 
362 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
363 	if (smb_share_dchk(dec_ctx) != 0) {
364 		(void) smb_dr_decode_finish(dec_ctx);
365 		smb_share_dexit(arg, "decode error");
366 		return (NERR_InternalError);
367 	}
368 
369 	rc = smb_dr_get_uint32(dec_ctx);
370 	smb_dr_get_share(dec_ctx, si);
371 	if (smb_dr_decode_finish(dec_ctx) != 0) {
372 		smb_share_dexit(arg, "decode error");
373 		return (NERR_InternalError);
374 	}
375 
376 	smb_share_dexit(arg, NULL);
377 	return (rc);
378 }
379 
380 uint32_t
381 smb_share_add(smb_share_t *si)
382 {
383 	door_arg_t *arg;
384 	smb_dr_ctx_t *dec_ctx;
385 	smb_dr_ctx_t *enc_ctx;
386 	uint32_t rc;
387 
388 	if ((arg = smb_share_denter()) == NULL)
389 		return (NERR_InternalError);
390 
391 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
392 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD);
393 	smb_dr_put_share(enc_ctx, si);
394 
395 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
396 	if (rc != 0) {
397 		smb_share_dexit(arg, "encode error");
398 		return (NERR_InternalError);
399 	}
400 
401 	if (door_call(smb_share_dfd, arg) < 0) {
402 		smb_share_dexit(arg, "door call error");
403 		smb_share_dclose();
404 		return (NERR_InternalError);
405 	}
406 
407 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
408 	if (smb_share_dchk(dec_ctx) != 0) {
409 		(void) smb_dr_decode_finish(dec_ctx);
410 		smb_share_dexit(arg, "decode error");
411 		return (NERR_InternalError);
412 	}
413 
414 	rc = smb_dr_get_uint32(dec_ctx);
415 	smb_dr_get_share(dec_ctx, si);
416 	if (smb_dr_decode_finish(dec_ctx) != 0) {
417 		smb_share_dexit(arg, "decode error");
418 		return (NERR_InternalError);
419 	}
420 
421 	smb_share_dexit(arg, NULL);
422 	return (rc);
423 }
424 
425 uint32_t
426 smb_share_set(smb_share_t *si)
427 {
428 	door_arg_t *arg;
429 	smb_dr_ctx_t *dec_ctx;
430 	smb_dr_ctx_t *enc_ctx;
431 	uint32_t rc;
432 
433 	if ((arg = smb_share_denter()) == NULL)
434 		return (NERR_InternalError);
435 
436 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
437 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_SETINFO);
438 	smb_dr_put_share(enc_ctx, si);
439 
440 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
441 	if (rc != 0) {
442 		smb_share_dexit(arg, "encode error");
443 		return (NERR_InternalError);
444 	}
445 
446 	if (door_call(smb_share_dfd, arg) < 0) {
447 		smb_share_dexit(arg, "door call error");
448 		smb_share_dclose();
449 		return (NERR_InternalError);
450 	}
451 
452 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
453 	if (smb_share_dchk(dec_ctx) != 0) {
454 		(void) smb_dr_decode_finish(dec_ctx);
455 		smb_share_dexit(arg, "decode error");
456 		return (NERR_InternalError);
457 	}
458 
459 	rc = smb_dr_get_uint32(dec_ctx);
460 	if (smb_dr_decode_finish(dec_ctx) != 0) {
461 		smb_share_dexit(arg, "decode error");
462 		return (NERR_InternalError);
463 	}
464 
465 	smb_share_dexit(arg, NULL);
466 	return (rc);
467 }
468