6 Copyright (C) Julien Kerihuel 2009
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.
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.
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/>.
22 #include "mapiproxy/dcesrv_mapiproxy.h"
23 #include "mapiproxy/libmapiproxy.h"
24 #include <util/debug.h>
27 \file dcesrv_mapiproxy_server.c
29 \brief mapiproxy server modules management
32 static struct server_module {
33 struct mapiproxy_module *server_module;
34 } *server_modules = NULL;
36 int num_server_modules;
37 static struct mapiproxy_module_list *server_list = NULL;
39 static TDB_CONTEXT *emsabp_tdb_ctx = NULL;
42 NTSTATUS mapiproxy_server_dispatch(struct dcesrv_call_state *dce_call,
43 TALLOC_CTX *mem_ctx, void *r,
44 struct mapiproxy *mapiproxy)
46 struct mapiproxy_module_list *server;
47 const struct ndr_interface_table *table;
50 table = (const struct ndr_interface_table *)dce_call->context->iface->private;
52 for (server = server_list; server; server = server->next) {
53 if (server->module->endpoint && table->name &&
54 !strcmp(table->name, server->module->endpoint)) {
55 if (server->module->dispatch) {
56 mapiproxy->norelay = true;
57 status = server->module->dispatch(dce_call, mem_ctx, r, mapiproxy);
58 NT_STATUS_NOT_OK_RETURN(status);
67 NTSTATUS mapiproxy_server_unbind(struct server_id server_id, uint32_t context_id)
69 struct mapiproxy_module_list *server;
72 for (server = server_list; server; server = server->next) {
73 if (server->module->unbind) {
74 status = server->module->unbind(server_id, context_id);
75 NT_STATUS_NOT_OK_RETURN(status);
83 extern NTSTATUS mapiproxy_server_register(const void *_server_module)
85 const struct mapiproxy_module *server_module = _server_module;
87 server_modules = realloc_p(server_modules, struct server_module, num_server_modules + 1);
88 if (!server_modules) {
89 smb_panic("out of memory in mapiproxy_server_register");
92 server_modules[num_server_modules].server_module = smb_xmemdup(server_module, sizeof (*server_module));
93 server_modules[num_server_modules].server_module->name = smb_xstrdup(server_module->name);
97 DEBUG(3, ("MAPIPROXY server '%s' registered\n", server_module->name));
103 _PUBLIC_ bool mapiproxy_server_loaded(const char *endpoint)
105 struct mapiproxy_module_list *server;
107 if (!endpoint) return false;
109 for (server = server_list; server; server = server->next) {
110 if (server->module->endpoint && !strcmp(endpoint, server->module->endpoint)) {
119 static NTSTATUS mapiproxy_server_overwrite(TALLOC_CTX *mem_ctx, const char *name, const char *endpoint)
121 struct mapiproxy_module_list *server;
122 struct mapiproxy_module_list *server_load;
124 if (!name) return NT_STATUS_NOT_FOUND;
125 if (!endpoint) return NT_STATUS_NOT_FOUND;
127 /* Step 0. Ensure given module matches with endpoint */
128 server_load = talloc_zero(mem_ctx, struct mapiproxy_module_list);
129 server_load->module = mapiproxy_server_byname(name);
130 if (!server_load->module) {
131 DEBUG(0, ("MAPIPROXY ERROR: couldn't load server '%s'\n", name));
132 talloc_free(server_load);
133 return NT_STATUS_NOT_FOUND;
135 if (strcmp(server_load->module->endpoint, endpoint)) {
136 DEBUG(0, ("MAPIPROXY ERROR: %s endpoint expected for %s but %s found!\n",
137 endpoint, server_load->module->name, server_load->module->endpoint));
138 talloc_free(server_load);
139 return NT_STATUS_NOT_FOUND;
143 /* Step 1. Seek if this module has already been loaded */
144 for (server = server_list; server; server = server->next) {
145 if (!strcmp(server->module->name, name) &&
146 !strcmp(server->module->endpoint, endpoint)) {
147 DEBUG(0, ("MAPIPROXY: server '%s' already loaded - skipped\n", name));
148 talloc_free(server_load);
153 /* Step 2. Delete any loaded server matching given endpoint */
154 for (server = server_list; server; server = server->next) {
155 if (!strcmp(server->module->endpoint, endpoint)) {
156 DLIST_REMOVE(server_list, server);
161 /* Step 3. Load custom server */
162 DLIST_ADD_END(server_list, server_load, struct mapiproxy_module_list *);
168 static NTSTATUS mapiproxy_server_load(struct dcesrv_context *dce_ctx)
171 struct mapiproxy_module_list *server;
177 const char *server_name[] = { NDR_EXCHANGE_NSP_NAME,
178 NDR_EXCHANGE_EMSMDB_NAME,
179 NDR_EXCHANGE_DS_RFR_NAME, NULL };
181 /* Check server mode */
182 server_mode = lp_parm_bool(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "server", false);
183 DEBUG(0, ("MAPIPROXY server mode %s\n", (server_mode == false) ? "disabled" : "enabled"));
185 if (server_mode == true) {
186 DEBUG(0, ("MAPIPROXY proxy mode disabled\n"));
188 for (i = 0; server_name[i]; i++) {
189 server = talloc_zero(dce_ctx, struct mapiproxy_module_list);
190 server->module = mapiproxy_server_bystatus(server_name[i], MAPIPROXY_DEFAULT);
191 if (server->module) {
192 DLIST_ADD_END(server_list, server, struct mapiproxy_module_list *);
194 DEBUG(0, ("MAPIPROXY ERROR: couldn't load server '%s'\n", server_name[i]));
199 /* Check for override/custom NSPI server */
200 nspi = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "nspi_server");
201 mapiproxy_server_overwrite(dce_ctx, nspi, NDR_EXCHANGE_NSP_NAME);
203 /* Check for override/custom EMSMDB server */
204 emsmdb = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "emsmdb_server");
205 mapiproxy_server_overwrite(dce_ctx, emsmdb, NDR_EXCHANGE_EMSMDB_NAME);
207 /* Check for override/custom RFR server */
208 rfr = lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_mapiproxy", "rfr_server");
209 mapiproxy_server_overwrite(dce_ctx, rfr, NDR_EXCHANGE_DS_RFR_NAME);
211 for (server = server_list; server; server = server->next) {
212 DEBUG(3, ("mapiproxy_server_load '%s' (%s)\n",
213 server->module->name, server->module->description));
214 if (server->module->init) {
215 status = server->module->init(dce_ctx);
216 NT_STATUS_NOT_OK_RETURN(status);
224 _PUBLIC_ NTSTATUS mapiproxy_server_init(struct dcesrv_context *dce_ctx)
226 init_module_fn *servers;
229 servers = load_samba_modules(NULL, dce_ctx->lp_ctx, "dcerpc_mapiproxy_server");
231 run_init_functions(servers);
232 talloc_free(servers);
234 ret = mapiproxy_server_load(dce_ctx);
240 const struct mapiproxy_module *mapiproxy_server_bystatus(const char *name, enum mapiproxy_status status)
244 if (!name) return NULL;
246 for (i = 0; i < num_server_modules; i++) {
247 if ((strcmp(server_modules[i].server_module->name, name) == 0) &&
248 (server_modules[i].server_module->status == status)) {
249 return server_modules[i].server_module;
257 const struct mapiproxy_module *mapiproxy_server_byname(const char *name)
261 if (!name) return NULL;
263 for (i = 0; i < num_server_modules; i++) {
264 if ((strcmp(server_modules[i].server_module->name, name) == 0)) {
265 return server_modules[i].server_module;
274 \details Initialize an EMSABP TDB context available to all
275 instances when Samba is not run in single mode.
277 \param lp_ctx pointer to the loadparm context
279 \note TDB database can't be opened twice with O_RDWR flags. We
280 ensure here we have a general context initialized, which we'll
281 reopen within forked instances
283 return Allocated TDB context on success, otherwise NULL
285 _PUBLIC_ TDB_CONTEXT *mapiproxy_server_emsabp_tdb_init(struct loadparm_context *lp_ctx)
290 if (emsabp_tdb_ctx) return emsabp_tdb_ctx;
292 mem_ctx = talloc_init("mapiproxy_server_emsabp_tdb_init");
293 if (!mem_ctx) return NULL;
295 /* Step 0. Retrieve a TDB context pointer on the emsabp_tdb database */
296 tdb_path = talloc_asprintf(mem_ctx, "%s/%s", lp_private_dir(lp_ctx), EMSABP_TDB_NAME);
297 emsabp_tdb_ctx = tdb_open(tdb_path, 0, 0, O_RDWR|O_CREAT, 0600);
298 talloc_free(tdb_path);
299 if (!emsabp_tdb_ctx) {
300 DEBUG(3, ("[%s:%d]: %s\n", __FUNCTION__, __LINE__, strerror(errno)));
301 talloc_free(mem_ctx);
305 talloc_free(mem_ctx);
307 return emsabp_tdb_ctx;