1/* 2 Unix SMB/CIFS implementation. 3 default IPC$ NTVFS backend 4 5 Copyright (C) Andrew Tridgell 2003 6 Copyright (C) Stefan (metze) Metzmacher 2004-2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21/* 22 this implements the IPC$ backend, called by the NTVFS subsystem to 23 handle requests on IPC$ shares 24*/ 25 26 27#include "includes.h" 28#include "../lib/util/dlinklist.h" 29#include "ntvfs/ntvfs.h" 30#include "libcli/rap/rap.h" 31#include "ntvfs/ipc/proto.h" 32#include "libcli/raw/ioctl.h" 33#include "param/param.h" 34#include "../lib/tsocket/tsocket.h" 35#include "../libcli/named_pipe_auth/npa_tstream.h" 36#include "auth/auth.h" 37#include "auth/auth_sam_reply.h" 38#include "lib/socket/socket.h" 39#include "auth/credentials/credentials.h" 40#include "auth/credentials/credentials_krb5.h" 41#include <gssapi/gssapi.h> 42#include "system/locale.h" 43 44/* this is the private structure used to keep the state of an open 45 ipc$ connection. It needs to keep information about all open 46 pipes */ 47struct ipc_private { 48 struct ntvfs_module_context *ntvfs; 49 50 /* a list of open pipes */ 51 struct pipe_state { 52 struct pipe_state *next, *prev; 53 struct ipc_private *ipriv; 54 const char *pipe_name; 55 struct ntvfs_handle *handle; 56 struct tstream_context *npipe; 57 uint16_t file_type; 58 uint16_t device_state; 59 uint64_t allocation_size; 60 struct tevent_queue *write_queue; 61 struct tevent_queue *read_queue; 62 } *pipe_list; 63}; 64 65 66/* 67 find a open pipe give a file handle 68*/ 69static struct pipe_state *pipe_state_find(struct ipc_private *ipriv, struct ntvfs_handle *handle) 70{ 71 struct pipe_state *s; 72 void *p; 73 74 p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs); 75 if (!p) return NULL; 76 77 s = talloc_get_type(p, struct pipe_state); 78 if (!s) return NULL; 79 80 return s; 81} 82 83/* 84 find a open pipe give a wire fnum 85*/ 86static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct ntvfs_request *req, const DATA_BLOB *key) 87{ 88 struct ntvfs_handle *h; 89 90 h = ntvfs_handle_search_by_wire_key(ipriv->ntvfs, req, key); 91 if (!h) return NULL; 92 93 return pipe_state_find(ipriv, h); 94} 95 96 97/* 98 connect to a share - always works 99*/ 100static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs, 101 struct ntvfs_request *req, 102 union smb_tcon* tcon) 103{ 104 struct ipc_private *ipriv; 105 const char *sharename; 106 107 switch (tcon->generic.level) { 108 case RAW_TCON_TCON: 109 sharename = tcon->tcon.in.service; 110 break; 111 case RAW_TCON_TCONX: 112 sharename = tcon->tconx.in.path; 113 break; 114 case RAW_TCON_SMB2: 115 sharename = tcon->smb2.in.path; 116 break; 117 default: 118 return NT_STATUS_INVALID_LEVEL; 119 } 120 121 if (strncmp(sharename, "\\\\", 2) == 0) { 122 char *p = strchr(sharename+2, '\\'); 123 if (p) { 124 sharename = p + 1; 125 } 126 } 127 128 ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC"); 129 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type); 130 131 ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC"); 132 NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type); 133 134 if (tcon->generic.level == RAW_TCON_TCONX) { 135 tcon->tconx.out.fs_type = ntvfs->ctx->fs_type; 136 tcon->tconx.out.dev_type = ntvfs->ctx->dev_type; 137 } 138 139 /* prepare the private state for this connection */ 140 ipriv = talloc(ntvfs, struct ipc_private); 141 NT_STATUS_HAVE_NO_MEMORY(ipriv); 142 143 ntvfs->private_data = ipriv; 144 145 ipriv->ntvfs = ntvfs; 146 ipriv->pipe_list = NULL; 147 148 return NT_STATUS_OK; 149} 150 151/* 152 disconnect from a share 153*/ 154static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs) 155{ 156 return NT_STATUS_OK; 157} 158 159/* 160 delete a file 161*/ 162static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs, 163 struct ntvfs_request *req, 164 union smb_unlink *unl) 165{ 166 return NT_STATUS_ACCESS_DENIED; 167} 168 169/* 170 check if a directory exists 171*/ 172static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs, 173 struct ntvfs_request *req, 174 union smb_chkpath *cp) 175{ 176 return NT_STATUS_ACCESS_DENIED; 177} 178 179/* 180 return info on a pathname 181*/ 182static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs, 183 struct ntvfs_request *req, union smb_fileinfo *info) 184{ 185 switch (info->generic.level) { 186 case RAW_FILEINFO_GENERIC: 187 return NT_STATUS_INVALID_DEVICE_REQUEST; 188 case RAW_FILEINFO_GETATTR: 189 return NT_STATUS_ACCESS_DENIED; 190 default: 191 return ntvfs_map_qpathinfo(ntvfs, req, info); 192 } 193} 194 195/* 196 set info on a pathname 197*/ 198static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs, 199 struct ntvfs_request *req, union smb_setfileinfo *st) 200{ 201 return NT_STATUS_ACCESS_DENIED; 202} 203 204 205/* 206 destroy a open pipe structure 207*/ 208static int ipc_fd_destructor(struct pipe_state *p) 209{ 210 DLIST_REMOVE(p->ipriv->pipe_list, p); 211 ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs); 212 return 0; 213} 214 215struct ipc_open_state { 216 struct ipc_private *ipriv; 217 struct pipe_state *p; 218 struct ntvfs_request *req; 219 union smb_open *oi; 220 struct netr_SamInfo3 *info3; 221}; 222 223static void ipc_open_done(struct tevent_req *subreq); 224 225/* 226 check the pipename is valid 227 */ 228static NTSTATUS validate_pipename(const char *name) 229{ 230 while (*name) { 231 if (!isalnum(*name)) return NT_STATUS_INVALID_PARAMETER; 232 name++; 233 } 234 return NT_STATUS_OK; 235} 236 237/* 238 open a file - used for MSRPC pipes 239*/ 240static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs, 241 struct ntvfs_request *req, union smb_open *oi) 242{ 243 NTSTATUS status; 244 struct pipe_state *p; 245 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 246 struct ipc_private); 247 struct smb_iconv_convenience *smb_ic 248 = lp_iconv_convenience(ipriv->ntvfs->ctx->lp_ctx); 249 struct ntvfs_handle *h; 250 struct ipc_open_state *state; 251 struct tevent_req *subreq; 252 const char *fname; 253 const char *directory; 254 struct socket_address *client_sa; 255 struct tsocket_address *client_addr; 256 struct socket_address *server_sa; 257 struct tsocket_address *server_addr; 258 int ret; 259 DATA_BLOB delegated_creds = data_blob_null; 260 261 switch (oi->generic.level) { 262 case RAW_OPEN_NTCREATEX: 263 fname = oi->ntcreatex.in.fname; 264 break; 265 case RAW_OPEN_OPENX: 266 fname = oi->openx.in.fname; 267 break; 268 case RAW_OPEN_SMB2: 269 fname = oi->smb2.in.fname; 270 break; 271 default: 272 status = NT_STATUS_NOT_SUPPORTED; 273 break; 274 } 275 276 directory = talloc_asprintf(req, "%s/np", 277 lp_ncalrpc_dir(ipriv->ntvfs->ctx->lp_ctx)); 278 NT_STATUS_HAVE_NO_MEMORY(directory); 279 280 state = talloc(req, struct ipc_open_state); 281 NT_STATUS_HAVE_NO_MEMORY(state); 282 283 status = ntvfs_handle_new(ntvfs, req, &h); 284 NT_STATUS_NOT_OK_RETURN(status); 285 286 p = talloc(h, struct pipe_state); 287 NT_STATUS_HAVE_NO_MEMORY(p); 288 289 while (fname[0] == '\\') fname++; 290 291 /* check for valid characters in name */ 292 fname = strlower_talloc(p, fname); 293 294 status = validate_pipename(fname); 295 NT_STATUS_NOT_OK_RETURN(status); 296 297 p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname); 298 NT_STATUS_HAVE_NO_MEMORY(p->pipe_name); 299 300 p->handle = h; 301 p->ipriv = ipriv; 302 303 p->write_queue = tevent_queue_create(p, "ipc_write_queue"); 304 NT_STATUS_HAVE_NO_MEMORY(p->write_queue); 305 306 p->read_queue = tevent_queue_create(p, "ipc_read_queue"); 307 NT_STATUS_HAVE_NO_MEMORY(p->read_queue); 308 309 state->ipriv = ipriv; 310 state->p = p; 311 state->req = req; 312 state->oi = oi; 313 314 status = auth_convert_server_info_saminfo3(state, 315 req->session_info->server_info, 316 &state->info3); 317 NT_STATUS_NOT_OK_RETURN(status); 318 319 client_sa = ntvfs_get_peer_addr(ntvfs, state); 320 if (!client_sa) { 321 return NT_STATUS_INTERNAL_ERROR; 322 } 323 324 server_sa = ntvfs_get_my_addr(ntvfs, state); 325 if (!server_sa) { 326 return NT_STATUS_INTERNAL_ERROR; 327 } 328 329 ret = tsocket_address_inet_from_strings(state, "ip", 330 client_sa->addr, 331 client_sa->port, 332 &client_addr); 333 if (ret == -1) { 334 status = map_nt_error_from_unix(errno); 335 return status; 336 } 337 338 ret = tsocket_address_inet_from_strings(state, "ip", 339 server_sa->addr, 340 server_sa->port, 341 &server_addr); 342 if (ret == -1) { 343 status = map_nt_error_from_unix(errno); 344 return status; 345 } 346 347 if (req->session_info->credentials) { 348 struct gssapi_creds_container *gcc; 349 OM_uint32 gret; 350 OM_uint32 minor_status; 351 gss_buffer_desc cred_token; 352 353 ret = cli_credentials_get_client_gss_creds(req->session_info->credentials, 354 ipriv->ntvfs->ctx->event_ctx, 355 ipriv->ntvfs->ctx->lp_ctx, 356 &gcc); 357 if (ret) { 358 goto skip; 359 } 360 361 gret = gss_export_cred(&minor_status, 362 gcc->creds, 363 &cred_token); 364 if (gret != GSS_S_COMPLETE) { 365 return NT_STATUS_INTERNAL_ERROR; 366 } 367 368 if (cred_token.length) { 369 delegated_creds = data_blob_talloc(req, 370 cred_token.value, 371 cred_token.length); 372 gss_release_buffer(&minor_status, &cred_token); 373 NT_STATUS_HAVE_NO_MEMORY(delegated_creds.data); 374 } 375 } 376 377skip: 378 379 subreq = tstream_npa_connect_send(p, 380 ipriv->ntvfs->ctx->event_ctx, 381 smb_ic, 382 directory, 383 fname, 384 client_addr, 385 NULL, 386 server_addr, 387 NULL, 388 state->info3, 389 req->session_info->session_key, 390 delegated_creds); 391 NT_STATUS_HAVE_NO_MEMORY(subreq); 392 tevent_req_set_callback(subreq, ipc_open_done, state); 393 394 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 395 return NT_STATUS_OK; 396} 397 398static void ipc_open_done(struct tevent_req *subreq) 399{ 400 struct ipc_open_state *state = tevent_req_callback_data(subreq, 401 struct ipc_open_state); 402 struct ipc_private *ipriv = state->ipriv; 403 struct pipe_state *p = state->p; 404 struct ntvfs_request *req = state->req; 405 union smb_open *oi = state->oi; 406 int ret; 407 int sys_errno; 408 NTSTATUS status; 409 410 ret = tstream_npa_connect_recv(subreq, &sys_errno, 411 p, &p->npipe, 412 &p->file_type, 413 &p->device_state, 414 &p->allocation_size); 415 TALLOC_FREE(subreq); 416 if (ret == -1) { 417 status = map_nt_error_from_unix(sys_errno); 418 goto reply; 419 } 420 421 DLIST_ADD(ipriv->pipe_list, p); 422 talloc_set_destructor(p, ipc_fd_destructor); 423 424 status = ntvfs_handle_set_backend_data(p->handle, ipriv->ntvfs, p); 425 if (!NT_STATUS_IS_OK(status)) { 426 goto reply; 427 } 428 429 switch (oi->generic.level) { 430 case RAW_OPEN_NTCREATEX: 431 ZERO_STRUCT(oi->ntcreatex.out); 432 oi->ntcreatex.out.file.ntvfs = p->handle; 433 oi->ntcreatex.out.oplock_level = 0; 434 oi->ntcreatex.out.create_action = NTCREATEX_ACTION_EXISTED; 435 oi->ntcreatex.out.create_time = 0; 436 oi->ntcreatex.out.access_time = 0; 437 oi->ntcreatex.out.write_time = 0; 438 oi->ntcreatex.out.change_time = 0; 439 oi->ntcreatex.out.attrib = FILE_ATTRIBUTE_NORMAL; 440 oi->ntcreatex.out.alloc_size = p->allocation_size; 441 oi->ntcreatex.out.size = 0; 442 oi->ntcreatex.out.file_type = p->file_type; 443 oi->ntcreatex.out.ipc_state = p->device_state; 444 oi->ntcreatex.out.is_directory = 0; 445 break; 446 case RAW_OPEN_OPENX: 447 ZERO_STRUCT(oi->openx.out); 448 oi->openx.out.file.ntvfs = p->handle; 449 oi->openx.out.attrib = FILE_ATTRIBUTE_NORMAL; 450 oi->openx.out.write_time = 0; 451 oi->openx.out.size = 0; 452 oi->openx.out.access = 0; 453 oi->openx.out.ftype = p->file_type; 454 oi->openx.out.devstate = p->device_state; 455 oi->openx.out.action = 0; 456 oi->openx.out.unique_fid = 0; 457 oi->openx.out.access_mask = 0; 458 oi->openx.out.unknown = 0; 459 break; 460 case RAW_OPEN_SMB2: 461 ZERO_STRUCT(oi->smb2.out); 462 oi->smb2.out.file.ntvfs = p->handle; 463 oi->smb2.out.oplock_level = oi->smb2.in.oplock_level; 464 oi->smb2.out.create_action = NTCREATEX_ACTION_EXISTED; 465 oi->smb2.out.create_time = 0; 466 oi->smb2.out.access_time = 0; 467 oi->smb2.out.write_time = 0; 468 oi->smb2.out.change_time = 0; 469 oi->smb2.out.alloc_size = p->allocation_size; 470 oi->smb2.out.size = 0; 471 oi->smb2.out.file_attr = FILE_ATTRIBUTE_NORMAL; 472 oi->smb2.out.reserved2 = 0; 473 break; 474 default: 475 break; 476 } 477 478reply: 479 req->async_states->status = status; 480 req->async_states->send_fn(req); 481} 482 483/* 484 create a directory 485*/ 486static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs, 487 struct ntvfs_request *req, union smb_mkdir *md) 488{ 489 return NT_STATUS_ACCESS_DENIED; 490} 491 492/* 493 remove a directory 494*/ 495static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs, 496 struct ntvfs_request *req, struct smb_rmdir *rd) 497{ 498 return NT_STATUS_ACCESS_DENIED; 499} 500 501/* 502 rename a set of files 503*/ 504static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs, 505 struct ntvfs_request *req, union smb_rename *ren) 506{ 507 return NT_STATUS_ACCESS_DENIED; 508} 509 510/* 511 copy a set of files 512*/ 513static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs, 514 struct ntvfs_request *req, struct smb_copy *cp) 515{ 516 return NT_STATUS_ACCESS_DENIED; 517} 518 519struct ipc_readv_next_vector_state { 520 uint8_t *buf; 521 size_t len; 522 off_t ofs; 523 size_t remaining; 524}; 525 526static void ipc_readv_next_vector_init(struct ipc_readv_next_vector_state *s, 527 uint8_t *buf, size_t len) 528{ 529 ZERO_STRUCTP(s); 530 531 s->buf = buf; 532 s->len = MIN(len, UINT16_MAX); 533 //DEBUG(0,("readv_next_vector_init[%u 0x%04X]\n", s->len, s->len)); 534} 535 536static int ipc_readv_next_vector(struct tstream_context *stream, 537 void *private_data, 538 TALLOC_CTX *mem_ctx, 539 struct iovec **_vector, 540 size_t *count) 541{ 542 struct ipc_readv_next_vector_state *state = 543 (struct ipc_readv_next_vector_state *)private_data; 544 struct iovec *vector; 545 ssize_t pending; 546 size_t wanted; 547 548 if (state->ofs == state->len) { 549 *_vector = NULL; 550 *count = 0; 551// DEBUG(0,("readv_next_vector done ofs[%u 0x%04X]\n", 552// state->ofs, state->ofs)); 553 return 0; 554 } 555 556 pending = tstream_pending_bytes(stream); 557 if (pending == -1) { 558 return -1; 559 } 560 561 if (pending == 0 && state->ofs != 0) { 562 /* return a short read */ 563 *_vector = NULL; 564 *count = 0; 565// DEBUG(0,("readv_next_vector short read ofs[%u 0x%04X]\n", 566// state->ofs, state->ofs)); 567 return 0; 568 } 569 570 if (pending == 0) { 571 /* we want at least one byte and recheck again */ 572 wanted = 1; 573 } else { 574 size_t missing = state->len - state->ofs; 575 if (pending > missing) { 576 /* there's more available */ 577 state->remaining = pending - missing; 578 wanted = missing; 579 } else { 580 /* read what we can get and recheck in the next cycle */ 581 wanted = pending; 582 } 583 } 584 585 vector = talloc_array(mem_ctx, struct iovec, 1); 586 if (!vector) { 587 return -1; 588 } 589 590 vector[0].iov_base = state->buf + state->ofs; 591 vector[0].iov_len = wanted; 592 593 state->ofs += wanted; 594 595 *_vector = vector; 596 *count = 1; 597 return 0; 598} 599 600struct ipc_read_state { 601 struct ipc_private *ipriv; 602 struct pipe_state *p; 603 struct ntvfs_request *req; 604 union smb_read *rd; 605 struct ipc_readv_next_vector_state next_vector; 606}; 607 608static void ipc_read_done(struct tevent_req *subreq); 609 610/* 611 read from a file 612*/ 613static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs, 614 struct ntvfs_request *req, union smb_read *rd) 615{ 616 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 617 struct ipc_private); 618 struct pipe_state *p; 619 struct ipc_read_state *state; 620 struct tevent_req *subreq; 621 622 if (rd->generic.level != RAW_READ_GENERIC) { 623 return ntvfs_map_read(ntvfs, req, rd); 624 } 625 626 p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs); 627 if (!p) { 628 return NT_STATUS_INVALID_HANDLE; 629 } 630 631 state = talloc(req, struct ipc_read_state); 632 NT_STATUS_HAVE_NO_MEMORY(state); 633 634 state->ipriv = ipriv; 635 state->p = p; 636 state->req = req; 637 state->rd = rd; 638 639 /* rd->readx.out.data is already allocated */ 640 ipc_readv_next_vector_init(&state->next_vector, 641 rd->readx.out.data, 642 rd->readx.in.maxcnt); 643 644 subreq = tstream_readv_pdu_queue_send(req, 645 ipriv->ntvfs->ctx->event_ctx, 646 p->npipe, 647 p->read_queue, 648 ipc_readv_next_vector, 649 &state->next_vector); 650 NT_STATUS_HAVE_NO_MEMORY(subreq); 651 tevent_req_set_callback(subreq, ipc_read_done, state); 652 653 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 654 return NT_STATUS_OK; 655} 656 657static void ipc_read_done(struct tevent_req *subreq) 658{ 659 struct ipc_read_state *state = 660 tevent_req_callback_data(subreq, 661 struct ipc_read_state); 662 struct ntvfs_request *req = state->req; 663 union smb_read *rd = state->rd; 664 int ret; 665 int sys_errno; 666 NTSTATUS status; 667 668 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno); 669 TALLOC_FREE(subreq); 670 if (ret == -1) { 671 status = map_nt_error_from_unix(sys_errno); 672 goto reply; 673 } 674 675 status = NT_STATUS_OK; 676 if (state->next_vector.remaining > 0) { 677 status = STATUS_BUFFER_OVERFLOW; 678 } 679 680 rd->readx.out.remaining = state->next_vector.remaining; 681 rd->readx.out.compaction_mode = 0; 682 rd->readx.out.nread = ret; 683 684reply: 685 req->async_states->status = status; 686 req->async_states->send_fn(req); 687} 688 689struct ipc_write_state { 690 struct ipc_private *ipriv; 691 struct pipe_state *p; 692 struct ntvfs_request *req; 693 union smb_write *wr; 694 struct iovec iov; 695}; 696 697static void ipc_write_done(struct tevent_req *subreq); 698 699/* 700 write to a file 701*/ 702static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs, 703 struct ntvfs_request *req, union smb_write *wr) 704{ 705 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 706 struct ipc_private); 707 struct pipe_state *p; 708 struct tevent_req *subreq; 709 struct ipc_write_state *state; 710 711 if (wr->generic.level != RAW_WRITE_GENERIC) { 712 return ntvfs_map_write(ntvfs, req, wr); 713 } 714 715 p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs); 716 if (!p) { 717 return NT_STATUS_INVALID_HANDLE; 718 } 719 720 state = talloc(req, struct ipc_write_state); 721 NT_STATUS_HAVE_NO_MEMORY(state); 722 723 state->ipriv = ipriv; 724 state->p = p; 725 state->req = req; 726 state->wr = wr; 727 state->iov.iov_base = discard_const_p(void, wr->writex.in.data); 728 state->iov.iov_len = wr->writex.in.count; 729 730 subreq = tstream_writev_queue_send(state, 731 ipriv->ntvfs->ctx->event_ctx, 732 p->npipe, 733 p->write_queue, 734 &state->iov, 1); 735 NT_STATUS_HAVE_NO_MEMORY(subreq); 736 tevent_req_set_callback(subreq, ipc_write_done, state); 737 738 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 739 return NT_STATUS_OK; 740} 741 742static void ipc_write_done(struct tevent_req *subreq) 743{ 744 struct ipc_write_state *state = 745 tevent_req_callback_data(subreq, 746 struct ipc_write_state); 747 struct ntvfs_request *req = state->req; 748 union smb_write *wr = state->wr; 749 int ret; 750 int sys_errno; 751 NTSTATUS status; 752 753 ret = tstream_writev_queue_recv(subreq, &sys_errno); 754 TALLOC_FREE(subreq); 755 if (ret == -1) { 756 status = map_nt_error_from_unix(sys_errno); 757 goto reply; 758 } 759 760 status = NT_STATUS_OK; 761 762 wr->writex.out.nwritten = ret; 763 wr->writex.out.remaining = 0; 764 765reply: 766 req->async_states->status = status; 767 req->async_states->send_fn(req); 768} 769 770/* 771 seek in a file 772*/ 773static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs, 774 struct ntvfs_request *req, 775 union smb_seek *io) 776{ 777 return NT_STATUS_ACCESS_DENIED; 778} 779 780/* 781 flush a file 782*/ 783static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs, 784 struct ntvfs_request *req, 785 union smb_flush *io) 786{ 787 return NT_STATUS_ACCESS_DENIED; 788} 789 790/* 791 close a file 792*/ 793static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs, 794 struct ntvfs_request *req, union smb_close *io) 795{ 796 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 797 struct ipc_private); 798 struct pipe_state *p; 799 800 if (io->generic.level != RAW_CLOSE_CLOSE) { 801 return ntvfs_map_close(ntvfs, req, io); 802 } 803 804 p = pipe_state_find(ipriv, io->close.in.file.ntvfs); 805 if (!p) { 806 return NT_STATUS_INVALID_HANDLE; 807 } 808 809 talloc_free(p); 810 811 return NT_STATUS_OK; 812} 813 814/* 815 exit - closing files 816*/ 817static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs, 818 struct ntvfs_request *req) 819{ 820 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 821 struct ipc_private); 822 struct pipe_state *p, *next; 823 824 for (p=ipriv->pipe_list; p; p=next) { 825 next = p->next; 826 if (p->handle->session_info == req->session_info && 827 p->handle->smbpid == req->smbpid) { 828 talloc_free(p); 829 } 830 } 831 832 return NT_STATUS_OK; 833} 834 835/* 836 logoff - closing files open by the user 837*/ 838static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs, 839 struct ntvfs_request *req) 840{ 841 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 842 struct ipc_private); 843 struct pipe_state *p, *next; 844 845 for (p=ipriv->pipe_list; p; p=next) { 846 next = p->next; 847 if (p->handle->session_info == req->session_info) { 848 talloc_free(p); 849 } 850 } 851 852 return NT_STATUS_OK; 853} 854 855/* 856 setup for an async call 857*/ 858static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs, 859 struct ntvfs_request *req, 860 void *private_data) 861{ 862 return NT_STATUS_OK; 863} 864 865/* 866 cancel an async call 867*/ 868static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs, 869 struct ntvfs_request *req) 870{ 871 return NT_STATUS_UNSUCCESSFUL; 872} 873 874/* 875 lock a byte range 876*/ 877static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs, 878 struct ntvfs_request *req, union smb_lock *lck) 879{ 880 return NT_STATUS_ACCESS_DENIED; 881} 882 883/* 884 set info on a open file 885*/ 886static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs, 887 struct ntvfs_request *req, union smb_setfileinfo *info) 888{ 889 return NT_STATUS_ACCESS_DENIED; 890} 891 892/* 893 query info on a open file 894*/ 895static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs, 896 struct ntvfs_request *req, union smb_fileinfo *info) 897{ 898 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 899 struct ipc_private); 900 struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs); 901 if (!p) { 902 return NT_STATUS_INVALID_HANDLE; 903 } 904 switch (info->generic.level) { 905 case RAW_FILEINFO_GENERIC: 906 { 907 ZERO_STRUCT(info->generic.out); 908 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL; 909 info->generic.out.fname.s = strrchr(p->pipe_name, '\\'); 910 info->generic.out.alloc_size = 4096; 911 info->generic.out.nlink = 1; 912 /* What the heck? Match Win2k3: IPC$ pipes are delete pending */ 913 info->generic.out.delete_pending = 1; 914 return NT_STATUS_OK; 915 } 916 case RAW_FILEINFO_ALT_NAME_INFO: 917 case RAW_FILEINFO_ALT_NAME_INFORMATION: 918 case RAW_FILEINFO_STREAM_INFO: 919 case RAW_FILEINFO_STREAM_INFORMATION: 920 case RAW_FILEINFO_COMPRESSION_INFO: 921 case RAW_FILEINFO_COMPRESSION_INFORMATION: 922 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION: 923 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION: 924 return NT_STATUS_INVALID_PARAMETER; 925 case RAW_FILEINFO_ALL_EAS: 926 return NT_STATUS_ACCESS_DENIED; 927 default: 928 return ntvfs_map_qfileinfo(ntvfs, req, info); 929 } 930 931 return NT_STATUS_ACCESS_DENIED; 932} 933 934 935/* 936 return filesystem info 937*/ 938static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs, 939 struct ntvfs_request *req, union smb_fsinfo *fs) 940{ 941 return NT_STATUS_ACCESS_DENIED; 942} 943 944/* 945 return print queue info 946*/ 947static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs, 948 struct ntvfs_request *req, union smb_lpq *lpq) 949{ 950 return NT_STATUS_ACCESS_DENIED; 951} 952 953/* 954 list files in a directory matching a wildcard pattern 955*/ 956static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs, 957 struct ntvfs_request *req, union smb_search_first *io, 958 void *search_private, 959 bool (*callback)(void *, const union smb_search_data *)) 960{ 961 return NT_STATUS_ACCESS_DENIED; 962} 963 964/* 965 continue listing files in a directory 966*/ 967static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs, 968 struct ntvfs_request *req, union smb_search_next *io, 969 void *search_private, 970 bool (*callback)(void *, const union smb_search_data *)) 971{ 972 return NT_STATUS_ACCESS_DENIED; 973} 974 975/* 976 end listing files in a directory 977*/ 978static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs, 979 struct ntvfs_request *req, union smb_search_close *io) 980{ 981 return NT_STATUS_ACCESS_DENIED; 982} 983 984struct ipc_trans_state { 985 struct ipc_private *ipriv; 986 struct pipe_state *p; 987 struct ntvfs_request *req; 988 struct smb_trans2 *trans; 989 struct iovec writev_iov; 990 struct ipc_readv_next_vector_state next_vector; 991}; 992 993static void ipc_trans_writev_done(struct tevent_req *subreq); 994static void ipc_trans_readv_done(struct tevent_req *subreq); 995 996/* SMBtrans - handle a DCERPC command */ 997static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs, 998 struct ntvfs_request *req, struct smb_trans2 *trans) 999{ 1000 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 1001 struct ipc_private); 1002 struct pipe_state *p; 1003 DATA_BLOB fnum_key; 1004 uint16_t fnum; 1005 struct ipc_trans_state *state; 1006 struct tevent_req *subreq; 1007 1008 /* 1009 * the fnum is in setup[1], a 16 bit value 1010 * the setup[*] values are already in host byteorder 1011 * but ntvfs_handle_search_by_wire_key() expects 1012 * network byteorder 1013 */ 1014 SSVAL(&fnum, 0, trans->in.setup[1]); 1015 fnum_key = data_blob_const(&fnum, 2); 1016 1017 p = pipe_state_find_key(ipriv, req, &fnum_key); 1018 if (!p) { 1019 return NT_STATUS_INVALID_HANDLE; 1020 } 1021 1022 /* 1023 * Trans requests are only allowed 1024 * if no other Trans or Read is active 1025 */ 1026 if (tevent_queue_length(p->read_queue) > 0) { 1027 return NT_STATUS_PIPE_BUSY; 1028 } 1029 1030 state = talloc(req, struct ipc_trans_state); 1031 NT_STATUS_HAVE_NO_MEMORY(state); 1032 1033 trans->out.setup_count = 0; 1034 trans->out.setup = NULL; 1035 trans->out.params = data_blob(NULL, 0); 1036 trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data); 1037 NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data); 1038 1039 state->ipriv = ipriv; 1040 state->p = p; 1041 state->req = req; 1042 state->trans = trans; 1043 state->writev_iov.iov_base = trans->in.data.data; 1044 state->writev_iov.iov_len = trans->in.data.length; 1045 1046 ipc_readv_next_vector_init(&state->next_vector, 1047 trans->out.data.data, 1048 trans->out.data.length); 1049 1050 subreq = tstream_writev_queue_send(state, 1051 ipriv->ntvfs->ctx->event_ctx, 1052 p->npipe, 1053 p->write_queue, 1054 &state->writev_iov, 1); 1055 NT_STATUS_HAVE_NO_MEMORY(subreq); 1056 tevent_req_set_callback(subreq, ipc_trans_writev_done, state); 1057 1058 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 1059 return NT_STATUS_OK; 1060} 1061 1062static void ipc_trans_writev_done(struct tevent_req *subreq) 1063{ 1064 struct ipc_trans_state *state = 1065 tevent_req_callback_data(subreq, 1066 struct ipc_trans_state); 1067 struct ipc_private *ipriv = state->ipriv; 1068 struct pipe_state *p = state->p; 1069 struct ntvfs_request *req = state->req; 1070 int ret; 1071 int sys_errno; 1072 NTSTATUS status; 1073 1074 ret = tstream_writev_queue_recv(subreq, &sys_errno); 1075 TALLOC_FREE(subreq); 1076 if (ret == 0) { 1077 status = NT_STATUS_PIPE_DISCONNECTED; 1078 goto reply; 1079 } else if (ret == -1) { 1080 status = map_nt_error_from_unix(sys_errno); 1081 goto reply; 1082 } 1083 1084 subreq = tstream_readv_pdu_queue_send(state, 1085 ipriv->ntvfs->ctx->event_ctx, 1086 p->npipe, 1087 p->read_queue, 1088 ipc_readv_next_vector, 1089 &state->next_vector); 1090 if (!subreq) { 1091 status = NT_STATUS_NO_MEMORY; 1092 goto reply; 1093 } 1094 tevent_req_set_callback(subreq, ipc_trans_readv_done, state); 1095 return; 1096 1097reply: 1098 req->async_states->status = status; 1099 req->async_states->send_fn(req); 1100} 1101 1102static void ipc_trans_readv_done(struct tevent_req *subreq) 1103{ 1104 struct ipc_trans_state *state = 1105 tevent_req_callback_data(subreq, 1106 struct ipc_trans_state); 1107 struct ntvfs_request *req = state->req; 1108 struct smb_trans2 *trans = state->trans; 1109 int ret; 1110 int sys_errno; 1111 NTSTATUS status; 1112 1113 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno); 1114 TALLOC_FREE(subreq); 1115 if (ret == -1) { 1116 status = map_nt_error_from_unix(sys_errno); 1117 goto reply; 1118 } 1119 1120 status = NT_STATUS_OK; 1121 if (state->next_vector.remaining > 0) { 1122 status = STATUS_BUFFER_OVERFLOW; 1123 } 1124 1125 trans->out.data.length = ret; 1126 1127reply: 1128 req->async_states->status = status; 1129 req->async_states->send_fn(req); 1130} 1131 1132/* SMBtrans - set named pipe state */ 1133static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs, 1134 struct ntvfs_request *req, struct smb_trans2 *trans) 1135{ 1136 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 1137 struct ipc_private); 1138 struct pipe_state *p; 1139 DATA_BLOB fnum_key; 1140 1141 /* the fnum is in setup[1] */ 1142 fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1])); 1143 1144 p = pipe_state_find_key(ipriv, req, &fnum_key); 1145 if (!p) { 1146 return NT_STATUS_INVALID_HANDLE; 1147 } 1148 1149 if (trans->in.params.length != 2) { 1150 return NT_STATUS_INVALID_PARAMETER; 1151 } 1152 1153 /* 1154 * TODO: pass this to the tstream_npa logic 1155 */ 1156 p->device_state = SVAL(trans->in.params.data, 0); 1157 1158 trans->out.setup_count = 0; 1159 trans->out.setup = NULL; 1160 trans->out.params = data_blob(NULL, 0); 1161 trans->out.data = data_blob(NULL, 0); 1162 1163 return NT_STATUS_OK; 1164} 1165 1166 1167/* SMBtrans - used to provide access to SMB pipes */ 1168static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs, 1169 struct ntvfs_request *req, struct smb_trans2 *trans) 1170{ 1171 NTSTATUS status; 1172 1173 if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN")) 1174 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans); 1175 1176 if (trans->in.setup_count != 2) { 1177 return NT_STATUS_INVALID_PARAMETER; 1178 } 1179 1180 switch (trans->in.setup[0]) { 1181 case TRANSACT_SETNAMEDPIPEHANDLESTATE: 1182 status = ipc_set_nm_pipe_state(ntvfs, req, trans); 1183 break; 1184 case TRANSACT_DCERPCCMD: 1185 status = ipc_dcerpc_cmd(ntvfs, req, trans); 1186 break; 1187 default: 1188 status = NT_STATUS_INVALID_PARAMETER; 1189 break; 1190 } 1191 1192 return status; 1193} 1194 1195struct ipc_ioctl_state { 1196 struct ipc_private *ipriv; 1197 struct pipe_state *p; 1198 struct ntvfs_request *req; 1199 union smb_ioctl *io; 1200 struct iovec writev_iov; 1201 struct ipc_readv_next_vector_state next_vector; 1202}; 1203 1204static void ipc_ioctl_writev_done(struct tevent_req *subreq); 1205static void ipc_ioctl_readv_done(struct tevent_req *subreq); 1206 1207static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs, 1208 struct ntvfs_request *req, union smb_ioctl *io) 1209{ 1210 struct ipc_private *ipriv = talloc_get_type_abort(ntvfs->private_data, 1211 struct ipc_private); 1212 struct pipe_state *p; 1213 struct ipc_ioctl_state *state; 1214 struct tevent_req *subreq; 1215 1216 switch (io->smb2.in.function) { 1217 case FSCTL_NAMED_PIPE_READ_WRITE: 1218 break; 1219 1220 default: 1221 return NT_STATUS_FS_DRIVER_REQUIRED; 1222 } 1223 1224 p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs); 1225 if (!p) { 1226 return NT_STATUS_INVALID_HANDLE; 1227 } 1228 1229 /* 1230 * Trans requests are only allowed 1231 * if no other Trans or Read is active 1232 */ 1233 if (tevent_queue_length(p->read_queue) > 0) { 1234 return NT_STATUS_PIPE_BUSY; 1235 } 1236 1237 state = talloc(req, struct ipc_ioctl_state); 1238 NT_STATUS_HAVE_NO_MEMORY(state); 1239 1240 io->smb2.out._pad = 0; 1241 io->smb2.out.function = io->smb2.in.function; 1242 io->smb2.out.unknown2 = 0; 1243 io->smb2.out.unknown3 = 0; 1244 io->smb2.out.in = io->smb2.in.out; 1245 io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_response_size); 1246 NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data); 1247 1248 state->ipriv = ipriv; 1249 state->p = p; 1250 state->req = req; 1251 state->io = io; 1252 state->writev_iov.iov_base = io->smb2.in.out.data; 1253 state->writev_iov.iov_len = io->smb2.in.out.length; 1254 1255 ipc_readv_next_vector_init(&state->next_vector, 1256 io->smb2.out.out.data, 1257 io->smb2.out.out.length); 1258 1259 subreq = tstream_writev_queue_send(state, 1260 ipriv->ntvfs->ctx->event_ctx, 1261 p->npipe, 1262 p->write_queue, 1263 &state->writev_iov, 1); 1264 NT_STATUS_HAVE_NO_MEMORY(subreq); 1265 tevent_req_set_callback(subreq, ipc_ioctl_writev_done, state); 1266 1267 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; 1268 return NT_STATUS_OK; 1269} 1270 1271static void ipc_ioctl_writev_done(struct tevent_req *subreq) 1272{ 1273 struct ipc_ioctl_state *state = 1274 tevent_req_callback_data(subreq, 1275 struct ipc_ioctl_state); 1276 struct ipc_private *ipriv = state->ipriv; 1277 struct pipe_state *p = state->p; 1278 struct ntvfs_request *req = state->req; 1279 int ret; 1280 int sys_errno; 1281 NTSTATUS status; 1282 1283 ret = tstream_writev_queue_recv(subreq, &sys_errno); 1284 TALLOC_FREE(subreq); 1285 if (ret == -1) { 1286 status = map_nt_error_from_unix(sys_errno); 1287 goto reply; 1288 } 1289 1290 subreq = tstream_readv_pdu_queue_send(state, 1291 ipriv->ntvfs->ctx->event_ctx, 1292 p->npipe, 1293 p->read_queue, 1294 ipc_readv_next_vector, 1295 &state->next_vector); 1296 if (!subreq) { 1297 status = NT_STATUS_NO_MEMORY; 1298 goto reply; 1299 } 1300 tevent_req_set_callback(subreq, ipc_ioctl_readv_done, state); 1301 return; 1302 1303reply: 1304 req->async_states->status = status; 1305 req->async_states->send_fn(req); 1306} 1307 1308static void ipc_ioctl_readv_done(struct tevent_req *subreq) 1309{ 1310 struct ipc_ioctl_state *state = 1311 tevent_req_callback_data(subreq, 1312 struct ipc_ioctl_state); 1313 struct ntvfs_request *req = state->req; 1314 union smb_ioctl *io = state->io; 1315 int ret; 1316 int sys_errno; 1317 NTSTATUS status; 1318 1319 ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno); 1320 TALLOC_FREE(subreq); 1321 if (ret == -1) { 1322 status = map_nt_error_from_unix(sys_errno); 1323 goto reply; 1324 } 1325 1326 status = NT_STATUS_OK; 1327 if (state->next_vector.remaining > 0) { 1328 status = STATUS_BUFFER_OVERFLOW; 1329 } 1330 1331 io->smb2.out.out.length = ret; 1332 1333reply: 1334 req->async_states->status = status; 1335 req->async_states->send_fn(req); 1336} 1337 1338/* 1339 ioctl interface 1340*/ 1341static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs, 1342 struct ntvfs_request *req, union smb_ioctl *io) 1343{ 1344 switch (io->generic.level) { 1345 case RAW_IOCTL_SMB2: 1346 return ipc_ioctl_smb2(ntvfs, req, io); 1347 1348 case RAW_IOCTL_SMB2_NO_HANDLE: 1349 return NT_STATUS_FS_DRIVER_REQUIRED; 1350 1351 default: 1352 return NT_STATUS_ACCESS_DENIED; 1353 } 1354 1355 return NT_STATUS_ACCESS_DENIED; 1356} 1357 1358 1359/* 1360 initialialise the IPC backend, registering ourselves with the ntvfs subsystem 1361 */ 1362NTSTATUS ntvfs_ipc_init(void) 1363{ 1364 NTSTATUS ret; 1365 struct ntvfs_ops ops; 1366 NTVFS_CURRENT_CRITICAL_SIZES(vers); 1367 1368 ZERO_STRUCT(ops); 1369 1370 /* fill in the name and type */ 1371 ops.name = "default"; 1372 ops.type = NTVFS_IPC; 1373 1374 /* fill in all the operations */ 1375 ops.connect = ipc_connect; 1376 ops.disconnect = ipc_disconnect; 1377 ops.unlink = ipc_unlink; 1378 ops.chkpath = ipc_chkpath; 1379 ops.qpathinfo = ipc_qpathinfo; 1380 ops.setpathinfo = ipc_setpathinfo; 1381 ops.open = ipc_open; 1382 ops.mkdir = ipc_mkdir; 1383 ops.rmdir = ipc_rmdir; 1384 ops.rename = ipc_rename; 1385 ops.copy = ipc_copy; 1386 ops.ioctl = ipc_ioctl; 1387 ops.read = ipc_read; 1388 ops.write = ipc_write; 1389 ops.seek = ipc_seek; 1390 ops.flush = ipc_flush; 1391 ops.close = ipc_close; 1392 ops.exit = ipc_exit; 1393 ops.lock = ipc_lock; 1394 ops.setfileinfo = ipc_setfileinfo; 1395 ops.qfileinfo = ipc_qfileinfo; 1396 ops.fsinfo = ipc_fsinfo; 1397 ops.lpq = ipc_lpq; 1398 ops.search_first = ipc_search_first; 1399 ops.search_next = ipc_search_next; 1400 ops.search_close = ipc_search_close; 1401 ops.trans = ipc_trans; 1402 ops.logoff = ipc_logoff; 1403 ops.async_setup = ipc_async_setup; 1404 ops.cancel = ipc_cancel; 1405 1406 /* register ourselves with the NTVFS subsystem. */ 1407 ret = ntvfs_register(&ops, &vers); 1408 1409 if (!NT_STATUS_IS_OK(ret)) { 1410 DEBUG(0,("Failed to register IPC backend!\n")); 1411 return ret; 1412 } 1413 1414 return ret; 1415} 1416