summaryrefslogtreecommitdiff
path: root/server/nss
diff options
context:
space:
mode:
Diffstat (limited to 'server/nss')
-rw-r--r--server/nss/nsssrv.c103
-rw-r--r--server/nss/nsssrv.h26
-rw-r--r--server/nss/nsssrv_cmd.c118
-rw-r--r--server/nss/nsssrv_packet.c28
4 files changed, 214 insertions, 61 deletions
diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c
index c2826d27..176da520 100644
--- a/server/nss/nsssrv.c
+++ b/server/nss/nsssrv.c
@@ -27,25 +27,12 @@
#include <sys/un.h>
#include <string.h>
#include <sys/time.h>
-#include "../events/events.h"
-#include "../talloc/talloc.h"
+#include "talloc.h"
+#include "events.h"
#include "util/util.h"
#include "service.h"
#include "nss/nsssrv.h"
-struct nss_ctx {
- struct task_server *task;
- struct fd_event *lfde;
- int lfd;
-};
-
-struct cli_ctx {
- int cfd;
- struct fd_event *cfde;
- struct sockaddr_un addr;
- struct cli_request *creq;
-};
-
static void set_nonblocking(int fd)
{
unsigned v;
@@ -66,58 +53,62 @@ static int client_destructor(struct cli_ctx *ctx)
return 0;
}
-static void client_send(struct event_context *ev, struct cli_ctx *ctx)
+static void client_send(struct event_context *ev, struct cli_ctx *cctx)
{
int ret;
- ret = nss_packet_send(ctx->creq->out, ctx->cfd);
+ ret = nss_packet_send(cctx->creq->out, cctx->cfd);
if (ret == RES_RETRY) {
/* not all data was sent, loop again */
return;
}
if (ret != RES_SUCCESS) {
DEBUG(0, ("Failed to read request, aborting client!\n"));
- talloc_free(ctx);
+ talloc_free(cctx);
return;
}
/* ok all sent */
- EVENT_FD_NOT_WRITEABLE(ctx->cfde);
- EVENT_FD_READABLE(ctx->cfde);
- talloc_free(ctx->creq);
- ctx->creq = NULL;
+ EVENT_FD_NOT_WRITEABLE(cctx->cfde);
+ EVENT_FD_READABLE(cctx->cfde);
+ talloc_free(cctx->creq);
+ cctx->creq = NULL;
return;
}
-static void client_recv(struct event_context *ev, struct cli_ctx *ctx)
+static void client_recv(struct event_context *ev, struct cli_ctx *cctx)
{
int ret;
- if (!ctx->creq) {
- ctx->creq = talloc_zero(ctx, struct cli_request);
- if (!ctx->creq) {
+ if (!cctx->creq) {
+ cctx->creq = talloc_zero(cctx, struct cli_request);
+ if (!cctx->creq) {
DEBUG(0, ("Failed to alloc request, aborting client!\n"));
- talloc_free(ctx);
+ talloc_free(cctx);
return;
}
}
- if (!ctx->creq->in) {
- ret = nss_packet_new(ctx->creq, 0, &ctx->creq->in);
+ if (!cctx->creq->in) {
+ ret = nss_packet_new(cctx->creq, 0, 0, &cctx->creq->in);
if (ret != RES_SUCCESS) {
DEBUG(0, ("Failed to alloc request, aborting client!\n"));
- talloc_free(ctx);
+ talloc_free(cctx);
return;
}
}
- ret = nss_packet_recv(ctx->creq->in, ctx->cfd);
+ ret = nss_packet_recv(cctx->creq->in, cctx->cfd);
switch (ret) {
case RES_SUCCESS:
/* do not read anymore */
- EVENT_FD_NOT_READABLE(ctx->cfde);
+ EVENT_FD_NOT_READABLE(cctx->cfde);
/* execute command */
- /* nss_cmd_execute(ctx); */
+ ret = nss_cmd_execute(ev, cctx);
+ if (ret != RES_SUCCESS) {
+ DEBUG(0, ("Failed to execute request, aborting client!\n"));
+ talloc_free(cctx);
+ }
break;
case RES_RETRY:
@@ -126,7 +117,7 @@ static void client_recv(struct event_context *ev, struct cli_ctx *ctx)
default:
DEBUG(0, ("Failed to read request, aborting client!\n"));
- talloc_free(ctx);
+ talloc_free(cctx);
}
return;
@@ -136,14 +127,14 @@ static void client_fd_handler(struct event_context *ev,
struct fd_event *fde,
uint16_t flags, void *ptr)
{
- struct cli_ctx *ctx = talloc_get_type(ptr, struct cli_ctx);
+ struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
if (flags & EVENT_FD_READ) {
- client_recv(ev, ctx);
+ client_recv(ev, cctx);
return;
}
if (flags & EVENT_FD_WRITE) {
- client_send(ev, ctx);
+ client_send(ev, cctx);
return;
}
}
@@ -153,11 +144,11 @@ static void accept_fd_handler(struct event_context *ev,
uint16_t flags, void *ptr)
{
/* accept and attach new event handler */
- struct nss_ctx *ctx = talloc_get_type(ptr, struct nss_ctx);
+ struct nss_ctx *nctx = talloc_get_type(ptr, struct nss_ctx);
struct cli_ctx *cctx;
socklen_t len;
- cctx = talloc_zero(ctx, struct cli_ctx);
+ cctx = talloc_zero(nctx, struct cli_ctx);
if (!cctx) {
struct sockaddr_un addr;
int fd;
@@ -165,7 +156,7 @@ static void accept_fd_handler(struct event_context *ev,
/* accept and close to signal the client we have a problem */
memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
- fd = accept(ctx->lfd, (struct sockaddr *)&addr, &len);
+ fd = accept(nctx->lfd, (struct sockaddr *)&addr, &len);
if (fd == -1) {
return;
}
@@ -174,7 +165,7 @@ static void accept_fd_handler(struct event_context *ev,
}
len = sizeof(cctx->addr);
- cctx->cfd = accept(ctx->lfd, (struct sockaddr *)&cctx->addr, &len);
+ cctx->cfd = accept(nctx->lfd, (struct sockaddr *)&cctx->addr, &len);
if (cctx->cfd == -1) {
DEBUG(1, ("Accept failed [%s]", strerror(errno)));
talloc_free(cctx);
@@ -196,7 +187,7 @@ static void accept_fd_handler(struct event_context *ev,
/* create a unix socket and listen to it */
static void set_unix_socket(struct event_context *ev,
- struct nss_ctx *ctx,
+ struct nss_ctx *nctx,
const char *sock_name)
{
struct sockaddr_un addr;
@@ -204,49 +195,49 @@ static void set_unix_socket(struct event_context *ev,
/* make sure we have no old sockets around */
unlink(sock_name);
- ctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (ctx->lfd == -1) {
+ nctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (nctx->lfd == -1) {
return;
}
- set_nonblocking(ctx->lfd);
- set_close_on_exec(ctx->lfd);
+ set_nonblocking(nctx->lfd);
+ set_close_on_exec(nctx->lfd);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path));
- if (bind(ctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ if (bind(nctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
DEBUG(0,("Unable to bind on socket '%s'\n", sock_name));
goto failed;
}
- if (listen(ctx->lfd, 10) != 0) {
+ if (listen(nctx->lfd, 10) != 0) {
DEBUG(0,("Unable to listen on socket '%s'\n", sock_name));
goto failed;
}
- ctx->lfde = event_add_fd(ev, ctx, ctx->lfd,
- EVENT_FD_READ, accept_fd_handler, ctx);
+ nctx->lfde = event_add_fd(ev, nctx, nctx->lfd,
+ EVENT_FD_READ, accept_fd_handler, nctx);
return;
failed:
- close(ctx->lfd);
+ close(nctx->lfd);
}
void nss_task_init(struct task_server *task)
{
- struct nss_ctx *ctx;
+ struct nss_ctx *nctx;
task_server_set_title(task, "sssd[nsssrv]");
- ctx = talloc_zero(task, struct nss_ctx);
- if (!ctx) {
+ nctx = talloc_zero(task, struct nss_ctx);
+ if (!nctx) {
task_server_terminate(task, "fatal error initializing nss_ctx\n");
return;
}
- ctx->task = task;
+ nctx->task = task;
- set_unix_socket(task->event_ctx, ctx, SSS_NSS_SOCKET_NAME);
+ set_unix_socket(task->event_ctx, nctx, SSS_NSS_SOCKET_NAME);
}
diff --git a/server/nss/nsssrv.h b/server/nss/nsssrv.h
index 5e6c9aa5..075db1d0 100644
--- a/server/nss/nsssrv.h
+++ b/server/nss/nsssrv.h
@@ -23,13 +23,27 @@
#define __NSSSRV_H__
#include <stdint.h>
+#include <sys/un.h>
+#include "talloc.h"
+#include "events.h"
#include "../nss_client/sss_nss.h"
+struct nss_ctx {
+ struct task_server *task;
+ struct fd_event *lfde;
+ int lfd;
+};
+
+struct cli_ctx {
+ int cfd;
+ struct fd_event *cfde;
+ struct sockaddr_un addr;
+ struct cli_request *creq;
+};
+
struct nss_packet;
struct cli_request {
- enum sss_nss_command cmd;
- void *cmd_req;
/* original request from the wire */
struct nss_packet *in;
@@ -40,9 +54,15 @@ struct cli_request {
/* from nsssrv_packet.c */
int nss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
- struct nss_packet **rpacket);
+ enum sss_nss_command cmd,
+ struct nss_packet **rpacket);
int nss_packet_grow(struct nss_packet *packet, size_t size);
int nss_packet_recv(struct nss_packet *packet, int fd);
int nss_packet_send(struct nss_packet *packet, int fd);
+enum sss_nss_command nss_get_cmd(struct nss_packet *packet);
+void nss_get_body(struct nss_packet *packet, uint8_t **body, size_t *blen);
+
+/* from nsssrv_cmd.c */
+int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx);
#endif /* __NSSSRV_H__ */
diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c
new file mode 100644
index 00000000..f66dc88c
--- /dev/null
+++ b/server/nss/nsssrv_cmd.c
@@ -0,0 +1,118 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "nss/nsssrv.h"
+
+struct nss_cmd_table {
+ enum sss_nss_command cmd;
+ int (*fn)(struct event_context *ev, struct cli_ctx *cctx);
+};
+
+static int nss_cmd_get_version(struct event_context *ev,
+ struct cli_ctx *cctx)
+{
+ uint8_t *body;
+ size_t blen;
+ int ret;
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, sizeof(uint32_t),
+ nss_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != RES_SUCCESS) {
+ return ret;
+ }
+ nss_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = SSS_NSS_VERSION;
+
+ /* now that the packet is in place, unlock queue
+ * making the event writable */
+ EVENT_FD_WRITEABLE(cctx->cfde);
+
+ return RES_SUCCESS;
+}
+
+static int nss_cmd_getpwnam(struct event_context *ev,
+ struct cli_ctx *cctx)
+{
+ uint8_t *body;
+ size_t blen;
+ int ret;
+ const char *name;
+
+ /* get user name to query */
+ nss_get_body(cctx->creq->in, &body, &blen);
+ name = (const char *)body;
+ /* if not terminated fail */
+ if (name[blen -1] != '\0') {
+ return RES_INVALID_DATA;
+ }
+
+ /* TODO: async search data and return */
+
+ /* fake data for now */
+
+ /* create response packet */
+ ret = nss_packet_new(cctx->creq, 4+4+(8+8+4+2+4+10+10),
+ nss_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != RES_SUCCESS) {
+ return ret;
+ }
+ nss_get_body(cctx->creq->out, &body, &blen);
+
+ ((uint32_t *)body)[0] = 1; /* 1 result */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ ((uint64_t *)body)[1] = 1234; /* first result uid */
+ ((uint64_t *)body)[2] = 1234; /* first result gid */
+
+ name = "foo\0x\0foo\0/home/foo\0/bin/bash\0";
+ memcpy(&body[24], name, (8+8+4+2+4+10+10));
+
+ /* now that the packet is in place, unlock queue
+ * making the event writable */
+ EVENT_FD_WRITEABLE(cctx->cfde);
+
+ return RES_SUCCESS;
+}
+
+struct nss_cmd_table nss_cmds[] = {
+ {SSS_NSS_GET_VERSION, nss_cmd_get_version},
+ {SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
+ {SSS_NSS_NULL, NULL}
+};
+
+int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx)
+{
+ enum sss_nss_command cmd;
+ int i;
+
+ cmd = nss_get_cmd(cctx->creq->in);
+
+ for (i = 0; nss_cmds[i].cmd != SSS_NSS_NULL; i++) {
+ if (cmd == nss_cmds[i].cmd) {
+ return nss_cmds[i].fn(ev, cctx);
+ }
+ }
+
+ return RES_INVALID_DATA;
+}
diff --git a/server/nss/nsssrv_packet.c b/server/nss/nsssrv_packet.c
index e33568a3..87d1acfe 100644
--- a/server/nss/nsssrv_packet.c
+++ b/server/nss/nsssrv_packet.c
@@ -55,6 +55,7 @@ struct nss_packet {
* firecgtly from the wire
*/
int nss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
+ enum sss_nss_command cmd,
struct nss_packet **rpacket)
{
struct nss_packet *packet;
@@ -63,7 +64,7 @@ int nss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
if (!packet) return RES_NOMEM;
if (size) {
- int n = size % NSSSRV_PACKET_MEM_SIZE;
+ int n = (size + SSS_NSS_HEADER_SIZE) % NSSSRV_PACKET_MEM_SIZE;
packet->memsize = (n + 1) * NSSSRV_PACKET_MEM_SIZE;
} else {
packet->memsize = NSSSRV_PACKET_MEM_SIZE;
@@ -82,7 +83,10 @@ int nss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
packet->reserved = &((uint32_t *)packet->buffer)[3];
packet->body = (uint8_t *)&((uint32_t *)packet->buffer)[4];
- *(packet->len) = size?size:SSS_NSS_HEADER_SIZE;
+ *(packet->len) = size + SSS_NSS_HEADER_SIZE;
+ *(packet->cmd) = cmd;
+
+ packet->iop = 0;
*rpacket = packet;
@@ -148,6 +152,10 @@ int nss_packet_recv(struct nss_packet *packet, int fd)
return RES_RETRY;
}
+ if (rb == 0) {
+ return RES_ERROR;
+ }
+
packet->iop += rb;
if (packet->iop < 4) {
return RES_RETRY;
@@ -176,10 +184,26 @@ int nss_packet_send(struct nss_packet *packet, int fd)
return RES_RETRY;
}
+ if (rb == 0) {
+ return RES_ERROR;
+ }
+
packet->iop += rb;
+
if (packet->iop < *packet->len) {
return RES_RETRY;
}
return RES_SUCCESS;
}
+
+enum sss_nss_command nss_get_cmd(struct nss_packet *packet)
+{
+ return (enum sss_nss_command)(*packet->cmd);
+}
+
+void nss_get_body(struct nss_packet *packet, uint8_t **body, size_t *blen)
+{
+ *body = packet->body;
+ *blen = *packet->len - SSS_NSS_HEADER_SIZE;
+}