summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2008-12-08 19:07:56 -0500
committerSimo Sorce <idra@samba.org>2008-12-08 19:25:21 -0500
commit8f86577722f9e880c82e7a98fcb14ee06acb7170 (patch)
tree2a4ed81a4c55c13cf93812fe7a577f081f4613b4
parent6092cf59d7f5d1c0d915c65bde20fdc98f80c950 (diff)
downloadsssd-8f86577722f9e880c82e7a98fcb14ee06acb7170.tar.gz
sssd-8f86577722f9e880c82e7a98fcb14ee06acb7170.tar.xz
sssd-8f86577722f9e880c82e7a98fcb14ee06acb7170.zip
Change data provider into a hub, where backends (ldap, nis, ipa providers)
and frontends (pam, nss, ... modules) can connect to.
-rw-r--r--server/Makefile.in2
-rw-r--r--server/monitor.c54
-rw-r--r--server/nss/nsssrv.c15
-rw-r--r--server/providers/data_provider.c356
-rw-r--r--server/providers/data_provider.h33
-rw-r--r--server/providers/data_provider_be.c515
-rw-r--r--server/server.mk6
-rw-r--r--server/util/server.c5
-rw-r--r--server/util/service_helpers.c21
-rw-r--r--server/util/service_helpers.h3
10 files changed, 824 insertions, 186 deletions
diff --git a/server/Makefile.in b/server/Makefile.in
index 4c989ee..fa57d80 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -59,7 +59,7 @@ OBJS = $(SERVER_OBJ) @LIBREPLACEOBJ@ $(EXTRA_OBJ)
headers = .h
-BINS = sbin/sssd sbin/sssd_nss sbin/sssd_dp
+BINS = sbin/sssd sbin/sssd_nss sbin/sssd_dp sbin/sssd_be
DIRS = sbin
diff --git a/server/monitor.c b/server/monitor.c
index fab88ff..0075aac 100644
--- a/server/monitor.c
+++ b/server/monitor.c
@@ -304,6 +304,7 @@ int monitor_process_init(TALLOC_CTX *mem_ctx,
{
struct mt_ctx *ctx;
struct mt_svc *svc;
+ char **doms;
char *path;
int ret, i;
@@ -327,6 +328,7 @@ int monitor_process_init(TALLOC_CTX *mem_ctx,
return ret;
}
+ /* start all services */
for (i = 0; ctx->services[i]; i++) {
svc = talloc_zero(ctx, struct mt_svc);
@@ -363,6 +365,58 @@ int monitor_process_init(TALLOC_CTX *mem_ctx,
set_tasks_checker(svc);
}
+ /* now start the data providers */
+ ret = confdb_get_domains(cdb, ctx, &doms);
+ if (ret != EOK) {
+ DEBUG(2, ("No domains configured. LOCAL should always exist!\n"));
+ return ret;
+ }
+
+ for (i = 0; doms[i]; i++) {
+ svc = talloc_zero(ctx, struct mt_svc);
+ if (!svc) {
+ talloc_free(ctx);
+ return ENOMEM;
+ }
+ svc->name = talloc_strdup(svc, doms[i]);
+ svc->mt_ctx = ctx;
+
+ path = talloc_asprintf(svc, "config/domains/%s", svc->name);
+ if (!path) {
+ talloc_free(ctx);
+ return ENOMEM;
+ }
+ ret = confdb_get_string(cdb, svc, path,
+ "command", NULL, &svc->command);
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to find provider [%s] configuration\n",
+ svc->name));
+ talloc_free(svc);
+ continue;
+ }
+
+ /* if no command is present to not run the domain */
+ if (svc->command == NULL) {
+ /* the LOCAL domain does not need a backend at the moment */
+ if (strcasecmp(svc->name, "LOCAL") != 0) {
+ DEBUG(0, ("Missing command to run provider [%s]\n"));
+ }
+ talloc_free(svc);
+ continue;
+ }
+
+ ret = start_service(svc->name, svc->command, &svc->pid);
+ if (ret != EOK) {
+ DEBUG(0,("Failed to start provider '%s'\n", svc->name));
+ talloc_free(svc);
+ continue;
+ }
+
+ DLIST_ADD(ctx->svc_list, svc);
+
+ set_tasks_checker(svc);
+ }
+
return EOK;
}
diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c
index ccbd7ba..a3fd672 100644
--- a/server/nss/nsssrv.c
+++ b/server/nss/nsssrv.c
@@ -43,14 +43,14 @@
#define SSS_NSS_PIPE_NAME "nss"
-static int provide_identity(DBusMessage *message, void *data, DBusMessage **r);
-static int reply_ping(DBusMessage *message, void *data, DBusMessage **r);
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r);
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r);
static int nss_init_domains(struct nss_ctx *nctx);
static int _domain_comparator(void *key1, void *key2);
struct sbus_method nss_sbus_methods[] = {
- {SERVICE_METHOD_IDENTITY, provide_identity},
- {SERVICE_METHOD_PING, reply_ping},
+ {SERVICE_METHOD_IDENTITY, service_identity},
+ {SERVICE_METHOD_PING, service_pong},
{NULL, NULL}
};
@@ -211,7 +211,7 @@ static void accept_fd_handler(struct event_context *ev,
return;
}
-static int provide_identity(DBusMessage *message, void *data, DBusMessage **r)
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r)
{
dbus_uint16_t version = NSS_SBUS_SERVICE_VERSION;
const char *name = NSS_SBUS_SERVICE_NAME;
@@ -231,7 +231,7 @@ static int provide_identity(DBusMessage *message, void *data, DBusMessage **r)
return EOK;
}
-static int reply_ping(DBusMessage *message, void *data, DBusMessage **r)
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r)
{
DBusMessage *reply;
dbus_bool_t ret;
@@ -252,8 +252,7 @@ static int nss_sbus_init(struct nss_ctx *nctx)
/* Set up SBUS connection to the monitor */
ss_ctx = sssd_service_sbus_init(nctx, nctx->ev, nctx->cdb,
- provide_identity,
- reply_ping);
+ nss_sbus_methods);
if (ss_ctx == NULL) {
DEBUG(0, ("Could not initialize D-BUS.\n"));
return ENOMEM;
diff --git a/server/providers/data_provider.c b/server/providers/data_provider.c
index bfc37a7..181e865 100644
--- a/server/providers/data_provider.c
+++ b/server/providers/data_provider.c
@@ -41,16 +41,57 @@
#include "data_provider.h"
#include "util/service_helpers.h"
-static int provide_identity(DBusMessage *message, void *data, DBusMessage **r);
-static int reply_ping(DBusMessage *message, void *data, DBusMessage **r);
+struct dp_backend;
+struct dp_frontend;
+
+struct dp_ctx {
+ struct event_context *ev;
+ struct confdb_ctx *cdb;
+ struct ldb_context *ldb;
+ struct service_sbus_ctx *ss_ctx;
+ struct dp_backend *be_list;
+ struct dp_frontend *fe_list;
+};
+
+struct dp_client {
+ struct dp_ctx *dpctx;
+ struct sbus_conn_ctx *conn_ctx;
+ const char *domain;
+};
+
+struct dp_backend {
+ struct dp_backend *prev;
+ struct dp_backend *next;
+ char *name;
+ char *domain;
+ struct dp_client *dpcli;
+};
+
+struct dp_frontend {
+ struct dp_frontend *prev;
+ struct dp_frontend *next;
+ char *name;
+ uint16_t flags;
+ struct dp_client *dpcli;
+};
+
+static int dp_backend_destructor(void *ctx);
+static int dp_frontend_destructor(void *ctx);
+
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r);
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r);
struct sbus_method mon_sbus_methods[] = {
- {SERVICE_METHOD_IDENTITY, provide_identity},
- {SERVICE_METHOD_PING, reply_ping},
+ {SERVICE_METHOD_IDENTITY, service_identity},
+ {SERVICE_METHOD_PING, service_pong},
{NULL, NULL}
};
-static int provide_identity(DBusMessage *message, void *data, DBusMessage **r)
+struct sbus_method dp_sbus_methods[] = {
+ {NULL, NULL}
+};
+
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r)
{
dbus_uint16_t version = DATA_PROVIDER_VERSION;
const char *name = DATA_PROVIDER_SERVICE_NAME;
@@ -70,7 +111,7 @@ static int provide_identity(DBusMessage *message, void *data, DBusMessage **r)
return EOK;
}
-static int reply_ping(DBusMessage *message, void *data, DBusMessage **r)
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r)
{
DBusMessage *reply;
dbus_bool_t ret;
@@ -91,8 +132,7 @@ static int dp_monitor_init(struct dp_ctx *dpctx)
/* Set up SBUS connection to the monitor */
ss_ctx = sssd_service_sbus_init(dpctx, dpctx->ev, dpctx->cdb,
- provide_identity,
- reply_ping);
+ mon_sbus_methods);
if (ss_ctx == NULL) {
DEBUG(0, ("Could not initialize D-BUS.\n"));
return ENOMEM;
@@ -150,19 +190,18 @@ static int dp_db_init(struct dp_ctx *dpctx)
return EOK;
}
-static int check_online(DBusMessage *message, void *data, DBusMessage **r);
-
-struct sbus_method dp_sbus_methods[] = {
- { DP_METHOD_CHECK_ONLINE, check_online },
- { NULL, NULL }
-};
+static void identity_check(DBusPendingCall *pending, void *data);
+static void online_check(DBusPendingCall *pending, void *data);
static int dbus_dp_init(struct sbus_conn_ctx *conn_ctx, void *data)
{
struct dp_ctx *dpctx;
struct dp_client *dpcli;
+ DBusMessage *msg;
+ DBusPendingCall *pending_reply;
DBusConnection *conn;
DBusError dbus_error;
+ dbus_bool_t dbret;
dpctx = talloc_get_type(data, struct dp_ctx);
conn = sbus_get_connection(conn_ctx);
@@ -178,15 +217,186 @@ static int dbus_dp_init(struct sbus_conn_ctx *conn_ctx, void *data)
return ENOMEM;
}
dpcli->dpctx = dpctx;
- dpcli->conn = conn;
+ dpcli->conn_ctx = conn_ctx;
/* Attach the client context to the connection context, so that it is
* always available when we need to manage the connection. */
sbus_conn_set_private_data(conn_ctx, dpcli);
+ /* identify the connecting client */
+ msg = dbus_message_new_method_call(NULL,
+ DP_CLI_PATH,
+ DP_CLI_INTERFACE,
+ DP_CLI_METHOD_IDENTITY);
+ if (msg == NULL) {
+ DEBUG(0,("Out of memory?!\n"));
+ talloc_free(conn_ctx);
+ return ENOMEM;
+ }
+ dbret = dbus_connection_send_with_reply(conn, msg, &pending_reply,
+ -1 /* TODO: set timeout */);
+ if (!dbret) {
+ /*
+ * Critical Failure
+ * We can't communicate on this connection
+ * We'll drop it using the default destructor.
+ */
+ DEBUG(0, ("D-BUS send failed.\n"));
+ talloc_free(conn_ctx);
+ return EIO;
+ }
+
+ /* Set up the reply handler */
+ dbus_pending_call_set_notify(pending_reply, identity_check, dpcli, NULL);
+ dbus_message_unref(msg);
+
return EOK;
}
+static void identity_check(DBusPendingCall *pending, void *data)
+{
+ struct dp_backend *dpbe;
+ struct dp_frontend *dpfe;
+ struct dp_client *dpcli;
+ DBusMessage *reply;
+ DBusConnection *conn;
+ DBusError dbus_error;
+ dbus_uint16_t cli_ver;
+ dbus_uint16_t cli_type;
+ char *cli_name;
+ char *cli_domain;
+ dbus_bool_t ret;
+ int type;
+
+ dpcli = talloc_get_type(data, struct dp_client);
+ conn = sbus_get_connection(dpcli->conn_ctx);
+ dbus_error_init(&dbus_error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+ if (!reply) {
+ /* reply should never be null. This function shouldn't be called
+ * until reply is valid or timeout has occurred. If reply is NULL
+ * here, something is seriously wrong and we should bail out.
+ */
+ DEBUG(0, ("Serious error. A reply callback was called but no reply was received and no timeout occurred\n"));
+
+ /* Destroy this connection */
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ type = dbus_message_get_type(reply);
+ switch (type) {
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ ret = dbus_message_get_args(reply, &dbus_error,
+ DBUS_TYPE_UINT16, &cli_type,
+ DBUS_TYPE_UINT16, &cli_ver,
+ DBUS_TYPE_STRING, &cli_name,
+ DBUS_TYPE_STRING, &cli_domain,
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ DEBUG(1,("Failed, to parse message, killing connection\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ switch (cli_type && DP_CLI_TYPE_MASK) {
+ case DP_CLI_BACKEND:
+ dpbe = talloc_zero(dpcli->dpctx, struct dp_backend);
+ if (!dpbe) {
+ DEBUG(0, ("Out of memory!\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ dpbe->name = talloc_strdup(dpbe, cli_name);
+ dpbe->domain = talloc_strdup(dpbe, cli_domain);
+ if (!dpbe->name || !dpbe->domain) {
+ DEBUG(0, ("Out of memory!\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ dpbe->dpcli = dpcli;
+
+ DLIST_ADD(dpcli->dpctx->be_list, dpbe);
+
+ talloc_set_destructor((TALLOC_CTX *)dpbe, dp_backend_destructor);
+ break;
+
+ case DP_CLI_FRONTEND:
+ dpfe = talloc_zero(dpcli->dpctx, struct dp_frontend);
+ if (!dpfe) {
+ DEBUG(0, ("Out of memory!\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ dpfe->name = talloc_strdup(dpfe, cli_name);
+ if (!dpfe->name) {
+ DEBUG(0, ("Out of memory!\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ dpfe->dpcli = dpcli;
+
+ DLIST_ADD(dpcli->dpctx->fe_list, dpfe);
+
+ talloc_set_destructor((TALLOC_CTX *)dpfe, dp_frontend_destructor);
+ break;
+
+ default:
+ DEBUG(1, ("Unknown client type, killing connection\n"));
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+
+ /* Set up the destructor for this service */
+ break;
+
+ case DBUS_MESSAGE_TYPE_ERROR:
+ DEBUG(0,("getIdentity returned an error [%s], closing connection.\n",
+ dbus_message_get_error_name(reply)));
+ /* Falling through to default intentionally*/
+ default:
+ /*
+ * Timeout or other error occurred or something
+ * unexpected happened.
+ * It doesn't matter which, because either way we
+ * know that this connection isn't trustworthy.
+ * We'll destroy it now.
+ */
+ sbus_disconnect(dpcli->conn_ctx);
+ return;
+ }
+}
+
+static void online_check(DBusPendingCall *pending, void *data)
+{
+ return;
+}
+
+static int dp_backend_destructor(void *ctx)
+{
+ struct dp_backend *dpbe = talloc_get_type(ctx, struct dp_backend);
+ if (dpbe->dpcli && dpbe->dpcli &&
+ dpbe->dpcli->dpctx && dpbe->dpcli->dpctx->be_list) {
+ DLIST_REMOVE(dpbe->dpcli->dpctx->be_list, dpbe);
+ }
+ return 0;
+}
+
+static int dp_frontend_destructor(void *ctx)
+{
+ struct dp_frontend *dpfe = talloc_get_type(ctx, struct dp_frontend);
+ if (dpfe->dpcli && dpfe->dpcli &&
+ dpfe->dpcli->dpctx && dpfe->dpcli->dpctx->fe_list) {
+ DLIST_REMOVE(dpfe->dpcli->dpctx->fe_list, dpfe);
+ }
+ return 0;
+}
+
/* monitor_dbus_init
* Set up the monitor service as a D-BUS Server */
static int dp_srv_init(struct dp_ctx *dpctx)
@@ -247,116 +457,6 @@ done:
return ret;
}
-static int check_online(DBusMessage *message, void *data, DBusMessage **r)
-{
- return EOK;
-}
-
-/* find list of backends */
-/* find library implementing them */
-/* dload() said library and set up a structure to hold pointers */
-
-static int init_data_providers(struct dp_ctx *dpctx)
-{
- TALLOC_CTX *tmp_ctx;
- struct dp_mod_ctx *module;
- char **doms;
- char *sec;
- char *mod_name;
- char *path;
- void *handle;
- char *mod_init_fn_name;
- sssm_init_fn_t mod_init_fn;
- int num_mods;
- int i, ret;
-
- tmp_ctx = talloc_new(dpctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- ret = confdb_get_domains(dpctx->cdb, tmp_ctx, &doms);
- if (ret != EOK) {
- DEBUG(2, ("No domains configured!\n"));
- return ret;
- }
-
- num_mods = 0;
- for (i = 0; doms[i]; i++) {
- sec = talloc_asprintf(tmp_ctx, "config/domains/%s", doms[i]);
- if (!sec) {
- ret = ENOMEM;
- goto done;
- }
- ret = confdb_get_string(dpctx->cdb, tmp_ctx, sec,
- "provider", NULL, &mod_name);
- if (ret != EOK) {
- goto done;
- }
-
- /* the LOCAL domain does not have a backend at the moment */
- if (strcasecmp(mod_name, "LOCAL") == 0) {
- continue;
- }
-
- path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
- DATA_PROVIDER_PLUGINS_PATH, mod_name);
-
- handle = dlopen(path, RTLD_NOW);
- if (!handle) {
- DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n",
- mod_name, path, dlerror()));
- ret = ELIBACC;
- goto done;
- }
-
- mod_init_fn_name = talloc_asprintf(tmp_ctx, "sssm_%s_init", mod_name);
- if (!mod_init_fn_name) {
- ret = ENOMEM;
- goto done;
- }
-
- mod_init_fn = (sssm_init_fn_t)dlsym(handle, mod_init_fn_name);
- if (!mod_init_fn) {
- DEBUG(0, ("Unable to load init fn from module %s, error: %s\n",
- mod_name, dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- dpctx->modules = talloc_array(tmp_ctx, struct dp_mod_ctx *, num_mods +1);
- if (!dpctx->modules) {
- ret = ENOMEM;
- goto done;
- }
- module = talloc(dpctx->modules, struct dp_mod_ctx);
- if (!module) {
- ret = ENOMEM;
- goto done;
- }
- dpctx->modules[num_mods] = module;
-
- module->dp_ctx = dpctx;
- module->domain = talloc_strdup(dpctx->modules, doms[i]);
- module->name = talloc_steal(dpctx->modules, mod_name);
-
- ret = mod_init_fn(module);
- if (ret != EOK) {
- DEBUG(0, ("Error (%d) in module (%s) initialization!\n",
- ret, mod_name));
- continue;
- }
-
- num_mods++;
- }
-
- ret = EOK;
-
-done:
- talloc_free(doms);
- return ret;
-}
-
int dp_process_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct confdb_ctx *cdb)
@@ -390,12 +490,6 @@ int dp_process_init(TALLOC_CTX *mem_ctx,
return ret;
}
- ret = init_data_providers(dpctx);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing data providers\n"));
- return ret;
- }
-
return EOK;
}
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
index 68c6db9..cd8098b 100644
--- a/server/providers/data_provider.h
+++ b/server/providers/data_provider.h
@@ -29,41 +29,24 @@
#include "ldb.h"
#define DATA_PROVIDER_VERSION 0x0001
+#define BE_VERSION 0x0001
#define DATA_PROVIDER_SERVICE_NAME "dp"
#define DATA_PROVIDER_PIPE "private/sbus-dp"
#define DATA_PROVIDER_DB_FILE "sssd.ldb"
#define DATA_PROVIDER_DB_CONF_SEC "config/services/nss"
-struct dp_mod_ops {
- int (*check_online)(void *pvt_data, int *reply);
-};
-
#define MOD_OFFLINE 0x0000
#define MOD_ONLINE 0x0001
-struct dp_mod_ctx;
-typedef int (*sssm_init_fn_t)(struct dp_mod_ctx *);
-
-struct dp_mod_ctx {
- struct dp_ctx *dp_ctx;
- const char *name;
- const char *domain;
- struct dp_mod_ops *ops;
- void *pvt_data;
-};
+#define DP_CLI_INTERFACE "org.freeipa.sssd.dataprovider"
+#define DP_CLI_PATH "/org/freeipa/sssd/dataprovider"
-struct dp_ctx {
- struct event_context *ev;
- struct confdb_ctx *cdb;
- struct ldb_context *ldb;
- struct service_sbus_ctx *ss_ctx;
- struct dp_mod_ctx **modules;
-};
+#define DP_CLI_BACKEND 0x0001
+#define DP_CLI_FRONTEND 0x0002
+#define DP_CLI_TYPE_MASK 0x0003
-struct dp_client {
- struct dp_ctx *dpctx;
- DBusConnection *conn;
-};
+#define DP_CLI_METHOD_IDENTITY "getIdentity"
+#define DP_CLI_METHOD_ONLINE "getOnline"
#endif /* __DATA_PROVIDER_ */
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
new file mode 100644
index 0000000..83659be
--- /dev/null
+++ b/server/providers/data_provider_be.c
@@ -0,0 +1,515 @@
+/*
+ SSSD
+
+ Data Provider Runner
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+#include <sys/time.h>
+#include <errno.h>
+#include "popt.h"
+#include "ldb.h"
+#include "ldb_errors.h"
+#include "util/util.h"
+#include "confdb/confdb.h"
+#include "dbus/dbus.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus_interfaces.h"
+#include "util/btreemap.h"
+#include "data_provider.h"
+#include "util/service_helpers.h"
+
+struct dp_mod_ops {
+ int (*check_online)(void *pvt_data, int *reply);
+};
+
+struct be_ctx {
+ struct event_context *ev;
+ struct confdb_ctx *cdb;
+ struct ldb_context *ldb;
+ struct service_sbus_ctx *ss_ctx;
+ struct service_sbus_ctx *dp_ctx;
+ const char *name;
+ const char *domain;
+ const char *identity;
+ struct dp_mod_ops *ops;
+ void *pvt_data;
+};
+
+typedef int (*be_init_fn_t)(struct be_ctx *, struct dp_mod_ops **, void **);
+
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r);
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r);
+
+struct sbus_method mon_sbus_methods[] = {
+ {SERVICE_METHOD_IDENTITY, service_identity},
+ {SERVICE_METHOD_PING, service_pong},
+ {NULL, NULL}
+};
+
+static int be_identity(DBusMessage *message, void *data, DBusMessage **r);
+static int check_online(DBusMessage *message, void *data, DBusMessage **r);
+
+struct sbus_method be_methods[] = {
+ { DP_CLI_METHOD_IDENTITY, be_identity },
+ { DP_CLI_METHOD_ONLINE, check_online },
+ { NULL, NULL }
+};
+
+static int service_identity(DBusMessage *message, void *data, DBusMessage **r)
+{
+ dbus_uint16_t version = BE_VERSION;
+ struct sbus_message_handler_ctx *smh_ctx;
+ struct be_ctx *ctx;
+ DBusMessage *reply;
+ dbus_bool_t ret;
+ void *user_data;
+
+ if (!data) return EINVAL;
+ smh_ctx = talloc_get_type(data, struct sbus_message_handler_ctx);
+ if (!smh_ctx) return EINVAL;
+ user_data = sbus_conn_get_private_data(smh_ctx->conn_ctx);
+ if (!user_data) return EINVAL;
+ ctx = talloc_get_type(user_data, struct be_ctx);
+ if (!ctx) return EINVAL;
+
+ reply = dbus_message_new_method_return(message);
+ ret = dbus_message_append_args(reply,
+ DBUS_TYPE_STRING, &ctx->identity,
+ DBUS_TYPE_UINT16, &version,
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ return EIO;
+ }
+
+ *r = reply;
+ return EOK;
+}
+
+static int service_pong(DBusMessage *message, void *data, DBusMessage **r)
+{
+ DBusMessage *reply;
+ dbus_bool_t ret;
+
+ reply = dbus_message_new_method_return(message);
+ ret = dbus_message_append_args(reply, DBUS_TYPE_INVALID);
+ if (!ret) {
+ return EIO;
+ }
+
+ *r = reply;
+ return EOK;
+}
+
+static int be_identity(DBusMessage *message, void *data, DBusMessage **r)
+{
+ dbus_uint16_t version = BE_VERSION;
+ dbus_uint16_t clitype = DP_CLI_BACKEND;
+ struct sbus_message_handler_ctx *smh_ctx;
+ struct be_ctx *ctx;
+ DBusMessage *reply;
+ dbus_bool_t ret;
+ void *user_data;
+
+ if (!data) return EINVAL;
+ smh_ctx = talloc_get_type(data, struct sbus_message_handler_ctx);
+ if (!smh_ctx) return EINVAL;
+ user_data = sbus_conn_get_private_data(smh_ctx->conn_ctx);
+ if (!user_data) return EINVAL;
+ ctx = talloc_get_type(user_data, struct be_ctx);
+ if (!ctx) return EINVAL;
+
+ reply = dbus_message_new_method_return(message);
+ ret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &clitype,
+ DBUS_TYPE_UINT16, &version,
+ DBUS_TYPE_STRING, &ctx->name,
+ DBUS_TYPE_STRING, &ctx->domain,
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ return EIO;
+ }
+
+ *r = reply;
+ return EOK;
+}
+
+static int check_online(DBusMessage *message, void *data, DBusMessage **r)
+{
+ struct sbus_message_handler_ctx *smh_ctx;
+ struct be_ctx *ctx;
+ DBusMessage *reply;
+ dbus_bool_t dbret;
+ void *user_data;
+ int online = 0;
+ int ret;
+
+ if (!data) return EINVAL;
+ smh_ctx = talloc_get_type(data, struct sbus_message_handler_ctx);
+ if (!smh_ctx) return EINVAL;
+ user_data = sbus_conn_get_private_data(smh_ctx->conn_ctx);
+ if (!user_data) return EINVAL;
+ ctx = talloc_get_type(user_data, struct be_ctx);
+ if (!ctx) return EINVAL;
+
+ ret = ctx->ops->check_online(ctx->pvt_data, &online);
+ if (ret != EOK) return ret;
+
+ reply = dbus_message_new_method_return(message);
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &online,
+ DBUS_TYPE_INVALID);
+ if (!dbret) return EIO;
+
+ *r = reply;
+ return EOK;
+}
+
+/* mon_cli_init
+ * sbus channel to the monitor daemon */
+static int mon_cli_init(struct be_ctx *ctx)
+{
+ struct service_sbus_ctx *ss_ctx;
+
+ /* Set up SBUS connection to the monitor */
+ ss_ctx = sssd_service_sbus_init(ctx, ctx->ev, ctx->cdb,
+ mon_sbus_methods);
+ if (ss_ctx == NULL) {
+ DEBUG(0, ("Could not initialize D-BUS.\n"));
+ return ENOMEM;
+ }
+
+ ctx->ss_ctx = ss_ctx;
+
+ /* attach be context to the connection */
+ sbus_conn_set_private_data(ss_ctx->scon_ctx, ctx);
+
+ return EOK;
+}
+
+static int be_dp_sbus_init(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct confdb_ctx *cdb,
+ const char *address,
+ struct sbus_method *methods,
+ struct service_sbus_ctx **srvs_ctx)
+{
+ struct service_sbus_ctx *ss_ctx;
+ struct sbus_method_ctx *sm_ctx;
+ TALLOC_CTX *tmp_ctx;
+ char *default_monitor_address;
+ char *sbus_address;
+ DBusConnection *conn;
+ int ret;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ss_ctx = talloc_zero(tmp_ctx, struct service_sbus_ctx);
+ if (ss_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ss_ctx->ev = ev;
+
+ default_monitor_address = talloc_asprintf(tmp_ctx, "unix:path=%s/%s",
+ PIPE_PATH, SSSD_SERVICE_PIPE);
+ if (default_monitor_address == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = confdb_get_string(cdb, tmp_ctx,
+ "config/services/monitor", "sbusAddress",
+ default_monitor_address, &sbus_address);
+ if (ret != EOK) goto done;
+
+ ret = sbus_new_connection(ss_ctx, ss_ctx->ev,
+ sbus_address, &ss_ctx->scon_ctx,
+ NULL);
+ if (ret != EOK) goto done;
+
+ conn = sbus_get_connection(ss_ctx->scon_ctx);
+
+ /* set up handler for service methods */
+ sm_ctx = talloc_zero(ss_ctx, struct sbus_method_ctx);
+ if (sm_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ sm_ctx->interface = talloc_strdup(sm_ctx, SERVICE_INTERFACE);
+ sm_ctx->path = talloc_strdup(sm_ctx, SERVICE_PATH);
+ if (!sm_ctx->interface || !sm_ctx->path) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Set up required monitor methods */
+ sm_ctx->methods = methods;
+
+ sm_ctx->message_handler = sbus_message_handler;
+ sbus_conn_add_method_ctx(ss_ctx->scon_ctx, sm_ctx);
+
+ talloc_steal(mem_ctx, ss_ctx);
+ *srvs_ctx = ss_ctx;
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/* be_cli_init
+ * sbus channel to the data provider daemon */
+static int be_cli_init(struct be_ctx *ctx)
+{
+ struct service_sbus_ctx *dp_ctx;
+ char *default_dp_address;
+ int ret;
+
+ default_dp_address = talloc_asprintf(ctx, "unix:path=%s/%s",
+ PIPE_PATH, DATA_PROVIDER_PIPE);
+ if (!default_dp_address) return ENOMEM;
+
+ ret = be_dp_sbus_init(ctx, ctx->ev, ctx->cdb,
+ default_dp_address, be_methods,
+ &dp_ctx);
+ if (ret != EOK) {
+ talloc_free(default_dp_address);
+ return ret;
+ }
+
+ ctx->dp_ctx = dp_ctx;
+
+ /* attach be context to the connection */
+ sbus_conn_set_private_data(dp_ctx->scon_ctx, ctx);
+
+ talloc_free(default_dp_address);
+ return EOK;
+}
+
+static int be_db_init(struct be_ctx *ctx)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *ldb_file;
+ char *default_db_file;
+ int ret;
+
+ tmp_ctx = talloc_new(ctx);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ default_db_file = talloc_asprintf(tmp_ctx, "%s/%s", DB_PATH, DATA_PROVIDER_DB_FILE);
+ if (!default_db_file) {
+ talloc_free(tmp_ctx);
+ return ENOMEM;
+ }
+
+ ret = confdb_get_string(ctx->cdb, tmp_ctx,
+ DATA_PROVIDER_DB_CONF_SEC, "ldbFile",
+ default_db_file, &ldb_file);
+ if (ret != EOK) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ctx->ldb = ldb_init(tmp_ctx, ctx->ev);
+ if (!ctx->ldb) {
+ talloc_free(tmp_ctx);
+ return EIO;
+ }
+
+ ret = ldb_connect(ctx->ldb, ldb_file, 0, NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return EIO;
+ }
+
+ talloc_steal(ctx, ctx->ldb);
+
+ talloc_free(tmp_ctx);
+ return EOK;
+}
+
+static int load_backend(struct be_ctx *ctx)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *path;
+ void *handle;
+ char *mod_init_fn_name;
+ be_init_fn_t mod_init_fn;
+ int ret;
+
+ tmp_ctx = talloc_new(ctx);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
+ DATA_PROVIDER_PLUGINS_PATH, ctx->name);
+
+ handle = dlopen(path, RTLD_NOW);
+ if (!handle) {
+ DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n",
+ ctx->name, path, dlerror()));
+ ret = ELIBACC;
+ goto done;
+ }
+
+ mod_init_fn_name = talloc_asprintf(tmp_ctx, "sssm_%s_init", ctx->name);
+ if (!mod_init_fn_name) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ mod_init_fn = (be_init_fn_t)dlsym(handle, mod_init_fn_name);
+ if (!mod_init_fn) {
+ DEBUG(0, ("Unable to load init fn from module %s, error: %s\n",
+ ctx->name, dlerror()));
+ ret = ELIBBAD;
+ goto done;
+ }
+
+ ret = mod_init_fn(ctx, &ctx->ops, &ctx->pvt_data);
+ if (ret != EOK) {
+ DEBUG(0, ("Error (%d) in module (%s) initialization!\n",
+ ret, ctx->name));
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+int be_process_init(TALLOC_CTX *mem_ctx,
+ const char *be_name,
+ const char *be_domain,
+ struct event_context *ev,
+ struct confdb_ctx *cdb)
+{
+ struct be_ctx *ctx;
+ int ret;
+
+ ctx = talloc_zero(mem_ctx, struct be_ctx);
+ if (!ctx) {
+ DEBUG(0, ("fatal error initializing be_ctx\n"));
+ return ENOMEM;
+ }
+ ctx->ev = ev;
+ ctx->cdb = cdb;
+ ctx->domain = talloc_strdup(ctx, be_domain);
+ ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain);
+ if (!ctx->domain || !ctx->identity) {
+ DEBUG(0, ("Out of memory!?\n"));
+ return ENOMEM;
+ }
+
+ ret = be_db_init(ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("fatal error opening database\n"));
+ return ret;
+ }
+
+ ret = mon_cli_init(ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("fatal error setting up monitor bus\n"));
+ return ret;
+ }
+
+ ret = be_cli_init(ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("fatal error setting up server bus\n"));
+ return ret;
+ }
+
+ ret = load_backend(ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("fatal error initializing data providers\n"));
+ return ret;
+ }
+
+ return EOK;
+}
+
+int main(int argc, const char *argv[])
+{
+ int opt;
+ poptContext pc;
+ char *be_name;
+ char *be_domain;
+ char *srv_name;
+ struct main_context *main_ctx;
+ int ret;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ SSSD_MAIN_OPTS
+ {"provider", 0, POPT_ARG_STRING, &be_name, 0,
+ "Information Provider", NULL },
+ {"domain", 0, POPT_ARG_STRING, &be_domain, 0,
+ "Domain of the information provider", NULL },
+ { NULL }
+ };
+
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ switch(opt) {
+ default:
+ fprintf(stderr, "\nInvalid option %s: %s\n\n",
+ poptBadOption(pc, 0), poptStrerror(opt));
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+ }
+
+ poptFreeContext(pc);
+
+ /* set up things like debug , signals, daemonization, etc... */
+ srv_name = talloc_asprintf(NULL, "sssd[be[%s]]", be_name);
+ if (!srv_name) return 2;
+
+ ret = server_setup(srv_name, 0, &main_ctx);
+ if (ret != EOK) return 2;
+
+ ret = be_process_init(main_ctx,
+ be_name, be_domain,
+ main_ctx->event_ctx,
+ main_ctx->confdb_ctx);
+ if (ret != EOK) return 3;
+
+ /* loop on main */
+ server_loop(main_ctx);
+
+ return 0;
+}
+
diff --git a/server/server.mk b/server/server.mk
index 480e58f..7f9274d 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -16,6 +16,9 @@ SERVER_OBJ = \
DP_OBJ = \
providers/data_provider.o
+DP_BE_OBJ = \
+ providers/data_provider_be.o
+
NSSSRV_OBJ = \
nss/nsssrv.o \
nss/nsssrv_packet.o \
@@ -34,3 +37,6 @@ sbin/sssd_nss: $(NSSSRV_OBJ) $(UTIL_OBJ)
sbin/sssd_dp: $(DP_OBJ) $(UTIL_OBJ)
$(CC) -o sbin/sssd_dp $(DP_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
+
+sbin/sssd_be: $(DP_BE_OBJ) $(UTIL_OBJ)
+ $(CC) -o sbin/sssd_be $(DP_BE_OBJ) $(UTIL_OBJ) $(LDFLAGS) $(LIBS)
diff --git a/server/util/server.c b/server/util/server.c
index def44f0..6983fca 100644
--- a/server/util/server.c
+++ b/server/util/server.c
@@ -242,7 +242,10 @@ int server_setup(const char *name, int flags,
uint16_t stdin_event_flags;
int ret = EOK;
- debug_prg_name = name;
+ debug_prg_name = strdup(name);
+ if (!debug_prg_name) {
+ return ENOMEM;
+ }
setup_signals();
diff --git a/server/util/service_helpers.c b/server/util/service_helpers.c
index 6232108..1630946 100644
--- a/server/util/service_helpers.c
+++ b/server/util/service_helpers.c
@@ -33,8 +33,7 @@
struct service_sbus_ctx *sssd_service_sbus_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct confdb_ctx *cdb,
- sbus_msg_handler_fn get_identity,
- sbus_msg_handler_fn ping)
+ struct sbus_method *methods)
{
struct service_sbus_ctx *ss_ctx;
struct sbus_method_ctx *sm_ctx;
@@ -75,22 +74,8 @@ struct service_sbus_ctx *sssd_service_sbus_init(TALLOC_CTX *mem_ctx,
sm_ctx->path = talloc_strdup(sm_ctx, SERVICE_PATH);
if (!sm_ctx->interface || !sm_ctx->path) goto error;
- /* Set up required monitor methods */
- sm_ctx->methods = talloc_array(sm_ctx, struct sbus_method, 3);
- if (sm_ctx->methods == NULL) goto error;
-
- /* Handle getIdentity */
- sm_ctx->methods[0].method = SERVICE_METHOD_IDENTITY;
- sm_ctx->methods[0].fn = get_identity;
-
- /* Handle ping */
- sm_ctx->methods[1].method = SERVICE_METHOD_PING;
- sm_ctx->methods[1].fn = ping;
-
- /* Terminate the list */
- sm_ctx->methods[2].method = NULL;
- sm_ctx->methods[2].fn = NULL;
-
+ /* Set up required monitor methods and handlers */
+ sm_ctx->methods = methods;
sm_ctx->message_handler = sbus_message_handler;
sbus_conn_add_method_ctx(ss_ctx->scon_ctx, sm_ctx);
diff --git a/server/util/service_helpers.h b/server/util/service_helpers.h
index 440186d..f2701d5 100644
--- a/server/util/service_helpers.h
+++ b/server/util/service_helpers.h
@@ -33,7 +33,6 @@ struct service_sbus_ctx {
struct service_sbus_ctx *sssd_service_sbus_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct confdb_ctx *cdb,
- sbus_msg_handler_fn get_identity,
- sbus_msg_handler_fn ping);
+ struct sbus_method *methods);
#endif /*SERVICE_HELPERS_H_*/