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 "@(#)smb_opipe.c 1.10 08/08/08 SMI" 27 28 /* 29 * This module provides the interface to NDR RPC. 30 */ 31 32 #include <sys/stat.h> 33 #include <sys/door.h> 34 #include <sys/door_data.h> 35 #include <sys/uio.h> 36 #include <sys/ksynch.h> 37 #include <smbsrv/smb_incl.h> 38 #include <smbsrv/smb_xdr.h> 39 40 #define SMB_OPIPE_ISOPEN(OPIPE) \ 41 (((OPIPE)->p_hdr.oh_magic == SMB_OPIPE_HDR_MAGIC) && \ 42 ((OPIPE)->p_hdr.oh_fid)) 43 44 extern volatile uint32_t smb_fids; 45 46 static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *); 47 static char *smb_opipe_lookup(const char *path); 48 static uint32_t smb_opipe_fid(void); 49 static int smb_opipe_set_hdr(smb_opipe_t *opipe, uint32_t, uint32_t); 50 static void smb_opipe_enter(smb_opipe_t *); 51 static void smb_opipe_exit(smb_opipe_t *); 52 53 static door_handle_t smb_opipe_door_hd = NULL; 54 static int smb_opipe_door_id = -1; 55 static uint64_t smb_opipe_door_ncall = 0; 56 static kmutex_t smb_opipe_door_mutex; 57 static kcondvar_t smb_opipe_door_cv; 58 59 static int smb_opipe_door_call(smb_opipe_t *); 60 static int smb_opipe_door_upcall(smb_opipe_t *); 61 static void smb_user_context_fini(smb_opipe_context_t *); 62 63 /* 64 * smb_opipe_open 65 * 66 * Open a well-known RPC named pipe. This routine should be called if 67 * a file open is requested on a share of type STYPE_IPC. 68 * If we recognize the pipe, we setup a new ofile. 69 * 70 * Returns 0 on success, Otherwise an NT status is returned to indicate 71 * an error. 72 */ 73 int 74 smb_opipe_open(smb_request_t *sr) 75 { 76 struct open_param *op = &sr->arg.open; 77 smb_ofile_t *of; 78 smb_opipe_t *opipe; 79 smb_opipe_hdr_t hdr; 80 smb_error_t err; 81 char *pipe_name; 82 83 if ((pipe_name = smb_opipe_lookup(op->fqi.path)) == NULL) 84 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 85 86 op->create_options = 0; 87 88 of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op, 89 SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err); 90 if (of == NULL) 91 return (err.status); 92 93 op->dsize = 0x01000; 94 op->dattr = FILE_ATTRIBUTE_NORMAL; 95 op->ftype = SMB_FTYPE_MESG_PIPE; 96 op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 97 op->devstate = SMB_PIPE_READMODE_MESSAGE 98 | SMB_PIPE_TYPE_MESSAGE 99 | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 100 op->fileid = of->f_fid; 101 102 sr->smb_fid = of->f_fid; 103 sr->fid_ofile = of; 104 105 opipe = of->f_pipe; 106 mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 107 cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 108 smb_opipe_enter(opipe); 109 110 opipe->p_name = pipe_name; 111 opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP); 112 113 /* 114 * p_data points to the offset within p_doorbuf at which 115 * data will be written or read. 116 */ 117 opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_opipe_hdr_xdr, &hdr); 118 119 if (smb_opipe_do_open(sr, opipe) != 0) { 120 /* 121 * On error, reset the header to clear the fid, 122 * which avoids confusion when smb_opipe_close() is 123 * called by smb_ofile_close(). 124 */ 125 bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t)); 126 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 127 smb_opipe_exit(opipe); 128 smb_ofile_close(of, 0); 129 return (NT_STATUS_NO_MEMORY); 130 } 131 132 smb_opipe_exit(opipe); 133 return (NT_STATUS_SUCCESS); 134 } 135 136 /* 137 * smb_opipe_lookup 138 * 139 * Lookup a path to see if it's a well-known RPC named pipe that we support. 140 * The full pipe path will be in the form \\PIPE\\SERVICE. The first part 141 * can be assumed, so all we need here are the service names. 142 * 143 * Returns a pointer to the pipe name (without any leading \'s) on sucess. 144 * Otherwise returns a null pointer. 145 */ 146 static char * 147 smb_opipe_lookup(const char *path) 148 { 149 static char *named_pipes[] = { 150 "LSARPC", 151 "NETLOGON", 152 "SAMR", 153 "SPOOLSS", 154 "SRVSVC", 155 "SVCCTL", 156 "WINREG", 157 "WKSSVC", 158 "EVENTLOG" 159 }; 160 161 const char *name; 162 int i; 163 164 if (path == NULL) 165 return (NULL); 166 167 name = path; 168 name += strspn(name, "\\"); 169 if (utf8_strncasecmp(name, "PIPE", 4) == 0) { 170 path += 4; 171 name += strspn(name, "\\"); 172 } 173 174 for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) { 175 if (utf8_strcasecmp(name, named_pipes[i]) == 0) 176 return (named_pipes[i]); 177 } 178 179 return (NULL); 180 } 181 182 /* 183 * Initialize the opipe header and context, and make the door call. 184 */ 185 static int 186 smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe) 187 { 188 smb_opipe_context_t *ctx = &opipe->p_context; 189 smb_user_t *user = sr->uid_user; 190 uint8_t *buf = opipe->p_doorbuf; 191 uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE; 192 uint32_t len; 193 194 smb_user_context_init(user, ctx); 195 len = xdr_sizeof(smb_opipe_context_xdr, ctx); 196 197 bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t)); 198 opipe->p_hdr.oh_magic = SMB_OPIPE_HDR_MAGIC; 199 opipe->p_hdr.oh_fid = smb_opipe_fid(); 200 201 if (smb_opipe_set_hdr(opipe, SMB_OPIPE_OPEN, len) == -1) 202 return (-1); 203 204 len = xdr_sizeof(smb_opipe_hdr_xdr, &opipe->p_hdr); 205 buf += len; 206 buflen -= len; 207 208 if (smb_opipe_context_encode(ctx, buf, buflen) == -1) 209 return (-1); 210 211 return (smb_opipe_door_call(opipe)); 212 } 213 214 /* 215 * smb_opipe_fid 216 * 217 * The opipe_fid is an arbitrary id used to associate RPC requests 218 * with a binding handle. A new fid is returned on each call. 219 * 0 or -1 are not assigned: 0 is used to indicate an invalid fid 220 * and SMB sometimes uses -1 to indicate all open fid's. 221 */ 222 static uint32_t 223 smb_opipe_fid(void) 224 { 225 static uint32_t opipe_fid; 226 static kmutex_t smb_opipe_fid_mutex; 227 228 mutex_enter(&smb_opipe_fid_mutex); 229 230 if (opipe_fid == 0) 231 opipe_fid = lbolt << 11; 232 233 do { 234 ++opipe_fid; 235 } while (opipe_fid == 0 || opipe_fid == (uint32_t)-1); 236 237 mutex_exit(&smb_opipe_fid_mutex); 238 239 return (opipe_fid); 240 } 241 242 /* 243 * smb_opipe_close 244 * 245 * Called whenever an IPC file/pipe is closed. 246 */ 247 void 248 smb_opipe_close(smb_ofile_t *of) 249 { 250 smb_opipe_t *opipe; 251 252 ASSERT(of); 253 ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 254 ASSERT(of->f_pipe != NULL); 255 256 opipe = of->f_pipe; 257 smb_opipe_enter(opipe); 258 259 if (SMB_OPIPE_ISOPEN(opipe)) { 260 (void) smb_opipe_set_hdr(opipe, SMB_OPIPE_CLOSE, 0); 261 (void) smb_opipe_door_call(opipe); 262 bzero(&opipe->p_hdr, sizeof (smb_opipe_hdr_t)); 263 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 264 } 265 266 smb_user_context_fini(&opipe->p_context); 267 smb_opipe_exit(opipe); 268 cv_destroy(&opipe->p_cv); 269 mutex_destroy(&opipe->p_mutex); 270 } 271 272 static int 273 smb_opipe_set_hdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen) 274 { 275 opipe->p_hdr.oh_op = cmd; 276 opipe->p_hdr.oh_datalen = datalen; 277 opipe->p_hdr.oh_resid = 0; 278 opipe->p_hdr.oh_status = 0; 279 280 return (smb_opipe_hdr_encode(&opipe->p_hdr, opipe->p_doorbuf, 281 SMB_OPIPE_DOOR_BUFSIZE)); 282 } 283 284 /* 285 * smb_opipe_transact 286 * 287 * This is the entry point for RPC bind and request transactions. 288 * The fid is an arbitrary id used to associate RPC requests with a 289 * particular binding handle. 290 * 291 * If the data to be returned is larger than the client expects, we 292 * return as much as the client can handle and report a buffer overflow 293 * warning, which informs the client that we have more data to return. 294 * The residual data remains in the pipe until the client claims it or 295 * closes the pipe. 296 */ 297 smb_sdrc_t 298 smb_opipe_transact(smb_request_t *sr, struct uio *uio) 299 { 300 smb_xa_t *xa; 301 smb_opipe_t *opipe; 302 struct mbuf *mhead; 303 int mdrcnt; 304 int nbytes; 305 int rc; 306 307 if ((rc = smb_opipe_write(sr, uio)) != 0) { 308 if (rc == EBADF) 309 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 310 ERRDOS, ERROR_INVALID_HANDLE); 311 else 312 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 313 ERRDOS, ERROR_INTERNAL_ERROR); 314 return (SDRC_ERROR); 315 } 316 317 xa = sr->r_xa; 318 mdrcnt = xa->smb_mdrcnt; 319 opipe = sr->fid_ofile->f_pipe; 320 smb_opipe_enter(opipe); 321 322 if (smb_opipe_set_hdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) { 323 smb_opipe_exit(opipe); 324 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 325 ERRDOS, ERROR_INTERNAL_ERROR); 326 return (SDRC_ERROR); 327 } 328 329 rc = smb_opipe_door_call(opipe); 330 nbytes = opipe->p_hdr.oh_datalen; 331 332 if (rc != 0) { 333 smb_opipe_exit(opipe); 334 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 335 ERRDOS, ERROR_INTERNAL_ERROR); 336 return (SDRC_ERROR); 337 } 338 339 if (nbytes) { 340 mhead = smb_mbuf_get(opipe->p_data, nbytes); 341 xa->rep_data_mb.max_bytes = nbytes; 342 MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); 343 } 344 345 if (opipe->p_hdr.oh_resid) { 346 /* 347 * The pipe contains more data than mdrcnt, warn the 348 * client that there is more data in the pipe. 349 * Typically, the client will call SmbReadX, which 350 * will call smb_opipe_read, to get the data. 351 */ 352 smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, 353 ERRDOS, ERROR_MORE_DATA); 354 } 355 356 smb_opipe_exit(opipe); 357 return (SDRC_SUCCESS); 358 } 359 360 /* 361 * smb_opipe_write 362 * 363 * Write RPC request data to the pipe. The client should call smb_opipe_read 364 * to complete the exchange and obtain the RPC response. 365 * 366 * Returns 0 on success or an errno on failure. 367 */ 368 int 369 smb_opipe_write(smb_request_t *sr, struct uio *uio) 370 { 371 smb_opipe_t *opipe; 372 uint32_t buflen; 373 uint32_t len; 374 int rc; 375 376 ASSERT(sr->fid_ofile); 377 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 378 ASSERT(sr->fid_ofile->f_pipe != NULL); 379 380 opipe = sr->fid_ofile->f_pipe; 381 smb_opipe_enter(opipe); 382 383 if (!SMB_OPIPE_ISOPEN(opipe)) { 384 smb_opipe_exit(opipe); 385 return (EBADF); 386 } 387 388 rc = smb_opipe_set_hdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid); 389 len = xdr_sizeof(smb_opipe_hdr_xdr, &opipe->p_hdr); 390 if (rc == -1 || len == 0) { 391 smb_opipe_exit(opipe); 392 return (ENOMEM); 393 } 394 395 buflen = SMB_OPIPE_DOOR_BUFSIZE - len; 396 (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio); 397 398 rc = smb_opipe_door_call(opipe); 399 400 smb_opipe_exit(opipe); 401 return ((rc == 0) ? 0 : EIO); 402 } 403 404 /* 405 * smb_opipe_read 406 * 407 * This interface may be called because smb_opipe_transact could not return 408 * all of the data in the original transaction or to form the second half 409 * of a transaction set up using smb_opipe_write. Either way, we just need 410 * to read data from the pipe and return it. 411 * 412 * The response data is encoded into raw_data as required by the smb_read 413 * functions. The uio_resid value indicates the number of bytes read. 414 */ 415 int 416 smb_opipe_read(smb_request_t *sr, struct uio *uio) 417 { 418 smb_opipe_t *opipe; 419 struct mbuf *mhead; 420 uint32_t nbytes; 421 int rc; 422 423 ASSERT(sr->fid_ofile); 424 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 425 ASSERT(sr->fid_ofile->f_pipe != NULL); 426 427 opipe = sr->fid_ofile->f_pipe; 428 smb_opipe_enter(opipe); 429 430 if (!SMB_OPIPE_ISOPEN(opipe)) { 431 smb_opipe_exit(opipe); 432 return (EBADF); 433 } 434 435 if (smb_opipe_set_hdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) { 436 smb_opipe_exit(opipe); 437 return (ENOMEM); 438 } 439 440 rc = smb_opipe_door_call(opipe); 441 nbytes = opipe->p_hdr.oh_datalen; 442 443 if (rc != 0 || nbytes > uio->uio_resid) { 444 smb_opipe_exit(opipe); 445 return (EIO); 446 } 447 448 if (nbytes) { 449 mhead = smb_mbuf_get(opipe->p_data, nbytes); 450 MBC_SETUP(&sr->raw_data, nbytes); 451 MBC_ATTACH_MBUF(&sr->raw_data, mhead); 452 uio->uio_resid -= nbytes; 453 } 454 455 smb_opipe_exit(opipe); 456 return (rc); 457 } 458 459 /* 460 * Named pipe I/O is serialized per fid to ensure that each request 461 * has exclusive opipe access for the duration of the request. 462 */ 463 static void 464 smb_opipe_enter(smb_opipe_t *opipe) 465 { 466 mutex_enter(&opipe->p_mutex); 467 468 while (opipe->p_busy) 469 cv_wait(&opipe->p_cv, &opipe->p_mutex); 470 471 opipe->p_busy = 1; 472 mutex_exit(&opipe->p_mutex); 473 } 474 475 static void 476 smb_opipe_exit(smb_opipe_t *opipe) 477 { 478 mutex_enter(&opipe->p_mutex); 479 opipe->p_busy = 0; 480 cv_signal(&opipe->p_cv); 481 mutex_exit(&opipe->p_mutex); 482 } 483 484 /* 485 * opipe door client (to user space door server). 486 */ 487 void 488 smb_opipe_door_init(void) 489 { 490 mutex_init(&smb_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL); 491 cv_init(&smb_opipe_door_cv, NULL, CV_DEFAULT, NULL); 492 } 493 494 void 495 smb_opipe_door_fini(void) 496 { 497 smb_opipe_door_close(); 498 cv_destroy(&smb_opipe_door_cv); 499 mutex_destroy(&smb_opipe_door_mutex); 500 } 501 502 /* 503 * Open the (user space) door. If the door is already open, 504 * close it first because the door-id has probably changed. 505 */ 506 int 507 smb_opipe_door_open(int door_id) 508 { 509 smb_opipe_door_close(); 510 511 mutex_enter(&smb_opipe_door_mutex); 512 smb_opipe_door_ncall = 0; 513 514 if (smb_opipe_door_hd == NULL) { 515 smb_opipe_door_id = door_id; 516 smb_opipe_door_hd = door_ki_lookup(door_id); 517 } 518 519 mutex_exit(&smb_opipe_door_mutex); 520 return ((smb_opipe_door_hd == NULL) ? -1 : 0); 521 } 522 523 /* 524 * Close the (user space) door. 525 */ 526 void 527 smb_opipe_door_close(void) 528 { 529 mutex_enter(&smb_opipe_door_mutex); 530 531 if (smb_opipe_door_hd != NULL) { 532 while (smb_opipe_door_ncall > 0) 533 cv_wait(&smb_opipe_door_cv, &smb_opipe_door_mutex); 534 535 door_ki_rele(smb_opipe_door_hd); 536 smb_opipe_door_hd = NULL; 537 } 538 539 mutex_exit(&smb_opipe_door_mutex); 540 } 541 542 /* 543 * opipe door call interface. 544 * Door serialization and call reference accounting is handled here. 545 */ 546 static int 547 smb_opipe_door_call(smb_opipe_t *opipe) 548 { 549 int rc; 550 551 mutex_enter(&smb_opipe_door_mutex); 552 553 if (smb_opipe_door_hd == NULL) { 554 mutex_exit(&smb_opipe_door_mutex); 555 556 if (smb_opipe_door_open(smb_opipe_door_id) != 0) 557 return (-1); 558 559 mutex_enter(&smb_opipe_door_mutex); 560 } 561 562 ++smb_opipe_door_ncall; 563 mutex_exit(&smb_opipe_door_mutex); 564 565 rc = smb_opipe_door_upcall(opipe); 566 567 mutex_enter(&smb_opipe_door_mutex); 568 --smb_opipe_door_ncall; 569 cv_signal(&smb_opipe_door_cv); 570 mutex_exit(&smb_opipe_door_mutex); 571 return (rc); 572 } 573 574 /* 575 * Door upcall wrapper - handles data marshalling. 576 * This function should only be called by smb_opipe_door_call. 577 */ 578 static int 579 smb_opipe_door_upcall(smb_opipe_t *opipe) 580 { 581 door_arg_t da; 582 smb_opipe_hdr_t hdr; 583 int i; 584 int rc; 585 586 da.data_ptr = (char *)opipe->p_doorbuf; 587 da.data_size = SMB_OPIPE_DOOR_BUFSIZE; 588 da.desc_ptr = NULL; 589 da.desc_num = 0; 590 da.rbuf = (char *)opipe->p_doorbuf; 591 da.rsize = SMB_OPIPE_DOOR_BUFSIZE; 592 593 for (i = 0; i < 3; ++i) { 594 if ((rc = door_ki_upcall_limited(smb_opipe_door_hd, &da, 595 NULL, SIZE_MAX, 0)) == 0) 596 break; 597 598 if (rc != EAGAIN && rc != EINTR) 599 return (-1); 600 } 601 602 if (rc != 0) 603 return (-1); 604 605 if (smb_opipe_hdr_decode(&hdr, (uint8_t *)da.rbuf, da.rsize) == -1) 606 return (-1); 607 608 if ((hdr.oh_magic != SMB_OPIPE_HDR_MAGIC) || 609 (hdr.oh_fid != opipe->p_hdr.oh_fid) || 610 (hdr.oh_op != opipe->p_hdr.oh_op) || 611 (hdr.oh_status != 0) || 612 (hdr.oh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) { 613 return (-1); 614 } 615 616 opipe->p_hdr.oh_datalen = hdr.oh_datalen; 617 opipe->p_hdr.oh_resid = hdr.oh_resid; 618 return (0); 619 } 620 621 void 622 smb_user_context_init(smb_user_t *user, smb_opipe_context_t *ctx) 623 { 624 smb_session_t *session; 625 626 ASSERT(user); 627 ASSERT(user->u_domain); 628 ASSERT(user->u_name); 629 630 session = user->u_session; 631 ASSERT(session); 632 ASSERT(session->workstation); 633 634 ctx->oc_session_id = session->s_kid; 635 ctx->oc_native_os = session->native_os; 636 ctx->oc_ipaddr = session->ipaddr; 637 ctx->oc_uid = user->u_uid; 638 ctx->oc_logon_time = user->u_logon_time; 639 ctx->oc_flags = user->u_flags; 640 641 ctx->oc_domain_len = user->u_domain_len; 642 ctx->oc_domain = smb_kstrdup(user->u_domain, ctx->oc_domain_len); 643 644 ctx->oc_account_len = user->u_name_len; 645 ctx->oc_account = smb_kstrdup(user->u_name, ctx->oc_account_len); 646 647 ctx->oc_workstation_len = strlen(session->workstation) + 1; 648 ctx->oc_workstation = smb_kstrdup(session->workstation, 649 ctx->oc_workstation_len); 650 } 651 652 static void 653 smb_user_context_fini(smb_opipe_context_t *ctx) 654 { 655 if (ctx) { 656 if (ctx->oc_domain) 657 kmem_free(ctx->oc_domain, ctx->oc_domain_len); 658 if (ctx->oc_account) 659 kmem_free(ctx->oc_account, ctx->oc_account_len); 660 if (ctx->oc_workstation) 661 kmem_free(ctx->oc_workstation, ctx->oc_workstation_len); 662 bzero(ctx, sizeof (smb_opipe_context_t)); 663 } 664 } 665 666 void 667 smb_user_list_free(smb_dr_ulist_t *userlist) 668 { 669 int i; 670 671 if (userlist) { 672 for (i = 0; i < userlist->dul_cnt; i++) 673 smb_user_context_fini(&userlist->dul_users[i]); 674 } 675 } 676