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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * LanMan share door server 30 */ 31 32 #include <door.h> 33 #include <unistd.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <errno.h> 38 #include <syslog.h> 39 #include <string.h> 40 #include <pthread.h> 41 42 #include <smbsrv/libsmb.h> 43 44 #include <smbsrv/lmshare.h> 45 #include <smbsrv/lmshare_door.h> 46 #include <smbsrv/smbinfo.h> 47 48 static smb_kmod_cfg_t smb_kcfg; 49 50 static int smb_lmshrd_fildes = -1; 51 static pthread_mutex_t smb_lmshrd_srv_mutex = PTHREAD_MUTEX_INITIALIZER; 52 53 /* forward declaration */ 54 static void smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, 55 door_desc_t *dp, uint_t n_desc); 56 static int smb_lmshrd_srv_check(int opcode, char *sharename); 57 58 /* 59 * smb_lmshrd_srv_start 60 * 61 * Start the LanMan share door service. 62 * Returns 0 on success. Otherwise, -1. 63 */ 64 int 65 smb_lmshrd_srv_start(void) 66 { 67 int newfd; 68 69 (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex); 70 71 if (smb_lmshrd_fildes != -1) { 72 syslog(LOG_ERR, "smb_lmshrd_srv_start: duplicate"); 73 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 74 return (smb_lmshrd_fildes); 75 } 76 77 if ((smb_lmshrd_fildes = door_create(smb_lmshrd_srv_door, 78 LMSHR_DOOR_COOKIE, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) { 79 syslog(LOG_ERR, "smb_lmshrd_srv_start: door_create: %s", 80 strerror(errno)); 81 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 82 return (-1); 83 } 84 85 (void) unlink(LMSHR_DOOR_NAME); 86 87 if ((newfd = creat(LMSHR_DOOR_NAME, 0644)) < 0) { 88 syslog(LOG_ERR, "smb_lmshrd_srv_start: open: %s", 89 strerror(errno)); 90 (void) door_revoke(smb_lmshrd_fildes); 91 smb_lmshrd_fildes = -1; 92 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 93 return (-1); 94 } 95 96 (void) close(newfd); 97 (void) fdetach(LMSHR_DOOR_NAME); 98 99 if (fattach(smb_lmshrd_fildes, LMSHR_DOOR_NAME) < 0) { 100 syslog(LOG_ERR, "smb_lmshrd_srv_start: fattach: %s", 101 strerror(errno)); 102 (void) door_revoke(smb_lmshrd_fildes); 103 smb_lmshrd_fildes = -1; 104 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 105 return (-1); 106 } 107 108 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 109 return (smb_lmshrd_fildes); 110 } 111 112 113 /* 114 * smb_lmshrd_srv_stop 115 * 116 * Stop the LanMan share door service. 117 */ 118 void 119 smb_lmshrd_srv_stop(void) 120 { 121 (void) pthread_mutex_lock(&smb_lmshrd_srv_mutex); 122 123 if (smb_lmshrd_fildes != -1) { 124 (void) fdetach(LMSHR_DOOR_NAME); 125 (void) door_revoke(smb_lmshrd_fildes); 126 smb_lmshrd_fildes = -1; 127 } 128 129 (void) pthread_mutex_unlock(&smb_lmshrd_srv_mutex); 130 } 131 132 133 /* 134 * smb_lmshrd_srv_door 135 * 136 * This function with which the LMSHARE door is associated 137 * will invoke the appropriate CIFS share management function 138 * based on the request type of the door call. 139 */ 140 /*ARGSUSED*/ 141 void 142 smb_lmshrd_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, 143 uint_t n_desc) 144 { 145 DWORD rc; 146 int req_type, mode, rc2; 147 char buf[LMSHR_DOOR_SIZE]; 148 unsigned int used; 149 smb_dr_ctx_t *dec_ctx = smb_dr_decode_start(ptr, size); 150 smb_dr_ctx_t *enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); 151 unsigned int dec_status; 152 unsigned int enc_status; 153 char *sharename, *sharename2; 154 lmshare_info_t lmshr_info; 155 lmshare_info_t *lmshr_infop; 156 lmshare_iterator_t *lmshr_iter; 157 int offset; 158 lmshare_list_t lmshr_list; 159 160 req_type = smb_dr_get_uint32(dec_ctx); 161 162 switch (req_type) { 163 case LMSHR_DOOR_OPEN_ITERATOR: 164 mode = smb_dr_get_int32(dec_ctx); 165 166 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 167 goto decode_error; 168 169 lmshr_iter = lmshare_open_iterator(mode); 170 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 171 smb_dr_put_lmshr_iterator(enc_ctx, 172 (uint64_t)(uintptr_t)lmshr_iter); 173 174 break; 175 176 case LMSHR_DOOR_CLOSE_ITERATOR: 177 lmshr_iter = (lmshare_iterator_t *)(uintptr_t) 178 smb_dr_get_lmshr_iterator(dec_ctx); 179 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 180 goto decode_error; 181 182 lmshare_close_iterator(lmshr_iter); 183 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 184 break; 185 186 case LMSHR_DOOR_ITERATE: 187 lmshr_iter = (lmshare_iterator_t *)(uintptr_t) 188 smb_dr_get_lmshr_iterator(dec_ctx); 189 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 190 goto decode_error; 191 192 lmshr_infop = lmshare_iterate(lmshr_iter); 193 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 194 smb_dr_put_lmshare(enc_ctx, lmshr_infop); 195 break; 196 197 case LMSHR_DOOR_NUM_SHARES: 198 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 199 goto decode_error; 200 201 rc = lmshare_num_shares(); 202 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 203 smb_dr_put_uint32(enc_ctx, rc); 204 break; 205 206 case LMSHR_DOOR_DELETE: 207 sharename = smb_dr_get_string(dec_ctx); 208 209 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { 210 smb_dr_free_string(sharename); 211 goto decode_error; 212 } 213 214 rc = lmshare_delete(sharename, 0); 215 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 216 smb_dr_put_uint32(enc_ctx, rc); 217 smb_dr_free_string(sharename); 218 break; 219 220 case LMSHR_DOOR_RENAME: 221 sharename = smb_dr_get_string(dec_ctx); 222 sharename2 = smb_dr_get_string(dec_ctx); 223 224 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { 225 smb_dr_free_string(sharename); 226 smb_dr_free_string(sharename2); 227 goto decode_error; 228 } 229 230 rc = lmshare_rename(sharename, sharename2, 0); 231 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 232 smb_dr_put_uint32(enc_ctx, rc); 233 smb_dr_free_string(sharename); 234 smb_dr_free_string(sharename2); 235 break; 236 237 case LMSHR_DOOR_GETINFO: 238 sharename = smb_dr_get_string(dec_ctx); 239 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { 240 smb_dr_free_string(sharename); 241 goto decode_error; 242 } 243 244 rc = lmshare_getinfo(sharename, &lmshr_info); 245 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 246 smb_dr_put_uint32(enc_ctx, rc); 247 smb_dr_put_lmshare(enc_ctx, &lmshr_info); 248 smb_dr_free_string(sharename); 249 break; 250 251 case LMSHR_DOOR_ADD: 252 smb_dr_get_lmshare(dec_ctx, &lmshr_info); 253 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 254 goto decode_error; 255 256 rc = lmshare_add(&lmshr_info, 0); 257 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 258 smb_dr_put_uint32(enc_ctx, rc); 259 smb_dr_put_lmshare(enc_ctx, &lmshr_info); 260 break; 261 262 case LMSHR_DOOR_SETINFO: 263 smb_dr_get_lmshare(dec_ctx, &lmshr_info); 264 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 265 goto decode_error; 266 267 rc = lmshare_setinfo(&lmshr_info, 0); 268 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 269 smb_dr_put_uint32(enc_ctx, rc); 270 break; 271 272 case LMSHR_DOOR_EXISTS: 273 case LMSHR_DOOR_IS_SPECIAL: 274 case LMSHR_DOOR_IS_RESTRICTED: 275 case LMSHR_DOOR_IS_ADMIN: 276 case LMSHR_DOOR_IS_VALID: 277 case LMSHR_DOOR_IS_DIR: 278 sharename = smb_dr_get_string(dec_ctx); 279 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { 280 smb_dr_free_string(sharename); 281 goto decode_error; 282 } 283 284 rc2 = smb_lmshrd_srv_check(req_type, sharename); 285 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 286 smb_dr_put_uint32(enc_ctx, rc2); 287 smb_dr_free_string(sharename); 288 break; 289 290 case LMSHR_DOOR_LIST: 291 offset = smb_dr_get_int32(dec_ctx); 292 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 293 goto decode_error; 294 295 rc = lmshare_list(offset, &lmshr_list); 296 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 297 smb_dr_put_uint32(enc_ctx, rc); 298 smb_dr_put_lmshr_list(enc_ctx, &lmshr_list); 299 break; 300 301 case SMB_GET_KCONFIG: 302 if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) 303 goto decode_error; 304 305 smb_load_kconfig(&smb_kcfg); 306 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_SUCCESS); 307 smb_dr_put_kconfig(enc_ctx, &smb_kcfg); 308 break; 309 310 default: 311 dec_status = smb_dr_decode_finish(dec_ctx); 312 goto decode_error; 313 } 314 315 if ((enc_status = smb_dr_encode_finish(enc_ctx, &used)) != 0) 316 goto encode_error; 317 318 (void) door_return(buf, used, NULL, 0); 319 320 return; 321 322 decode_error: 323 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR); 324 smb_dr_put_uint32(enc_ctx, dec_status); 325 (void) smb_dr_encode_finish(enc_ctx, &used); 326 (void) door_return(buf, used, NULL, 0); 327 return; 328 329 encode_error: 330 enc_ctx = smb_dr_encode_start(buf, sizeof (buf)); 331 smb_dr_put_int32(enc_ctx, LMSHR_DOOR_SRV_ERROR); 332 smb_dr_put_uint32(enc_ctx, enc_status); 333 (void) smb_dr_encode_finish(enc_ctx, &used); 334 (void) door_return(buf, used, NULL, 0); 335 } 336 337 /* 338 * smb_lmshrd_srv_check 339 * 340 * Depending upon the opcode, this function will 341 * either check the existence of a share/dir or 342 * the the type of the specified share. 343 */ 344 static int 345 smb_lmshrd_srv_check(int opcode, char *sharename) 346 { 347 int rc; 348 349 switch (opcode) { 350 case LMSHR_DOOR_EXISTS: 351 rc = lmshare_exists(sharename); 352 break; 353 354 case LMSHR_DOOR_IS_SPECIAL: 355 rc = lmshare_is_special(sharename); 356 break; 357 358 case LMSHR_DOOR_IS_RESTRICTED: 359 rc = lmshare_is_restricted(sharename); 360 break; 361 362 case LMSHR_DOOR_IS_ADMIN: 363 rc = lmshare_is_admin(sharename); 364 break; 365 366 case LMSHR_DOOR_IS_VALID: 367 rc = lmshare_is_valid(sharename); 368 break; 369 370 case LMSHR_DOOR_IS_DIR: 371 rc = lmshare_is_dir(sharename); 372 } 373 374 return (rc); 375 } 376