summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2011-10-26 18:04:59 +0200
committerStephen Gallagher <sgallagh@redhat.com>2011-12-16 14:46:17 -0500
commit88c5d362804244a5a74785b94018ddf887094553 (patch)
tree98dbcea8339e78b15fc2c626b38de733e24c058e
parent3f98cdc011bb4e8cd22c088f288b0bcdb6452492 (diff)
downloadsssd-88c5d362804244a5a74785b94018ddf887094553.tar.gz
sssd-88c5d362804244a5a74785b94018ddf887094553.tar.bz2
sssd-88c5d362804244a5a74785b94018ddf887094553.zip
SUDO integration - data provider backend handler
-rw-r--r--src/confdb/confdb.h1
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/providers/data_provider_be.c158
-rw-r--r--src/providers/dp_backend.h6
4 files changed, 166 insertions, 0 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 2ebbf4f4..5b935c41 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -101,6 +101,7 @@
#define CONFDB_DOMAIN_AUTH_PROVIDER "auth_provider"
#define CONFDB_DOMAIN_ACCESS_PROVIDER "access_provider"
#define CONFDB_DOMAIN_CHPASS_PROVIDER "chpass_provider"
+#define CONFDB_DOMAIN_SUDO_PROVIDER "sudo_provider"
#define CONFDB_DOMAIN_COMMAND "command"
#define CONFDB_DOMAIN_TIMEOUT "timeout"
#define CONFDB_DOMAIN_ATTR "cn"
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index bf595472..1b055e39 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -50,6 +50,7 @@
#define DP_METHOD_REGISTER "RegisterService"
#define DP_METHOD_GETACCTINFO "getAccountInfo"
+#define DP_METHOD_SUDOHANDLER "sudoHandler"
/**
* @defgroup pamHandler PAM DBUS request
* @ingroup sss_pam
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 6557f9bc..2de986cc 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -80,11 +80,13 @@ struct sbus_interface monitor_be_interface = {
static int client_registration(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);
+static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn);
struct sbus_method be_methods[] = {
{ DP_METHOD_REGISTER, client_registration },
{ DP_METHOD_GETACCTINFO, be_get_account_info },
{ DP_METHOD_PAMHANDLER, be_pam_handler },
+ { DP_METHOD_SUDOHANDLER, be_sudo_handler },
{ NULL, NULL }
};
@@ -102,6 +104,7 @@ static struct bet_data bet_data[] = {
{BET_AUTH, CONFDB_DOMAIN_AUTH_PROVIDER, "sssm_%s_auth_init"},
{BET_ACCESS, CONFDB_DOMAIN_ACCESS_PROVIDER, "sssm_%s_access_init"},
{BET_CHPASS, CONFDB_DOMAIN_CHPASS_PROVIDER, "sssm_%s_chpass_init"},
+ {BET_SUDO, CONFDB_DOMAIN_SUDO_PROVIDER, "sssm_%s_sudo_init"},
{BET_MAX, NULL, NULL}
};
@@ -593,6 +596,141 @@ done:
return EOK;
}
+static void be_sudo_handler_callback(struct be_req *req,
+ int dp_err_type,
+ int errnum,
+ const char *errstr)
+{
+ DBusMessage *reply = NULL;
+ DBusConnection *dbus_conn = NULL;
+ dbus_bool_t dbret;
+ dbus_uint16_t err_maj = 0;
+ dbus_uint32_t err_min = 0;
+ const char *err_msg = NULL;
+
+ reply = (DBusMessage*)(req->pvt);
+
+ err_maj = dp_err_type;
+ err_min = errnum;
+ err_msg = errstr ? errstr : talloc_strdup(req, "No errmsg set\n");
+ if (!err_msg) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to set err_msg\n"));
+ err_msg = "OOM";
+ }
+
+ dbret = dbus_message_append_args(reply,
+ DBUS_TYPE_UINT16, &err_maj,
+ DBUS_TYPE_UINT32, &err_min,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+ if (!dbret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to generate dbus reply\n"));
+ return;
+ }
+
+ DEBUG(SSSDBG_FUNC_DATA, ("SUDO Backend returned: (%d, %d, %s)\n",
+ dp_err_type, errnum, errstr ? errstr : "<NULL>"));
+
+ dbus_conn = sbus_get_connection(req->becli->conn);
+ dbus_connection_send(dbus_conn, reply, NULL);
+ dbus_message_unref(reply);
+
+ talloc_free(req);
+}
+
+static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
+{
+ dbus_bool_t dbus_ret;
+ DBusError dbus_error;
+ DBusMessageIter iter;
+ DBusMessage *reply = NULL;
+ struct be_client *be_cli = NULL;
+ struct be_req *be_req = NULL;
+ struct be_sudo_req *be_sudo_req = NULL;
+ void *user_data = NULL;
+ int ret = 0;
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Entering be_sudo_handler()\n"));
+
+ user_data = sbus_conn_get_private_data(conn);
+ if (user_data == NULL) {
+ return EINVAL;
+ }
+
+ be_cli = talloc_get_type(user_data, struct be_client);
+ if (be_cli == NULL) {
+ return EINVAL;
+ }
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("dbus_message_new_method_return failed, cannot send reply.\n"));
+ return ENOMEM;
+ }
+
+ /* create be request */
+ be_req = talloc_zero(be_cli, struct be_req);
+ if (be_req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
+ dbus_message_unref(reply);
+ return ENOMEM;
+ }
+
+ be_req->becli = be_cli;
+ be_req->be_ctx = be_cli->bectx;
+ be_req->pvt = reply;
+ be_req->fn = be_sudo_handler_callback;
+
+ /* get and set sudo request data */
+ be_sudo_req = talloc_zero(be_req, struct be_sudo_req);
+ if (be_sudo_req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
+ goto fail;
+ }
+
+ if (dbus_message_iter_init(message, &iter)) {
+ dbus_error_init(&dbus_error);
+ dbus_ret = dbus_message_get_args(message, &dbus_error,
+ DBUS_TYPE_STRING, &(be_sudo_req->username),
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&dbus_error)) {
+ dbus_error_free(&dbus_error);
+ }
+
+ if (!dbus_ret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("dbus_message_get_args failed.\n"));
+ ret = EINVAL;
+ goto fail;
+ }
+ }
+ be_req->req_data = be_sudo_req;
+
+ /* return an error if corresponding backend target is not configured */
+ if (!be_cli->bectx->bet_info[BET_SUDO].bet_ops) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Undefined backend target.\n"));
+ ret = ENODEV;
+ goto fail;
+ }
+
+ ret = be_file_request(be_cli->bectx,
+ be_cli->bectx->bet_info[BET_SUDO].bet_ops->handler,
+ be_req);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("be_file_request failed.\n"));
+ goto fail;
+ }
+
+ return EOK;
+
+fail:
+ /* send reply back immediately */
+ be_sudo_handler_callback(be_req, DP_ERR_FATAL, ret, strerror(ret));
+
+ return EOK;
+}
+
static int be_client_destructor(void *ctx)
{
struct be_client *becli = talloc_get_type(ctx, struct be_client);
@@ -603,6 +741,9 @@ static int be_client_destructor(void *ctx)
} else if (becli->bectx->pam_cli == becli) {
DEBUG(4, ("Removed PAM client\n"));
becli->bectx->pam_cli = NULL;
+ } else if (becli->bectx->sudo_cli == becli) {
+ DEBUG(4, ("Removed SUDO client\n"));
+ becli->bectx->sudo_cli = NULL;
} else {
DEBUG(2, ("Unknown client removed ...\n"));
}
@@ -651,6 +792,8 @@ static int client_registration(DBusMessage *message,
becli->bectx->nss_cli = becli;
} else if (strcasecmp(cli_name, "PAM") == 0) {
becli->bectx->pam_cli = becli;
+ } else if (strcasecmp(cli_name, "SUDO") == 0) {
+ becli->bectx->sudo_cli = becli;
} else {
DEBUG(1, ("Unknown client! [%s]\n", cli_name));
}
@@ -1168,6 +1311,21 @@ int be_process_init(TALLOC_CTX *mem_ctx,
"from provider [%s].\n", ctx->bet_info[BET_CHPASS].mod_name));
}
+ ret = load_backend_module(ctx, BET_SUDO,
+ &ctx->bet_info[BET_SUDO],
+ ctx->bet_info[BET_ID].mod_name);
+ if (ret != EOK) {
+ if (ret != ENOENT) {
+ DEBUG(0, ("fatal error initializing data providers\n"));
+ return ret;
+ }
+ DEBUG(1, ("No SUDO module provided for [%s] !!\n",
+ be_domain));
+ } else {
+ DEBUG(9, ("SUDO backend target successfully loaded "
+ "from provider [%s].\n", ctx->bet_info[BET_SUDO].mod_name));
+ }
+
/* Handle SIGUSR1 to force offline behavior */
BlockSignals(false, SIGUSR1);
tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 3d5e40ba..ef9fe0d4 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -48,6 +48,7 @@ enum bet_type {
BET_AUTH,
BET_ACCESS,
BET_CHPASS,
+ BET_SUDO,
BET_MAX
};
@@ -108,6 +109,7 @@ struct be_ctx {
struct be_client *nss_cli;
struct be_client *pam_cli;
+ struct be_client *sudo_cli;
struct loaded_be loaded_be[BET_MAX];
struct bet_info bet_info[BET_MAX];
@@ -141,6 +143,10 @@ struct be_acct_req {
char *filter_value;
};
+struct be_sudo_req {
+ char *username;
+};
+
bool be_is_offline(struct be_ctx *ctx);
void be_mark_offline(struct be_ctx *ctx);