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 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 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 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