summaryrefslogtreecommitdiffstats
path: root/server/providers/data_provider_be.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/providers/data_provider_be.c')
-rw-r--r--server/providers/data_provider_be.c384
1 files changed, 206 insertions, 178 deletions
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 2fa99da2a..c891a0f1e 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -57,20 +57,22 @@ struct sbus_interface monitor_be_interface = {
NULL
};
+static int client_registration(DBusMessage *message, struct sbus_connection *conn);
static int be_check_online(DBusMessage *message, struct sbus_connection *conn);
static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn);
static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn);
struct sbus_method be_methods[] = {
- { DP_CLI_METHOD_ONLINE, be_check_online },
- { DP_CLI_METHOD_GETACCTINFO, be_get_account_info },
- { DP_CLI_METHOD_PAMHANDLER, be_pam_handler },
+ { DP_METHOD_REGISTER, client_registration },
+ { DP_METHOD_ONLINE, be_check_online },
+ { DP_METHOD_GETACCTINFO, be_get_account_info },
+ { DP_METHOD_PAMHANDLER, be_pam_handler },
{ NULL, NULL }
};
struct sbus_interface be_interface = {
- DP_CLI_INTERFACE,
- DP_CLI_PATH,
+ DP_INTERFACE,
+ DP_PATH,
SBUS_DEFAULT_VTABLE,
be_methods,
NULL
@@ -154,7 +156,7 @@ void be_mark_offline(struct be_ctx *ctx)
static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
{
- struct be_ctx *ctx;
+ struct be_client *becli;
DBusMessage *reply;
DBusConnection *dbus_conn;
dbus_bool_t dbret;
@@ -166,13 +168,13 @@ static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
user_data = sbus_conn_get_private_data(conn);
if (!user_data) return EINVAL;
- ctx = talloc_get_type(user_data, struct be_ctx);
- if (!ctx) return EINVAL;
+ becli = talloc_get_type(user_data, struct be_client);
+ if (!becli) return EINVAL;
reply = dbus_message_new_method_return(message);
if (!reply) return ENOMEM;
- if (be_is_offline(ctx)) {
+ if (be_is_offline(becli->bectx)) {
online = MOD_OFFLINE;
} else {
online = MOD_ONLINE;
@@ -189,7 +191,7 @@ static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
return EIO;
}
- dbus_conn = sbus_get_connection(ctx->dp_conn);
+ dbus_conn = sbus_get_connection(becli->conn);
dbus_connection_send(dbus_conn, reply, NULL);
dbus_message_unref(reply);
@@ -229,7 +231,7 @@ static void acctinfo_callback(struct be_req *req, int status,
return;
}
- dbus_conn = sbus_get_connection(req->be_ctx->dp_conn);
+ dbus_conn = sbus_get_connection(req->becli->conn);
dbus_connection_send(dbus_conn, reply, NULL);
dbus_message_unref(reply);
@@ -244,7 +246,7 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
{
struct be_acct_req *req;
struct be_req *be_req;
- struct be_ctx *ctx;
+ struct be_client *becli;
DBusMessage *reply;
DBusError dbus_error;
dbus_bool_t dbret;
@@ -262,8 +264,8 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
user_data = sbus_conn_get_private_data(conn);
if (!user_data) return EINVAL;
- ctx = talloc_get_type(user_data, struct be_ctx);
- if (!ctx) return EINVAL;
+ becli = talloc_get_type(user_data, struct be_client);
+ if (!becli) return EINVAL;
dbus_error_init(&dbus_error);
@@ -321,14 +323,15 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
}
/* process request */
- be_req = talloc(ctx, struct be_req);
+ be_req = talloc(becli, struct be_req);
if (!be_req) {
err_maj = DP_ERR_FATAL;
err_min = ENOMEM;
err_msg = "Out of memory";
goto done;
}
- be_req->be_ctx = ctx;
+ be_req->becli = becli;
+ be_req->be_ctx = becli->bectx;
be_req->fn = acctinfo_callback;
be_req->pvt = reply;
@@ -346,7 +349,9 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
be_req->req_data = req;
- ret = be_file_request(ctx, ctx->bet_info[BET_ID].bet_ops->handler, be_req);
+ ret = be_file_request(becli->bectx,
+ becli->bectx->bet_info[BET_ID].bet_ops->handler,
+ be_req);
if (ret != EOK) {
err_maj = DP_ERR_FATAL;
err_min = ret;
@@ -395,7 +400,7 @@ static void be_pam_handler_callback(struct be_req *req, int status,
return;
}
- dbus_conn = sbus_get_connection(req->be_ctx->dp_conn);
+ dbus_conn = sbus_get_connection(req->becli->conn);
dbus_connection_send(dbus_conn, reply, NULL);
dbus_message_unref(reply);
@@ -408,7 +413,7 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
{
DBusError dbus_error;
DBusMessage *reply;
- struct be_ctx *ctx;
+ struct be_client *becli;
dbus_bool_t ret;
void *user_data;
struct pam_data *pd = NULL;
@@ -418,8 +423,8 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
user_data = sbus_conn_get_private_data(conn);
if (!user_data) return EINVAL;
- ctx = talloc_get_type(user_data, struct be_ctx);
- if (!ctx) return EINVAL;
+ becli = talloc_get_type(user_data, struct be_client);
+ if (!becli) return EINVAL;
reply = dbus_message_new_method_return(message);
if (!reply) {
@@ -428,7 +433,18 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
return ENOMEM;
}
- pd = talloc_zero(ctx, struct pam_data);
+ be_req = talloc_zero(becli, struct be_req);
+ if (!be_req) {
+ DEBUG(7, ("talloc_zero failed.\n"));
+ goto done;
+ }
+
+ be_req->becli = becli;
+ be_req->be_ctx = becli->bectx;
+ be_req->fn = be_pam_handler_callback;
+ be_req->pvt = reply;
+
+ pd = talloc_zero(be_req, struct pam_data);
if (!pd) return ENOMEM;
dbus_error_init(&dbus_error);
@@ -461,23 +477,16 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
}
/* return an error if corresponding backend target is configured */
- if (!ctx->bet_info[target].bet_ops) {
+ if (!becli->bectx->bet_info[target].bet_ops) {
DEBUG(7, ("Undefined backend target.\n"));
goto done;
}
- be_req = talloc_zero(ctx, struct be_req);
- if (!be_req) {
- DEBUG(7, ("talloc_zero failed.\n"));
- goto done;
- }
-
- be_req->be_ctx = ctx;
- be_req->fn = be_pam_handler_callback;
- be_req->pvt = reply;
be_req->req_data = pd;
- ret = be_file_request(ctx, ctx->bet_info[target].bet_ops->handler, be_req);
+ ret = be_file_request(becli->bectx,
+ becli->bectx->bet_info[target].bet_ops->handler,
+ be_req);
if (ret != EOK) {
DEBUG(7, ("be_file_request failed.\n"));
goto done;
@@ -488,207 +497,226 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
done:
talloc_free(be_req);
- DEBUG(4, ("Sending result [%d][%s]\n", pam_status, ctx->domain->name));
+ DEBUG(4, ("Sending result [%d][%s]\n",
+ pam_status, becli->bectx->domain->name));
ret = dbus_message_append_args(reply,
DBUS_TYPE_UINT32, &pam_status,
- DBUS_TYPE_STRING, &ctx->domain->name,
+ DBUS_TYPE_STRING, &becli->bectx->domain->name,
DBUS_TYPE_INVALID);
- if (!ret) return EIO;
+ if (!ret) {
+ return EIO;
+ }
/* send reply back immediately */
sbus_conn_send_reply(conn, reply);
dbus_message_unref(reply);
- talloc_free(pd);
return EOK;
}
-/* mon_cli_init
- * sbus channel to the monitor daemon */
-static int mon_cli_init(struct be_ctx *ctx)
+static int be_client_destructor(void *ctx)
{
- char *sbus_address;
- int ret;
-
- /* Set up SBUS connection to the monitor */
- ret = monitor_get_sbus_address(ctx, &sbus_address);
- if (ret != EOK) {
- DEBUG(0, ("Could not locate monitor address.\n"));
- return ret;
+ struct be_client *becli = talloc_get_type(ctx, struct be_client);
+ if (becli->bectx) {
+ if (becli->bectx->nss_cli == becli) {
+ DEBUG(4, ("Removed NSS client\n"));
+ becli->bectx->nss_cli = NULL;
+ } else if (becli->bectx->pam_cli == becli) {
+ DEBUG(4, ("Removed PAM client\n"));
+ becli->bectx->pam_cli = NULL;
+ } else {
+ DEBUG(2, ("Unknown client removed ...\n"));
+ }
}
+ return 0;
+}
- ret = sbus_client_init(ctx, ctx->ev, sbus_address,
- &monitor_be_interface, &ctx->mon_conn,
- NULL, ctx);
- if (ret != EOK) {
- DEBUG(0, ("Failed to connect to monitor services.\n"));
- return ret;
- }
+static int client_registration(DBusMessage *message,
+ struct sbus_connection *conn)
+{
+ dbus_uint16_t version = DATA_PROVIDER_VERSION;
+ struct be_client *becli;
+ DBusMessage *reply;
+ DBusError dbus_error;
+ dbus_uint16_t cli_ver;
+ char *cli_name;
+ char *cli_domain;
+ dbus_bool_t dbret;
+ void *data;
- /* Identify ourselves to the monitor */
- ret = monitor_common_send_id(ctx->mon_conn,
- ctx->identity,
- DATA_PROVIDER_VERSION);
- if (ret != EOK) {
- DEBUG(0, ("Failed to identify to the monitor!\n"));
- return ret;
+ data = sbus_conn_get_private_data(conn);
+ becli = talloc_get_type(data, struct be_client);
+ if (!becli) {
+ DEBUG(0, ("Connection holds no valid init data\n"));
+ return EINVAL;
}
- return EOK;
-}
+ /* First thing, cancel the timeout */
+ DEBUG(4, ("Cancel DP ID timeout [%p]\n", becli->timeout));
+ talloc_zfree(becli->timeout);
-static void be_cli_reconnect_init(struct sbus_connection *conn, int status, void *pvt);
-
-/* be_cli_init
- * sbus channel to the data provider daemon */
-static int be_cli_init(struct be_ctx *ctx)
-{
- int ret, max_retries;
- char *sbus_address;
+ dbus_error_init(&dbus_error);
- /* Set up SBUS connection to the monitor */
- ret = dp_get_sbus_address(ctx, &sbus_address);
- if (ret != EOK) {
- DEBUG(0, ("Could not locate monitor address.\n"));
- return ret;
+ dbret = dbus_message_get_args(message, &dbus_error,
+ DBUS_TYPE_UINT16, &cli_ver,
+ DBUS_TYPE_STRING, &cli_name,
+ DBUS_TYPE_STRING, &cli_domain,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(1, ("Failed to parse message, killing connection\n"));
+ if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
+ sbus_disconnect(conn);
+ /* FIXME: should we just talloc_zfree(conn) ? */
+ return EIO;
}
- ret = sbus_client_init(ctx, ctx->ev, sbus_address,
- &be_interface, &ctx->dp_conn,
- NULL, ctx);
- if (ret != EOK) {
- DEBUG(0, ("Failed to connect to monitor services.\n"));
- return ret;
+ if (strcasecmp(cli_name, "NSS") == 0) {
+ becli->bectx->nss_cli = becli;
+ } else if (strcasecmp(cli_name, "PAM") == 0) {
+ becli->bectx->pam_cli = becli;
+ } else {
+ DEBUG(1, ("Unknown client! [%s]\n", cli_name));
}
+ talloc_set_destructor((TALLOC_CTX *)becli, be_client_destructor);
- /* Identify ourselves to the data provider */
- ret = dp_common_send_id(ctx->dp_conn,
- DP_CLI_BACKEND, DATA_PROVIDER_VERSION,
- "", ctx->domain->name);
- if (ret != EOK) {
- DEBUG(0, ("Failed to identify to the data provider!\n"));
- return ret;
+ DEBUG(4, ("Added Frontend client [%s]\n", cli_name));
+
+ /* reply that all is ok */
+ reply = dbus_message_new_method_return(message);
+ if (!reply) {
+ DEBUG(0, ("Dbus Out of memory!\n"));
+ return ENOMEM;
}
- /* Enable automatic reconnection to the Data Provider */
- ret = confdb_get_int(ctx->cdb, ctx, CONFDB_DP_CONF_ENTRY,
- CONFDB_SERVICE_RECON_RETRIES, 3, &max_retries);
- if (ret != EOK) {
- DEBUG(0, ("Failed to set up automatic reconnection\n"));
- return ret;
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &version,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(0, ("Failed to build dbus reply\n"));
+ dbus_message_unref(reply);
+ sbus_disconnect(conn);
+ return EIO;
}
- sbus_reconnect_init(ctx->dp_conn, max_retries,
- be_cli_reconnect_init, ctx);
+ /* send reply back */
+ sbus_conn_send_reply(conn, reply);
+ dbus_message_unref(reply);
+ becli->initialized = true;
return EOK;
}
-static int be_finalize(struct be_ctx *ctx);
-static void be_shutdown(struct be_req *req, int status, const char *errstr);
-
-static void be_cli_reconnect_init(struct sbus_connection *conn, int status, void *pvt)
+static void init_timeout(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval t, void *ptr)
{
- int ret;
- struct be_ctx *be_ctx = talloc_get_type(pvt, struct be_ctx);
-
- /* Did we reconnect successfully? */
- if (status == SBUS_RECONNECT_SUCCESS) {
- DEBUG(1, ("Reconnected to the Data Provider.\n"));
-
- /* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_ctx->dp_conn,
- DP_CLI_BACKEND, DATA_PROVIDER_VERSION,
- "", be_ctx->domain->name);
- if (ret != EOK) {
- DEBUG(0, ("Failed to send id to the data provider!\n"));
- } else {
- return;
- }
- }
+ struct be_client *becli;
- /* Handle failure */
- DEBUG(0, ("Could not reconnect to data provider.\n"));
+ DEBUG(2, ("Client timed out before Identification [%p]!\n", te));
- /* Kill the backend and let the monitor restart it */
- ret = be_finalize(be_ctx);
- if (ret != EOK) {
- DEBUG(0, ("Finalizing back-end failed with error [%d] [%s]\n",
- ret, strerror(ret)));
- be_shutdown(NULL, ret, NULL);
- }
+ becli = talloc_get_type(ptr, struct be_client);
+
+ sbus_disconnect(becli->conn);
+ talloc_zfree(becli);
}
-static void be_shutdown(struct be_req *req, int status, const char *errstr)
+static int be_client_init(struct sbus_connection *conn, void *data)
{
- /* Nothing left to do but exit() */
- if (status == EOK)
- exit(0);
-
- /* Something went wrong in finalize */
- DEBUG(0, ("Finalizing auth module failed with error [%d] [%s]\n",
- status, errstr ? : strerror(status)));
+ struct be_ctx *bectx;
+ struct be_client *becli;
+ struct timeval tv;
- exit(1);
-}
+ bectx = talloc_get_type(data, struct be_ctx);
-static void be_id_shutdown(struct be_req *req, int status, const char *errstr)
-{
- struct be_req *shutdown_req;
- struct be_ctx *ctx;
- int ret;
+ /* hang off this memory to the connection so that when the connection
+ * is freed we can potentially call a destructor */
- if (status != EOK) {
- /* Something went wrong in finalize */
- DEBUG(0, ("Finalizing auth module failed with error [%d] [%s]\n",
- status, errstr ? : strerror(status)));
+ becli = talloc(conn, struct be_client);
+ if (!becli) {
+ DEBUG(0,("Out of memory?!\n"));
+ talloc_zfree(conn);
+ return ENOMEM;
}
+ becli->bectx = bectx;
+ becli->conn = conn;
+ becli->initialized = false;
- ctx = req->be_ctx;
+ /* 5 seconds should be plenty */
+ tv = tevent_timeval_current_ofs(5, 0);
- /* Now shutdown the id module too */
- shutdown_req = talloc_zero(ctx, struct be_req);
- if (!shutdown_req) {
- ret = ENOMEM;
- goto fail;
+ becli->timeout = tevent_add_timer(bectx->ev, becli,
+ tv, init_timeout, becli);
+ if (!becli->timeout) {
+ DEBUG(0,("Out of memory?!\n"));
+ talloc_zfree(conn);
+ return ENOMEM;
}
+ DEBUG(4, ("Set-up Backend ID timeout [%p]\n", becli->timeout));
- shutdown_req->be_ctx = ctx;
- shutdown_req->fn = be_id_shutdown;
+ /* 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, becli);
- shutdown_req->pvt = ctx->bet_info[BET_ID].pvt_bet_data;
+ return EOK;
+}
- ret = be_file_request(ctx, ctx->bet_info[BET_ID].bet_ops->finalize, shutdown_req);
- if (ret == EOK)
- return;
+/* be_srv_init
+ * set up per-domain sbus channel */
+static int be_srv_init(struct be_ctx *ctx)
+{
+ char *sbus_address;
+ int ret;
-fail:
- /* If we got here, we couldn't shut down cleanly. */
- be_shutdown(NULL, ret, NULL);
+ /* Set up SBUS connection to the monitor */
+ ret = dp_get_sbus_address(ctx, &sbus_address, ctx->domain->name);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not get sbus backend address.\n"));
+ return ret;
+ }
+
+ ret = sbus_new_server(ctx, ctx->ev, sbus_address,
+ &be_interface, &ctx->sbus_srv,
+ be_client_init, ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not set up sbus server.\n"));
+ return ret;
+ }
+
+ return EOK;
}
-static int be_finalize(struct be_ctx *ctx)
+/* mon_cli_init
+ * sbus channel to the monitor daemon */
+static int mon_cli_init(struct be_ctx *ctx)
{
- struct be_req *shutdown_req;
+ char *sbus_address;
int ret;
- shutdown_req = talloc_zero(ctx, struct be_req);
- if (!shutdown_req) {
- ret = ENOMEM;
- goto fail;
+ /* Set up SBUS connection to the monitor */
+ ret = monitor_get_sbus_address(ctx, &sbus_address);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not locate monitor address.\n"));
+ return ret;
}
- shutdown_req->be_ctx = ctx;
- shutdown_req->fn = be_id_shutdown;
- shutdown_req->pvt = ctx->bet_info[BET_AUTH].pvt_bet_data;
+ ret = sbus_client_init(ctx, ctx->ev, sbus_address,
+ &monitor_be_interface, &ctx->mon_conn,
+ NULL, ctx);
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to connect to monitor services.\n"));
+ return ret;
+ }
- ret = be_file_request(ctx, ctx->bet_info[BET_AUTH].bet_ops->finalize, shutdown_req);
- if (ret == EOK) return EOK;
+ /* Identify ourselves to the monitor */
+ ret = monitor_common_send_id(ctx->mon_conn,
+ ctx->identity,
+ DATA_PROVIDER_VERSION);
+ if (ret != EOK) {
+ DEBUG(0, ("Failed to identify to the monitor!\n"));
+ return ret;
+ }
-fail:
- /* If we got here, we couldn't shut down cleanly. */
- DEBUG(0, ("ERROR: could not shut down cleanly.\n"));
- return ret;
+ return EOK;
}
static void be_target_access_permit(struct be_req *be_req)
@@ -854,7 +882,7 @@ int be_process_init(TALLOC_CTX *mem_ctx,
return ret;
}
- ret = be_cli_init(ctx);
+ ret = be_srv_init(ctx);
if (ret != EOK) {
DEBUG(0, ("fatal error setting up server bus\n"));
return ret;