root/source4/ntvfs/ipc/vfs_ipc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pipe_state_find
  2. pipe_state_find_key
  3. ipc_connect
  4. ipc_disconnect
  5. ipc_unlink
  6. ipc_chkpath
  7. ipc_qpathinfo
  8. ipc_setpathinfo
  9. ipc_fd_destructor
  10. ipc_get_my_addr
  11. ipc_get_peer_addr
  12. ipc_open_generic
  13. ipc_open_ntcreatex
  14. ipc_open_openx
  15. ipc_open_smb2
  16. ipc_open
  17. ipc_mkdir
  18. ipc_rmdir
  19. ipc_rename
  20. ipc_copy
  21. ipc_readx_dcesrv_output
  22. ipc_read
  23. ipc_write
  24. ipc_seek
  25. ipc_flush
  26. ipc_close
  27. ipc_exit
  28. ipc_logoff
  29. ipc_async_setup
  30. ipc_cancel
  31. ipc_lock
  32. ipc_setfileinfo
  33. ipc_qfileinfo
  34. ipc_fsinfo
  35. ipc_lpq
  36. ipc_search_first
  37. ipc_search_next
  38. ipc_search_close
  39. ipc_trans_dcesrv_output
  40. ipc_dcerpc_cmd
  41. ipc_set_nm_pipe_state
  42. ipc_trans
  43. ipc_ioctl_smb2
  44. ipc_ioctl
  45. ntvfs_ipc_init

   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 "rpc_server/dcerpc_server.h"
  33 #include "libcli/raw/ioctl.h"
  34 #include "param/param.h"
  35 
  36 /* this is the private structure used to keep the state of an open
  37    ipc$ connection. It needs to keep information about all open
  38    pipes */
  39 struct ipc_private {
  40         struct ntvfs_module_context *ntvfs;
  41 
  42         struct dcesrv_context *dcesrv;
  43 
  44         /* a list of open pipes */
  45         struct pipe_state {
  46                 struct pipe_state *next, *prev;
  47                 struct ipc_private *ipriv;
  48                 const char *pipe_name;
  49                 struct ntvfs_handle *handle;
  50                 struct dcesrv_connection *dce_conn;
  51                 uint16_t ipc_state;
  52         } *pipe_list;
  53 };
  54 
  55 
  56 /*
  57   find a open pipe give a file handle
  58 */
  59 static struct pipe_state *pipe_state_find(struct ipc_private *ipriv, struct ntvfs_handle *handle)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         struct pipe_state *s;
  62         void *p;
  63 
  64         p = ntvfs_handle_get_backend_data(handle, ipriv->ntvfs);
  65         if (!p) return NULL;
  66 
  67         s = talloc_get_type(p, struct pipe_state);
  68         if (!s) return NULL;
  69 
  70         return s;
  71 }
  72 
  73 /*
  74   find a open pipe give a wire fnum
  75 */
  76 static struct pipe_state *pipe_state_find_key(struct ipc_private *ipriv, struct ntvfs_request *req, const DATA_BLOB *key)
     /* [<][>][^][v][top][bottom][index][help] */
  77 {
  78         struct ntvfs_handle *h;
  79 
  80         h = ntvfs_handle_search_by_wire_key(ipriv->ntvfs, req, key);
  81         if (!h) return NULL;
  82 
  83         return pipe_state_find(ipriv, h);
  84 }
  85 
  86 
  87 /*
  88   connect to a share - always works 
  89 */
  90 static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  91                             struct ntvfs_request *req, const char *sharename)
  92 {
  93         NTSTATUS status;
  94         struct ipc_private *ipriv;
  95 
  96         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "IPC");
  97         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
  98 
  99         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "IPC");
 100         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
 101 
 102         /* prepare the private state for this connection */
 103         ipriv = talloc(ntvfs, struct ipc_private);
 104         NT_STATUS_HAVE_NO_MEMORY(ipriv);
 105 
 106         ntvfs->private_data = ipriv;
 107 
 108         ipriv->ntvfs = ntvfs;
 109         ipriv->pipe_list = NULL;
 110 
 111         /* setup the DCERPC server subsystem */
 112         status = dcesrv_init_ipc_context(ipriv, ntvfs->ctx->lp_ctx, &ipriv->dcesrv);
 113         NT_STATUS_NOT_OK_RETURN(status);
 114 
 115         return NT_STATUS_OK;
 116 }
 117 
 118 /*
 119   disconnect from a share
 120 */
 121 static NTSTATUS ipc_disconnect(struct ntvfs_module_context *ntvfs)
     /* [<][>][^][v][top][bottom][index][help] */
 122 {
 123         return NT_STATUS_OK;
 124 }
 125 
 126 /*
 127   delete a file
 128 */
 129 static NTSTATUS ipc_unlink(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 130                            struct ntvfs_request *req,
 131                            union smb_unlink *unl)
 132 {
 133         return NT_STATUS_ACCESS_DENIED;
 134 }
 135 
 136 /*
 137   check if a directory exists
 138 */
 139 static NTSTATUS ipc_chkpath(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 140                             struct ntvfs_request *req,
 141                             union smb_chkpath *cp)
 142 {
 143         return NT_STATUS_ACCESS_DENIED;
 144 }
 145 
 146 /*
 147   return info on a pathname
 148 */
 149 static NTSTATUS ipc_qpathinfo(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 150                               struct ntvfs_request *req, union smb_fileinfo *info)
 151 {
 152         switch (info->generic.level) {
 153         case  RAW_FILEINFO_GENERIC:
 154                 return NT_STATUS_INVALID_DEVICE_REQUEST;
 155         case RAW_FILEINFO_GETATTR:
 156                 return NT_STATUS_ACCESS_DENIED;
 157         default:
 158                 return ntvfs_map_qpathinfo(ntvfs, req, info);
 159         }
 160 }
 161 
 162 /*
 163   set info on a pathname
 164 */
 165 static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 166                                 struct ntvfs_request *req, union smb_setfileinfo *st)
 167 {
 168         return NT_STATUS_ACCESS_DENIED;
 169 }
 170 
 171 
 172 /*
 173   destroy a open pipe structure
 174 */
 175 static int ipc_fd_destructor(struct pipe_state *p)
     /* [<][>][^][v][top][bottom][index][help] */
 176 {
 177         DLIST_REMOVE(p->ipriv->pipe_list, p);
 178         ntvfs_handle_remove_backend_data(p->handle, p->ipriv->ntvfs);
 179         return 0;
 180 }
 181 
 182 static struct socket_address *ipc_get_my_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 183 {
 184         struct ipc_private *ipriv = dce_conn->transport.private_data;
 185 
 186         return ntvfs_get_my_addr(ipriv->ntvfs, mem_ctx);
 187 }
 188 
 189 static struct socket_address *ipc_get_peer_addr(struct dcesrv_connection *dce_conn, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 190 {
 191         struct ipc_private *ipriv = dce_conn->transport.private_data;
 192 
 193         return ntvfs_get_peer_addr(ipriv->ntvfs, mem_ctx);
 194 }
 195 
 196 /*
 197   open a file backend - used for MSRPC pipes
 198 */
 199 static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 200                                  struct ntvfs_request *req, const char *fname, 
 201                                  struct pipe_state **ps)
 202 {
 203         struct pipe_state *p;
 204         NTSTATUS status;
 205         struct dcerpc_binding *ep_description;
 206         struct ipc_private *ipriv = ntvfs->private_data;
 207         struct ntvfs_handle *h;
 208 
 209         status = ntvfs_handle_new(ntvfs, req, &h);
 210         NT_STATUS_NOT_OK_RETURN(status);
 211 
 212         p = talloc(h, struct pipe_state);
 213         NT_STATUS_HAVE_NO_MEMORY(p);
 214 
 215         ep_description = talloc(req, struct dcerpc_binding);
 216         NT_STATUS_HAVE_NO_MEMORY(ep_description);
 217 
 218         while (fname[0] == '\\') fname++;
 219 
 220         p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname);
 221         NT_STATUS_HAVE_NO_MEMORY(p->pipe_name);
 222 
 223         p->handle = h;
 224         p->ipc_state = 0x5ff;
 225 
 226         /*
 227           we're all set, now ask the dcerpc server subsystem to open the 
 228           endpoint. At this stage the pipe isn't bound, so we don't
 229           know what interface the user actually wants, just that they want
 230           one of the interfaces attached to this pipe endpoint.
 231         */
 232         ep_description->transport = NCACN_NP;
 233         ep_description->endpoint = talloc_reference(ep_description, p->pipe_name);
 234 
 235         /* The session info is refcount-increased in the 
 236          * dcesrv_endpoint_search_connect() function
 237          */
 238         status = dcesrv_endpoint_search_connect(ipriv->dcesrv,
 239                                                 p,
 240                                                 ep_description, 
 241                                                 h->session_info,
 242                                                 ntvfs->ctx->event_ctx,
 243                                                 ntvfs->ctx->msg_ctx,
 244                                                 ntvfs->ctx->server_id,
 245                                                 0,
 246                                                 &p->dce_conn);
 247         NT_STATUS_NOT_OK_RETURN(status);
 248 
 249         p->dce_conn->transport.private_data             = ipriv;
 250         p->dce_conn->transport.report_output_data       = NULL;
 251         p->dce_conn->transport.get_my_addr              = ipc_get_my_addr;
 252         p->dce_conn->transport.get_peer_addr            = ipc_get_peer_addr;
 253         
 254         DLIST_ADD(ipriv->pipe_list, p);
 255 
 256         p->ipriv = ipriv;
 257 
 258         talloc_set_destructor(p, ipc_fd_destructor);
 259 
 260         status = ntvfs_handle_set_backend_data(h, ipriv->ntvfs, p);
 261         NT_STATUS_NOT_OK_RETURN(status);
 262 
 263         *ps = p;
 264         return NT_STATUS_OK;
 265 }
 266 
 267 /*
 268   open a file with ntcreatex - used for MSRPC pipes
 269 */
 270 static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 271                                    struct ntvfs_request *req, union smb_open *oi)
 272 {
 273         struct pipe_state *p;
 274         NTSTATUS status;
 275 
 276         status = ipc_open_generic(ntvfs, req, oi->ntcreatex.in.fname, &p);
 277         if (!NT_STATUS_IS_OK(status)) {
 278                 return status;
 279         }
 280 
 281         ZERO_STRUCT(oi->ntcreatex.out);
 282         oi->ntcreatex.out.file.ntvfs= p->handle;
 283         oi->ntcreatex.out.ipc_state = p->ipc_state;
 284         oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
 285 
 286         return status;
 287 }
 288 
 289 /*
 290   open a file with openx - used for MSRPC pipes
 291 */
 292 static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 293                                struct ntvfs_request *req, union smb_open *oi)
 294 {
 295         struct pipe_state *p;
 296         NTSTATUS status;
 297         const char *fname = oi->openx.in.fname;
 298 
 299         status = ipc_open_generic(ntvfs, req, fname, &p);
 300         if (!NT_STATUS_IS_OK(status)) {
 301                 return status;
 302         }
 303 
 304         ZERO_STRUCT(oi->openx.out);
 305         oi->openx.out.file.ntvfs= p->handle;
 306         oi->openx.out.ftype     = 2;
 307         oi->openx.out.devstate  = p->ipc_state;
 308         
 309         return status;
 310 }
 311 
 312 /*
 313   open a file with SMB2 Create - used for MSRPC pipes
 314 */
 315 static NTSTATUS ipc_open_smb2(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 316                               struct ntvfs_request *req, union smb_open *oi)
 317 {
 318         struct pipe_state *p;
 319         NTSTATUS status;
 320 
 321         status = ipc_open_generic(ntvfs, req, oi->smb2.in.fname, &p);
 322         NT_STATUS_NOT_OK_RETURN(status);
 323 
 324         ZERO_STRUCT(oi->smb2.out);
 325         oi->smb2.out.file.ntvfs         = p->handle;
 326         oi->smb2.out.oplock_level       = oi->smb2.in.oplock_level;
 327         oi->smb2.out.create_action      = NTCREATEX_ACTION_EXISTED;
 328         oi->smb2.out.create_time        = 0;
 329         oi->smb2.out.access_time        = 0;
 330         oi->smb2.out.write_time         = 0;
 331         oi->smb2.out.change_time        = 0;
 332         oi->smb2.out.alloc_size         = 4096;
 333         oi->smb2.out.size               = 0;
 334         oi->smb2.out.file_attr          = FILE_ATTRIBUTE_NORMAL;
 335         oi->smb2.out.reserved2          = 0;
 336 
 337         return status;
 338 }
 339 
 340 /*
 341   open a file - used for MSRPC pipes
 342 */
 343 static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 344                                 struct ntvfs_request *req, union smb_open *oi)
 345 {
 346         NTSTATUS status;
 347 
 348         switch (oi->generic.level) {
 349         case RAW_OPEN_NTCREATEX:
 350                 status = ipc_open_ntcreatex(ntvfs, req, oi);
 351                 break;
 352         case RAW_OPEN_OPENX:
 353                 status = ipc_open_openx(ntvfs, req, oi);
 354                 break;
 355         case RAW_OPEN_SMB2:
 356                 status = ipc_open_smb2(ntvfs, req, oi);
 357                 break;
 358         default:
 359                 status = NT_STATUS_NOT_SUPPORTED;
 360                 break;
 361         }
 362 
 363         return status;
 364 }
 365 
 366 /*
 367   create a directory
 368 */
 369 static NTSTATUS ipc_mkdir(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 370                           struct ntvfs_request *req, union smb_mkdir *md)
 371 {
 372         return NT_STATUS_ACCESS_DENIED;
 373 }
 374 
 375 /*
 376   remove a directory
 377 */
 378 static NTSTATUS ipc_rmdir(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 379                           struct ntvfs_request *req, struct smb_rmdir *rd)
 380 {
 381         return NT_STATUS_ACCESS_DENIED;
 382 }
 383 
 384 /*
 385   rename a set of files
 386 */
 387 static NTSTATUS ipc_rename(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 388                            struct ntvfs_request *req, union smb_rename *ren)
 389 {
 390         return NT_STATUS_ACCESS_DENIED;
 391 }
 392 
 393 /*
 394   copy a set of files
 395 */
 396 static NTSTATUS ipc_copy(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 397                          struct ntvfs_request *req, struct smb_copy *cp)
 398 {
 399         return NT_STATUS_ACCESS_DENIED;
 400 }
 401 
 402 static NTSTATUS ipc_readx_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
     /* [<][>][^][v][top][bottom][index][help] */
 403 {
 404         DATA_BLOB *blob = private_data;
 405 
 406         if (out->length < blob->length) {
 407                 blob->length = out->length;
 408         }
 409         memcpy(blob->data, out->data, blob->length);
 410         *nwritten = blob->length;
 411         return NT_STATUS_OK;
 412 }
 413 
 414 /*
 415   read from a file
 416 */
 417 static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 418                          struct ntvfs_request *req, union smb_read *rd)
 419 {
 420         struct ipc_private *ipriv = ntvfs->private_data;
 421         DATA_BLOB data;
 422         struct pipe_state *p;
 423         NTSTATUS status = NT_STATUS_OK;
 424 
 425         if (rd->generic.level != RAW_READ_GENERIC) {
 426                 return ntvfs_map_read(ntvfs, req, rd);
 427         }
 428 
 429         p = pipe_state_find(ipriv, rd->readx.in.file.ntvfs);
 430         if (!p) {
 431                 return NT_STATUS_INVALID_HANDLE;
 432         }
 433 
 434         data.length = rd->readx.in.maxcnt;
 435         data.data = rd->readx.out.data;
 436         if (data.length > UINT16_MAX) {
 437                 data.length = UINT16_MAX;
 438         }
 439 
 440         if (data.length != 0) {
 441                 status = dcesrv_output(p->dce_conn, &data, ipc_readx_dcesrv_output);
 442                 if (NT_STATUS_IS_ERR(status)) {
 443                         return status;
 444                 }
 445         }
 446 
 447         rd->readx.out.remaining = 0;
 448         rd->readx.out.compaction_mode = 0;
 449         rd->readx.out.nread = data.length;
 450 
 451         return status;
 452 }
 453 
 454 /*
 455   write to a file
 456 */
 457 static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 458                           struct ntvfs_request *req, union smb_write *wr)
 459 {
 460         struct ipc_private *ipriv = ntvfs->private_data;
 461         DATA_BLOB data;
 462         struct pipe_state *p;
 463         NTSTATUS status;
 464 
 465         if (wr->generic.level != RAW_WRITE_GENERIC) {
 466                 return ntvfs_map_write(ntvfs, req, wr);
 467         }
 468 
 469         data.data = discard_const_p(void, wr->writex.in.data);
 470         data.length = wr->writex.in.count;
 471 
 472         p = pipe_state_find(ipriv, wr->writex.in.file.ntvfs);
 473         if (!p) {
 474                 return NT_STATUS_INVALID_HANDLE;
 475         }
 476 
 477         status = dcesrv_input(p->dce_conn, &data);
 478         if (!NT_STATUS_IS_OK(status)) {
 479                 return status;
 480         }
 481 
 482         wr->writex.out.nwritten = data.length;
 483         wr->writex.out.remaining = 0;
 484 
 485         return NT_STATUS_OK;
 486 }
 487 
 488 /*
 489   seek in a file
 490 */
 491 static NTSTATUS ipc_seek(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 492                          struct ntvfs_request *req,
 493                          union smb_seek *io)
 494 {
 495         return NT_STATUS_ACCESS_DENIED;
 496 }
 497 
 498 /*
 499   flush a file
 500 */
 501 static NTSTATUS ipc_flush(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 502                           struct ntvfs_request *req,
 503                           union smb_flush *io)
 504 {
 505         return NT_STATUS_ACCESS_DENIED;
 506 }
 507 
 508 /*
 509   close a file
 510 */
 511 static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 512                           struct ntvfs_request *req, union smb_close *io)
 513 {
 514         struct ipc_private *ipriv = ntvfs->private_data;
 515         struct pipe_state *p;
 516 
 517         if (io->generic.level != RAW_CLOSE_CLOSE) {
 518                 return ntvfs_map_close(ntvfs, req, io);
 519         }
 520 
 521         p = pipe_state_find(ipriv, io->close.in.file.ntvfs);
 522         if (!p) {
 523                 return NT_STATUS_INVALID_HANDLE;
 524         }
 525 
 526         talloc_free(p);
 527 
 528         return NT_STATUS_OK;
 529 }
 530 
 531 /*
 532   exit - closing files
 533 */
 534 static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 535                          struct ntvfs_request *req)
 536 {
 537         struct ipc_private *ipriv = ntvfs->private_data;
 538         struct pipe_state *p, *next;
 539         
 540         for (p=ipriv->pipe_list; p; p=next) {
 541                 next = p->next;
 542                 if (p->handle->session_info == req->session_info &&
 543                     p->handle->smbpid == req->smbpid) {
 544                         talloc_free(p);
 545                 }
 546         }
 547 
 548         return NT_STATUS_OK;
 549 }
 550 
 551 /*
 552   logoff - closing files open by the user
 553 */
 554 static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 555                            struct ntvfs_request *req)
 556 {
 557         struct ipc_private *ipriv = ntvfs->private_data;
 558         struct pipe_state *p, *next;
 559         
 560         for (p=ipriv->pipe_list; p; p=next) {
 561                 next = p->next;
 562                 if (p->handle->session_info == req->session_info) {
 563                         talloc_free(p);
 564                 }
 565         }
 566 
 567         return NT_STATUS_OK;
 568 }
 569 
 570 /*
 571   setup for an async call
 572 */
 573 static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 574                                 struct ntvfs_request *req,
 575                                 void *private_data)
 576 {
 577         return NT_STATUS_OK;
 578 }
 579 
 580 /*
 581   cancel an async call
 582 */
 583 static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 584                            struct ntvfs_request *req)
 585 {
 586         return NT_STATUS_UNSUCCESSFUL;
 587 }
 588 
 589 /*
 590   lock a byte range
 591 */
 592 static NTSTATUS ipc_lock(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 593                          struct ntvfs_request *req, union smb_lock *lck)
 594 {
 595         return NT_STATUS_ACCESS_DENIED;
 596 }
 597 
 598 /*
 599   set info on a open file
 600 */
 601 static NTSTATUS ipc_setfileinfo(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 602                                 struct ntvfs_request *req, union smb_setfileinfo *info)
 603 {
 604         return NT_STATUS_ACCESS_DENIED;
 605 }
 606 
 607 /*
 608   query info on a open file
 609 */
 610 static NTSTATUS ipc_qfileinfo(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 611                               struct ntvfs_request *req, union smb_fileinfo *info)
 612 {
 613         struct ipc_private *ipriv = ntvfs->private_data;
 614         struct pipe_state *p = pipe_state_find(ipriv, info->generic.in.file.ntvfs);
 615         if (!p) {
 616                 return NT_STATUS_INVALID_HANDLE;
 617         }
 618         switch (info->generic.level) {
 619         case RAW_FILEINFO_GENERIC: 
 620         {
 621                 ZERO_STRUCT(info->generic.out);
 622                 info->generic.out.attrib = FILE_ATTRIBUTE_NORMAL;
 623                 info->generic.out.fname.s = strrchr(p->pipe_name, '\\');
 624                 info->generic.out.alloc_size = 4096;
 625                 info->generic.out.nlink = 1;
 626                 /* What the heck?  Match Win2k3: IPC$ pipes are delete pending */
 627                 info->generic.out.delete_pending = 1;
 628                 return NT_STATUS_OK;
 629         }
 630         case RAW_FILEINFO_ALT_NAME_INFO:
 631         case RAW_FILEINFO_ALT_NAME_INFORMATION:
 632         case RAW_FILEINFO_STREAM_INFO:
 633         case RAW_FILEINFO_STREAM_INFORMATION:
 634         case RAW_FILEINFO_COMPRESSION_INFO:
 635         case RAW_FILEINFO_COMPRESSION_INFORMATION:
 636         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
 637         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
 638                 return NT_STATUS_INVALID_PARAMETER;
 639         case  RAW_FILEINFO_ALL_EAS:
 640                 return NT_STATUS_ACCESS_DENIED;
 641         default:
 642                 return ntvfs_map_qfileinfo(ntvfs, req, info);
 643         }
 644         
 645         return NT_STATUS_ACCESS_DENIED;
 646 }
 647 
 648 
 649 /*
 650   return filesystem info
 651 */
 652 static NTSTATUS ipc_fsinfo(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 653                            struct ntvfs_request *req, union smb_fsinfo *fs)
 654 {
 655         return NT_STATUS_ACCESS_DENIED;
 656 }
 657 
 658 /*
 659   return print queue info
 660 */
 661 static NTSTATUS ipc_lpq(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 662                         struct ntvfs_request *req, union smb_lpq *lpq)
 663 {
 664         return NT_STATUS_ACCESS_DENIED;
 665 }
 666 
 667 /* 
 668    list files in a directory matching a wildcard pattern
 669 */
 670 static NTSTATUS ipc_search_first(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 671                           struct ntvfs_request *req, union smb_search_first *io,
 672                           void *search_private, 
 673                           bool (*callback)(void *, const union smb_search_data *))
 674 {
 675         return NT_STATUS_ACCESS_DENIED;
 676 }
 677 
 678 /* 
 679    continue listing files in a directory 
 680 */
 681 static NTSTATUS ipc_search_next(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 682                          struct ntvfs_request *req, union smb_search_next *io,
 683                          void *search_private, 
 684                          bool (*callback)(void *, const union smb_search_data *))
 685 {
 686         return NT_STATUS_ACCESS_DENIED;
 687 }
 688 
 689 /* 
 690    end listing files in a directory 
 691 */
 692 static NTSTATUS ipc_search_close(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 693                           struct ntvfs_request *req, union smb_search_close *io)
 694 {
 695         return NT_STATUS_ACCESS_DENIED;
 696 }
 697 
 698 static NTSTATUS ipc_trans_dcesrv_output(void *private_data, DATA_BLOB *out, size_t *nwritten)
     /* [<][>][^][v][top][bottom][index][help] */
 699 {
 700         NTSTATUS status = NT_STATUS_OK;
 701         DATA_BLOB *blob = private_data;
 702 
 703         if (out->length > blob->length) {
 704                 status = STATUS_BUFFER_OVERFLOW;
 705         }
 706 
 707         if (out->length < blob->length) {
 708                 blob->length = out->length;
 709         }
 710         memcpy(blob->data, out->data, blob->length);
 711         *nwritten = blob->length;
 712         return status;
 713 }
 714 
 715 /* SMBtrans - handle a DCERPC command */
 716 static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 717                                struct ntvfs_request *req, struct smb_trans2 *trans)
 718 {
 719         struct pipe_state *p;
 720         struct ipc_private *ipriv = ntvfs->private_data;
 721         NTSTATUS status;
 722         DATA_BLOB fnum_key;
 723         uint16_t fnum;
 724 
 725         /*
 726          * the fnum is in setup[1], a 16 bit value
 727          * the setup[*] values are already in host byteorder
 728          * but ntvfs_handle_search_by_wire_key() expects
 729          * network byteorder
 730          */
 731         SSVAL(&fnum, 0, trans->in.setup[1]);
 732         fnum_key = data_blob_const(&fnum, 2);
 733 
 734         p = pipe_state_find_key(ipriv, req, &fnum_key);
 735         if (!p) {
 736                 return NT_STATUS_INVALID_HANDLE;
 737         }
 738 
 739         trans->out.data = data_blob_talloc(req, NULL, trans->in.max_data);
 740         if (!trans->out.data.data) {
 741                 return NT_STATUS_NO_MEMORY;
 742         }
 743 
 744         /* pass the data to the dcerpc server. Note that we don't
 745            expect this to fail, and things like NDR faults are not
 746            reported at this stage. Those sorts of errors happen in the
 747            dcesrv_output stage */
 748         status = dcesrv_input(p->dce_conn, &trans->in.data);
 749         if (!NT_STATUS_IS_OK(status)) {
 750                 return status;
 751         }
 752 
 753         /*
 754           now ask the dcerpc system for some output. This doesn't yet handle
 755           async calls. Again, we only expect NT_STATUS_OK. If the call fails then
 756           the error is encoded at the dcerpc level
 757         */
 758         status = dcesrv_output(p->dce_conn, &trans->out.data, ipc_trans_dcesrv_output);
 759         if (NT_STATUS_IS_ERR(status)) {
 760                 return status;
 761         }
 762 
 763         trans->out.setup_count = 0;
 764         trans->out.setup = NULL;
 765         trans->out.params = data_blob(NULL, 0);
 766 
 767         return status;
 768 }
 769 
 770 
 771 /* SMBtrans - set named pipe state */
 772 static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 773                                       struct ntvfs_request *req, struct smb_trans2 *trans)
 774 {
 775         struct ipc_private *ipriv = ntvfs->private_data;
 776         struct pipe_state *p;
 777         DATA_BLOB fnum_key;
 778 
 779         /* the fnum is in setup[1] */
 780         fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1]));
 781 
 782         p = pipe_state_find_key(ipriv, req, &fnum_key);
 783         if (!p) {
 784                 return NT_STATUS_INVALID_HANDLE;
 785         }
 786 
 787         if (trans->in.params.length != 2) {
 788                 return NT_STATUS_INVALID_PARAMETER;
 789         }
 790         p->ipc_state = SVAL(trans->in.params.data, 0);
 791 
 792         trans->out.setup_count = 0;
 793         trans->out.setup = NULL;
 794         trans->out.params = data_blob(NULL, 0);
 795         trans->out.data = data_blob(NULL, 0);
 796 
 797         return NT_STATUS_OK;
 798 }
 799 
 800 
 801 /* SMBtrans - used to provide access to SMB pipes */
 802 static NTSTATUS ipc_trans(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 803                                 struct ntvfs_request *req, struct smb_trans2 *trans)
 804 {
 805         NTSTATUS status;
 806 
 807         if (strequal(trans->in.trans_name, "\\PIPE\\LANMAN"))
 808                 return ipc_rap_call(req, ntvfs->ctx->event_ctx, ntvfs->ctx->lp_ctx, trans);
 809 
 810         if (trans->in.setup_count != 2) {
 811                 return NT_STATUS_INVALID_PARAMETER;
 812         }
 813 
 814         switch (trans->in.setup[0]) {
 815         case TRANSACT_SETNAMEDPIPEHANDLESTATE:
 816                 status = ipc_set_nm_pipe_state(ntvfs, req, trans);
 817                 break;
 818         case TRANSACT_DCERPCCMD:
 819                 status = ipc_dcerpc_cmd(ntvfs, req, trans);
 820                 break;
 821         default:
 822                 status = NT_STATUS_INVALID_PARAMETER;
 823                 break;
 824         }
 825 
 826         return status;
 827 }
 828 
 829 static NTSTATUS ipc_ioctl_smb2(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 830                                struct ntvfs_request *req, union smb_ioctl *io)
 831 {
 832         struct pipe_state *p;
 833         struct ipc_private *ipriv = ntvfs->private_data;
 834         NTSTATUS status;
 835 
 836         switch (io->smb2.in.function) {
 837         case FSCTL_NAMED_PIPE_READ_WRITE:
 838                 break;
 839 
 840         default:
 841                 return NT_STATUS_FS_DRIVER_REQUIRED;
 842         }
 843 
 844         p = pipe_state_find(ipriv, io->smb2.in.file.ntvfs);
 845         if (!p) {
 846                 return NT_STATUS_INVALID_HANDLE;
 847         }
 848 
 849         io->smb2.out.out = data_blob_talloc(req, NULL, io->smb2.in.max_response_size);
 850         NT_STATUS_HAVE_NO_MEMORY(io->smb2.out.out.data);
 851 
 852         /* pass the data to the dcerpc server. Note that we don't
 853            expect this to fail, and things like NDR faults are not
 854            reported at this stage. Those sorts of errors happen in the
 855            dcesrv_output stage */
 856         status = dcesrv_input(p->dce_conn, &io->smb2.in.out);
 857         NT_STATUS_NOT_OK_RETURN(status);
 858 
 859         /*
 860           now ask the dcerpc system for some output. This doesn't yet handle
 861           async calls. Again, we only expect NT_STATUS_OK. If the call fails then
 862           the error is encoded at the dcerpc level
 863         */
 864         status = dcesrv_output(p->dce_conn, &io->smb2.out.out, ipc_trans_dcesrv_output);
 865         NT_STATUS_IS_ERR_RETURN(status);
 866 
 867         io->smb2.out._pad       = 0;
 868         io->smb2.out.function   = io->smb2.in.function;
 869         io->smb2.out.unknown2   = 0;
 870         io->smb2.out.unknown3   = 0;
 871         io->smb2.out.in         = io->smb2.in.out;
 872 
 873         return status;
 874 }
 875 
 876 /*
 877   ioctl interface
 878 */
 879 static NTSTATUS ipc_ioctl(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 880                           struct ntvfs_request *req, union smb_ioctl *io)
 881 {
 882         switch (io->generic.level) {
 883         case RAW_IOCTL_SMB2:
 884                 return ipc_ioctl_smb2(ntvfs, req, io);
 885 
 886         case RAW_IOCTL_SMB2_NO_HANDLE:
 887                 return NT_STATUS_FS_DRIVER_REQUIRED;
 888 
 889         default:
 890                 return NT_STATUS_ACCESS_DENIED;
 891         }
 892 
 893         return NT_STATUS_ACCESS_DENIED;
 894 }
 895 
 896 
 897 /*
 898   initialialise the IPC backend, registering ourselves with the ntvfs subsystem
 899  */
 900 NTSTATUS ntvfs_ipc_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 901 {
 902         NTSTATUS ret;
 903         struct ntvfs_ops ops;
 904         NTVFS_CURRENT_CRITICAL_SIZES(vers);
 905 
 906         ZERO_STRUCT(ops);
 907         
 908         /* fill in the name and type */
 909         ops.name = "default";
 910         ops.type = NTVFS_IPC;
 911 
 912         /* fill in all the operations */
 913         ops.connect = ipc_connect;
 914         ops.disconnect = ipc_disconnect;
 915         ops.unlink = ipc_unlink;
 916         ops.chkpath = ipc_chkpath;
 917         ops.qpathinfo = ipc_qpathinfo;
 918         ops.setpathinfo = ipc_setpathinfo;
 919         ops.open = ipc_open;
 920         ops.mkdir = ipc_mkdir;
 921         ops.rmdir = ipc_rmdir;
 922         ops.rename = ipc_rename;
 923         ops.copy = ipc_copy;
 924         ops.ioctl = ipc_ioctl;
 925         ops.read = ipc_read;
 926         ops.write = ipc_write;
 927         ops.seek = ipc_seek;
 928         ops.flush = ipc_flush;  
 929         ops.close = ipc_close;
 930         ops.exit = ipc_exit;
 931         ops.lock = ipc_lock;
 932         ops.setfileinfo = ipc_setfileinfo;
 933         ops.qfileinfo = ipc_qfileinfo;
 934         ops.fsinfo = ipc_fsinfo;
 935         ops.lpq = ipc_lpq;
 936         ops.search_first = ipc_search_first;
 937         ops.search_next = ipc_search_next;
 938         ops.search_close = ipc_search_close;
 939         ops.trans = ipc_trans;
 940         ops.logoff = ipc_logoff;
 941         ops.async_setup = ipc_async_setup;
 942         ops.cancel = ipc_cancel;
 943 
 944         /* register ourselves with the NTVFS subsystem. */
 945         ret = ntvfs_register(&ops, &vers);
 946 
 947         if (!NT_STATUS_IS_OK(ret)) {
 948                 DEBUG(0,("Failed to register IPC backend!\n"));
 949                 return ret;
 950         }
 951 
 952         return ret;
 953 }

/* [<][>][^][v][top][bottom][index][help] */