diff options
Diffstat (limited to 'server/nss/nsssrv_cmd.c')
-rw-r--r-- | server/nss/nsssrv_cmd.c | 146 |
1 files changed, 122 insertions, 24 deletions
diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c index f66dc88c..a1400487 100644 --- a/server/nss/nsssrv_cmd.c +++ b/server/nss/nsssrv_cmd.c @@ -19,16 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "ldb.h" +#include "ldb_errors.h" #include "util/util.h" #include "nss/nsssrv.h" +#include "nss/nsssrv_ldb.h" + +struct nss_cmd_ctx { + struct cli_ctx *cctx; +}; struct nss_cmd_table { enum sss_nss_command cmd; - int (*fn)(struct event_context *ev, struct cli_ctx *cctx); + int (*fn)(struct cli_ctx *cctx); }; -static int nss_cmd_get_version(struct event_context *ev, - struct cli_ctx *cctx) +static int nss_cmd_get_version(struct cli_ctx *cctx) { uint8_t *body; size_t blen; @@ -51,28 +57,75 @@ static int nss_cmd_get_version(struct event_context *ev, return RES_SUCCESS; } -static int nss_cmd_getpwnam(struct event_context *ev, - struct cli_ctx *cctx) +static int nss_cmd_getpwnam_callback(void *ptr, int status, + struct ldb_result *res) { + struct nss_cmd_ctx *nctx = talloc_get_type(ptr, struct nss_cmd_ctx); + struct cli_ctx *cctx = nctx->cctx; + struct ldb_message *msg; uint8_t *body; - size_t blen; - int ret; const char *name; + const char *fullname; + const char *homedir; + const char *shell; + uint64_t uid; + uint64_t gid; + size_t rsize, rp, rl, blen; + int ret; - /* 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; + if (res->count != 1) { + if (res->count > 1) { + DEBUG(1, ("getpwnam call returned more than oine result !?!\n")); + } + if (res->count == 0) { + DEBUG(2, ("No results for getpwnam call")); + } + ret = nss_packet_new(cctx->creq, 2*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] = 0; /* 0 results */ + ((uint32_t *)body)[1] = 0; /* reserved */ + goto done; } - /* TODO: async search data and return */ + msg = res->msgs[0]; + + name = ldb_msg_find_attr_as_string(msg, NSS_PW_NAME, NULL); + fullname = ldb_msg_find_attr_as_string(msg, NSS_PW_FULLNAME, NULL); + homedir = ldb_msg_find_attr_as_string(msg, NSS_PW_HOMEDIR, NULL); + shell = ldb_msg_find_attr_as_string(msg, NSS_PW_SHELL, NULL); + uid = ldb_msg_find_attr_as_uint64(msg, NSS_PW_UIDNUM, 0); + gid = ldb_msg_find_attr_as_uint64(msg, NSS_PW_UIDNUM, 0); + + if (!name || !fullname || !homedir || !shell || !uid || !gid) { + DEBUG(1, ("Incomplede user object?!? Aborting\n")); - /* fake data for now */ + ret = nss_packet_new(cctx->creq, 2*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] = 0; /* 0 results */ + ((uint32_t *)body)[1] = 0; /* reserved */ + goto done; + } + + rsize = 2*sizeof(uint32_t); + rsize += 2*sizeof(uint64_t); + rsize += strlen(name) + 1; + rsize += 2; /* password always set to 'x' */ + rsize += strlen(fullname) + 1; + rsize += strlen(homedir) + 1; + rsize += strlen(shell) + 1; /* create response packet */ - ret = nss_packet_new(cctx->creq, 4+4+(8+8+4+2+4+10+10), + ret = nss_packet_new(cctx->creq, rsize, nss_get_cmd(cctx->creq->in), &cctx->creq->out); if (ret != RES_SUCCESS) { @@ -82,26 +135,71 @@ static int nss_cmd_getpwnam(struct event_context *ev, ((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)); - + ((uint64_t *)body)[1] = uid; /* first result uid */ + ((uint64_t *)body)[2] = gid; /* first result gid */ + + rp = 2*sizeof(uint32_t) + 2*sizeof(uint64_t); + rl = strlen(name)+1; + memcpy(&body[rp], name, rl); + rp += rl; + rl = 2; + memcpy(&body[rp], "x", rl); + rp += rl; + rl = strlen(fullname)+1; + memcpy(&body[rp], fullname, rl); + rp += rl; + rl = strlen(homedir)+1; + memcpy(&body[rp], homedir, rl); + rp += rl; + rl = strlen(shell)+1; + memcpy(&body[rp], shell, rl); + +done: /* now that the packet is in place, unlock queue * making the event writable */ EVENT_FD_WRITEABLE(cctx->cfde); + /* free all request related data through the talloc hierarchy */ + talloc_free(nctx); + return RES_SUCCESS; } +static int nss_cmd_getpwnam(struct cli_ctx *cctx) +{ + struct nss_cmd_ctx *nctx; + 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; + } + + nctx = talloc(cctx, struct nss_cmd_ctx); + if (!nctx) { + return RES_NOMEM; + } + nctx->cctx = cctx; + + ret = nss_ldb_getpwnam(nctx, cctx->ev, cctx->ldb, name, + nss_cmd_getpwnam_callback, nctx); + + return ret; +} + 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) +int nss_cmd_execute(struct cli_ctx *cctx) { enum sss_nss_command cmd; int i; @@ -110,7 +208,7 @@ int nss_cmd_execute(struct event_context *ev, struct cli_ctx *cctx) 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 nss_cmds[i].fn(cctx); } } |