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