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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * LanMan share door server
27 */
28
29 #include <door.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <syslog.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <pthread.h>
39 #include <smbsrv/libsmb.h>
40 #include <smbsrv/smb_share.h>
41 #include <smbsrv/smbinfo.h>
42 #include "smbd.h"
43
44 #define SMB_SHARE_DSRV_VERSION 1
45 #define SMB_SHARE_DSRV_COOKIE ((void*)(0xdeadbeef^SMB_SHARE_DSRV_VERSION))
46
47 static int smb_share_dsrv_fd = -1;
48 static pthread_mutex_t smb_share_dsrv_mtx = PTHREAD_MUTEX_INITIALIZER;
49 static smbd_door_t smb_share_sdh;
50
51 static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
52
53 /*
54 * Start the LanMan share door service.
55 * Returns 0 on success. Otherwise, -1.
56 */
57 int
smbd_share_start(void)58 smbd_share_start(void)
59 {
60 int newfd;
61
62 (void) pthread_mutex_lock(&smb_share_dsrv_mtx);
63
64 if (smb_share_dsrv_fd != -1) {
65 syslog(LOG_ERR, "smbd_share_start: duplicate");
66 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
67 return (smb_share_dsrv_fd);
68 }
69
70 smbd_door_init(&smb_share_sdh, "share");
71
72 if ((smb_share_dsrv_fd = door_create(smbd_share_dispatch,
73 SMB_SHARE_DSRV_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
74 syslog(LOG_ERR, "smbd_share_start: door_create: %s",
75 strerror(errno));
76 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
77 return (-1);
78 }
79
80 (void) unlink(SMB_SHARE_DNAME);
81
82 if ((newfd = creat(SMB_SHARE_DNAME, 0644)) < 0) {
83 syslog(LOG_ERR, "smbd_share_start: open: %s",
84 strerror(errno));
85 (void) door_revoke(smb_share_dsrv_fd);
86 smb_share_dsrv_fd = -1;
87 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
88 return (-1);
89 }
90
91 (void) close(newfd);
92 (void) fdetach(SMB_SHARE_DNAME);
93
94 if (fattach(smb_share_dsrv_fd, SMB_SHARE_DNAME) < 0) {
95 syslog(LOG_ERR, "smbd_share_start: fattach: %s",
96 strerror(errno));
97 (void) door_revoke(smb_share_dsrv_fd);
98 smb_share_dsrv_fd = -1;
99 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
100 return (-1);
101 }
102
103 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
104 return (smb_share_dsrv_fd);
105 }
106
107 /*
108 * Stop the LanMan share door service.
109 */
110 void
smbd_share_stop(void)111 smbd_share_stop(void)
112 {
113 (void) pthread_mutex_lock(&smb_share_dsrv_mtx);
114
115 smbd_door_fini(&smb_share_sdh);
116
117 if (smb_share_dsrv_fd != -1) {
118 (void) fdetach(SMB_SHARE_DNAME);
119 (void) door_revoke(smb_share_dsrv_fd);
120 smb_share_dsrv_fd = -1;
121 }
122
123 (void) pthread_mutex_unlock(&smb_share_dsrv_mtx);
124 }
125
126 /*
127 * This function with which the LMSHARE door is associated
128 * will invoke the appropriate CIFS share management function
129 * based on the request type of the door call.
130 */
131 /*ARGSUSED*/
132 static void
smbd_share_dispatch(void * cookie,char * ptr,size_t size,door_desc_t * dp,uint_t n_desc)133 smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp,
134 uint_t n_desc)
135 {
136 uint32_t rc;
137 int req_type;
138 char buf[SMB_SHARE_DSIZE];
139 unsigned int used;
140 smb_dr_ctx_t *dec_ctx;
141 smb_dr_ctx_t *enc_ctx;
142 unsigned int dec_status;
143 unsigned int enc_status;
144 char *sharename, *sharename2;
145 smb_share_t lmshr_info;
146 smb_shrlist_t lmshr_list;
147 int offset;
148
149 smbd_door_enter(&smb_share_sdh);
150
151 if ((cookie != SMB_SHARE_DSRV_COOKIE) || (ptr == NULL) ||
152 (size < sizeof (uint32_t))) {
153 smbd_door_return(&smb_share_sdh, NULL, 0, NULL, 0);
154 }
155
156 dec_ctx = smb_dr_decode_start(ptr, size);
157 enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
158 req_type = smb_dr_get_uint32(dec_ctx);
159
160 switch (req_type) {
161 case SMB_SHROP_NUM_SHARES:
162 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
163 goto decode_error;
164
165 rc = smb_shr_count();
166 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
167 smb_dr_put_uint32(enc_ctx, rc);
168 break;
169
170 case SMB_SHROP_DELETE:
171 sharename = smb_dr_get_string(dec_ctx);
172
173 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
174 smb_dr_free_string(sharename);
175 goto decode_error;
176 }
177
178 rc = smb_shr_remove(sharename);
179 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
180 smb_dr_put_uint32(enc_ctx, rc);
181 smb_dr_free_string(sharename);
182 break;
183
184 case SMB_SHROP_RENAME:
185 sharename = smb_dr_get_string(dec_ctx);
186 sharename2 = smb_dr_get_string(dec_ctx);
187
188 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
189 smb_dr_free_string(sharename);
190 smb_dr_free_string(sharename2);
191 goto decode_error;
192 }
193
194 rc = smb_shr_rename(sharename, sharename2);
195 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
196 smb_dr_put_uint32(enc_ctx, rc);
197 smb_dr_free_string(sharename);
198 smb_dr_free_string(sharename2);
199 break;
200
201 case SMB_SHROP_ADD:
202 smb_dr_get_share(dec_ctx, &lmshr_info);
203 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
204 goto decode_error;
205
206 rc = smb_shr_add(&lmshr_info);
207 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
208 smb_dr_put_uint32(enc_ctx, rc);
209 smb_dr_put_share(enc_ctx, &lmshr_info);
210 break;
211
212 case SMB_SHROP_MODIFY:
213 smb_dr_get_share(dec_ctx, &lmshr_info);
214 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
215 goto decode_error;
216 }
217
218 rc = smb_shr_modify(&lmshr_info);
219 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
220 smb_dr_put_uint32(enc_ctx, rc);
221
222 break;
223
224 case SMB_SHROP_LIST:
225 offset = smb_dr_get_int32(dec_ctx);
226 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0)
227 goto decode_error;
228
229 smb_shr_list(offset, &lmshr_list);
230 smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
231 smb_dr_put_buf(enc_ctx, (unsigned char *)&lmshr_list,
232 sizeof (smb_shrlist_t));
233 break;
234
235 default:
236 dec_status = smb_dr_decode_finish(dec_ctx);
237 goto decode_error;
238 }
239
240 if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
241 enc_ctx = smb_dr_encode_start(buf, sizeof (buf));
242 smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
243 smb_dr_put_uint32(enc_ctx, enc_status);
244 (void) smb_dr_encode_finish(enc_ctx, &used);
245 }
246
247 smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
248 return;
249
250 decode_error:
251 smb_dr_put_int32(enc_ctx, SMB_SHARE_DERROR);
252 smb_dr_put_uint32(enc_ctx, dec_status);
253 (void) smb_dr_encode_finish(enc_ctx, &used);
254 smbd_door_return(&smb_share_sdh, buf, used, NULL, 0);
255 }
256