LCOV - code coverage report
Current view: top level - source4/ntvfs - ntvfs_base.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 70 89 78.7 %
Date: 2021-09-23 10:06:22 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    NTVFS base code
       4             : 
       5             :    Copyright (C) Andrew Tridgell 2003
       6             :    Copyright (C) Stefan (metze) Metzmacher 2004
       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 core code for all NTVFS modules. Backends register themselves here.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "../lib/util/dlinklist.h"
      27             : #include "ntvfs/ntvfs.h"
      28             : #include "param/param.h"
      29             : #include "lib/util/samba_modules.h"
      30             : 
      31             : /* the list of currently registered NTVFS backends, note that there
      32             :  * can be more than one backend with the same name, as long as they
      33             :  * have different typesx */
      34             : static struct ntvfs_backend {
      35             :         const struct ntvfs_ops *ops;
      36             : } *backends = NULL;
      37             : static int num_backends;
      38             : 
      39             : /*
      40             :   register a NTVFS backend. 
      41             : 
      42             :   The 'name' can be later used by other backends to find the operations
      43             :   structure for this backend.  
      44             : 
      45             :   The 'type' is used to specify whether this is for a disk, printer or IPC$ share
      46             : */
      47         528 : NTSTATUS ntvfs_register(const struct ntvfs_ops *ops,
      48             :                                  const struct ntvfs_critical_sizes *const sizes)
      49             : {
      50             :         struct ntvfs_ops *new_ops;
      51             : 
      52         528 :         if (ntvfs_interface_differs(sizes)) {
      53           0 :                 DEBUG(0, ("NTVFS backend '%s' for type %d "
      54             :                           "failed version check\n",
      55             :                           ops->name, (int)ops->type));
      56           0 :                 return NT_STATUS_BAD_FUNCTION_TABLE;
      57             :         }
      58             : 
      59         528 :         if (ntvfs_backend_byname(ops->name, ops->type) != NULL) {
      60             :                 /* its already registered! */
      61           0 :                 DEBUG(0,("NTVFS backend '%s' for type %d already registered\n", 
      62             :                          ops->name, (int)ops->type));
      63           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
      64             :         }
      65             : 
      66         528 :         backends = realloc_p(backends, struct ntvfs_backend, num_backends+1);
      67         528 :         if (!backends) {
      68           0 :                 smb_panic("out of memory in ntvfs_register");
      69             :         }
      70             : 
      71         528 :         new_ops = smb_xmemdup(ops, sizeof(*ops));
      72         528 :         new_ops->name = smb_xstrdup(ops->name);
      73             : 
      74         528 :         backends[num_backends].ops = new_ops;
      75             : 
      76         528 :         num_backends++;
      77             : 
      78         528 :         DEBUG(3,("NTVFS backend '%s' for type %d registered\n", 
      79             :                  ops->name,ops->type));
      80             : 
      81         528 :         return NT_STATUS_OK;
      82             : }
      83             : 
      84             : 
      85             : /*
      86             :   return the operations structure for a named backend of the specified type
      87             : */
      88        4561 : const struct ntvfs_ops *ntvfs_backend_byname(const char *name, enum ntvfs_type type)
      89             : {
      90             :         int i;
      91             : 
      92       18210 :         for (i=0;i<num_backends;i++) {
      93       25682 :                 if (backends[i].ops->type == type && 
      94        9110 :                     strcmp(backends[i].ops->name, name) == 0) {
      95        4033 :                         return backends[i].ops;
      96             :                 }
      97             :         }
      98             : 
      99         504 :         return NULL;
     100             : }
     101             : 
     102             : 
     103             : /*
     104             :   return the NTVFS interface version, and the size of some critical types
     105             :   This can be used by backends to either detect compilation errors, or provide
     106             :   multiple implementations for different smbd compilation options in one module
     107             : */
     108             : 
     109             : static const NTVFS_CURRENT_CRITICAL_SIZES(critical_sizes);
     110             : 
     111           0 : const struct ntvfs_critical_sizes *ntvfs_interface_version(void)
     112             : {
     113           0 :         return &critical_sizes;
     114             : }
     115             : 
     116         528 : bool ntvfs_interface_differs(const struct ntvfs_critical_sizes *const iface)
     117             : {
     118             :         /* The comparison would be easier with memcmp, but compiler-interset
     119             :          * alignment padding is not guaranteed to be zeroed.
     120             :          */
     121             : 
     122             : #define FIELD_DIFFERS(field) (iface->field != critical_sizes.field)
     123             : 
     124         528 :         if (FIELD_DIFFERS(interface_version))
     125           0 :                 return true;
     126             : 
     127         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_critical_sizes))
     128           0 :                 return true;
     129             : 
     130         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_context))
     131           0 :                 return true;
     132             : 
     133         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_module_context))
     134           0 :                 return true;
     135             : 
     136         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_ops))
     137           0 :                 return true;
     138             : 
     139         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_async_state))
     140           0 :                 return true;
     141             : 
     142         528 :         if (FIELD_DIFFERS(sizeof_ntvfs_request))
     143           0 :                 return true;
     144             : 
     145             :         /* Versions match. */
     146         528 :         return false;
     147             : 
     148             : #undef FIELD_DIFFERS
     149             : }
     150             : 
     151             : /*
     152             :   initialise a connection structure to point at a NTVFS backend
     153             : */
     154        2690 : NTSTATUS ntvfs_init_connection(TALLOC_CTX *mem_ctx, struct share_config *scfg, enum ntvfs_type type,
     155             :                                enum protocol_types protocol,
     156             :                                uint64_t ntvfs_client_caps,
     157             :                                struct tevent_context *ev, struct imessaging_context *msg,
     158             :                                struct loadparm_context *lp_ctx,
     159             :                                struct server_id server_id, struct ntvfs_context **_ctx)
     160             : {
     161        2690 :         const char **handlers = share_string_list_option(mem_ctx, scfg, SHARE_NTVFS_HANDLER);
     162             :         int i;
     163             :         struct ntvfs_context *ctx;
     164             : 
     165        2690 :         if (!handlers) {
     166           0 :                 return NT_STATUS_INTERNAL_ERROR;
     167             :         }
     168             : 
     169        2690 :         ctx = talloc_zero(mem_ctx, struct ntvfs_context);
     170        2690 :         NT_STATUS_HAVE_NO_MEMORY(ctx);
     171        2690 :         ctx->protocol                = protocol;
     172        2690 :         ctx->client_caps     = ntvfs_client_caps;
     173        2690 :         ctx->type            = type;
     174        2690 :         ctx->config          = talloc_steal(ctx, scfg);
     175        2690 :         ctx->event_ctx               = ev;
     176        2690 :         ctx->msg_ctx         = msg;
     177        2690 :         ctx->server_id               = server_id;
     178        2690 :         ctx->lp_ctx          = lp_ctx;
     179             : 
     180        6723 :         for (i=0; handlers[i]; i++) {
     181             :                 struct ntvfs_module_context *ntvfs;
     182             : 
     183        4033 :                 ntvfs = talloc_zero(ctx, struct ntvfs_module_context);
     184        4033 :                 NT_STATUS_HAVE_NO_MEMORY(ntvfs);
     185        4033 :                 ntvfs->ctx = ctx;
     186        4033 :                 ntvfs->ops = ntvfs_backend_byname(handlers[i], ctx->type);
     187        4033 :                 if (!ntvfs->ops) {
     188           0 :                         DEBUG(1,("ntvfs_init_connection: failed to find backend=%s, type=%d\n",
     189             :                                 handlers[i], ctx->type));
     190           0 :                         return NT_STATUS_INTERNAL_ERROR;
     191             :                 }
     192        4033 :                 ntvfs->depth = i;
     193        4033 :                 DLIST_ADD_END(ctx->modules, ntvfs);
     194             :         }
     195             : 
     196        2690 :         if (!ctx->modules) {
     197           0 :                 return NT_STATUS_INTERNAL_ERROR;
     198             :         }
     199             : 
     200        2690 :         *_ctx = ctx;
     201        2690 :         return NT_STATUS_OK;
     202             : }
     203             : 
     204             : /*
     205             :   adds the IPC$ share, needed for RPC calls
     206             :  */
     207          66 : static NTSTATUS ntvfs_add_ipc_share(struct loadparm_context *lp_ctx)
     208             : {
     209             :         struct loadparm_service *ipc;
     210             : 
     211          66 :         if (lpcfg_service(lp_ctx, "IPC$")) {
     212             :                 /* it has already been defined in smb.conf or elsewhere */
     213           0 :                 return NT_STATUS_OK;
     214             :         }
     215             : 
     216          66 :         ipc = lpcfg_add_service(lp_ctx, NULL, "IPC$");
     217          66 :         NT_STATUS_HAVE_NO_MEMORY(ipc);
     218             : 
     219          66 :         lpcfg_do_service_parameter(lp_ctx, ipc, "comment", "IPC Service");
     220          66 :         lpcfg_do_service_parameter(lp_ctx, ipc, "path", "/dev/null");
     221          66 :         lpcfg_do_service_parameter(lp_ctx, ipc, "ntvfs handler", "default");
     222          66 :         lpcfg_do_service_parameter(lp_ctx, ipc, "browseable", "No");
     223          66 :         lpcfg_do_service_parameter(lp_ctx, ipc, "fstype", "IPC");
     224             : 
     225          66 :         return NT_STATUS_OK;
     226             : }
     227             : 
     228          66 : NTSTATUS ntvfs_init(struct loadparm_context *lp_ctx)
     229             : {
     230             :         static bool initialized = false;
     231             : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
     232             :         STATIC_ntvfs_MODULES_PROTO;
     233          66 :         init_module_fn static_init[] = { STATIC_ntvfs_MODULES };
     234             :         init_module_fn *shared_init;
     235             : 
     236          66 :         if (initialized) return NT_STATUS_OK;
     237          66 :         initialized = true;
     238             :         
     239          66 :         shared_init = load_samba_modules(NULL, "ntvfs");
     240             : 
     241          66 :         run_init_functions(NULL, static_init);
     242          66 :         run_init_functions(NULL, shared_init);
     243             : 
     244          66 :         talloc_free(shared_init);
     245             : 
     246          66 :         ntvfs_add_ipc_share(lp_ctx);
     247             :         
     248          66 :         return NT_STATUS_OK;
     249             : }

Generated by: LCOV version 1.13