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 #include <sys/errno.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <strings.h>
30 #include <string.h>
31 #include <rpc/xdr.h>
32 #include <synch.h>
33 #include <pthread.h>
34 #include <smbsrv/smb_door_svc.h>
35 #include <smbsrv/smb_common_door.h>
36 #include <smbsrv/libsmb.h>
37 #include <smbsrv/libmlsvc.h>
38 #include <mlsvc.h>
39 
40 static void *mlsvc_keepalive(void *);
41 
42 static pthread_t mlsvc_keepalive_thr;
43 #define	MLSVC_KEEPALIVE_INTERVAL	(10 * 60)	/* 10 minutes */
44 
45 /*
46  * Door fd for downcalls to the smbsrv kernel door service.
47  * smbsrv will make an upcall to smbd during initialization to
48  * provide this file descriptor.
49  */
50 static int mlsvc_door_fd = -1;
51 static mutex_t mlsvc_fd_mutex;
52 
53 /*
54  * All NDR RPC service initialization is invoked from here.
55  * Returns 0 upon success.  Otherwise, returns -1.
56  */
57 int
58 mlsvc_init(void)
59 {
60 	pthread_attr_t tattr;
61 	int rc;
62 
63 	if ((rc = smb_dclocator_init()) != 0)
64 		return (rc);
65 
66 	srvsvc_initialize();
67 	wkssvc_initialize();
68 	lsarpc_initialize();
69 	netr_initialize();
70 	dssetup_initialize();
71 	samr_initialize();
72 	svcctl_initialize();
73 	winreg_initialize();
74 	logr_initialize();
75 	msgsvcsend_initialize();
76 	spoolss_initialize();
77 
78 	(void) pthread_attr_init(&tattr);
79 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
80 	rc = pthread_create(&mlsvc_keepalive_thr, &tattr,
81 	    mlsvc_keepalive, 0);
82 	(void) pthread_attr_destroy(&tattr);
83 	return (rc);
84 }
85 
86 /*ARGSUSED*/
87 static void *
88 mlsvc_keepalive(void *arg)
89 {
90 	unsigned long t;
91 
92 	for (;;) {
93 		(void) sleep(MLSVC_KEEPALIVE_INTERVAL);
94 
95 		if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN)
96 			(void) srvsvc_gettime(&t);
97 	}
98 
99 	/*NOTREACHED*/
100 	return (NULL);
101 }
102 
103 void
104 mlsvc_set_door_fd(int fd)
105 {
106 	(void) mutex_lock(&mlsvc_fd_mutex);
107 	mlsvc_door_fd = fd;
108 	(void) mutex_unlock(&mlsvc_fd_mutex);
109 }
110 
111 int
112 mlsvc_get_door_fd(void)
113 {
114 	int fd;
115 
116 	(void) mutex_lock(&mlsvc_fd_mutex);
117 	fd = mlsvc_door_fd;
118 	(void) mutex_unlock(&mlsvc_fd_mutex);
119 
120 	return (fd);
121 }
122 
123 uint64_t
124 mlsvc_get_num_users(void)
125 {
126 	door_arg_t arg;
127 	char *buf;
128 	size_t len;
129 	int64_t n_users = 0;
130 	int fd;
131 
132 	if ((fd = mlsvc_get_door_fd()) < 0)
133 		return (0);
134 
135 	if ((buf = smb_dr_set_opcode(SMB_KDR_USER_NUM, &len)) == NULL)
136 		return (0);
137 
138 	smb_dr_clnt_setup(&arg, buf, len);
139 
140 	if (smb_dr_clnt_call(fd, &arg) == 0) {
141 		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
142 		len = arg.rsize - SMB_DR_DATA_OFFSET;
143 
144 		if (smb_dr_decode_common(buf, len, xdr_uint32_t, &n_users) != 0)
145 			n_users = 0;
146 	}
147 
148 	smb_dr_clnt_cleanup(&arg);
149 	return (n_users);
150 }
151 
152 /*
153  * The calling function must free the output parameter 'users'.
154  */
155 int
156 mlsvc_get_user_list(int offset, smb_dr_ulist_t *users)
157 {
158 	door_arg_t arg;
159 	char *buf;
160 	size_t len;
161 	uint_t opcode = SMB_KDR_USER_LIST;
162 	int fd, rc = -1;
163 
164 	bzero(users, sizeof (smb_dr_ulist_t));
165 
166 	if ((fd = mlsvc_get_door_fd()) < 0)
167 		return (-1);
168 
169 	buf = smb_dr_encode_common(opcode, &offset, xdr_uint32_t, &len);
170 	if (buf == NULL)
171 		return (-1);
172 
173 	smb_dr_clnt_setup(&arg, buf, len);
174 
175 	if (smb_dr_clnt_call(fd, &arg) == 0) {
176 		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
177 		len = arg.rsize - SMB_DR_DATA_OFFSET;
178 
179 		rc = smb_dr_decode_common(buf, len, xdr_smb_dr_ulist_t, users);
180 		if (rc == 0)
181 			rc = users->dul_cnt;
182 	}
183 
184 	smb_dr_clnt_cleanup(&arg);
185 	return (rc);
186 }
187 
188 /*
189  * Downcall to the kernel that is executed upon share enable and disable.
190  */
191 int
192 mlsvc_set_share(int shrop, char *path, char *sharename)
193 {
194 	door_arg_t arg;
195 	char *buf;
196 	size_t len;
197 	smb_dr_kshare_t kshare;
198 	int fd, rc = 0;
199 
200 	if ((shrop != SMB_SHROP_ADD) && (shrop != SMB_SHROP_DELETE))
201 		return (EINVAL);
202 
203 	if ((fd = mlsvc_get_door_fd()) < 0)
204 		return (EBADF);
205 
206 	kshare.k_op = shrop;
207 	kshare.k_path = strdup(path);
208 	kshare.k_sharename = strdup(sharename);
209 
210 	buf = smb_dr_encode_kshare(&kshare, &len);
211 	free(kshare.k_path);
212 	free(kshare.k_sharename);
213 
214 	if (buf == NULL)
215 		return (ENOMEM);
216 
217 	smb_dr_clnt_setup(&arg, buf, len);
218 
219 	if (smb_dr_clnt_call(fd, &arg) == 0) {
220 		buf = arg.rbuf + SMB_DR_DATA_OFFSET;
221 		len = arg.rsize - SMB_DR_DATA_OFFSET;
222 
223 		if (smb_dr_decode_common(buf, len, xdr_int32_t, &rc) != 0)
224 			rc = ENOMEM;
225 	}
226 
227 	smb_dr_clnt_cleanup(&arg);
228 	return (rc);
229 }
230