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	"@(#)smb_share_doorclnt.c	1.5	08/08/05 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 	bzero(list, sizeof (smb_shrlist_t));
166 
167 	if ((arg = smb_share_denter()) == NULL)
168 		return (NERR_InternalError);
169 
170 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
171 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_LIST);
172 	smb_dr_put_int32(enc_ctx, offset);
173 
174 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
175 	if (rc != 0) {
176 		smb_share_dexit(arg, "encode error");
177 		return (NERR_InternalError);
178 	}
179 
180 	if (door_call(smb_share_dfd, arg) < 0) {
181 		smb_share_dexit(arg, "door call error");
182 		smb_share_dclose();
183 		return (NERR_InternalError);
184 	}
185 
186 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
187 	if (smb_share_dchk(dec_ctx) != 0) {
188 		(void) smb_dr_decode_finish(dec_ctx);
189 		smb_share_dexit(arg, "decode error");
190 		return (NERR_InternalError);
191 	}
192 
193 	(void) smb_dr_get_buf(dec_ctx, (unsigned char *)list,
194 	    sizeof (smb_shrlist_t));
195 	if (smb_dr_decode_finish(dec_ctx) != 0) {
196 		smb_share_dexit(arg, "decode error");
197 		return (NERR_InternalError);
198 	}
199 
200 	smb_share_dexit(arg, NULL);
201 	return (NERR_Success);
202 }
203 
204 int
205 smb_share_count(void)
206 {
207 	door_arg_t *arg;
208 	smb_dr_ctx_t *dec_ctx;
209 	smb_dr_ctx_t *enc_ctx;
210 	uint32_t num_shares;
211 	int rc;
212 
213 	if ((arg = smb_share_denter()) == NULL)
214 		return (-1);
215 
216 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
217 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_NUM_SHARES);
218 
219 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
220 	if (rc != 0) {
221 		smb_share_dexit(arg, "encode error");
222 		return (-1);
223 	}
224 
225 	if (door_call(smb_share_dfd, arg) < 0) {
226 		smb_share_dexit(arg, "door call error");
227 		smb_share_dclose();
228 		return (-1);
229 	}
230 
231 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
232 	if (smb_share_dchk(dec_ctx) != 0) {
233 		(void) smb_dr_decode_finish(dec_ctx);
234 		smb_share_dexit(arg, "decode error");
235 		return (-1);
236 	}
237 
238 	num_shares = smb_dr_get_uint32(dec_ctx);
239 	if (smb_dr_decode_finish(dec_ctx) != 0) {
240 		smb_share_dexit(arg, "decode error");
241 		return (-1);
242 	}
243 
244 	smb_share_dexit(arg, NULL);
245 	return (num_shares);
246 }
247 
248 uint32_t
249 smb_share_delete(char *share_name)
250 {
251 	door_arg_t *arg;
252 	smb_dr_ctx_t *dec_ctx;
253 	smb_dr_ctx_t *enc_ctx;
254 	uint32_t rc;
255 
256 	if ((arg = smb_share_denter()) == NULL)
257 		return (NERR_InternalError);
258 
259 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
260 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_DELETE);
261 	smb_dr_put_string(enc_ctx, share_name);
262 
263 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
264 	if (rc != 0) {
265 		smb_share_dexit(arg, "encode error");
266 		return (NERR_InternalError);
267 	}
268 
269 	if (door_call(smb_share_dfd, arg) < 0) {
270 		smb_share_dexit(arg, "door call error");
271 		smb_share_dclose();
272 		return (NERR_InternalError);
273 	}
274 
275 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
276 	if (smb_share_dchk(dec_ctx) != 0) {
277 		(void) smb_dr_decode_finish(dec_ctx);
278 		smb_share_dexit(arg, "decode error");
279 		return (NERR_InternalError);
280 	}
281 
282 	rc = smb_dr_get_uint32(dec_ctx);
283 	if (smb_dr_decode_finish(dec_ctx) != 0) {
284 		smb_share_dexit(arg, "decode error");
285 		return (NERR_InternalError);
286 	}
287 
288 	smb_share_dexit(arg, NULL);
289 	return (rc);
290 
291 }
292 
293 uint32_t
294 smb_share_rename(char *from, char *to)
295 {
296 	door_arg_t *arg;
297 	smb_dr_ctx_t *dec_ctx;
298 	smb_dr_ctx_t *enc_ctx;
299 	uint32_t rc;
300 
301 	if ((arg = smb_share_denter()) == NULL)
302 		return (NERR_InternalError);
303 
304 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
305 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_RENAME);
306 	smb_dr_put_string(enc_ctx, from);
307 	smb_dr_put_string(enc_ctx, to);
308 
309 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
310 	if (rc != 0) {
311 		smb_share_dexit(arg, "encode error");
312 		return (NERR_InternalError);
313 	}
314 
315 	if (door_call(smb_share_dfd, arg) < 0) {
316 		smb_share_dexit(arg, "door call error");
317 		smb_share_dclose();
318 		return (NERR_InternalError);
319 	}
320 
321 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
322 	if (smb_share_dchk(dec_ctx) != 0) {
323 		(void) smb_dr_decode_finish(dec_ctx);
324 		smb_share_dexit(arg, "decode error");
325 		return (NERR_InternalError);
326 	}
327 
328 	rc = smb_dr_get_uint32(dec_ctx);
329 	if (smb_dr_decode_finish(dec_ctx) != 0) {
330 		smb_share_dexit(arg, "decode error");
331 		return (NERR_InternalError);
332 	}
333 
334 	smb_share_dexit(arg, NULL);
335 	return (rc);
336 }
337 
338 uint32_t
339 smb_share_get(char *share_name, smb_share_t *si)
340 {
341 	door_arg_t *arg;
342 	smb_dr_ctx_t *dec_ctx;
343 	smb_dr_ctx_t *enc_ctx;
344 	uint32_t rc;
345 
346 	if ((arg = smb_share_denter()) == NULL)
347 		return (NERR_InternalError);
348 
349 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
350 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_GETINFO);
351 	smb_dr_put_string(enc_ctx, share_name);
352 
353 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
354 	if (rc != 0) {
355 		smb_share_dexit(arg, "encode error");
356 		return (NERR_InternalError);
357 	}
358 
359 	if (door_call(smb_share_dfd, arg) < 0) {
360 		smb_share_dexit(arg, "door call error");
361 		smb_share_dclose();
362 		return (NERR_InternalError);
363 	}
364 
365 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
366 	if (smb_share_dchk(dec_ctx) != 0) {
367 		(void) smb_dr_decode_finish(dec_ctx);
368 		smb_share_dexit(arg, "decode error");
369 		return (NERR_InternalError);
370 	}
371 
372 	rc = smb_dr_get_uint32(dec_ctx);
373 	smb_dr_get_share(dec_ctx, si);
374 	if (smb_dr_decode_finish(dec_ctx) != 0) {
375 		smb_share_dexit(arg, "decode error");
376 		return (NERR_InternalError);
377 	}
378 
379 	smb_share_dexit(arg, NULL);
380 	return (rc);
381 }
382 
383 uint32_t
384 smb_share_create(smb_share_t *si)
385 {
386 	door_arg_t *arg;
387 	smb_dr_ctx_t *dec_ctx;
388 	smb_dr_ctx_t *enc_ctx;
389 	uint32_t rc;
390 
391 	if ((arg = smb_share_denter()) == NULL)
392 		return (NERR_InternalError);
393 
394 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
395 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_ADD);
396 	smb_dr_put_share(enc_ctx, si);
397 
398 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
399 	if (rc != 0) {
400 		smb_share_dexit(arg, "encode error");
401 		return (NERR_InternalError);
402 	}
403 
404 	if (door_call(smb_share_dfd, arg) < 0) {
405 		smb_share_dexit(arg, "door call error");
406 		smb_share_dclose();
407 		return (NERR_InternalError);
408 	}
409 
410 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
411 	if (smb_share_dchk(dec_ctx) != 0) {
412 		(void) smb_dr_decode_finish(dec_ctx);
413 		smb_share_dexit(arg, "decode error");
414 		return (NERR_InternalError);
415 	}
416 
417 	rc = smb_dr_get_uint32(dec_ctx);
418 	smb_dr_get_share(dec_ctx, si);
419 	if (smb_dr_decode_finish(dec_ctx) != 0) {
420 		smb_share_dexit(arg, "decode error");
421 		return (NERR_InternalError);
422 	}
423 
424 	smb_share_dexit(arg, NULL);
425 	return (rc);
426 }
427 
428 uint32_t
429 smb_share_modify(char *sharename, char *cmnt, char *ad_container)
430 {
431 	door_arg_t *arg;
432 	smb_dr_ctx_t *dec_ctx;
433 	smb_dr_ctx_t *enc_ctx;
434 	uint32_t rc;
435 
436 	if ((arg = smb_share_denter()) == NULL)
437 		return (NERR_InternalError);
438 
439 	enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
440 	smb_dr_put_uint32(enc_ctx, SMB_SHROP_MODIFY);
441 	smb_dr_put_string(enc_ctx, sharename);
442 	smb_dr_put_string(enc_ctx, cmnt);
443 	smb_dr_put_string(enc_ctx, ad_container);
444 
445 	rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
446 	if (rc != 0) {
447 		smb_share_dexit(arg, "encode error");
448 		return (NERR_InternalError);
449 	}
450 
451 	if (door_call(smb_share_dfd, arg) < 0) {
452 		smb_share_dexit(arg, "door call error");
453 		smb_share_dclose();
454 		return (NERR_InternalError);
455 	}
456 
457 	dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
458 	if (smb_share_dchk(dec_ctx) != 0) {
459 		(void) smb_dr_decode_finish(dec_ctx);
460 		smb_share_dexit(arg, "decode error");
461 		return (NERR_InternalError);
462 	}
463 
464 	rc = smb_dr_get_uint32(dec_ctx);
465 	if (smb_dr_decode_finish(dec_ctx) != 0) {
466 		smb_share_dexit(arg, "decode error");
467 		return (NERR_InternalError);
468 	}
469 
470 	smb_share_dexit(arg, NULL);
471 	return (rc);
472 }
473