Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2016 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <dlfcn.h>
22 : #include "config.h"
23 : #include "providers/data_provider/dp.h"
24 : #include "providers/data_provider/dp_private.h"
25 : #include "providers/backend.h"
26 : #include "util/util.h"
27 :
28 : /* There can be at most the same number of different modules loaded at
29 : * one time as the maximum number of defined targets. */
30 : #define DP_MAX_MODULES DP_TARGET_SENTINEL
31 :
32 : #define DP_MODULE_PATH DATA_PROVIDER_PLUGINS_PATH "/libsss_%s.so"
33 : #define DP_MODULE_INIT_FN "sssm_%s_init"
34 :
35 0 : static errno_t dp_module_open_lib(struct dp_module *module)
36 : {
37 0 : char *libpath = NULL;
38 : errno_t ret;
39 :
40 0 : libpath = talloc_asprintf(module, DP_MODULE_PATH, module->name);
41 0 : if (libpath == NULL) {
42 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
43 0 : return ENOMEM;
44 : }
45 :
46 0 : DEBUG(SSSDBG_TRACE_LIBS, "Loading module [%s] with path [%s]\n",
47 : module->name, libpath);
48 :
49 0 : module->libhandle = dlopen(libpath, RTLD_NOW);
50 0 : if (module->libhandle == NULL) {
51 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load module [%s] with path "
52 : "[%s]: %s\n", module->name, libpath, dlerror());
53 0 : ret = ELIBACC;
54 0 : goto done;
55 : }
56 :
57 0 : ret = EOK;
58 :
59 : done:
60 0 : talloc_free(libpath);
61 0 : return ret;
62 : }
63 :
64 0 : static errno_t dp_module_run_constructor(struct dp_module *module,
65 : struct be_ctx *be_ctx,
66 : struct data_provider *provider)
67 : {
68 : char *fn_name;
69 : dp_module_init_fn fn;
70 : errno_t ret;
71 :
72 0 : fn_name = talloc_asprintf(module, DP_MODULE_INIT_FN, module->name);
73 0 : if (fn_name == NULL) {
74 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
75 0 : return ENOMEM;
76 : }
77 :
78 0 : fn = (dp_module_init_fn)dlsym(module->libhandle, fn_name);
79 0 : if (fn != NULL) {
80 0 : DEBUG(SSSDBG_TRACE_FUNC, "Executing module [%s] constructor.\n",
81 : module->name);
82 :
83 0 : ret = fn(module, be_ctx, provider, module->name, &module->module_data);
84 0 : if (ret != EOK) {
85 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Module [%s] constructor failed "
86 : "[%d]: %s\n", module->name, ret, sss_strerror(ret));
87 0 : goto done;
88 : }
89 : } else {
90 0 : DEBUG(SSSDBG_TRACE_FUNC, "No constructor found for module [%s].\n",
91 : module->name);
92 0 : module->module_data = NULL;
93 0 : ret = EOK;
94 0 : goto done;
95 : }
96 :
97 0 : ret = EOK;
98 :
99 : done:
100 0 : talloc_free(fn_name);
101 0 : return ret;
102 : }
103 :
104 0 : static errno_t dp_module_find(struct dp_module **modules,
105 : const char *name,
106 : struct dp_module **_module,
107 : unsigned int *_slot)
108 : {
109 : unsigned int slot;
110 :
111 0 : for (slot = 0; modules[slot] != NULL; slot++) {
112 0 : if (strcmp(modules[slot]->name, name) == 0) {
113 0 : *_module = modules[slot];
114 0 : *_slot = slot;
115 :
116 0 : return EOK;
117 : }
118 : }
119 :
120 0 : if (slot == DP_MAX_MODULES) {
121 : /* This should not happen. */
122 0 : DEBUG(SSSDBG_CRIT_FAILURE, "All module slots are taken.\n");
123 :
124 0 : return ERR_INTERNAL;
125 : }
126 :
127 0 : *_module = NULL;
128 0 : *_slot = slot;
129 :
130 0 : return EOK;
131 : }
132 :
133 0 : static struct dp_module *dp_module_create(TALLOC_CTX *mem_ctx,
134 : struct be_ctx *be_ctx,
135 : struct data_provider *provider,
136 : const char *name)
137 : {
138 : struct dp_module *module;
139 : errno_t ret;
140 :
141 0 : module = talloc_zero(mem_ctx, struct dp_module);
142 0 : if (module == NULL) {
143 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n");
144 0 : ret = ENOMEM;
145 0 : goto done;
146 : }
147 :
148 0 : module->name = talloc_strdup(module, name);
149 0 : if (module->name == NULL) {
150 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
151 0 : ret = ENOMEM;
152 0 : goto done;
153 : }
154 :
155 0 : ret = dp_module_open_lib(module);
156 0 : if (ret != EOK) {
157 0 : goto done;
158 : }
159 :
160 0 : ret = dp_module_run_constructor(module, be_ctx, provider);
161 0 : if (ret != EOK) {
162 0 : goto done;
163 : }
164 :
165 0 : module->initialized = true;
166 :
167 0 : ret = EOK;
168 :
169 : done:
170 0 : if (ret != EOK) {
171 0 : talloc_free(module);
172 0 : return NULL;
173 : }
174 :
175 0 : return module;
176 : }
177 :
178 0 : struct dp_module *dp_load_module(TALLOC_CTX *mem_ctx,
179 : struct be_ctx *be_ctx,
180 : struct data_provider *provider,
181 : struct dp_module **modules,
182 : const char *name)
183 : {
184 : struct dp_module *module;
185 : unsigned int free_slot;
186 : errno_t ret;
187 :
188 0 : ret = dp_module_find(modules, name, &module, &free_slot);
189 0 : if (ret != EOK) {
190 0 : return NULL;
191 : }
192 :
193 0 : if (module != NULL) {
194 0 : DEBUG(SSSDBG_TRACE_FUNC, "Module [%s] is already loaded.\n", name);
195 0 : return module;
196 : }
197 :
198 0 : DEBUG(SSSDBG_TRACE_FUNC, "About to load module [%s].\n", name);
199 :
200 0 : module = dp_module_create(mem_ctx, be_ctx, provider, name);
201 0 : if (module == NULL) {
202 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create DP module.\n");
203 0 : return NULL;
204 : }
205 :
206 0 : modules[free_slot] = module;
207 :
208 0 : return module;
209 : }
210 :
211 0 : errno_t dp_init_modules(TALLOC_CTX *mem_ctx, struct dp_module ***_modules)
212 : {
213 : struct dp_module **modules;
214 :
215 0 : modules = talloc_zero_array(mem_ctx, struct dp_module *,
216 : DP_MAX_MODULES + 1);
217 0 : if (modules == NULL) {
218 0 : return ENOMEM;
219 : }
220 :
221 0 : *_modules = modules;
222 :
223 0 : return EOK;
224 : }
|