diff options
Diffstat (limited to 'src/responder/common/responder_common.c')
-rw-r--r-- | src/responder/common/responder_common.c | 206 |
1 files changed, 122 insertions, 84 deletions
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; |