From 0f8453a07102da842b77538756dffe661f14c72c Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 18 May 2011 13:28:17 +0200 Subject: [PATCH 4/7] Add server-side pac support --- src/responder/pac/pacsrv.c | 2 +- src/responder/pac/pacsrv_cmd.c | 156 ++++++++++++++++++++++++++++++++++++++++ src/sss_client/sss_cli.h | 3 + 3 files changed, 160 insertions(+), 1 deletions(-) diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c index e8a9842..bc4a805 100644 --- a/src/responder/pac/pacsrv.c +++ b/src/responder/pac/pacsrv.c @@ -48,7 +48,7 @@ struct sbus_method monitor_pac_methods[] = { { MON_CLI_METHOD_PING, monitor_common_pong }, { MON_CLI_METHOD_RES_INIT, monitor_common_res_init }, - { MON_CLI_METHOD_ROTATE, monitor_common_rotate_logs }, + { MON_CLI_METHOD_ROTATE, responder_logrotate }, { NULL, NULL } }; diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c index 42ff3f8..b9b1efb 100644 --- a/src/responder/pac/pacsrv_cmd.c +++ b/src/responder/pac/pacsrv_cmd.c @@ -24,6 +24,161 @@ #include "confdb/confdb.h" #include "db/sysdb.h" +#include +#include + +#include "gen_ndr/krb5pac.h" +#include "gen_ndr/ndr_krb5pac.h" + +#define PAC_USER_OFFSET 200000 +#define PAC_HOME_PATH "/home/" +#define PAC_DEFAULT_SHELL "/bin/bash" + +static errno_t pac_cmd_done(struct cli_ctx *cctx, int cmd_ret) +{ + int ret; + + ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in), + &cctx->creq->out); + if (ret != EOK) { + DEBUG(1, ("sss_packet_new failed [%d][%s].\n", ret, strerror(ret))); + return ret; + } + + sss_packet_set_error(cctx->creq->out, cmd_ret); + + sss_cmd_done(cctx, NULL); + + return EOK; +} + +static errno_t pac_add_pac_user(struct cli_ctx *cctx) +{ + struct ndr_pull *ndr_pull; + DATA_BLOB blob; + TALLOC_CTX *tmp_ctx = NULL; + struct PAC_DATA *pac_data; + enum ndr_err_code ndr_err; + int ret; + struct sysdb_ctx *sysdb; + struct sss_domain_info *dom = NULL; + size_t c; + struct passwd pwd; + uint8_t *body; + size_t blen; + + sss_packet_get_body(cctx->creq->in, &body, &blen); + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(1, ("talloc_new failed.\n")); + return ENOMEM; + } + + blob.data = body; + blob.length = blen; + + ndr_pull = ndr_pull_init_blob(&blob, tmp_ctx); + if (ndr_pull == NULL) { + DEBUG(1, ("ndr_pull_init_blob failed.\n")); + ret = ENOMEM; + goto done; + } + ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC; /* FIXME: is this really needed ? */ + + pac_data = talloc_zero(tmp_ctx, struct PAC_DATA); + if (pac_data == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + ret = ENOMEM; + goto done; + } + + ndr_err = ndr_pull_PAC_DATA(ndr_pull, NDR_SCALARS|NDR_BUFFERS, pac_data); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(1, ("ndr_pull_PAC_DATA failed [%d]\n", ndr_err)); + ret = EBADMSG; + goto done; + } + + 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; + } + + for(c = 0; c < pac_data->num_buffers; c++) { + if (pac_data->buffers[c].type == PAC_TYPE_LOGON_INFO) { + break; + } + } + + memset(&pwd, 0, sizeof(pwd)); + + if (pac_data->buffers[c].info->logon_info.info->info3.base.account_name.size != 0) { + pwd.pw_name = discard_const(pac_data->buffers[c].info->logon_info.info->info3.base.account_name.string); + } else { + DEBUG(1, ("Missing account name in PAC.\n")); + ret = EINVAL; + goto done; + } + + if (pac_data->buffers[c].info->logon_info.info->info3.base.rid > 0) { + pwd.pw_uid = PAC_USER_OFFSET + pac_data->buffers[c].info->logon_info.info->info3.base.rid; + } else { + DEBUG(1, ("Missing user RID in PAC.\n")); + ret = EINVAL; + goto done; + } + + if (pac_data->buffers[c].info->logon_info.info->info3.base.primary_gid > 0) { + pwd.pw_gid = PAC_USER_OFFSET + pac_data->buffers[c].info->logon_info.info->info3.base.primary_gid; + } else { + DEBUG(1, ("Missing primary GID in PAC.\n")); + ret = EINVAL; + goto done; + } + pwd.pw_gid = 0; /* FIXME: for local domain tests */ + + if (pac_data->buffers[c].info->logon_info.info->info3.base.full_name.size != 0) { + pwd.pw_gecos = discard_const(pac_data->buffers[c].info->logon_info.info->info3.base.full_name.string); + } else { + DEBUG(1, ("Missing full name in PAC using account name for gecos.\n")); + pwd.pw_gecos = discard_const(pac_data->buffers[c].info->logon_info.info->info3.base.account_name.string); + } + + pwd.pw_dir = talloc_asprintf(tmp_ctx, PAC_HOME_PATH"%s", pac_data->buffers[c].info->logon_info.info->info3.base.account_name.string); + if (pwd.pw_dir == NULL) { + DEBUG(1, ("talloc_asprintf failed.\n")); + ret = ENOMEM; + goto done; + } + + pwd.pw_shell = discard_const(PAC_DEFAULT_SHELL); + + ret = sysdb_store_user(tmp_ctx, sysdb, dom, pwd.pw_name, NULL, + 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 pac_cmd_done(cctx, ret); +} + struct cli_protocol_version *register_cli_protocol_version(void) { static struct cli_protocol_version pac_cli_protocol_version[] = { @@ -36,6 +191,7 @@ 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_CLI_NULL, NULL} }; diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index 7c0ec11..c5751fd 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -144,6 +144,9 @@ enum sss_cli_command { SSS_NSS_ENDSPENT = 0x00B5, #endif +/* PAC responder calls */ + SSS_PAC_ADD_PAC_USER = 0x00E1, + /* PAM related calls */ SSS_PAM_AUTHENTICATE = 0x00F1, /**< see pam_sm_authenticate(3) for * details. -- 1.7.5.1