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 2007 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 
41 #include <smbsrv/libsmb.h>
42 
43 #include <smbsrv/lmshare.h>
44 #include <smbsrv/lmerr.h>
45 #include <smbsrv/lmshare_door.h>
46 #include <smbsrv/cifs.h>
47 
48 int lmshrd_fildes = -1;
49 
50 char *lmshrd_desc[] = {
51 	"",
52 	"LmshrdOpenIter",
53 	"LmshrdCloseIter",
54 	"LmshrdIterate",
55 	"LmshrdNumShares",
56 	"LmshrdDelete",
57 	"LmshrdRename",
58 	"LmshrdGetinfo",
59 	"LmshrdAdd",
60 	"LmshrdSetinfo",
61 	"LmshrdExists",
62 	"LmshrdIsSpecial",
63 	"LmshrdIsRestricted",
64 	"LmshrdIsAdmin",
65 	"LmshrdIsValid",
66 	"LmshrdIsDir",
67 	"LmshrdList",
68 	"LmshrdListTrans",
69 	"LmshrdNumTrans",
70 	"N/A",
71 	0
72 };
73 
74 /*
75  * Returns 0 on success. Otherwise, -1.
76  */
77 static int
78 lmshrd_door_open(int opcode)
79 {
80 	int rc = 0;
81 
82 	if (lmshrd_fildes == -1 &&
83 	    (lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) {
84 		syslog(LOG_DEBUG, "%s: open %s failed %s", lmshrd_desc[opcode],
85 		    LMSHR_DOOR_NAME, strerror(errno));
86 		rc = -1;
87 	}
88 	return (rc);
89 }
90 
91 /*
92  * Return 0 upon success. Otherwise, -1.
93  */
94 static int
95 lmshrd_door_check_srv_status(int opcode, smb_dr_ctx_t *dec_ctx)
96 {
97 	int status = smb_dr_get_int32(dec_ctx);
98 	int err;
99 	int rc = -1;
100 
101 	switch (status) {
102 	case LMSHR_DOOR_SRV_SUCCESS:
103 		rc = 0;
104 		break;
105 
106 	case LMSHR_DOOR_SRV_ERROR:
107 		err = smb_dr_get_uint32(dec_ctx);
108 		syslog(LOG_ERR, "%s: Encountered door server error %s",
109 		    lmshrd_desc[opcode], strerror(err));
110 		break;
111 
112 	default:
113 		syslog(LOG_ERR, "%s: Unknown door server status",
114 		    lmshrd_desc[opcode]);
115 	}
116 
117 	if (rc != 0) {
118 		if ((err = smb_dr_decode_finish(dec_ctx)) != 0)
119 			syslog(LOG_ERR, "%s: Decode error %s",
120 			    lmshrd_desc[opcode], strerror(err));
121 	}
122 
123 	return (rc);
124 }
125 
126 uint64_t
127 lmshrd_open_iterator(int mode)
128 {
129 	door_arg_t arg;
130 	char *buf;
131 	unsigned int used;
132 	smb_dr_ctx_t *dec_ctx;
133 	smb_dr_ctx_t *enc_ctx;
134 	unsigned int status = 0;
135 	uint64_t lmshr_iter = 0;
136 	int opcode = LMSHR_DOOR_OPEN_ITERATOR;
137 
138 	if (lmshrd_door_open(opcode) == -1)
139 		return (lmshr_iter);
140 
141 	buf = malloc(LMSHR_DOOR_SIZE);
142 	if (!buf)
143 		return (lmshr_iter);
144 
145 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
146 	smb_dr_put_uint32(enc_ctx, opcode);
147 	smb_dr_put_int32(enc_ctx, mode);
148 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
149 		syslog(LOG_ERR, "%s: Encode error %s",
150 		    lmshrd_desc[opcode], strerror(status));
151 		(void) free(buf);
152 		return (lmshr_iter);
153 	}
154 
155 	arg.data_ptr = buf;
156 	arg.data_size = used;
157 	arg.desc_ptr = NULL;
158 	arg.desc_num = 0;
159 	arg.rbuf = buf;
160 	arg.rsize = LMSHR_DOOR_SIZE;
161 
162 	if (door_call(lmshrd_fildes, &arg) < 0) {
163 		syslog(LOG_DEBUG, "%s: Door call failed %s",
164 		    lmshrd_desc[opcode], strerror(errno));
165 		(void) free(buf);
166 		lmshrd_fildes = -1;
167 		return (lmshr_iter);
168 	}
169 
170 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
171 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
172 		(void) free(buf);
173 		return (lmshr_iter);
174 	}
175 
176 	lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx);
177 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
178 		syslog(LOG_ERR, "%s: Decode error %s",
179 		    lmshrd_desc[opcode], strerror(status));
180 		(void) free(buf);
181 		return (lmshr_iter);
182 	}
183 
184 	(void) free(buf);
185 	return (lmshr_iter);
186 }
187 
188 
189 DWORD
190 lmshrd_close_iterator(uint64_t iterator)
191 {
192 	door_arg_t arg;
193 	char *buf;
194 	unsigned int used;
195 	smb_dr_ctx_t *dec_ctx;
196 	smb_dr_ctx_t *enc_ctx;
197 	unsigned int status = 0;
198 	int opcode = LMSHR_DOOR_CLOSE_ITERATOR;
199 
200 	if (lmshrd_door_open(opcode) == -1)
201 		return (NERR_InternalError);
202 
203 	buf = malloc(LMSHR_DOOR_SIZE);
204 	if (!buf)
205 		return (NERR_InternalError);
206 
207 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
208 	smb_dr_put_uint32(enc_ctx, opcode);
209 	smb_dr_put_lmshr_iterator(enc_ctx, iterator);
210 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
211 		syslog(LOG_ERR, "%s: Encode error %s",
212 		    lmshrd_desc[opcode], strerror(status));
213 		(void) free(buf);
214 		return (NERR_InternalError);
215 	}
216 
217 	arg.data_ptr = buf;
218 	arg.data_size = used;
219 	arg.desc_ptr = NULL;
220 	arg.desc_num = 0;
221 	arg.rbuf = buf;
222 	arg.rsize = LMSHR_DOOR_SIZE;
223 
224 	if (door_call(lmshrd_fildes, &arg) < 0) {
225 		syslog(LOG_DEBUG, "%s: Door call failed %s",
226 		    lmshrd_desc[opcode], strerror(errno));
227 		(void) free(buf);
228 		lmshrd_fildes = -1;
229 		return (NERR_InternalError);
230 	}
231 
232 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
233 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
234 		(void) free(buf);
235 		return (NERR_InternalError);
236 	}
237 
238 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
239 		syslog(LOG_ERR, "%s: Decode error %s",
240 		    lmshrd_desc[opcode], strerror(status));
241 		(void) free(buf);
242 		return (NERR_InternalError);
243 	}
244 
245 	(void) free(buf);
246 	return (NERR_Success);
247 }
248 
249 DWORD
250 lmshrd_iterate(uint64_t iterator, lmshare_info_t *si)
251 {
252 	door_arg_t arg;
253 	char *buf;
254 	unsigned int used;
255 	smb_dr_ctx_t *dec_ctx;
256 	smb_dr_ctx_t *enc_ctx;
257 	unsigned int status = 0;
258 	int opcode = LMSHR_DOOR_ITERATE;
259 
260 	if (lmshrd_door_open(opcode) == -1)
261 		return (NERR_InternalError);
262 
263 	buf = malloc(LMSHR_DOOR_SIZE);
264 	if (!buf)
265 		return (NERR_InternalError);
266 
267 	bzero(si, sizeof (lmshare_info_t));
268 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
269 	smb_dr_put_uint32(enc_ctx, opcode);
270 	smb_dr_put_lmshr_iterator(enc_ctx, iterator);
271 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
272 		syslog(LOG_ERR, "%s: Encode error %s",
273 		    lmshrd_desc[opcode], strerror(status));
274 		(void) free(buf);
275 		return (NERR_InternalError);
276 	}
277 
278 	arg.data_ptr = buf;
279 	arg.data_size = used;
280 	arg.desc_ptr = NULL;
281 	arg.desc_num = 0;
282 	arg.rbuf = buf;
283 	arg.rsize = LMSHR_DOOR_SIZE;
284 
285 	if (door_call(lmshrd_fildes, &arg) < 0) {
286 		syslog(LOG_DEBUG, "%s: Door call failed %s",
287 		    lmshrd_desc[opcode], strerror(errno));
288 		(void) free(buf);
289 		lmshrd_fildes = -1;
290 		return (NERR_InternalError);
291 	}
292 
293 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
294 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
295 		(void) free(buf);
296 		return (NERR_InternalError);
297 	}
298 
299 	smb_dr_get_lmshare(dec_ctx, si);
300 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
301 		syslog(LOG_ERR, "%s: Decode error %s",
302 		    lmshrd_desc[opcode], strerror(status));
303 		(void) free(buf);
304 		return (NERR_InternalError);
305 	}
306 
307 	(void) free(buf);
308 	return (NERR_Success);
309 }
310 
311 DWORD
312 lmshrd_list(int offset, lmshare_list_t *list)
313 {
314 	door_arg_t arg;
315 	char *buf;
316 	unsigned int used;
317 	smb_dr_ctx_t *dec_ctx;
318 	smb_dr_ctx_t *enc_ctx;
319 	int status;
320 	DWORD rc;
321 	int opcode = LMSHR_DOOR_LIST;
322 
323 	if (lmshrd_door_open(opcode) == -1)
324 		return (NERR_InternalError);
325 
326 	buf = malloc(LMSHR_DOOR_SIZE);
327 
328 	if (!buf)
329 		return (NERR_InternalError);
330 
331 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
332 	smb_dr_put_uint32(enc_ctx, opcode);
333 	smb_dr_put_int32(enc_ctx, offset);
334 
335 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
336 		syslog(LOG_ERR, "%s: Encode error %s",
337 		    lmshrd_desc[opcode], strerror(status));
338 		(void) free(buf);
339 		return (NERR_InternalError);
340 	}
341 
342 	arg.data_ptr = buf;
343 	arg.data_size = used;
344 	arg.desc_ptr = NULL;
345 	arg.desc_num = 0;
346 	arg.rbuf = buf;
347 	arg.rsize = LMSHR_DOOR_SIZE;
348 
349 	if (door_call(lmshrd_fildes, &arg) < 0) {
350 		syslog(LOG_DEBUG, "%s: Door call failed %s",
351 		    lmshrd_desc[opcode], strerror(errno));
352 		(void) free(buf);
353 		lmshrd_fildes = -1;
354 		return (NERR_InternalError);
355 	}
356 
357 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
358 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
359 		(void) free(buf);
360 		return (NERR_InternalError);
361 	}
362 
363 	rc = smb_dr_get_uint32(dec_ctx);
364 	smb_dr_get_lmshr_list(dec_ctx, list);
365 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
366 		syslog(LOG_ERR, "%s: Decode error %s",
367 		    lmshrd_desc[opcode], strerror(status));
368 		(void) free(buf);
369 		return (NERR_InternalError);
370 	}
371 
372 	(void) free(buf);
373 
374 	return (rc);
375 }
376 
377 int
378 lmshrd_num_shares(void)
379 {
380 	door_arg_t arg;
381 	char *buf;
382 	unsigned int used;
383 	smb_dr_ctx_t *dec_ctx;
384 	smb_dr_ctx_t *enc_ctx;
385 	unsigned int status = 0;
386 	DWORD num_shares;
387 	int opcode = LMSHR_DOOR_NUM_SHARES;
388 
389 	if (lmshrd_door_open(opcode) == -1)
390 		return (-1);
391 
392 	buf = malloc(LMSHR_DOOR_SIZE);
393 	if (!buf)
394 		return (-1);
395 
396 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
397 	smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_NUM_SHARES);
398 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
399 		syslog(LOG_ERR, "%s: Encode error %s",
400 		    lmshrd_desc[opcode], strerror(status));
401 		(void) free(buf);
402 		return (-1);
403 	}
404 
405 	arg.data_ptr = buf;
406 	arg.data_size = used;
407 	arg.desc_ptr = NULL;
408 	arg.desc_num = 0;
409 	arg.rbuf = buf;
410 	arg.rsize = LMSHR_DOOR_SIZE;
411 
412 	if (door_call(lmshrd_fildes, &arg) < 0) {
413 		syslog(LOG_DEBUG, "%s: Door call failed %s",
414 		    lmshrd_desc[opcode], strerror(errno));
415 		(void) free(buf);
416 		lmshrd_fildes = -1;
417 		return (-1);
418 	}
419 
420 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
421 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
422 		(void) free(buf);
423 		return (-1);
424 	}
425 
426 	num_shares = smb_dr_get_uint32(dec_ctx);
427 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
428 		syslog(LOG_ERR, "%s: Decode error %s",
429 		    lmshrd_desc[opcode], strerror(status));
430 		(void) free(buf);
431 		return (-1);
432 	}
433 
434 	(void) free(buf);
435 	return (num_shares);
436 }
437 
438 DWORD
439 lmshrd_delete(char *share_name)
440 {
441 	door_arg_t arg;
442 	char *buf;
443 	unsigned int used;
444 	smb_dr_ctx_t *dec_ctx;
445 	smb_dr_ctx_t *enc_ctx;
446 	int status;
447 	DWORD rc;
448 	int opcode = LMSHR_DOOR_DELETE;
449 
450 	if (lmshrd_door_open(opcode) == -1)
451 		return (NERR_InternalError);
452 
453 	buf = malloc(LMSHR_DOOR_SIZE);
454 	if (!buf)
455 		return (NERR_InternalError);
456 
457 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
458 	smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_DELETE);
459 	smb_dr_put_string(enc_ctx, share_name);
460 
461 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
462 		syslog(LOG_ERR, "%s: Encode error %s",
463 		    lmshrd_desc[opcode], strerror(status));
464 		(void) free(buf);
465 		return (NERR_InternalError);
466 	}
467 
468 	arg.data_ptr = buf;
469 	arg.data_size = used;
470 	arg.desc_ptr = NULL;
471 	arg.desc_num = 0;
472 	arg.rbuf = buf;
473 	arg.rsize = LMSHR_DOOR_SIZE;
474 
475 	if (door_call(lmshrd_fildes, &arg) < 0) {
476 		syslog(LOG_DEBUG, "%s: Door call failed %s",
477 		    lmshrd_desc[opcode], strerror(errno));
478 		(void) free(buf);
479 		lmshrd_fildes = -1;
480 		return (NERR_InternalError);
481 	}
482 
483 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
484 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
485 		(void) free(buf);
486 		return (NERR_InternalError);
487 	}
488 
489 	rc = smb_dr_get_uint32(dec_ctx);
490 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
491 		syslog(LOG_ERR, "%s: Decode error %s",
492 		    lmshrd_desc[opcode], strerror(status));
493 		(void) free(buf);
494 		return (NERR_InternalError);
495 	}
496 
497 	(void) free(buf);
498 	return (rc);
499 
500 }
501 
502 DWORD
503 lmshrd_rename(char *from, char *to)
504 {
505 	door_arg_t arg;
506 	char *buf;
507 	unsigned int used;
508 	smb_dr_ctx_t *dec_ctx;
509 	smb_dr_ctx_t *enc_ctx;
510 	int status;
511 	DWORD rc;
512 	int opcode = LMSHR_DOOR_RENAME;
513 
514 	if (lmshrd_door_open(opcode) == -1)
515 		return (NERR_InternalError);
516 
517 	buf = malloc(LMSHR_DOOR_SIZE);
518 	if (!buf)
519 		return (NERR_InternalError);
520 
521 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
522 	smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_RENAME);
523 	smb_dr_put_string(enc_ctx, from);
524 	smb_dr_put_string(enc_ctx, to);
525 
526 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
527 		syslog(LOG_ERR, "%s: Encode error %s",
528 		    lmshrd_desc[opcode], strerror(status));
529 		(void) free(buf);
530 		return (NERR_InternalError);
531 	}
532 
533 	arg.data_ptr = buf;
534 	arg.data_size = used;
535 	arg.desc_ptr = NULL;
536 	arg.desc_num = 0;
537 	arg.rbuf = buf;
538 	arg.rsize = LMSHR_DOOR_SIZE;
539 
540 	if (door_call(lmshrd_fildes, &arg) < 0) {
541 		syslog(LOG_DEBUG, "%s: Door call failed %s",
542 		    lmshrd_desc[opcode], strerror(errno));
543 		(void) free(buf);
544 		lmshrd_fildes = -1;
545 		return (NERR_InternalError);
546 	}
547 
548 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
549 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
550 		(void) free(buf);
551 		return (NERR_InternalError);
552 	}
553 
554 	rc = smb_dr_get_uint32(dec_ctx);
555 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
556 		syslog(LOG_ERR, "%s: Decode error %s",
557 		    lmshrd_desc[opcode], strerror(status));
558 		(void) free(buf);
559 		return (NERR_InternalError);
560 	}
561 
562 	(void) free(buf);
563 	return (rc);
564 }
565 
566 DWORD
567 lmshrd_getinfo(char *share_name, lmshare_info_t *si)
568 {
569 	door_arg_t arg;
570 	char *buf;
571 	unsigned int used;
572 	smb_dr_ctx_t *dec_ctx;
573 	smb_dr_ctx_t *enc_ctx;
574 	int status;
575 	DWORD rc;
576 	int opcode = LMSHR_DOOR_GETINFO;
577 
578 	if (lmshrd_door_open(opcode) == -1)
579 		return (NERR_InternalError);
580 
581 	buf = malloc(LMSHR_DOOR_SIZE);
582 	if (!buf)
583 		return (NERR_InternalError);
584 
585 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
586 	smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_GETINFO);
587 	smb_dr_put_string(enc_ctx, share_name);
588 
589 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
590 		syslog(LOG_ERR, "%s: Encode error %s",
591 		    lmshrd_desc[opcode], strerror(status));
592 		(void) free(buf);
593 		return (NERR_InternalError);
594 	}
595 
596 	arg.data_ptr = buf;
597 	arg.data_size = used;
598 	arg.desc_ptr = NULL;
599 	arg.desc_num = 0;
600 	arg.rbuf = buf;
601 	arg.rsize = LMSHR_DOOR_SIZE;
602 
603 	if (door_call(lmshrd_fildes, &arg) < 0) {
604 		syslog(LOG_DEBUG, "%s: Door call failed %s",
605 		    lmshrd_desc[opcode], strerror(errno));
606 		(void) free(buf);
607 		lmshrd_fildes = -1;
608 		return (NERR_InternalError);
609 	}
610 
611 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
612 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
613 		(void) free(buf);
614 		return (NERR_InternalError);
615 	}
616 
617 	rc = smb_dr_get_uint32(dec_ctx);
618 	smb_dr_get_lmshare(dec_ctx, si);
619 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
620 		syslog(LOG_ERR, "%s: Decode error %s",
621 		    lmshrd_desc[opcode], strerror(status));
622 		(void) free(buf);
623 		return (NERR_InternalError);
624 	}
625 
626 	(void) free(buf);
627 	return (rc);
628 }
629 
630 DWORD
631 lmshrd_add(lmshare_info_t *si)
632 {
633 	door_arg_t arg;
634 	char *buf;
635 	unsigned int used;
636 	smb_dr_ctx_t *dec_ctx;
637 	smb_dr_ctx_t *enc_ctx;
638 	int status;
639 	DWORD rc;
640 	int opcode = LMSHR_DOOR_ADD;
641 
642 	if (lmshrd_door_open(opcode) == -1)
643 		return (NERR_InternalError);
644 
645 	buf = malloc(LMSHR_DOOR_SIZE);
646 	if (!buf)
647 		return (NERR_InternalError);
648 
649 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
650 	smb_dr_put_uint32(enc_ctx, opcode);
651 	smb_dr_put_lmshare(enc_ctx, si);
652 
653 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
654 		syslog(LOG_ERR, "%s: Encode error %s",
655 		    lmshrd_desc[opcode], strerror(status));
656 		(void) free(buf);
657 		return (NERR_InternalError);
658 	}
659 
660 	arg.data_ptr = buf;
661 	arg.data_size = used;
662 	arg.desc_ptr = NULL;
663 	arg.desc_num = 0;
664 	arg.rbuf = buf;
665 	arg.rsize = LMSHR_DOOR_SIZE;
666 
667 	if (door_call(lmshrd_fildes, &arg) < 0) {
668 		syslog(LOG_DEBUG, "%s: Door call failed %s",
669 		    lmshrd_desc[opcode], strerror(errno));
670 		(void) free(buf);
671 		lmshrd_fildes = -1;
672 		return (NERR_InternalError);
673 	}
674 
675 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
676 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
677 		(void) free(buf);
678 		return (NERR_InternalError);
679 	}
680 
681 	rc = smb_dr_get_uint32(dec_ctx);
682 	smb_dr_get_lmshare(dec_ctx, si);
683 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
684 		syslog(LOG_ERR, "%s: Decode error %s",
685 		    lmshrd_desc[opcode], strerror(status));
686 		(void) free(buf);
687 		return (NERR_InternalError);
688 	}
689 
690 	(void) free(buf);
691 	return (rc);
692 }
693 
694 DWORD
695 lmshrd_setinfo(lmshare_info_t *si)
696 {
697 	door_arg_t arg;
698 	char *buf;
699 	unsigned int used;
700 	smb_dr_ctx_t *dec_ctx;
701 	smb_dr_ctx_t *enc_ctx;
702 	int status;
703 	DWORD rc;
704 	int opcode = LMSHR_DOOR_SETINFO;
705 
706 	if (lmshrd_door_open(opcode) == -1)
707 		return (NERR_InternalError);
708 
709 	buf = malloc(LMSHR_DOOR_SIZE);
710 	if (!buf)
711 		return (NERR_InternalError);
712 
713 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
714 	smb_dr_put_uint32(enc_ctx, opcode);
715 	smb_dr_put_lmshare(enc_ctx, si);
716 
717 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
718 		syslog(LOG_ERR, "%s: Encode error %s",
719 		    lmshrd_desc[opcode], strerror(status));
720 		(void) free(buf);
721 		return (NERR_InternalError);
722 	}
723 
724 	arg.data_ptr = buf;
725 	arg.data_size = used;
726 	arg.desc_ptr = NULL;
727 	arg.desc_num = 0;
728 	arg.rbuf = buf;
729 	arg.rsize = LMSHR_DOOR_SIZE;
730 
731 	if (door_call(lmshrd_fildes, &arg) < 0) {
732 		syslog(LOG_DEBUG, "%s: Door call failed %s",
733 		    lmshrd_desc[opcode], strerror(errno));
734 		(void) free(buf);
735 		lmshrd_fildes = -1;
736 		return (NERR_InternalError);
737 	}
738 
739 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
740 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
741 		(void) free(buf);
742 		return (NERR_InternalError);
743 	}
744 
745 	rc = smb_dr_get_uint32(dec_ctx);
746 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
747 		syslog(LOG_ERR, "%s: Decode error %s",
748 		    lmshrd_desc[opcode], strerror(status));
749 		(void) free(buf);
750 		return (NERR_InternalError);
751 	}
752 
753 	(void) free(buf);
754 	return (rc);
755 }
756 
757 static int
758 lmshrd_check(char *share_name, int opcode)
759 {
760 	door_arg_t arg;
761 	char *buf;
762 	unsigned int used;
763 	smb_dr_ctx_t *dec_ctx;
764 	smb_dr_ctx_t *enc_ctx;
765 	int status, rc;
766 
767 	if (lmshrd_door_open(opcode) == -1)
768 		return (NERR_InternalError);
769 
770 	buf = malloc(LMSHR_DOOR_SIZE);
771 	if (!buf)
772 		return (NERR_InternalError);
773 
774 	enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE);
775 	smb_dr_put_uint32(enc_ctx, opcode);
776 	smb_dr_put_string(enc_ctx, share_name);
777 
778 	if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
779 		syslog(LOG_ERR, "%s: Encode error %s",
780 		    lmshrd_desc[opcode], strerror(status));
781 		(void) free(buf);
782 		return (NERR_InternalError);
783 	}
784 
785 	arg.data_ptr = buf;
786 	arg.data_size = used;
787 	arg.desc_ptr = NULL;
788 	arg.desc_num = 0;
789 	arg.rbuf = buf;
790 	arg.rsize = LMSHR_DOOR_SIZE;
791 
792 	if (door_call(lmshrd_fildes, &arg) < 0) {
793 		syslog(LOG_DEBUG, "%s: Door call failed %s",
794 		    lmshrd_desc[opcode], strerror(errno));
795 		(void) free(buf);
796 		lmshrd_fildes = -1;
797 		return (NERR_InternalError);
798 	}
799 
800 	dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
801 	if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) {
802 		(void) free(buf);
803 		return (NERR_InternalError);
804 	}
805 
806 	rc = smb_dr_get_int32(dec_ctx);
807 	if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
808 		syslog(LOG_ERR, "%s: Decode error %s",
809 		    lmshrd_desc[opcode], strerror(status));
810 		(void) free(buf);
811 		return (NERR_InternalError);
812 	}
813 
814 	(void) free(buf);
815 	return (rc);
816 }
817 
818 int
819 lmshrd_exists(char *share_name)
820 {
821 	return (lmshrd_check(share_name, LMSHR_DOOR_EXISTS));
822 }
823 
824 int
825 lmshrd_is_special(char *share_name)
826 {
827 	return (lmshrd_check(share_name, LMSHR_DOOR_IS_SPECIAL));
828 }
829 
830 int
831 lmshrd_is_restricted(char *share_name)
832 {
833 	return (lmshrd_check(share_name, LMSHR_DOOR_IS_RESTRICTED));
834 }
835 
836 int
837 lmshrd_is_admin(char *share_name)
838 {
839 	return (lmshrd_check(share_name, LMSHR_DOOR_IS_ADMIN));
840 }
841 
842 int
843 lmshrd_is_valid(char *share_name)
844 {
845 	return (lmshrd_check(share_name, LMSHR_DOOR_IS_VALID));
846 }
847 
848 int
849 lmshrd_is_dir(char *path)
850 {
851 	return (lmshrd_check(path, LMSHR_DOOR_IS_DIR));
852 }
853 
854 static char *
855 lmshare_decode_type(unsigned int stype)
856 {
857 	switch (stype) {
858 	case STYPE_DISKTREE:
859 		return ("Disk");
860 	case STYPE_PRINTQ:
861 		return ("Print Queue");
862 	case STYPE_DEVICE:
863 		return ("Device");
864 	case STYPE_IPC:
865 		return ("IPC");
866 	case STYPE_DFS:
867 		return ("DFS");
868 	case STYPE_SPECIAL:
869 		return ("Special");
870 	default:
871 		return ("Unknown");
872 	};
873 }
874 
875 
876 static void
877 lmshare_loginfo(FILE *fp, lmshare_info_t *si)
878 {
879 	if (!si) {
880 		return;
881 	}
882 
883 	(void) fprintf(fp, "\n%s Information:\n", si->share_name);
884 	(void) fprintf(fp, "\tFolder: %s\n", si->directory);
885 	(void) fprintf(fp, "\tType: %s\n", lmshare_decode_type(si->stype));
886 	(void) fprintf(fp, "\tComment: %s\n", si->comment);
887 
888 	(void) fprintf(fp, "\tStatus: %s\n",
889 	    ((si->mode & LMSHRM_TRANS) ? "Transient" : "Permanent"));
890 
891 	(void) fprintf(fp, "\tContainer: %s\n", si->container);
892 }
893 
894 int
895 lmshrd_dump_hash(char *logfname)
896 {
897 	lmshare_info_t si;
898 	uint64_t it;
899 	FILE *fp;
900 
901 	if ((logfname == 0) || (*logfname == 0))
902 		fp = stdout;
903 	else {
904 		fp = fopen(logfname, "w");
905 		if (fp == 0) {
906 			syslog(LOG_WARNING, "LmshareDump [%s]:"
907 			    " cannot create logfile", logfname);
908 			syslog(LOG_WARNING, "LmshareDump:"
909 			    " output will be written on screen");
910 		}
911 	}
912 
913 	it = lmshrd_open_iterator(LMSHRM_PERM);
914 	if (it == NULL) {
915 		syslog(LOG_ERR, "LmshareDump: resource shortage");
916 		if (fp && fp != stdout) {
917 			(void) fclose(fp);
918 		}
919 		return (1);
920 	}
921 
922 	if (lmshrd_iterate(it, &si) != NERR_Success) {
923 		syslog(LOG_ERR, "LmshareDump: Iterator iterate failed");
924 		if (fp && fp != stdout) {
925 			(void) fclose(fp);
926 		}
927 		return (1);
928 	}
929 	while (*si.share_name != 0) {
930 		lmshare_loginfo(fp, &si);
931 		if (lmshrd_iterate(it, &si) != NERR_Success) {
932 			syslog(LOG_ERR, "LmshareDump: Iterator iterate failed");
933 			if (fp && fp != stdout) {
934 				(void) fclose(fp);
935 			}
936 			return (1);
937 		}
938 	}
939 
940 	if (lmshrd_close_iterator(it) != NERR_Success) {
941 		syslog(LOG_ERR, "LmshareDump: Iterator close failed");
942 		if (fp && fp != stdout) {
943 			(void) fclose(fp);
944 		}
945 		return (1);
946 	}
947 	if (fp && fp != stdout) {
948 		(void) fclose(fp);
949 	}
950 	return (0);
951 }
952