LCOV - code coverage report
Current view: top level - lib/util - modules.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 87 131 66.4 %
Date: 2024-02-28 12:06:22 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    Copyright (C) Jelmer Vernooij 2002-2003,2005-2007
       5             :    Copyright (C) Stefan (metze) Metzmacher 2003
       6             :    Copyright (C) Andrew Bartlett 2011
       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             : #include "includes.h"
      23             : #include "dynconfig/dynconfig.h"
      24             : #include "lib/util/samba_modules.h"
      25             : #include "lib/util/util_paths.h"
      26             : #include "system/filesys.h"
      27             : #include "system/dir.h"
      28             : 
      29             : /**
      30             :  * Obtain the init function from a shared library file
      31             :  */
      32      200332 : init_module_fn load_module(const char *path, bool is_probe, void **handle_out)
      33             : {
      34        4207 :         void *handle;
      35        4207 :         void *init_fn;
      36        4207 :         char *error;
      37             : 
      38             :         /* This should be a WAF build, where modules should be built
      39             :          * with no undefined symbols and are already linked against
      40             :          * the libraries that they are loaded by */
      41      200332 :         handle = dlopen(path, RTLD_NOW);
      42             : 
      43             :         /* This call should reset any possible non-fatal errors that
      44             :            occurred since last call to dl* functions */
      45      200332 :         error = dlerror();
      46             : 
      47      200332 :         if (handle == NULL) {
      48           0 :                 int level = is_probe ? 5 : 0;
      49           0 :                 DEBUG(level, ("Error loading module '%s': %s\n", path, error ? error : ""));
      50           0 :                 return NULL;
      51             :         }
      52             : 
      53      200332 :         init_fn = (init_module_fn)dlsym(handle, SAMBA_INIT_MODULE);
      54             : 
      55             :         /* we could check dlerror() to determine if it worked, because
      56             :            dlsym() can validly return NULL, but what would we do with
      57             :            a NULL pointer as a module init function? */
      58             : 
      59      200332 :         if (init_fn == NULL) {
      60           0 :                 DEBUG(0, ("Unable to find %s() in %s: %s\n",
      61             :                           SAMBA_INIT_MODULE, path, dlerror()));
      62           0 :                 DEBUG(1, ("Loading module '%s' failed\n", path));
      63           0 :                 dlclose(handle);
      64           0 :                 return NULL;
      65             :         }
      66             : 
      67      200332 :         if (handle_out) {
      68      180999 :                 *handle_out = handle;
      69             :         }
      70             : 
      71      200332 :         return (init_module_fn)init_fn;
      72             : }
      73             : 
      74             : /**
      75             :  * Obtain list of init functions from the modules in the specified
      76             :  * directory
      77             :  */
      78       62211 : static init_module_fn *load_modules(TALLOC_CTX *mem_ctx, const char *path)
      79             : {
      80        1310 :         DIR *dir;
      81        1310 :         struct dirent *entry;
      82        1310 :         char *filename;
      83       62211 :         int success = 0;
      84       62211 :         init_module_fn *ret = talloc_array(mem_ctx, init_module_fn, 2);
      85             : 
      86       62211 :         ret[0] = NULL;
      87             : 
      88       62211 :         dir = opendir(path);
      89       62211 :         if (dir == NULL) {
      90       43804 :                 talloc_free(ret);
      91       43804 :                 return NULL;
      92             :         }
      93             : 
      94       74554 :         while((entry = readdir(dir))) {
      95       56147 :                 if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name))
      96       36814 :                         continue;
      97             : 
      98       19333 :                 filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);
      99             : 
     100       19333 :                 ret[success] = load_module(filename, true, NULL);
     101       19333 :                 if (ret[success]) {
     102       19333 :                         ret = talloc_realloc(mem_ctx, ret, init_module_fn, success+2);
     103       19333 :                         success++;
     104       19333 :                         ret[success] = NULL;
     105             :                 }
     106             : 
     107       19333 :                 talloc_free(filename);
     108             :         }
     109             : 
     110       18407 :         closedir(dir);
     111             : 
     112       18407 :         return ret;
     113             : }
     114             : 
     115             : /**
     116             :  * Run the specified init functions.
     117             :  *
     118             :  * @return true if all functions ran successfully, false otherwise
     119             :  */
     120      136439 : bool run_init_functions(TALLOC_CTX *ctx, init_module_fn *fns)
     121             : {
     122        3588 :         int i;
     123      136439 :         bool ret = true;
     124             : 
     125      136439 :         if (fns == NULL)
     126       43674 :                 return true;
     127             : 
     128      687386 :         for (i = 0; fns[i]; i++) { ret &= (bool)NT_STATUS_IS_OK(fns[i](ctx)); }
     129             : 
     130       89177 :         return ret;
     131             : }
     132             : 
     133             : /**
     134             :  * Load the initialization functions from DSO files for a specific subsystem.
     135             :  *
     136             :  * Will return an array of function pointers to initialization functions
     137             :  */
     138             : 
     139       62211 : init_module_fn *load_samba_modules(TALLOC_CTX *mem_ctx, const char *subsystem)
     140             : {
     141       62211 :         char *path = modules_path(mem_ctx, subsystem);
     142        1310 :         init_module_fn *ret;
     143             : 
     144       62211 :         ret = load_modules(mem_ctx, path);
     145             : 
     146       62211 :         talloc_free(path);
     147             : 
     148       62211 :         return ret;
     149             : }
     150             : 
     151      180999 : static NTSTATUS load_module_absolute_path(const char *module_path,
     152             :                                           bool is_probe)
     153             : {
     154        2985 :         void *handle;
     155        2985 :         init_module_fn init;
     156        2985 :         NTSTATUS status;
     157             : 
     158      180999 :         DBG_INFO("%s module '%s'\n",
     159             :                  is_probe ? "Probing" : "Loading",
     160             :                  module_path);
     161             : 
     162      180999 :         init = load_module(module_path, is_probe, &handle);
     163      180999 :         if (init == NULL) {
     164           0 :                 return NT_STATUS_UNSUCCESSFUL;
     165             :         }
     166             : 
     167      180999 :         DBG_NOTICE("Module '%s' loaded\n", module_path);
     168             : 
     169      180999 :         status = init(NULL);
     170      180999 :         if (!NT_STATUS_IS_OK(status)) {
     171           0 :                 DBG_ERR("Module '%s' initialization failed: %s\n",
     172             :                         module_path,
     173             :                         get_friendly_nt_error_msg(status));
     174           0 :                 dlclose(handle);
     175           0 :                 return status;
     176             :         }
     177             : 
     178      180999 :         return NT_STATUS_OK;
     179             : }
     180             : 
     181             : /* Load all modules in list and return number of
     182             :  * modules that has been successfully loaded */
     183           0 : int smb_load_all_modules_absoute_path(const char **modules)
     184             : {
     185           0 :         int i;
     186           0 :         int success = 0;
     187             : 
     188           0 :         for(i = 0; modules[i] != NULL; i++) {
     189           0 :                 const char *module = modules[i];
     190           0 :                 NTSTATUS status;
     191             : 
     192           0 :                 if (module[0] != '/') {
     193           0 :                         continue;
     194             :                 }
     195             : 
     196           0 :                 status = load_module_absolute_path(module, false);
     197           0 :                 if (NT_STATUS_IS_OK(status)) {
     198           0 :                         success++;
     199             :                 }
     200             :         }
     201             : 
     202           0 :         DEBUG(2, ("%d modules successfully loaded\n", success));
     203             : 
     204           0 :         return success;
     205             : }
     206             : 
     207             : /**
     208             :  * @brief Check if a module exist and load it.
     209             :  *
     210             :  * @param[in]  subsystem  The name of the subsystem the module belongs too.
     211             :  *
     212             :  * @param[in]  module     The name of the module
     213             :  *
     214             :  * @return  A NTSTATUS code
     215             :  */
     216           2 : NTSTATUS smb_probe_module(const char *subsystem, const char *module)
     217             : {
     218           2 :         NTSTATUS status;
     219           2 :         char *module_path = NULL;
     220           2 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     221             : 
     222           2 :         if (subsystem == NULL) {
     223           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     224           0 :                 goto done;
     225             :         }
     226           2 :         if (module == NULL) {
     227           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     228           0 :                 goto done;
     229             :         }
     230             : 
     231           2 :         if (strchr(module, '/')) {
     232           1 :                 status = NT_STATUS_INVALID_PARAMETER;
     233           1 :                 goto done;
     234             :         }
     235             : 
     236           1 :         module_path = talloc_asprintf(tmp_ctx,
     237             :                                       "%s/%s.%s",
     238             :                                       modules_path(tmp_ctx, subsystem),
     239             :                                       module,
     240             :                                       shlib_ext());
     241           1 :         if (module_path == NULL) {
     242           0 :                 status = NT_STATUS_NO_MEMORY;
     243           0 :                 goto done;
     244             :         }
     245             : 
     246           1 :         status = load_module_absolute_path(module_path, true);
     247             : 
     248           2 : done:
     249           2 :         TALLOC_FREE(tmp_ctx);
     250           2 :         return status;
     251             : }
     252             : 
     253             : /**
     254             :  * @brief Check if a module exist and load it.
     255             :  *
     256             :  * Warning: Using this function can have security implecations!
     257             :  *
     258             :  * @param[in]  subsystem  The name of the subsystem the module belongs too.
     259             :  *
     260             :  * @param[in]  module     Load a module using an absolute path.
     261             :  *
     262             :  * @return  A NTSTATUS code
     263             :  */
     264           0 : NTSTATUS smb_probe_module_absolute_path(const char *module)
     265             : {
     266           0 :         if (module == NULL) {
     267           0 :                 return NT_STATUS_INVALID_PARAMETER;
     268             :         }
     269           0 :         if (module[0] != '/') {
     270           0 :                 return NT_STATUS_INVALID_PARAMETER;
     271             :         }
     272             : 
     273           0 :         return load_module_absolute_path(module, true);
     274             : }
     275             : 
     276             : /**
     277             :  * @brief Load a module.
     278             :  *
     279             :  * @param[in]  subsystem  The name of the subsystem the module belongs too.
     280             :  *
     281             :  * @param[in]  module     Check if a module exists and load it.
     282             :  *
     283             :  * @return  A NTSTATUS code
     284             :  */
     285      180998 : NTSTATUS smb_load_module(const char *subsystem, const char *module)
     286             : {
     287        2984 :         NTSTATUS status;
     288      180998 :         char *module_path = NULL;
     289      180998 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     290             : 
     291      180998 :         if (subsystem == NULL) {
     292           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     293           0 :                 goto done;
     294             :         }
     295      180998 :         if (module == NULL) {
     296           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     297           0 :                 goto done;
     298             :         }
     299             : 
     300      180998 :         if (strchr(module, '/')) {
     301           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     302           0 :                 goto done;
     303             :         }
     304             : 
     305      180998 :         module_path = talloc_asprintf(tmp_ctx,
     306             :                                       "%s/%s.%s",
     307             :                                       modules_path(tmp_ctx, subsystem),
     308             :                                       module,
     309             :                                       shlib_ext());
     310      180998 :         if (module_path == NULL) {
     311           0 :                 status = NT_STATUS_NO_MEMORY;
     312           0 :                 goto done;
     313             :         }
     314             : 
     315      180998 :         status = load_module_absolute_path(module_path, false);
     316             : 
     317      180998 : done:
     318      180998 :         TALLOC_FREE(tmp_ctx);
     319      180998 :         return status;
     320             : }

Generated by: LCOV version 1.14