summaryrefslogtreecommitdiffstats
path: root/src/responder/common
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-01-08 17:51:06 -0500
committerJakub Hrozek <jhrozek@redhat.com>2016-06-29 21:46:03 +0200
commit4f3a9d837a55b49448eca3c713c85a406207e523 (patch)
treecf983b0fac5ddbc39ca259306342a0c05245168c /src/responder/common
parent9a6d162cacfaf6946a1bf974b80b643d2a052d7a (diff)
downloadsssd-4f3a9d837a55b49448eca3c713c85a406207e523.tar.gz
sssd-4f3a9d837a55b49448eca3c713c85a406207e523.tar.xz
sssd-4f3a9d837a55b49448eca3c713c85a406207e523.zip
Responders: Make the client context more generic
This is useufl to allow reusing the responder code with other protocols. Store protocol data and responder state data behind opaque pointers and use tallog_get_type to check they are of the right type. This also allows to store per responder state_ctx so that, for example, the autofs responder does not have to carry useless variables used only by the nss responder. Resolves: https://fedorahosted.org/sssd/ticket/2918 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/responder/common')
-rw-r--r--src/responder/common/responder.h30
-rw-r--r--src/responder/common/responder_cmd.c51
-rw-r--r--src/responder/common/responder_common.c66
3 files changed, 97 insertions, 50 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 2b5b05412..adf7b3d19 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -68,6 +68,11 @@ struct cli_protocol_version {
const char *description;
};
+struct cli_protocol {
+ struct cli_request *creq;
+ struct cli_protocol_version *cli_protocol_version;
+};
+
struct resp_ctx;
struct be_conn {
@@ -130,26 +135,14 @@ struct cli_ctx {
struct resp_ctx *rctx;
int cfd;
struct tevent_fd *cfde;
+ tevent_fd_handler_t cfd_handler;
struct sockaddr_un addr;
- struct cli_request *creq;
- struct cli_protocol_version *cli_protocol_version;
int priv;
struct cli_creds *creds;
- int pwent_dom_idx;
- int pwent_cur;
-
- int grent_dom_idx;
- int grent_cur;
-
- int svc_dom_idx;
- int svcent_cur;
-
- char *netgr_name;
- int netgrent_cur;
-
- char *automntmap_name;
+ void *protocol_ctx;
+ void *state_ctx;
struct tevent_timer *idle;
};
@@ -165,6 +158,12 @@ struct mon_cli_iface;
/*
* responder_common.c
*
+ */
+
+typedef int (*connection_setup_t)(struct cli_ctx *cctx);
+
+int sss_connection_setup(struct cli_ctx *cctx);
+/*
* NOTE: We would like to use more strong typing for the @dp_vtable argument
* but can't since it accepts either a struct data_provider_iface
* or struct data_provider_rev_iface. So pass the base struct: sbus_vtable
@@ -183,6 +182,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
struct mon_cli_iface *monitor_intf,
const char *cli_name,
struct sbus_vtable *dp_intf,
+ connection_setup_t conn_setup,
struct resp_ctx **responder_ctx);
int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
diff --git a/src/responder/common/responder_cmd.c b/src/responder/common/responder_cmd.c
index 1ac86fddf..175a8e5d6 100644
--- a/src/responder/common/responder_cmd.c
+++ b/src/responder/common/responder_cmd.c
@@ -24,20 +24,25 @@
#include "responder/common/responder.h"
#include "responder/common/responder_packet.h"
+
int sss_cmd_send_error(struct cli_ctx *cctx, int err)
{
+ struct cli_protocol *pctx;
int ret;
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+ if (!pctx) return EINVAL;
+
/* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
+ ret = sss_packet_new(pctx->creq, 0,
+ sss_packet_get_cmd(pctx->creq->in),
+ &pctx->creq->out);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create new packet: %d\n", ret);
return ret;
}
- sss_packet_set_error(cctx->creq->out, err);
+ sss_packet_set_error(pctx->creq->out, err);
return EOK;
}
@@ -63,22 +68,26 @@ int sss_cmd_empty_packet(struct sss_packet *packet)
int sss_cmd_send_empty(struct cli_ctx *cctx, TALLOC_CTX *freectx)
{
+ struct cli_protocol *pctx;
int ret;
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+ if (!pctx) return EINVAL;
+
/* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
+ ret = sss_packet_new(pctx->creq, 0,
+ sss_packet_get_cmd(pctx->creq->in),
+ &pctx->creq->out);
if (ret != EOK) {
return ret;
}
- ret = sss_cmd_empty_packet(cctx->creq->out);
+ ret = sss_cmd_empty_packet(pctx->creq->out);
if (ret != EOK) {
return ret;
}
- sss_packet_set_error(cctx->creq->out, EOK);
+ sss_packet_set_error(pctx->creq->out, EOK);
sss_cmd_done(cctx, freectx);
return EOK;
}
@@ -95,6 +104,7 @@ void sss_cmd_done(struct cli_ctx *cctx, void *freectx)
int sss_cmd_get_version(struct cli_ctx *cctx)
{
+ struct cli_protocol *pctx;
uint8_t *req_body;
size_t req_blen;
uint8_t *body;
@@ -105,16 +115,19 @@ int sss_cmd_get_version(struct cli_ctx *cctx)
int i;
static struct cli_protocol_version *cli_protocol_version = NULL;
- cctx->cli_protocol_version = NULL;
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+ if (!pctx) return EINVAL;
+
+ pctx->cli_protocol_version = NULL;
if (cli_protocol_version == NULL) {
cli_protocol_version = register_cli_protocol_version();
}
if (cli_protocol_version != NULL) {
- cctx->cli_protocol_version = &cli_protocol_version[0];
+ pctx->cli_protocol_version = &cli_protocol_version[0];
- sss_packet_get_body(cctx->creq->in, &req_body, &req_blen);
+ sss_packet_get_body(pctx->creq->in, &req_body, &req_blen);
if (req_blen == sizeof(uint32_t)) {
memcpy(&client_version, req_body, sizeof(uint32_t));
DEBUG(SSSDBG_FUNC_DATA,
@@ -123,7 +136,7 @@ int sss_cmd_get_version(struct cli_ctx *cctx)
i=0;
while(cli_protocol_version[i].version>0) {
if (cli_protocol_version[i].version == client_version) {
- cctx->cli_protocol_version = &cli_protocol_version[i];
+ pctx->cli_protocol_version = &cli_protocol_version[i];
break;
}
i++;
@@ -132,16 +145,16 @@ int sss_cmd_get_version(struct cli_ctx *cctx)
}
/* create response packet */
- ret = sss_packet_new(cctx->creq, sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
+ ret = sss_packet_new(pctx->creq, sizeof(uint32_t),
+ sss_packet_get_cmd(pctx->creq->in),
+ &pctx->creq->out);
if (ret != EOK) {
return ret;
}
- sss_packet_get_body(cctx->creq->out, &body, &blen);
+ sss_packet_get_body(pctx->creq->out, &body, &blen);
- protocol_version = (cctx->cli_protocol_version != NULL)
- ? cctx->cli_protocol_version->version : 0;
+ protocol_version = (pctx->cli_protocol_version != NULL)
+ ? pctx->cli_protocol_version->version : 0;
SAFEALIGN_COPY_UINT32(body, &protocol_version, NULL);
DEBUG(SSSDBG_FUNC_DATA, "Offered version [%d].\n", protocol_version);
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 67a7aa8f9..e67456bb1 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -241,12 +241,14 @@ done:
return ret;
}
-
static void client_send(struct cli_ctx *cctx)
{
+ struct cli_protocol *pctx;
int ret;
- ret = sss_packet_send(cctx->creq->out, cctx->cfd);
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+
+ ret = sss_packet_send(pctx->creq->out, cctx->cfd);
if (ret == EAGAIN) {
/* not all data was sent, loop again */
return;
@@ -260,26 +262,30 @@ static void client_send(struct cli_ctx *cctx)
/* ok all sent */
TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
TEVENT_FD_READABLE(cctx->cfde);
- talloc_free(cctx->creq);
- cctx->creq = NULL;
+ talloc_zfree(pctx->creq);
return;
}
static int client_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
{
+ struct cli_protocol *pctx;
enum sss_cli_command cmd;
- cmd = sss_packet_get_cmd(cctx->creq->in);
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+ cmd = sss_packet_get_cmd(pctx->creq->in);
return sss_cmd_execute(cctx, cmd, sss_cmds);
}
static void client_recv(struct cli_ctx *cctx)
{
+ struct cli_protocol *pctx;
int ret;
- if (!cctx->creq) {
- cctx->creq = talloc_zero(cctx, struct cli_request);
- if (!cctx->creq) {
+ pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
+
+ if (!pctx->creq) {
+ pctx->creq = talloc_zero(cctx, struct cli_request);
+ if (!pctx->creq) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Failed to alloc request, aborting client!\n");
talloc_free(cctx);
@@ -287,9 +293,9 @@ static void client_recv(struct cli_ctx *cctx)
}
}
- if (!cctx->creq->in) {
- ret = sss_packet_new(cctx->creq, SSS_PACKET_MAX_RECV_SIZE,
- 0, &cctx->creq->in);
+ if (!pctx->creq->in) {
+ ret = sss_packet_new(pctx->creq, SSS_PACKET_MAX_RECV_SIZE,
+ 0, &pctx->creq->in);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Failed to alloc request, aborting client!\n");
@@ -298,7 +304,7 @@ static void client_recv(struct cli_ctx *cctx)
}
}
- ret = sss_packet_recv(cctx->creq->in, cctx->cfd);
+ ret = sss_packet_recv(pctx->creq->in, cctx->cfd);
switch (ret) {
case EOK:
/* do not read anymore */
@@ -368,6 +374,7 @@ static void client_fd_handler(struct tevent_context *ev,
struct accept_fd_ctx {
struct resp_ctx *rctx;
bool is_private;
+ connection_setup_t connection_setup;
};
static void idle_handler(struct tevent_context *ev,
@@ -468,8 +475,19 @@ static void accept_fd_handler(struct tevent_context *ev,
}
}
+ ret = accept_ctx->connection_setup(cctx);
+ if (ret != EOK) {
+ close(cctx->cfd);
+ talloc_free(cctx);
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to setup client handler%s\n",
+ accept_ctx->is_private ? " on privileged pipe" : "");
+ return;
+ }
+
cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
- TEVENT_FD_READ, client_fd_handler, cctx);
+ TEVENT_FD_READ, cctx->cfd_handler,
+ cctx);
if (!cctx->cfde) {
close(cctx->cfd);
talloc_free(cctx);
@@ -644,10 +662,11 @@ done:
}
/* create a unix socket and listen to it */
-static int set_unix_socket(struct resp_ctx *rctx)
+static int set_unix_socket(struct resp_ctx *rctx,
+ connection_setup_t conn_setup)
{
errno_t ret;
- struct accept_fd_ctx *accept_ctx;
+ struct accept_fd_ctx *accept_ctx = NULL;
/* for future use */
#if 0
@@ -699,6 +718,7 @@ static int set_unix_socket(struct resp_ctx *rctx)
if(!accept_ctx) goto failed;
accept_ctx->rctx = rctx;
accept_ctx->is_private = false;
+ accept_ctx->connection_setup = conn_setup;
rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
TEVENT_FD_READ, accept_fd_handler,
@@ -723,6 +743,7 @@ static int set_unix_socket(struct resp_ctx *rctx)
if(!accept_ctx) goto failed;
accept_ctx->rctx = rctx;
accept_ctx->is_private = true;
+ accept_ctx->connection_setup = conn_setup;
rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
TEVENT_FD_READ, accept_fd_handler,
@@ -742,6 +763,18 @@ failed:
return EIO;
}
+int sss_connection_setup(struct cli_ctx *cctx)
+{
+ cctx->protocol_ctx = talloc_zero(cctx, struct cli_protocol);
+ if (!cctx->protocol_ctx) {
+ return ENOMEM;
+ }
+
+ cctx->cfd_handler = client_fd_handler;
+
+ return EOK;
+}
+
static int sss_responder_ctx_destructor(void *ptr)
{
struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
@@ -829,6 +862,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
struct mon_cli_iface *monitor_intf,
const char *cli_name,
struct sbus_vtable *dp_intf,
+ connection_setup_t conn_setup,
struct resp_ctx **responder_ctx)
{
struct resp_ctx *rctx;
@@ -959,7 +993,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
}
/* after all initializations we are ready to listen on our socket */
- ret = set_unix_socket(rctx);
+ ret = set_unix_socket(rctx, conn_setup);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing socket\n");
goto fail;