summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/responder/common/responder.h2
-rw-r--r--src/responder/common/responder_common.c206
-rw-r--r--src/sss_client/common.c31
3 files changed, 147 insertions, 92 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index c17ccdf1c..a3e567ac8 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -121,6 +121,8 @@ struct cli_ctx {
int netgrent_cur;
time_t pam_timeout;
+
+ struct tevent_timer *idle;
};
struct sss_cmd_table {
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 261d91fb7..488e22a5a 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -90,7 +90,18 @@ static errno_t set_close_on_exec(int fd)
static int client_destructor(struct cli_ctx *ctx)
{
- if (ctx->cfd > 0) close(ctx->cfd);
+ errno_t ret;
+
+ if ((ctx->cfd > 0) && close(ctx->cfd) < 0) {
+ ret = errno;
+ DEBUG(1,
+ ("Failed to close fd [%d]: [%s]\n",
+ ctx->cfd, strerror(ret)));
+ }
+
+ DEBUG(8,
+ ("Terminated client [%p][%d]\n",
+ ctx, ctx->cfd));
return 0;
}
@@ -211,12 +222,24 @@ static void client_recv(struct cli_ctx *cctx)
return;
}
+static errno_t reset_idle_timer(struct cli_ctx *cctx);
+
static void client_fd_handler(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags, void *ptr)
{
+ errno_t ret;
struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
+ /* Always reset the idle timer on any activity */
+ ret = reset_idle_timer(cctx);
+ if (ret != EOK) {
+ DEBUG(1,
+ ("Could not create idle timer for client. "
+ "This connection may not auto-terminate\n"));
+ /* Non-fatal, continue */
+ }
+
if (flags & TEVENT_FD_READ) {
client_recv(cctx);
return;
@@ -227,59 +250,72 @@ static void client_fd_handler(struct tevent_context *ev,
}
}
-/* TODO: this is a copy of accept_fd_handler, maybe both can be put into on
- * handler. */
-static void accept_priv_fd_handler(struct tevent_context *ev,
+struct accept_fd_ctx {
+ struct resp_ctx *rctx;
+ bool is_private;
+};
+
+static void idle_handler(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval current_time,
+ void *data);
+
+static void accept_fd_handler(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags, void *ptr)
{
/* accept and attach new event handler */
- struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
+ struct accept_fd_ctx *accept_ctx =
+ talloc_get_type(ptr, struct accept_fd_ctx);
+ struct resp_ctx *rctx = accept_ctx->rctx;
struct cli_ctx *cctx;
socklen_t len;
struct stat stat_buf;
int ret;
+ int fd = accept_ctx->is_private ? rctx->priv_lfd : rctx->lfd;
+ int client_fd;
+
+ if (accept_ctx->is_private) {
+ ret = stat(rctx->priv_sock_name, &stat_buf);
+ if (ret == -1) {
+ DEBUG(1, ("stat on privileged pipe failed: [%d][%s].\n", errno,
+ strerror(errno)));
+ return;
+ }
- ret = stat(rctx->priv_sock_name, &stat_buf);
- if (ret == -1) {
- DEBUG(1, ("stat on privileged pipe failed: [%d][%s].\n", errno,
- strerror(errno)));
- return;
- }
-
- if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
- (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
- DEBUG(1, ("privileged pipe has an illegal status.\n"));
-/* TODO: what is the best response to this condition? Terminate? */
- return;
+ if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
+ (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
+ DEBUG(1, ("privileged pipe has an illegal status.\n"));
+ /* TODO: what is the best response to this condition? Terminate? */
+ return;
+ }
}
-
cctx = talloc_zero(rctx, struct cli_ctx);
if (!cctx) {
struct sockaddr_un addr;
- int fd;
- DEBUG(0, ("Out of memory trying to setup client context on privileged pipe!\n"));
+ DEBUG(0, ("Out of memory trying to setup client context%s!\n",
+ accept_ctx->is_private ? " on privileged pipe": ""));
/* accept and close to signal the client we have a problem */
memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
- fd = accept(rctx->priv_lfd, (struct sockaddr *)&addr, &len);
- if (fd == -1) {
+ client_fd = accept(fd, (struct sockaddr *)&addr, &len);
+ if (client_fd == -1) {
return;
}
- close(fd);
+ close(client_fd);
return;
}
len = sizeof(cctx->addr);
- cctx->cfd = accept(rctx->priv_lfd, (struct sockaddr *)&cctx->addr, &len);
+ cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len);
if (cctx->cfd == -1) {
DEBUG(1, ("Accept failed [%s]\n", strerror(errno)));
talloc_free(cctx);
return;
}
- cctx->priv = 1;
+ cctx->priv = accept_ctx->is_private;
ret = get_client_cred(cctx);
if (ret != EOK) {
@@ -292,7 +328,8 @@ static void accept_priv_fd_handler(struct tevent_context *ev,
if (!cctx->cfde) {
close(cctx->cfd);
talloc_free(cctx);
- DEBUG(2, ("Failed to queue client handler on privileged pipe\n"));
+ DEBUG(2, ("Failed to queue client handler%\n",
+ accept_ctx->is_private ? " on privileged pipe" : ""));
}
cctx->ev = ev;
@@ -300,65 +337,18 @@ static void accept_priv_fd_handler(struct tevent_context *ev,
talloc_set_destructor(cctx, client_destructor);
- DEBUG(4, ("Client connected to privileged pipe!\n"));
-
- return;
-}
-
-static void accept_fd_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *ptr)
-{
- /* accept and attach new event handler */
- struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
- struct cli_ctx *cctx;
- socklen_t len;
- int ret;
-
- cctx = talloc_zero(rctx, struct cli_ctx);
- if (!cctx) {
- struct sockaddr_un addr;
- int fd;
- DEBUG(0, ("Out of memory trying to setup client context!\n"));
- /* accept and close to signal the client we have a problem */
- memset(&addr, 0, sizeof(addr));
- len = sizeof(addr);
- fd = accept(rctx->lfd, (struct sockaddr *)&addr, &len);
- if (fd == -1) {
- return;
- }
- close(fd);
- return;
- }
-
- len = sizeof(cctx->addr);
- cctx->cfd = accept(rctx->lfd, (struct sockaddr *)&cctx->addr, &len);
- if (cctx->cfd == -1) {
- DEBUG(1, ("Accept failed [%s]\n", strerror(errno)));
- talloc_free(cctx);
- return;
- }
-
- ret = get_client_cred(cctx);
+ /* Set up the idle timer */
+ ret = reset_idle_timer(cctx);
if (ret != EOK) {
- DEBUG(2, ("get_client_cred failed, "
- "client cred may not be available.\n"));
- }
-
- cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
- TEVENT_FD_READ, client_fd_handler, cctx);
- if (!cctx->cfde) {
- close(cctx->cfd);
- talloc_free(cctx);
- DEBUG(2, ("Failed to queue client handler\n"));
+ DEBUG(1,
+ ("Could not create idle timer for client. "
+ "This connection may not auto-terminate\n"));
+ /* Non-fatal, continue */
}
- cctx->ev = ev;
- cctx->rctx = rctx;
-
- talloc_set_destructor(cctx, client_destructor);
-
- DEBUG(4, ("Client connected!\n"));
+ DEBUG(6,
+ ("Client connected%s!\n",
+ accept_ctx->is_private ? " to privileged pipe" : ""));
return;
}
@@ -395,6 +385,41 @@ static int sss_monitor_init(struct resp_ctx *rctx,
return EOK;
}
+static errno_t reset_idle_timer(struct cli_ctx *cctx)
+{
+ struct timeval tv;
+
+ /* TODO: make this configurable */
+ tv = tevent_timeval_current_ofs(60, 0);
+
+ talloc_zfree(cctx->idle);
+
+ cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, idle_handler, cctx);
+ if (!cctx->idle) return ENOMEM;
+
+ DEBUG(9,
+ ("Idle timer re-set for client [%p][%d]\n",
+ cctx, cctx->cfd));
+
+ return EOK;
+}
+
+static void idle_handler(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval current_time,
+ void *data)
+{
+ /* This connection is idle. Terminate it */
+ struct cli_ctx *cctx =
+ talloc_get_type(data, struct cli_ctx);
+
+ DEBUG(9,
+ ("Terminating idle client [%p][%d]\n",
+ cctx, cctx->cfd));
+
+ /* The cli_ctx destructor will handle the rest */
+ talloc_free(cctx);
+}
static int sss_dp_init(struct resp_ctx *rctx,
struct sbus_interface *intf,
@@ -445,6 +470,7 @@ static int set_unix_socket(struct resp_ctx *rctx)
{
struct sockaddr_un addr;
errno_t ret;
+ struct accept_fd_ctx *accept_ctx;
/* for future use */
#if 0
@@ -519,8 +545,14 @@ static int set_unix_socket(struct resp_ctx *rctx)
goto failed;
}
+ accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
+ if(!accept_ctx) goto failed;
+ accept_ctx->rctx = rctx;
+ accept_ctx->is_private = false;
+
rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
- TEVENT_FD_READ, accept_fd_handler, rctx);
+ TEVENT_FD_READ, accept_fd_handler,
+ accept_ctx);
if (!rctx->lfde) {
DEBUG(0, ("Failed to queue handler on pipe\n"));
goto failed;
@@ -563,8 +595,14 @@ static int set_unix_socket(struct resp_ctx *rctx)
goto failed;
}
+ accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
+ if(!accept_ctx) goto failed;
+ accept_ctx->rctx = rctx;
+ accept_ctx->is_private = true;
+
rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
- TEVENT_FD_READ, accept_priv_fd_handler, rctx);
+ TEVENT_FD_READ, accept_fd_handler,
+ accept_ctx);
if (!rctx->priv_lfde) {
DEBUG(0, ("Failed to queue handler on privileged pipe\n"));
goto failed;
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 5f6af418a..624e93294 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -50,6 +50,19 @@
#include <pthread.h>
#endif
+/*
+* Note we set MSG_NOSIGNAL to avoid
+* having to fiddle with signal masks
+* but also do not want to die in case
+* SIGPIPE gets raised and the application
+* does not handle it.
+*/
+#ifdef MSG_NOSIGNAL
+#define SSS_DEFAULT_WRITE_FLAGS MSG_NOSIGNAL
+#else
+#define SSS_DEFAULT_WRITE_FLAGS 0
+#endif
+
/* common functions */
int sss_cli_sd = -1; /* the sss client socket descriptor */
@@ -134,14 +147,16 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
errno = 0;
if (datasent < SSS_NSS_HEADER_SIZE) {
- res = write(sss_cli_sd,
- (char *)header + datasent,
- SSS_NSS_HEADER_SIZE - datasent);
+ res = send(sss_cli_sd,
+ (char *)header + datasent,
+ SSS_NSS_HEADER_SIZE - datasent,
+ SSS_DEFAULT_WRITE_FLAGS);
} else {
rdsent = datasent - SSS_NSS_HEADER_SIZE;
- res = write(sss_cli_sd,
- (const char *)rd->data + rdsent,
- rd->len - rdsent);
+ res = send(sss_cli_sd,
+ (const char *)rd->data + rdsent,
+ rd->len - rdsent,
+ SSS_DEFAULT_WRITE_FLAGS);
}
error = errno;
@@ -155,7 +170,7 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
/* Write failed */
sss_cli_close_socket();
- *errnop = errno;
+ *errnop = error;
return NSS_STATUS_UNAVAIL;
}
@@ -265,7 +280,7 @@ static enum nss_status sss_nss_recv_rep(enum sss_cli_command cmd,
* through. */
sss_cli_close_socket();
- *errnop = errno;
+ *errnop = error;
ret = NSS_STATUS_UNAVAIL;
goto failed;
}