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 2011 Nexenta Systems, Inc. All rights reserved. 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * This module provides the interface to NDR RPC. 28 */ 29 30 #include <sys/stat.h> 31 #include <sys/door.h> 32 #include <sys/door_data.h> 33 #include <sys/uio.h> 34 #include <sys/ksynch.h> 35 #include <smbsrv/smb_kproto.h> 36 #include <smbsrv/smb_xdr.h> 37 38 #define SMB_OPIPE_ISOPEN(OPIPE) \ 39 (((OPIPE)->p_hdr.dh_magic == SMB_OPIPE_HDR_MAGIC) && \ 40 ((OPIPE)->p_hdr.dh_fid)) 41 42 extern volatile uint32_t smb_fids; 43 #define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids) 44 45 static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *); 46 static char *smb_opipe_lookup(const char *); 47 static int smb_opipe_sethdr(smb_opipe_t *, uint32_t, uint32_t); 48 static int smb_opipe_exec(smb_opipe_t *); 49 static void smb_opipe_enter(smb_opipe_t *); 50 static void smb_opipe_exit(smb_opipe_t *); 51 52 53 smb_opipe_t * 54 smb_opipe_alloc(smb_server_t *sv) 55 { 56 smb_opipe_t *opipe; 57 58 opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP); 59 60 bzero(opipe, sizeof (smb_opipe_t)); 61 mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 62 cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 63 opipe->p_magic = SMB_OPIPE_MAGIC; 64 opipe->p_server = sv; 65 66 smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 67 smb_llist_insert_tail(&sv->sv_opipe_list, opipe); 68 smb_llist_exit(&sv->sv_opipe_list); 69 70 return (opipe); 71 } 72 73 void 74 smb_opipe_dealloc(smb_opipe_t *opipe) 75 { 76 smb_server_t *sv; 77 78 SMB_OPIPE_VALID(opipe); 79 sv = opipe->p_server; 80 SMB_SERVER_VALID(sv); 81 82 smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 83 smb_llist_remove(&sv->sv_opipe_list, opipe); 84 smb_llist_exit(&sv->sv_opipe_list); 85 86 opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC; 87 smb_event_destroy(opipe->p_event); 88 cv_destroy(&opipe->p_cv); 89 mutex_destroy(&opipe->p_mutex); 90 91 kmem_cache_free(smb_cache_opipe, opipe); 92 } 93 94 /* 95 * smb_opipe_open 96 * 97 * Open a well-known RPC named pipe. This routine should be called if 98 * a file open is requested on a share of type STYPE_IPC. 99 * If we recognize the pipe, we setup a new ofile. 100 * 101 * Returns 0 on success, Otherwise an NT status is returned to indicate 102 * an error. 103 */ 104 int 105 smb_opipe_open(smb_request_t *sr) 106 { 107 smb_arg_open_t *op = &sr->sr_open; 108 smb_ofile_t *of; 109 smb_opipe_t *opipe; 110 smb_doorhdr_t hdr; 111 smb_error_t err; 112 char *pipe_name; 113 114 if ((pipe_name = smb_opipe_lookup(op->fqi.fq_path.pn_path)) == NULL) 115 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 116 117 /* 118 * If printing is disabled, pretend spoolss does not exist. 119 */ 120 if (sr->sr_server->sv_cfg.skc_print_enable == 0 && 121 strcmp(pipe_name, "SPOOLSS") == 0) 122 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 123 124 op->create_options = 0; 125 126 of = smb_ofile_open(sr, NULL, sr->smb_pid, op, SMB_FTYPE_MESG_PIPE, 127 SMB_UNIQ_FID(), &err); 128 129 if (of == NULL) 130 return (err.status); 131 132 if (!smb_tree_is_connected(sr->tid_tree)) { 133 smb_ofile_close(of, 0); 134 smb_ofile_release(of); 135 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 136 } 137 138 op->dsize = 0x01000; 139 op->dattr = FILE_ATTRIBUTE_NORMAL; 140 op->ftype = SMB_FTYPE_MESG_PIPE; 141 op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 142 op->devstate = SMB_PIPE_READMODE_MESSAGE 143 | SMB_PIPE_TYPE_MESSAGE 144 | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 145 op->fileid = of->f_fid; 146 147 sr->smb_fid = of->f_fid; 148 sr->fid_ofile = of; 149 150 opipe = of->f_pipe; 151 smb_opipe_enter(opipe); 152 153 opipe->p_server = of->f_server; 154 opipe->p_name = pipe_name; 155 opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP); 156 157 /* 158 * p_data points to the offset within p_doorbuf at which 159 * data will be written or read. 160 */ 161 opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_doorhdr_xdr, &hdr); 162 163 if (smb_opipe_do_open(sr, opipe) != 0) { 164 /* 165 * On error, reset the header to clear the fid, 166 * which avoids confusion when smb_opipe_close() is 167 * called by smb_ofile_close(). 168 */ 169 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 170 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 171 smb_opipe_exit(opipe); 172 smb_ofile_close(of, 0); 173 return (NT_STATUS_NO_MEMORY); 174 } 175 smb_opipe_exit(opipe); 176 return (NT_STATUS_SUCCESS); 177 } 178 179 /* 180 * smb_opipe_lookup 181 * 182 * Lookup a path to see if it's a well-known RPC named pipe that we support. 183 * The full pipe path will be in the form \\PIPE\\SERVICE. The first part 184 * can be assumed, so all we need here are the service names. 185 * 186 * Returns a pointer to the pipe name (without any leading \'s) on success. 187 * Otherwise returns a null pointer. 188 */ 189 static char * 190 smb_opipe_lookup(const char *path) 191 { 192 static char *named_pipes[] = { 193 "lsass", 194 "LSARPC", 195 "NETLOGON", 196 "SAMR", 197 "SPOOLSS", 198 "SRVSVC", 199 "SVCCTL", 200 "WINREG", 201 "WKSSVC", 202 "EVENTLOG", 203 "NETDFS" 204 }; 205 206 const char *name; 207 int i; 208 209 if (path == NULL) 210 return (NULL); 211 212 name = path; 213 name += strspn(name, "\\"); 214 if (smb_strcasecmp(name, "PIPE", 4) == 0) { 215 path += 4; 216 name += strspn(name, "\\"); 217 } 218 219 for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) { 220 if (smb_strcasecmp(name, named_pipes[i], 0) == 0) 221 return (named_pipes[i]); 222 } 223 224 return (NULL); 225 } 226 227 /* 228 * Initialize the opipe header and context, and make the door call. 229 */ 230 static int 231 smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe) 232 { 233 smb_netuserinfo_t *userinfo = &opipe->p_user; 234 smb_user_t *user = sr->uid_user; 235 smb_server_t *sv = sr->sr_server; 236 uint8_t *buf = opipe->p_doorbuf; 237 uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE; 238 uint32_t len; 239 240 if ((opipe->p_event = smb_event_create(sv, SMB_EVENT_TIMEOUT)) == NULL) 241 return (-1); 242 243 smb_user_netinfo_init(user, userinfo); 244 len = xdr_sizeof(smb_netuserinfo_xdr, userinfo); 245 246 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 247 opipe->p_hdr.dh_magic = SMB_OPIPE_HDR_MAGIC; 248 opipe->p_hdr.dh_flags = SMB_DF_SYSSPACE; 249 opipe->p_hdr.dh_fid = smb_event_txid(opipe->p_event); 250 251 if (smb_opipe_sethdr(opipe, SMB_OPIPE_OPEN, len) == -1) 252 return (-1); 253 254 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 255 buf += len; 256 buflen -= len; 257 258 if (smb_netuserinfo_encode(userinfo, buf, buflen, NULL) == -1) 259 return (-1); 260 261 return (smb_opipe_door_call(opipe)); 262 } 263 264 /* 265 * smb_opipe_close 266 * 267 * Called whenever an IPC file/pipe is closed. 268 */ 269 void 270 smb_opipe_close(smb_ofile_t *of) 271 { 272 smb_opipe_t *opipe; 273 274 ASSERT(of); 275 ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 276 277 opipe = of->f_pipe; 278 SMB_OPIPE_VALID(opipe); 279 280 (void) smb_server_cancel_event(of->f_server, opipe->p_hdr.dh_fid); 281 smb_opipe_enter(opipe); 282 283 if (SMB_OPIPE_ISOPEN(opipe)) { 284 (void) smb_opipe_sethdr(opipe, SMB_OPIPE_CLOSE, 0); 285 (void) smb_opipe_door_call(opipe); 286 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 287 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 288 } 289 290 smb_user_netinfo_fini(&opipe->p_user); 291 smb_opipe_exit(opipe); 292 } 293 294 static int 295 smb_opipe_sethdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen) 296 { 297 opipe->p_hdr.dh_op = cmd; 298 opipe->p_hdr.dh_txid = opipe->p_hdr.dh_fid; 299 opipe->p_hdr.dh_datalen = datalen; 300 opipe->p_hdr.dh_resid = 0; 301 opipe->p_hdr.dh_door_rc = EINVAL; 302 303 return (smb_doorhdr_encode(&opipe->p_hdr, opipe->p_doorbuf, 304 SMB_OPIPE_DOOR_BUFSIZE)); 305 } 306 307 /* 308 * smb_opipe_transact 309 * 310 * This is the entry point for RPC bind and request transactions. 311 * The fid is an arbitrary id used to associate RPC requests with a 312 * particular binding handle. 313 * 314 * If the data to be returned is larger than the client expects, we 315 * return as much as the client can handle and report a buffer overflow 316 * warning, which informs the client that we have more data to return. 317 * The residual data remains in the pipe until the client claims it or 318 * closes the pipe. 319 */ 320 smb_sdrc_t 321 smb_opipe_transact(smb_request_t *sr, struct uio *uio) 322 { 323 smb_xa_t *xa; 324 smb_opipe_t *opipe; 325 struct mbuf *mhead; 326 int mdrcnt; 327 int nbytes; 328 int rc; 329 330 if ((rc = smb_opipe_write(sr, uio)) != 0) { 331 if (rc == EBADF) 332 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 333 ERRDOS, ERROR_INVALID_HANDLE); 334 else 335 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 336 ERRDOS, ERROR_INTERNAL_ERROR); 337 return (SDRC_ERROR); 338 } 339 340 opipe = sr->fid_ofile->f_pipe; 341 342 if ((rc = smb_opipe_exec(opipe)) != 0) { 343 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 344 ERRDOS, ERROR_INTERNAL_ERROR); 345 return (SDRC_ERROR); 346 } 347 348 xa = sr->r_xa; 349 mdrcnt = xa->smb_mdrcnt; 350 smb_opipe_enter(opipe); 351 352 if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) { 353 smb_opipe_exit(opipe); 354 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 355 ERRDOS, ERROR_INTERNAL_ERROR); 356 return (SDRC_ERROR); 357 } 358 359 rc = smb_opipe_door_call(opipe); 360 nbytes = opipe->p_hdr.dh_datalen; 361 362 if (rc != 0) { 363 smb_opipe_exit(opipe); 364 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 365 ERRDOS, ERROR_INTERNAL_ERROR); 366 return (SDRC_ERROR); 367 } 368 369 if (nbytes) { 370 mhead = smb_mbuf_get(opipe->p_data, nbytes); 371 xa->rep_data_mb.max_bytes = nbytes; 372 MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); 373 } 374 375 if (opipe->p_hdr.dh_resid) { 376 /* 377 * The pipe contains more data than mdrcnt, warn the 378 * client that there is more data in the pipe. 379 * Typically, the client will call SmbReadX, which 380 * will call smb_opipe_read, to get the data. 381 */ 382 smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, 383 ERRDOS, ERROR_MORE_DATA); 384 } 385 386 smb_opipe_exit(opipe); 387 return (SDRC_SUCCESS); 388 } 389 390 /* 391 * smb_opipe_write 392 * 393 * Write RPC request data to the pipe. The client should call smb_opipe_read 394 * to complete the exchange and obtain the RPC response. 395 * 396 * Returns 0 on success or an errno on failure. 397 */ 398 int 399 smb_opipe_write(smb_request_t *sr, struct uio *uio) 400 { 401 smb_opipe_t *opipe; 402 uint32_t buflen; 403 uint32_t len; 404 int rc; 405 406 ASSERT(sr->fid_ofile); 407 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 408 409 opipe = sr->fid_ofile->f_pipe; 410 SMB_OPIPE_VALID(opipe); 411 smb_opipe_enter(opipe); 412 413 if (!SMB_OPIPE_ISOPEN(opipe)) { 414 smb_opipe_exit(opipe); 415 return (EBADF); 416 } 417 418 rc = smb_opipe_sethdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid); 419 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 420 if (rc == -1 || len == 0) { 421 smb_opipe_exit(opipe); 422 return (ENOMEM); 423 } 424 425 buflen = SMB_OPIPE_DOOR_BUFSIZE - len; 426 (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio); 427 428 rc = smb_opipe_door_call(opipe); 429 430 smb_opipe_exit(opipe); 431 return ((rc == 0) ? 0 : EIO); 432 } 433 434 /* 435 * smb_opipe_read 436 * 437 * This interface may be called because smb_opipe_transact could not return 438 * all of the data in the original transaction or to form the second half 439 * of a transaction set up using smb_opipe_write. Either way, we just need 440 * to read data from the pipe and return it. 441 * 442 * The response data is encoded into raw_data as required by the smb_read 443 * functions. The uio_resid value indicates the number of bytes read. 444 */ 445 int 446 smb_opipe_read(smb_request_t *sr, struct uio *uio) 447 { 448 smb_opipe_t *opipe; 449 struct mbuf *mhead; 450 uint32_t nbytes; 451 int rc; 452 453 ASSERT(sr->fid_ofile); 454 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 455 456 opipe = sr->fid_ofile->f_pipe; 457 SMB_OPIPE_VALID(opipe); 458 459 if ((rc = smb_opipe_exec(opipe)) != 0) 460 return (EIO); 461 462 smb_opipe_enter(opipe); 463 464 if (!SMB_OPIPE_ISOPEN(opipe)) { 465 smb_opipe_exit(opipe); 466 return (EBADF); 467 } 468 469 if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) { 470 smb_opipe_exit(opipe); 471 return (ENOMEM); 472 } 473 474 rc = smb_opipe_door_call(opipe); 475 nbytes = opipe->p_hdr.dh_datalen; 476 477 if (rc != 0 || nbytes > uio->uio_resid) { 478 smb_opipe_exit(opipe); 479 return (EIO); 480 } 481 482 if (nbytes) { 483 mhead = smb_mbuf_get(opipe->p_data, nbytes); 484 MBC_SETUP(&sr->raw_data, nbytes); 485 MBC_ATTACH_MBUF(&sr->raw_data, mhead); 486 uio->uio_resid -= nbytes; 487 } 488 489 smb_opipe_exit(opipe); 490 return (rc); 491 } 492 493 static int 494 smb_opipe_exec(smb_opipe_t *opipe) 495 { 496 uint32_t len; 497 int rc; 498 499 smb_opipe_enter(opipe); 500 501 rc = smb_opipe_sethdr(opipe, SMB_OPIPE_EXEC, 0); 502 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 503 if (rc == -1 || len == 0) { 504 smb_opipe_exit(opipe); 505 return (ENOMEM); 506 } 507 508 if ((rc = smb_opipe_door_call(opipe)) == 0) 509 rc = smb_event_wait(opipe->p_event); 510 511 smb_opipe_exit(opipe); 512 return (rc); 513 } 514 515 /* 516 * Named pipe I/O is serialized per fid to ensure that each request 517 * has exclusive opipe access for the duration of the request. 518 */ 519 static void 520 smb_opipe_enter(smb_opipe_t *opipe) 521 { 522 mutex_enter(&opipe->p_mutex); 523 524 while (opipe->p_busy) 525 cv_wait(&opipe->p_cv, &opipe->p_mutex); 526 527 opipe->p_busy = 1; 528 mutex_exit(&opipe->p_mutex); 529 } 530 531 /* 532 * Exit busy state. If we have exec'd an RPC, we may have 533 * to wait for notification that processing has completed. 534 */ 535 static void 536 smb_opipe_exit(smb_opipe_t *opipe) 537 { 538 mutex_enter(&opipe->p_mutex); 539 opipe->p_busy = 0; 540 cv_signal(&opipe->p_cv); 541 mutex_exit(&opipe->p_mutex); 542 } 543