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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * User-space door client for LanMan share management. 31 */ 32 33 #include <syslog.h> 34 #include <door.h> 35 #include <fcntl.h> 36 #include <stdarg.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <strings.h> 40 #include <unistd.h> 41 #include <thread.h> 42 #include <synch.h> 43 44 #include <smbsrv/libsmb.h> 45 #include <smbsrv/lmshare.h> 46 #include <smbsrv/lmerr.h> 47 #include <smbsrv/lmshare_door.h> 48 #include <smbsrv/cifs.h> 49 50 static int lmshrd_fildes = -1; 51 static uint64_t lmshrd_door_ncall = 0; 52 static mutex_t lmshrd_mutex; 53 static cond_t lmshrd_cv; 54 55 char *lmshrd_desc[] = { 56 "", 57 "LmshrdNumShares", 58 "LmshrdDelete", 59 "LmshrdRename", 60 "LmshrdGetinfo", 61 "LmshrdAdd", 62 "LmshrdSetinfo", 63 "LmshrdExists", 64 "LmshrdIsSpecial", 65 "LmshrdIsRestricted", 66 "LmshrdIsAdmin", 67 "LmshrdIsValid", 68 "LmshrdIsDir", 69 "LmshrdList", 70 "LmshrdNumTrans", 71 "N/A", 72 0 73 }; 74 75 /* 76 * Open the lmshrd door. This is a private call for use by 77 * lmshrd_door_enter() and must be called with lmshrd_mutex held. 78 * 79 * Returns the door fd on success. Otherwise, -1. 80 */ 81 static int 82 lmshrd_door_open(void) 83 { 84 if (lmshrd_fildes == -1) { 85 if ((lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) 86 lmshrd_fildes = -1; 87 else 88 lmshrd_door_ncall = 0; 89 } 90 91 return (lmshrd_fildes); 92 } 93 94 /* 95 * Close the lmshrd door. 96 */ 97 void 98 lmshrd_door_close(void) 99 { 100 (void) mutex_lock(&lmshrd_mutex); 101 102 if (lmshrd_fildes != -1) { 103 while (lmshrd_door_ncall > 0) 104 (void) cond_wait(&lmshrd_cv, &lmshrd_mutex); 105 106 if (lmshrd_fildes != -1) { 107 (void) close(lmshrd_fildes); 108 lmshrd_fildes = -1; 109 } 110 } 111 112 (void) mutex_unlock(&lmshrd_mutex); 113 } 114 115 /* 116 * Entry handler for lmshrd door calls. 117 */ 118 static door_arg_t * 119 lmshrd_door_enter(void) 120 { 121 door_arg_t *arg; 122 char *buf; 123 124 (void) mutex_lock(&lmshrd_mutex); 125 126 if (lmshrd_door_open() == -1) { 127 (void) mutex_unlock(&lmshrd_mutex); 128 return (NULL); 129 } 130 131 if ((arg = malloc(sizeof (door_arg_t) + LMSHR_DOOR_SIZE)) != NULL) { 132 buf = ((char *)arg) + sizeof (door_arg_t); 133 bzero(arg, sizeof (door_arg_t)); 134 arg->data_ptr = buf; 135 arg->rbuf = buf; 136 arg->rsize = LMSHR_DOOR_SIZE; 137 138 ++lmshrd_door_ncall; 139 } 140 141 (void) mutex_unlock(&lmshrd_mutex); 142 return (arg); 143 } 144 145 /* 146 * Exit handler for lmshrd door calls. 147 */ 148 static void 149 lmshrd_door_exit(door_arg_t *arg, char *errmsg) 150 { 151 if (errmsg) 152 syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg); 153 154 (void) mutex_lock(&lmshrd_mutex); 155 free(arg); 156 --lmshrd_door_ncall; 157 (void) cond_signal(&lmshrd_cv); 158 (void) mutex_unlock(&lmshrd_mutex); 159 } 160 161 /* 162 * Return 0 upon success. Otherwise, -1. 163 */ 164 static int 165 lmshrd_door_check_status(smb_dr_ctx_t *dec_ctx) 166 { 167 int status = smb_dr_get_int32(dec_ctx); 168 169 if (status != LMSHR_DOOR_SRV_SUCCESS) { 170 if (status == LMSHR_DOOR_SRV_ERROR) 171 (void) smb_dr_get_uint32(dec_ctx); 172 return (-1); 173 } 174 175 return (0); 176 } 177 178 DWORD 179 lmshrd_list(int offset, lmshare_list_t *list) 180 { 181 door_arg_t *arg; 182 smb_dr_ctx_t *dec_ctx; 183 smb_dr_ctx_t *enc_ctx; 184 DWORD rc; 185 186 if ((arg = lmshrd_door_enter()) == NULL) 187 return (NERR_InternalError); 188 189 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 190 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_LIST); 191 smb_dr_put_int32(enc_ctx, offset); 192 193 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 194 if (rc != 0) { 195 lmshrd_door_exit(arg, "encode error"); 196 return (NERR_InternalError); 197 } 198 199 if (door_call(lmshrd_fildes, arg) < 0) { 200 lmshrd_door_exit(arg, "door call error"); 201 lmshrd_door_close(); 202 return (NERR_InternalError); 203 } 204 205 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 206 if (lmshrd_door_check_status(dec_ctx) != 0) { 207 (void) smb_dr_decode_finish(dec_ctx); 208 lmshrd_door_exit(arg, "decode error"); 209 return (NERR_InternalError); 210 } 211 212 smb_dr_get_lmshr_list(dec_ctx, list); 213 if (smb_dr_decode_finish(dec_ctx) != 0) { 214 lmshrd_door_exit(arg, "decode error"); 215 return (NERR_InternalError); 216 } 217 218 lmshrd_door_exit(arg, NULL); 219 return (NERR_Success); 220 } 221 222 int 223 lmshrd_num_shares(void) 224 { 225 door_arg_t *arg; 226 smb_dr_ctx_t *dec_ctx; 227 smb_dr_ctx_t *enc_ctx; 228 DWORD num_shares; 229 int rc; 230 231 if ((arg = lmshrd_door_enter()) == NULL) 232 return (-1); 233 234 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 235 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_NUM_SHARES); 236 237 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 238 if (rc != 0) { 239 lmshrd_door_exit(arg, "encode error"); 240 return (-1); 241 } 242 243 if (door_call(lmshrd_fildes, arg) < 0) { 244 lmshrd_door_exit(arg, "door call error"); 245 lmshrd_door_close(); 246 return (-1); 247 } 248 249 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 250 if (lmshrd_door_check_status(dec_ctx) != 0) { 251 (void) smb_dr_decode_finish(dec_ctx); 252 lmshrd_door_exit(arg, "decode error"); 253 return (-1); 254 } 255 256 num_shares = smb_dr_get_uint32(dec_ctx); 257 if (smb_dr_decode_finish(dec_ctx) != 0) { 258 lmshrd_door_exit(arg, "decode error"); 259 return (-1); 260 } 261 262 lmshrd_door_exit(arg, NULL); 263 return (num_shares); 264 } 265 266 DWORD 267 lmshrd_delete(char *share_name) 268 { 269 door_arg_t *arg; 270 smb_dr_ctx_t *dec_ctx; 271 smb_dr_ctx_t *enc_ctx; 272 DWORD rc; 273 274 if ((arg = lmshrd_door_enter()) == NULL) 275 return (NERR_InternalError); 276 277 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 278 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_DELETE); 279 smb_dr_put_string(enc_ctx, share_name); 280 281 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 282 if (rc != 0) { 283 lmshrd_door_exit(arg, "encode error"); 284 return (NERR_InternalError); 285 } 286 287 if (door_call(lmshrd_fildes, arg) < 0) { 288 lmshrd_door_exit(arg, "door call error"); 289 lmshrd_door_close(); 290 return (NERR_InternalError); 291 } 292 293 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 294 if (lmshrd_door_check_status(dec_ctx) != 0) { 295 (void) smb_dr_decode_finish(dec_ctx); 296 lmshrd_door_exit(arg, "decode error"); 297 return (NERR_InternalError); 298 } 299 300 rc = smb_dr_get_uint32(dec_ctx); 301 if (smb_dr_decode_finish(dec_ctx) != 0) { 302 lmshrd_door_exit(arg, "decode error"); 303 return (NERR_InternalError); 304 } 305 306 lmshrd_door_exit(arg, NULL); 307 return (rc); 308 309 } 310 311 DWORD 312 lmshrd_rename(char *from, char *to) 313 { 314 door_arg_t *arg; 315 smb_dr_ctx_t *dec_ctx; 316 smb_dr_ctx_t *enc_ctx; 317 DWORD rc; 318 319 if ((arg = lmshrd_door_enter()) == NULL) 320 return (NERR_InternalError); 321 322 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 323 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_RENAME); 324 smb_dr_put_string(enc_ctx, from); 325 smb_dr_put_string(enc_ctx, to); 326 327 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 328 if (rc != 0) { 329 lmshrd_door_exit(arg, "encode error"); 330 return (NERR_InternalError); 331 } 332 333 if (door_call(lmshrd_fildes, arg) < 0) { 334 lmshrd_door_exit(arg, "door call error"); 335 lmshrd_door_close(); 336 return (NERR_InternalError); 337 } 338 339 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 340 if (lmshrd_door_check_status(dec_ctx) != 0) { 341 (void) smb_dr_decode_finish(dec_ctx); 342 lmshrd_door_exit(arg, "decode error"); 343 return (NERR_InternalError); 344 } 345 346 rc = smb_dr_get_uint32(dec_ctx); 347 if (smb_dr_decode_finish(dec_ctx) != 0) { 348 lmshrd_door_exit(arg, "decode error"); 349 return (NERR_InternalError); 350 } 351 352 lmshrd_door_exit(arg, NULL); 353 return (rc); 354 } 355 356 DWORD 357 lmshrd_getinfo(char *share_name, lmshare_info_t *si) 358 { 359 door_arg_t *arg; 360 smb_dr_ctx_t *dec_ctx; 361 smb_dr_ctx_t *enc_ctx; 362 DWORD rc; 363 364 if ((arg = lmshrd_door_enter()) == NULL) 365 return (NERR_InternalError); 366 367 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 368 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_GETINFO); 369 smb_dr_put_string(enc_ctx, share_name); 370 371 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 372 if (rc != 0) { 373 lmshrd_door_exit(arg, "encode error"); 374 return (NERR_InternalError); 375 } 376 377 if (door_call(lmshrd_fildes, arg) < 0) { 378 lmshrd_door_exit(arg, "door call error"); 379 lmshrd_door_close(); 380 return (NERR_InternalError); 381 } 382 383 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 384 if (lmshrd_door_check_status(dec_ctx) != 0) { 385 (void) smb_dr_decode_finish(dec_ctx); 386 lmshrd_door_exit(arg, "decode error"); 387 return (NERR_InternalError); 388 } 389 390 rc = smb_dr_get_uint32(dec_ctx); 391 smb_dr_get_lmshare(dec_ctx, si); 392 if (smb_dr_decode_finish(dec_ctx) != 0) { 393 lmshrd_door_exit(arg, "decode error"); 394 return (NERR_InternalError); 395 } 396 397 lmshrd_door_exit(arg, NULL); 398 return (rc); 399 } 400 401 DWORD 402 lmshrd_add(lmshare_info_t *si) 403 { 404 door_arg_t *arg; 405 smb_dr_ctx_t *dec_ctx; 406 smb_dr_ctx_t *enc_ctx; 407 DWORD rc; 408 409 if ((arg = lmshrd_door_enter()) == NULL) 410 return (NERR_InternalError); 411 412 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 413 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ADD); 414 smb_dr_put_lmshare(enc_ctx, si); 415 416 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 417 if (rc != 0) { 418 lmshrd_door_exit(arg, "encode error"); 419 return (NERR_InternalError); 420 } 421 422 if (door_call(lmshrd_fildes, arg) < 0) { 423 lmshrd_door_exit(arg, "door call error"); 424 lmshrd_door_close(); 425 return (NERR_InternalError); 426 } 427 428 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 429 if (lmshrd_door_check_status(dec_ctx) != 0) { 430 (void) smb_dr_decode_finish(dec_ctx); 431 lmshrd_door_exit(arg, "decode error"); 432 return (NERR_InternalError); 433 } 434 435 rc = smb_dr_get_uint32(dec_ctx); 436 smb_dr_get_lmshare(dec_ctx, si); 437 if (smb_dr_decode_finish(dec_ctx) != 0) { 438 lmshrd_door_exit(arg, "decode error"); 439 return (NERR_InternalError); 440 } 441 442 lmshrd_door_exit(arg, NULL); 443 return (rc); 444 } 445 446 DWORD 447 lmshrd_setinfo(lmshare_info_t *si) 448 { 449 door_arg_t *arg; 450 smb_dr_ctx_t *dec_ctx; 451 smb_dr_ctx_t *enc_ctx; 452 DWORD rc; 453 454 if ((arg = lmshrd_door_enter()) == NULL) 455 return (NERR_InternalError); 456 457 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 458 smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_SETINFO); 459 smb_dr_put_lmshare(enc_ctx, si); 460 461 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 462 if (rc != 0) { 463 lmshrd_door_exit(arg, "encode error"); 464 return (NERR_InternalError); 465 } 466 467 if (door_call(lmshrd_fildes, arg) < 0) { 468 lmshrd_door_exit(arg, "door call error"); 469 lmshrd_door_close(); 470 return (NERR_InternalError); 471 } 472 473 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 474 if (lmshrd_door_check_status(dec_ctx) != 0) { 475 (void) smb_dr_decode_finish(dec_ctx); 476 lmshrd_door_exit(arg, "decode error"); 477 return (NERR_InternalError); 478 } 479 480 rc = smb_dr_get_uint32(dec_ctx); 481 if (smb_dr_decode_finish(dec_ctx) != 0) { 482 lmshrd_door_exit(arg, "decode error"); 483 return (NERR_InternalError); 484 } 485 486 lmshrd_door_exit(arg, NULL); 487 return (rc); 488 } 489 490 static int 491 lmshrd_check(char *share_name, int opcode) 492 { 493 door_arg_t *arg; 494 smb_dr_ctx_t *dec_ctx; 495 smb_dr_ctx_t *enc_ctx; 496 int rc; 497 498 if ((arg = lmshrd_door_enter()) == NULL) 499 return (NERR_InternalError); 500 501 enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); 502 smb_dr_put_uint32(enc_ctx, opcode); 503 smb_dr_put_string(enc_ctx, share_name); 504 505 rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); 506 if (rc != 0) { 507 lmshrd_door_exit(arg, "encode error"); 508 return (NERR_InternalError); 509 } 510 511 if (door_call(lmshrd_fildes, arg) < 0) { 512 lmshrd_door_exit(arg, "door call error"); 513 lmshrd_door_close(); 514 return (NERR_InternalError); 515 } 516 517 dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); 518 if (lmshrd_door_check_status(dec_ctx) != 0) { 519 (void) smb_dr_decode_finish(dec_ctx); 520 lmshrd_door_exit(arg, "decode error"); 521 return (NERR_InternalError); 522 } 523 524 rc = smb_dr_get_int32(dec_ctx); 525 if (smb_dr_decode_finish(dec_ctx) != 0) { 526 lmshrd_door_exit(arg, "decode error"); 527 return (NERR_InternalError); 528 } 529 530 lmshrd_door_exit(arg, NULL); 531 return (rc); 532 } 533 534 int 535 lmshrd_exists(char *share_name) 536 { 537 return (lmshrd_check(share_name, LMSHR_DOOR_EXISTS)); 538 } 539 540 int 541 lmshrd_is_special(char *share_name) 542 { 543 return (lmshrd_check(share_name, LMSHR_DOOR_IS_SPECIAL)); 544 } 545 546 int 547 lmshrd_is_restricted(char *share_name) 548 { 549 return (lmshrd_check(share_name, LMSHR_DOOR_IS_RESTRICTED)); 550 } 551 552 int 553 lmshrd_is_admin(char *share_name) 554 { 555 return (lmshrd_check(share_name, LMSHR_DOOR_IS_ADMIN)); 556 } 557 558 int 559 lmshrd_is_valid(char *share_name) 560 { 561 return (lmshrd_check(share_name, LMSHR_DOOR_IS_VALID)); 562 } 563 564 int 565 lmshrd_is_dir(char *path) 566 { 567 return (lmshrd_check(path, LMSHR_DOOR_IS_DIR)); 568 } 569