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