From e7ee24655cf217d39e56ba938f078de29f06247d Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 2 May 2011 10:47:25 +0200 Subject: [PATCH 7/7] Implement SSS_PAC_PUTPWENT in pac responder --- src/responder/pac/pacsrv_cmd.c | 188 ++++++++++++++++++++++++++++++++++++++++ src/sss_client/sss_cli.h | 2 + 2 files changed, 190 insertions(+), 0 deletions(-) diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c index b9b1efb..13dc9ae 100644 --- a/src/responder/pac/pacsrv_cmd.c +++ b/src/responder/pac/pacsrv_cmd.c @@ -179,6 +179,192 @@ done: return pac_cmd_done(cctx, ret); } +static errno_t pac_putpwent(struct cli_ctx *cctx, uint8_t *body, size_t blen) +{ + struct passwd pwd; + size_t c = 0; + uint32_t id; + TALLOC_CTX *tmp_ctx; + struct sysdb_ctx *sysdb; + struct sss_domain_info *dom = NULL; + int ret; + + if (blen < 13) { + DEBUG(1, ("putpwent message too short.\n")); + return EBADMSG; + } + + if (body[blen -1] != '\0') { + DEBUG(1, ("putpwent message is not terminated by \\0.\n")); + return EBADMSG; + } + + memset(&pwd, 0, sizeof(pwd)); + + SAFEALIGN_COPY_UINT32(&id, body, NULL); + pwd.pw_uid = id; + c += sizeof(uint32_t); + DEBUG(9, ("Got uid [%d].\n", pwd.pw_uid)); + + SAFEALIGN_COPY_UINT32(&id, body+c, NULL); + pwd.pw_gid = id; + c += sizeof(uint32_t); + DEBUG(9, ("Got gid [%d].\n", pwd.pw_gid)); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(1, ("talloc_new failed.\n")); + return ENOMEM; + } + + pwd.pw_name = talloc_strdup(tmp_ctx, (const char *) body+c); + if (pwd.pw_name == NULL && body+c != '\0') { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + c += strlen(pwd.pw_name) + 1; + if (c >= blen) { + DEBUG(1, ("putpwent message is too short.\n")); + ret = EBADMSG; + goto done; + } + DEBUG(9, ("Got name [%s].\n", pwd.pw_name)); + + pwd.pw_passwd = talloc_strdup(tmp_ctx, (const char *) body+c); + if (pwd.pw_passwd == NULL && body+c != '\0') { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + c += strlen(pwd.pw_passwd) + 1; + if (c >= blen) { + DEBUG(1, ("putpwent message is too short.\n")); + ret = EBADMSG; + goto done; + } + DEBUG(9, ("Got passwd [%s].\n", pwd.pw_passwd)); + + pwd.pw_gecos = talloc_strdup(tmp_ctx, (const char *) body+c); + if (pwd.pw_gecos == NULL && body+c != '\0') { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + c += strlen(pwd.pw_gecos) + 1; + if (c >= blen) { + DEBUG(1, ("putpwent message is too short.\n")); + ret = EBADMSG; + goto done; + } + DEBUG(9, ("Got gecos [%s].\n", pwd.pw_gecos)); + + pwd.pw_dir = talloc_strdup(tmp_ctx, (const char *) body+c); + if (pwd.pw_dir == NULL && body+c != '\0') { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + c += strlen(pwd.pw_dir) + 1; + if (c >= blen) { + DEBUG(1, ("putpwent message is too short.\n")); + ret = EBADMSG; + goto done; + } + DEBUG(9, ("Got dir [%s].\n", pwd.pw_dir)); + + pwd.pw_shell = talloc_strdup(tmp_ctx, (const char *) body+c); + if (pwd.pw_shell == NULL && body+c != '\0') { + DEBUG(1, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + c += strlen(pwd.pw_shell) + 1; + if (c != blen) { + DEBUG(1, ("putpwent message has the wrong size.\n")); + ret = EBADMSG; + goto done; + } + DEBUG(9, ("Got shell [%s].\n", pwd.pw_shell)); + + for (dom = cctx->rctx->domains; dom; dom = dom->next) { + if (strcasecmp(dom->provider, "local") == 0) break; + } + if (!dom) { + DEBUG(1, ("No local domain found.\n")); + ret = ENOENT; + goto done; + } + + + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, dom, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + goto done; + } + + ret = sysdb_store_user(tmp_ctx, sysdb, dom, pwd.pw_name, pwd.pw_passwd, + pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir, + pwd.pw_shell, NULL, NULL, 0); + if (ret != EOK) { + DEBUG(1, ("sysdb_store_user failed [%d][%s].\n", ret, strerror(ret))); + goto done; + } + +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t pac_putgrent(struct cli_ctx *cctx, uint8_t *body, size_t blen) +{ + return EOPNOTSUPP; +} + +static errno_t pac_cmd_handler(struct cli_ctx *cctx, + enum sss_cli_command pac_cmd) +{ + int ret; + uint8_t *body; + size_t blen; + + sss_packet_get_body(cctx->creq->in, &body, &blen); + + switch(pac_cmd) { + case SSS_PAC_PUTPWENT: + ret = pac_putpwent(cctx, body, blen); + if (ret != EOK) { + DEBUG(1, ("pac_putpwent failed [%d][%s].\n", + ret, strerror(ret))); + } + break; + case SSS_PAC_PUTGRENT: + ret = pac_putgrent(cctx, body, blen); + if (ret != EOK) { + DEBUG(1, ("pac_putgrent failed [%d][%s].\n", + ret, strerror(ret))); + } + break; + default: + DEBUG(1, ("Unsupported PAC command [%d].\n", pac_cmd)); + ret = EINVAL; + } + + return pac_cmd_done(cctx, ret); +} + +static int pac_cmd_putpwent(struct cli_ctx *cctx) +{ + DEBUG(4, ("entering pac_cmd_putpwent.\n")); + return pac_cmd_handler(cctx, SSS_PAC_PUTPWENT); +} + +static int pac_cmd_putgrent(struct cli_ctx *cctx) +{ + DEBUG(4, ("entering pac_cmd_putgrent.\n")); + return pac_cmd_handler(cctx, SSS_PAC_PUTGRENT); +} + struct cli_protocol_version *register_cli_protocol_version(void) { static struct cli_protocol_version pac_cli_protocol_version[] = { @@ -192,6 +378,8 @@ struct cli_protocol_version *register_cli_protocol_version(void) static struct sss_cmd_table pac_cmds[] = { {SSS_GET_VERSION, sss_cmd_get_version}, {SSS_PAC_ADD_PAC_USER, pac_add_pac_user}, + {SSS_PAC_PUTPWENT, pac_cmd_putpwent}, + {SSS_PAC_PUTGRENT, pac_cmd_putgrent}, {SSS_CLI_NULL, NULL} }; diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index c5751fd..09800d5 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -146,6 +146,8 @@ enum sss_cli_command { /* PAC responder calls */ SSS_PAC_ADD_PAC_USER = 0x00E1, + SSS_PAC_PUTPWENT = 0x00E2, /* only for testing */ + SSS_PAC_PUTGRENT = 0x00E3, /* only for testing */ /* PAM related calls */ SSS_PAM_AUTHENTICATE = 0x00F1, /**< see pam_sm_authenticate(3) for -- 1.7.5.1