summaryrefslogtreecommitdiffstats
path: root/server/responder/pam
diff options
context:
space:
mode:
Diffstat (limited to 'server/responder/pam')
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c476
-rw-r--r--server/responder/pam/pamsrv.c224
-rw-r--r--server/responder/pam/pamsrv.h57
-rw-r--r--server/responder/pam/pamsrv_cmd.c1181
-rw-r--r--server/responder/pam/pamsrv_dp.c142
5 files changed, 0 insertions, 2080 deletions
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
deleted file mode 100644
index 34f0c8dd5..000000000
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- SSSD
-
- PAM e credentials
-
- Copyright (C) Sumit Bose <sbose@redhat.com> 2009
-
- 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 <time.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "util/sha512crypt.h"
-#include "providers/data_provider.h"
-#include "responder/pam/pamsrv.h"
-
-
-#define NULL_CHECK_OR_JUMP(var, msg, ret, err, label) do { \
- if (var == NULL) { \
- DEBUG(1, (msg)); \
- ret = (err); \
- goto label; \
- } \
-} while(0)
-
-#define NEQ_CHECK_OR_JUMP(var, val, msg, ret, err, label) do { \
- if (var != (val)) { \
- DEBUG(1, (msg)); \
- ret = (err); \
- goto label; \
- } \
-} while(0)
-
-
-struct LOCAL_request {
- struct tevent_context *ev;
- struct sysdb_ctx *dbctx;
- struct sysdb_attrs *mod_attrs;
- struct sysdb_handle *handle;
-
- struct ldb_result *res;
- int error;
-
- struct pam_auth_req *preq;
-};
-
-static void prepare_reply(struct LOCAL_request *lreq)
-{
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- if (lreq->error != EOK && pd->pam_status == PAM_SUCCESS)
- pd->pam_status = PAM_SYSTEM_ERR;
-
- lreq->preq->callback(lreq->preq);
-}
-
-static void set_user_attr_done(struct tevent_req *req)
-{
- struct LOCAL_request *lreq;
- int ret;
-
- lreq = tevent_req_callback_data(req, struct LOCAL_request);
-
- ret = sysdb_transaction_commit_recv(req);
- if (ret) {
- DEBUG(2, ("set_user_attr failed.\n"));
- lreq->error =ret;
- }
-
- prepare_reply(lreq);
-}
-
-static void set_user_attr_req_done(struct tevent_req *subreq);
-static void set_user_attr_req(struct tevent_req *req)
-{
- struct LOCAL_request *lreq = tevent_req_callback_data(req,
- struct LOCAL_request);
- struct tevent_req *subreq;
- int ret;
-
- DEBUG(4, ("entering set_user_attr_req\n"));
-
- ret = sysdb_transaction_recv(req, lreq, &lreq->handle);
- if (ret) {
- lreq->error = ret;
- return prepare_reply(lreq);
- }
-
- subreq = sysdb_set_user_attr_send(lreq, lreq->ev, lreq->handle,
- lreq->preq->domain,
- lreq->preq->pd->user,
- lreq->mod_attrs, SYSDB_MOD_REP);
- if (!subreq) {
- /* cancel transaction */
- talloc_zfree(lreq->handle);
- lreq->error = ret;
- return prepare_reply(lreq);
- }
- tevent_req_set_callback(subreq, set_user_attr_req_done, lreq);
-}
-
-static void set_user_attr_req_done(struct tevent_req *subreq)
-{
- struct LOCAL_request *lreq = tevent_req_callback_data(subreq,
- struct LOCAL_request);
- struct tevent_req *req;
- int ret;
-
- ret = sysdb_set_user_attr_recv(subreq);
- talloc_zfree(subreq);
-
- DEBUG(4, ("set_user_attr_callback, status [%d][%s]\n", ret, strerror(ret)));
-
- if (ret) {
- lreq->error = ret;
- goto fail;
- }
-
- req = sysdb_transaction_commit_send(lreq, lreq->ev, lreq->handle);
- if (!req) {
- lreq->error = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, set_user_attr_done, lreq);
-
- return;
-
-fail:
- DEBUG(2, ("set_user_attr failed.\n"));
-
- /* cancel transaction */
- talloc_zfree(lreq->handle);
-
- prepare_reply(lreq);
-}
-
-static void do_successful_login(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_LAST_LOGIN, (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0L);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-
-done:
-
- prepare_reply(lreq);
-}
-
-static void do_failed_login(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
- int failedLoginAttempts;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
- pd->pam_status = PAM_AUTH_ERR;
-/* TODO: maybe add more inteligent delay calculation */
- pd->response_delay = 3;
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_LAST_FAILED_LOGIN, (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- failedLoginAttempts = ldb_msg_find_attr_as_int(lreq->res->msgs[0],
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- 0);
- failedLoginAttempts++;
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- (long)failedLoginAttempts);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-
-done:
-
- prepare_reply(lreq);
-}
-
-static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
-{
- const char *disabled;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- disabled = ldb_msg_find_attr_as_string(lreq->res->msgs[0],
- SYSDB_DISABLED, NULL);
- if ((disabled != NULL) &&
- (strncasecmp(disabled, "false",5) != 0) &&
- (strncasecmp(disabled, "no",2) != 0) ) {
- pd->pam_status = PAM_PERM_DENIED;
- }
-
- prepare_reply(lreq);
-}
-
-static void do_pam_chauthtok(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
- char *newauthtok;
- char *salt;
- char *new_hash;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- newauthtok = talloc_strndup(lreq, (char *) pd->newauthtok,
- pd->newauthtok_size);
- NULL_CHECK_OR_JUMP(newauthtok, ("talloc_strndup failed.\n"), lreq->error,
- ENOMEM, done);
- memset(pd->newauthtok, 0, pd->newauthtok_size);
-
- if (strlen(newauthtok) == 0) {
- /* TODO: should we allow null passwords via a config option ? */
- DEBUG(1, ("Empty passwords are not allowed!"));
- ret = EINVAL;
- goto done;
- }
-
- ret = s3crypt_gen_salt(lreq, &salt);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("Salt generation failed.\n"),
- lreq->error, ret, done);
- DEBUG(4, ("Using salt [%s]\n", salt));
-
- ret = s3crypt_sha512(lreq, newauthtok, salt, &new_hash);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
- lreq->error, ret, done);
- DEBUG(4, ("New hash [%s]\n", new_hash));
- memset(newauthtok, 0, pd->newauthtok_size);
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_string(lreq->mod_attrs, SYSDB_PWD, new_hash);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_string failed.\n"),
- lreq->error, ret, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- "lastPasswordChange", (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-done:
-
- prepare_reply(lreq);
-}
-
-static void local_handler_callback(void *pvt, int ldb_status,
- struct ldb_result *res)
-{
- struct LOCAL_request *lreq;
- const char *username = NULL;
- const char *password = NULL;
- char *newauthtok = NULL;
- char *new_hash = NULL;
- char *authtok = NULL;
- struct pam_data *pd;
- int ret;
-
- lreq = talloc_get_type(pvt, struct LOCAL_request);
- pd = lreq->preq->pd;
-
- DEBUG(4, ("pam_handler_callback called with ldb_status [%d].\n",
- ldb_status));
-
- NEQ_CHECK_OR_JUMP(ldb_status, LDB_SUCCESS, ("ldb search failed.\n"),
- lreq->error, sysdb_error_to_errno(ldb_status), done);
-
-
- if (res->count < 1) {
- DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n",
- pd->user));
- pd->pam_status = PAM_USER_UNKNOWN;
- goto done;
- } else if (res->count > 1) {
- DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n"));
- lreq->error = EFAULT;
- goto done;
- }
-
- username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
- if (strcmp(username, pd->user) != 0) {
- DEBUG(1, ("Expected username [%s] get [%s].\n", pd->user, username));
- lreq->error = EINVAL;
- goto done;
- }
-
- lreq->res = res;
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- if ((pd->cmd == SSS_PAM_CHAUTHTOK ||
- pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) &&
- lreq->preq->cctx->priv == 1) {
-/* TODO: maybe this is a candiate for an explicit audit message. */
- DEBUG(4, ("allowing root to reset a password.\n"));
- break;
- }
- authtok = talloc_strndup(lreq, (char *) pd->authtok,
- pd->authtok_size);
- NULL_CHECK_OR_JUMP(authtok, ("talloc_strndup failed.\n"),
- lreq->error, ENOMEM, done);
- memset(pd->authtok, 0, pd->authtok_size);
-
- password = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
- NULL_CHECK_OR_JUMP(password, ("No password stored.\n"),
- lreq->error, LDB_ERR_NO_SUCH_ATTRIBUTE, done);
- DEBUG(4, ("user: [%s], password hash: [%s]\n", username, password));
-
- ret = s3crypt_sha512(lreq, authtok, password, &new_hash);
- memset(authtok, 0, pd->authtok_size);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("nss_sha512_crypt failed.\n"),
- lreq->error, ret, done);
-
- DEBUG(4, ("user: [%s], new hash: [%s]\n", username, new_hash));
-
- if (strcmp(new_hash, password) != 0) {
- DEBUG(1, ("Passwords do not match.\n"));
- do_failed_login(lreq);
- return;
- }
-
- break;
- }
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- do_successful_login(lreq);
- return;
- break;
- case SSS_PAM_CHAUTHTOK:
- do_pam_chauthtok(lreq);
- return;
- break;
- case SSS_PAM_ACCT_MGMT:
- do_pam_acct_mgmt(lreq);
- return;
- break;
- case SSS_PAM_SETCRED:
- break;
- case SSS_PAM_OPEN_SESSION:
- break;
- case SSS_PAM_CLOSE_SESSION:
- break;
- case SSS_PAM_CHAUTHTOK_PRELIM:
- break;
- default:
- lreq->error = EINVAL;
- DEBUG(1, ("Unknown PAM task [%d].\n"));
- }
-
-done:
- if (pd->authtok != NULL)
- memset(pd->authtok, 0, pd->authtok_size);
- if (authtok != NULL)
- memset(authtok, 0, pd->authtok_size);
- if (pd->newauthtok != NULL)
- memset(pd->newauthtok, 0, pd->newauthtok_size);
- if (newauthtok != NULL)
- memset(newauthtok, 0, pd->newauthtok_size);
-
- prepare_reply(lreq);
-}
-
-int LOCAL_pam_handler(struct pam_auth_req *preq)
-{
- int ret;
- struct LOCAL_request *lreq;
-
- static const char *attrs[] = {SYSDB_NAME,
- SYSDB_PWD,
- SYSDB_DISABLED,
- SYSDB_LAST_LOGIN,
- "lastPasswordChange",
- "accountExpires",
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- "passwordHint",
- "passwordHistory",
- SYSDB_LAST_FAILED_LOGIN,
- NULL};
-
- DEBUG(4, ("LOCAL pam handler.\n"));
-
- lreq = talloc_zero(preq, struct LOCAL_request);
- if (!lreq) {
- return ENOMEM;
- }
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &lreq->dbctx);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- talloc_free(lreq);
- return ret;
- }
- lreq->ev = preq->cctx->ev;
- lreq->preq = preq;
-
- preq->pd->pam_status = PAM_SUCCESS;
-
- ret = sysdb_get_user_attr(lreq, lreq->dbctx,
- preq->domain, preq->pd->user, attrs,
- local_handler_callback, lreq);
-
- if (ret != EOK) {
- DEBUG(1, ("sysdb_get_user_attr failed.\n"));
- talloc_free(lreq);
- return ret;
- }
-
- return EOK;
-}
diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c
deleted file mode 100644
index 84b13dc45..000000000
--- a/server/responder/pam/pamsrv.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- SSSD
-
- PAM Responder
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
- Copyright (C) Sumit Bose <sbose@redhat.com> 2009
-
- 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 <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <string.h>
-#include <sys/time.h>
-#include <errno.h>
-
-#include "popt.h"
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "monitor/monitor_interfaces.h"
-#include "sbus/sbus_client.h"
-#include "responder/pam/pamsrv.h"
-
-#define SSS_PAM_SBUS_SERVICE_VERSION 0x0001
-#define SSS_PAM_SBUS_SERVICE_NAME "pam"
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn);
-
-struct sbus_method monitor_pam_methods[] = {
- { MON_CLI_METHOD_PING, monitor_common_pong },
- { MON_CLI_METHOD_RELOAD, service_reload },
- { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
- { NULL, NULL }
-};
-
-struct sbus_interface monitor_pam_interface = {
- MONITOR_INTERFACE,
- MONITOR_PATH,
- SBUS_DEFAULT_VTABLE,
- monitor_pam_methods,
- NULL
-};
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn) {
- /* Monitor calls this function when we need to reload
- * our configuration information. Perform whatever steps
- * are needed to update the configuration objects.
- */
-
- /* Send an empty reply to acknowledge receipt */
- return monitor_common_pong(message, conn);
-}
-
-static struct sbus_method pam_dp_methods[] = {
- { NULL, NULL }
-};
-
-struct sbus_interface pam_dp_interface = {
- DP_INTERFACE,
- DP_PATH,
- SBUS_DEFAULT_VTABLE,
- pam_dp_methods,
- NULL
-};
-
-
-static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void *pvt)
-{
- struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
- int ret;
-
- /* Did we reconnect successfully? */
- if (status == SBUS_RECONNECT_SUCCESS) {
- DEBUG(1, ("Reconnected to the Data Provider.\n"));
-
- /* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "PAM", be_conn->domain->name);
- /* all fine */
- if (ret == EOK) return;
- }
-
- /* Handle failure */
- DEBUG(0, ("Could not reconnect to %s provider.\n",
- be_conn->domain->name));
-
- /* FIXME: kill the frontend and let the monitor restart it ? */
- /* pam_shutdown(rctx); */
-}
-
-static errno_t pam_get_config(struct pam_ctx *pctx,
- struct resp_ctx *rctx,
- struct confdb_ctx *cdb)
-{
- int ret = EOK;
- ret = confdb_get_int(cdb, pctx, CONFDB_PAM_CONF_ENTRY,
- CONFDB_PAM_CRED_TIMEOUT, 0,
- &pctx->cred_expiration);
- return ret;
-}
-
-static int pam_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb)
-{
- struct sss_cmd_table *pam_cmds;
- struct be_conn *iter;
- struct pam_ctx *pctx;
- int ret, max_retries;
-
- pctx = talloc_zero(mem_ctx, struct pam_ctx);
- if (!pctx) {
- return ENOMEM;
- }
-
- pam_cmds = get_pam_cmds();
- ret = sss_process_init(pctx, ev, cdb,
- pam_cmds,
- SSS_PAM_SOCKET_NAME,
- SSS_PAM_PRIV_SOCKET_NAME,
- CONFDB_PAM_CONF_ENTRY,
- SSS_PAM_SBUS_SERVICE_NAME,
- SSS_PAM_SBUS_SERVICE_VERSION,
- &monitor_pam_interface,
- "PAM", &pam_dp_interface,
- &pctx->rctx);
- if (ret != EOK) {
- return ret;
- }
-
- pctx->rctx->pvt_ctx = pctx;
- ret = pam_get_config(pctx, pctx->rctx, pctx->rctx->cdb);
-
- /* Enable automatic reconnection to the Data Provider */
-
- /* FIXME: "retries" is too generic, either get it from a global config
- * or specify these retries are about the sbus connections to DP */
- ret = confdb_get_int(pctx->rctx->cdb, pctx->rctx, CONFDB_PAM_CONF_ENTRY,
- CONFDB_SERVICE_RECON_RETRIES, 3, &max_retries);
- if (ret != EOK) {
- DEBUG(0, ("Failed to set up automatic reconnection\n"));
- return ret;
- }
-
- for (iter = pctx->rctx->be_conns; iter; iter = iter->next) {
- sbus_reconnect_init(iter->conn, max_retries,
- pam_dp_reconnect_init, iter);
- }
-
- return EOK;
-}
-
-int main(int argc, const char *argv[])
-{
- int opt;
- poptContext pc;
- struct main_context *main_ctx;
- int ret;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- SSSD_MAIN_OPTS
- { NULL }
- };
-
- pc = poptGetContext(argv[0], argc, argv, long_options, 0);
- while((opt = poptGetNextOpt(pc)) != -1) {
- switch(opt) {
- default:
- fprintf(stderr, "\nInvalid option %s: %s\n\n",
- poptBadOption(pc, 0), poptStrerror(opt));
- poptPrintUsage(pc, stderr, 0);
- return 1;
- }
- }
-
- poptFreeContext(pc);
-
- /* set up things like debug, signals, daemonization, etc... */
- debug_log_file = "sssd_pam";
-
- ret = server_setup("sssd[pam]", 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
- if (ret != EOK) return 2;
-
- ret = die_if_parent_died();
- if (ret != EOK) {
- /* This is not fatal, don't return */
- DEBUG(2, ("Could not set up to exit when parent process does\n"));
- }
-
- ret = pam_process_init(main_ctx,
- main_ctx->event_ctx,
- main_ctx->confdb_ctx);
- if (ret != EOK) return 3;
-
- /* loop on main */
- server_loop(main_ctx);
-
- return 0;
-}
-
diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h
deleted file mode 100644
index 60f9c66ae..000000000
--- a/server/responder/pam/pamsrv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Authors:
- Simo Sorce <ssorce@redhat.com>
- Sumit Bose <sbose@redhat.com>
-
- Copyright (C) 2009 Red Hat
-
- 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/>.
-*/
-
-#ifndef __PAMSRV_H__
-#define __PAMSRV_H__
-
-#include <security/pam_appl.h>
-#include "util/util.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder.h"
-
-struct pam_auth_req;
-
-typedef void (pam_dp_callback_t)(struct pam_auth_req *preq);
-
-struct pam_ctx {
- int cred_expiration;
- struct resp_ctx *rctx;
-};
-
-struct pam_auth_req {
- struct cli_ctx *cctx;
- struct sss_domain_info *domain;
-
- struct pam_data *pd;
-
- pam_dp_callback_t *callback;
-
- bool check_provider;
- void *data;
-};
-
-struct sss_cmd_table *get_pam_cmds(void);
-
-int pam_dp_send_req(struct pam_auth_req *preq, int timeout);
-
-int LOCAL_pam_handler(struct pam_auth_req *preq);
-
-#endif /* __PAMSRV_H__ */
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
deleted file mode 100644
index 37aad8299..000000000
--- a/server/responder/pam/pamsrv_cmd.c
+++ /dev/null
@@ -1,1181 +0,0 @@
-/*
- SSSD
-
- PAM Responder
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
- Copyright (C) Sumit Bose <sbose@redhat.com> 2009
-
- 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 <time.h>
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "responder/common/responder_packet.h"
-#include "responder/common/responder.h"
-#include "providers/data_provider.h"
-#include "responder/pam/pamsrv.h"
-#include "db/sysdb.h"
-
-static void pam_reply(struct pam_auth_req *preq);
-
-static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok, uint8_t *body, size_t blen, size_t *c) {
- uint32_t data_size;
-
- if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;
-
- memcpy(&data_size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
- if (data_size < sizeof(uint32_t) || (*c)+(data_size) > blen) return EINVAL;
- *size = data_size - sizeof(uint32_t);
-
- memcpy(type, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- *tok = body+(*c);
-
- *c += (*size);
-
- return EOK;
-}
-
-static int extract_string(char **var, uint8_t *body, size_t blen, size_t *c) {
- uint32_t size;
- uint8_t *str;
-
- if (blen-(*c) < sizeof(uint32_t)+1) return EINVAL;
-
- memcpy(&size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
- if (*c+size > blen) return EINVAL;
-
- str = body+(*c);
-
- if (str[size-1]!='\0') return EINVAL;
-
- *c += size;
-
- *var = (char *) str;
-
- return EOK;
-}
-
-static int extract_uint32_t(uint32_t *var, uint8_t *body, size_t blen, size_t *c) {
- uint32_t size;
-
- if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;
-
- memcpy(&size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- memcpy(var, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- return EOK;
-}
-
-static int pam_parse_in_data_v2(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- size_t c;
- uint32_t type;
- uint32_t size;
- char *pam_user;
- int ret;
- uint32_t terminator = SSS_END_OF_PAM_REQUEST;
-
- if (blen < 4*sizeof(uint32_t)+2 ||
- ((uint32_t *)body)[0] != SSS_START_OF_PAM_REQUEST ||
- memcmp(&body[blen - sizeof(uint32_t)], &terminator, sizeof(uint32_t)) != 0) {
- DEBUG(1, ("Received data is invalid.\n"));
- return EINVAL;
- }
-
- c = sizeof(uint32_t);
- do {
- memcpy(&type, &body[c], sizeof(uint32_t));
- c += sizeof(uint32_t);
- if (c > blen) return EINVAL;
-
- switch(type) {
- case SSS_PAM_ITEM_USER:
- ret = extract_string(&pam_user, body, blen, &c);
- if (ret != EOK) return ret;
-
- ret = sss_parse_name(pd, snctx, pam_user,
- &pd->domain, &pd->user);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_SERVICE:
- ret = extract_string(&pd->service, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_TTY:
- ret = extract_string(&pd->tty, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_RUSER:
- ret = extract_string(&pd->ruser, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_RHOST:
- ret = extract_string(&pd->rhost, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_CLI_PID:
- ret = extract_uint32_t(&pd->cli_pid,
- body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_AUTHTOK:
- ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,
- &pd->authtok, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_NEWAUTHTOK:
- ret = extract_authtok(&pd->newauthtok_type,
- &pd->newauthtok_size,
- &pd->newauthtok, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_END_OF_PAM_REQUEST:
- if (c != blen) return EINVAL;
- break;
- default:
- DEBUG(1,("Ignoring unknown data type [%d].\n", type));
- size = ((uint32_t *)&body[c])[0];
- c += size+sizeof(uint32_t);
- }
- } while(c < blen);
-
- if (pd->user == NULL || *pd->user == '\0') return EINVAL;
-
- DEBUG_PAM_DATA(4, pd);
-
- return EOK;
-
-}
-
-static int pam_parse_in_data_v3(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- int ret;
-
- ret = pam_parse_in_data_v2(snctx, pd, body, blen);
- if (ret != EOK) {
- DEBUG(1, ("pam_parse_in_data_v2 failed.\n"));
- return ret;
- }
-
- if (pd->cli_pid == 0) {
- DEBUG(1, ("Missing client PID.\n"));
- return EINVAL;
- }
-
- return EOK;
-}
-
-static int pam_parse_in_data(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- int start;
- int end;
- int last;
- int ret;
-
- last = blen - 1;
- end = 0;
-
- /* user name */
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
-
- ret = sss_parse_name(pd, snctx, (char *)&body[start], &pd->domain, &pd->user);
- if (ret != EOK) return ret;
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->service = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->tty = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->ruser = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->rhost = (char *) &body[start];
-
- start = end;
- pd->authtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->authtok_size = (int) body[start];
-
- start += sizeof(uint32_t);
- end = start + pd->authtok_size;
- if (pd->authtok_size == 0) {
- pd->authtok = NULL;
- } else {
- if (end <= blen) {
- pd->authtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid authtok size: %d\n", pd->authtok_size));
- return EINVAL;
- }
- }
-
- start = end;
- pd->newauthtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->newauthtok_size = (int) body[start];
-
- start += sizeof(uint32_t);
- end = start + pd->newauthtok_size;
-
- if (pd->newauthtok_size == 0) {
- pd->newauthtok = NULL;
- } else {
- if (end <= blen) {
- pd->newauthtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid newauthtok size: %d\n", pd->newauthtok_size));
- return EINVAL;
- }
- }
-
- DEBUG_PAM_DATA(4, pd);
-
- return EOK;
-}
-
-/*=Save-Last-Login-State===================================================*/
-
-struct set_last_login_state {
- struct tevent_context *ev;
- struct sysdb_ctx *dbctx;
-
- struct sss_domain_info *dom;
- const char *username;
- struct sysdb_attrs *attrs;
-
- struct sysdb_handle *handle;
-
- struct ldb_result *res;
-};
-
-static void set_last_login_trans_done(struct tevent_req *subreq);
-static void set_last_login_attrs_done(struct tevent_req *subreq);
-static void set_last_login_done(struct tevent_req *subreq);
-
-static struct tevent_req *set_last_login_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sysdb_ctx *dbctx,
- struct sss_domain_info *dom,
- const char *username,
- struct sysdb_attrs *attrs)
-{
- struct tevent_req *req, *subreq;
- struct set_last_login_state *state;
-
- req = tevent_req_create(memctx, &state, struct set_last_login_state);
- if (!req) {
- return NULL;
- }
-
- state->ev = ev;
- state->dbctx = dbctx;
- state->dom = dom;
- state->username = username;
- state->attrs = attrs;
- state->handle = NULL;
-
- subreq = sysdb_transaction_send(state, state->ev, state->dbctx);
- if (!subreq) {
- talloc_free(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, set_last_login_trans_done, req);
-
- return req;
-}
-
-static void set_last_login_trans_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct set_last_login_state *state = tevent_req_data(req,
- struct set_last_login_state);
- int ret;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(1, ("Unable to acquire sysdb transaction lock\n"));
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
- state->dom, state->username,
- state->attrs, SYSDB_MOD_REP);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, set_last_login_attrs_done, req);
-}
-
-static void set_last_login_attrs_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct set_last_login_state *state = tevent_req_data(req,
- struct set_last_login_state);
- int ret;
-
- ret = sysdb_set_user_attr_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(4, ("set_user_attr_callback, status [%d][%s]\n",
- ret, strerror(ret)));
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, set_last_login_done, req);
-}
-
-static void set_last_login_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- int ret;
-
- ret = sysdb_transaction_commit_recv(subreq);
- if (ret != EOK) {
- DEBUG(2, ("set_last_login failed.\n"));
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static int set_last_login_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-/*=========================================================================*/
-
-
-static void set_last_login_reply(struct tevent_req *req);
-
-static errno_t set_last_login(struct pam_auth_req *preq)
-{
- struct tevent_req *req;
- struct sysdb_ctx *dbctx;
- struct sysdb_attrs *attrs;
- errno_t ret;
-
- attrs = sysdb_new_attrs(preq);
- if (!attrs) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
- if (ret != EOK) {
- goto fail;
- }
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, preq->domain,
- &dbctx);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb context not found for this domain!\n"));
- goto fail;
- }
-
- req = set_last_login_send(preq, preq->cctx->ev, dbctx,
- preq->domain, preq->pd->user, attrs);
- if (!req) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, set_last_login_reply, preq);
-
- return EOK;
-
-fail:
- return ret;
-}
-
-static void set_last_login_reply(struct tevent_req *req)
-{
- struct pam_auth_req *preq = tevent_req_callback_data(req,
- struct pam_auth_req);
- int ret;
-
- ret = set_last_login_recv(req);
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- } else {
- preq->pd->last_auth_saved = true;
- }
-
- preq->callback(preq);
-}
-
-static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- struct pam_auth_req *preq;
-
- DEBUG(4, ("pam_reply_delay get called.\n"));
-
- preq = talloc_get_type(pvt, struct pam_auth_req);
-
- pam_reply(preq);
-}
-
-static void pam_cache_auth_done(struct tevent_req *req);
-
-static void pam_reply(struct pam_auth_req *preq)
-{
- struct cli_ctx *cctx;
- uint8_t *body;
- size_t blen;
- int ret;
- int32_t resp_c;
- int32_t resp_size;
- struct response_data *resp;
- int p;
- struct timeval tv;
- struct tevent_timer *te;
- struct pam_data *pd;
- struct tevent_req *req;
- struct sysdb_ctx *sysdb;
- struct pam_ctx *pctx;
- uint32_t user_info_type;
-
- pd = preq->pd;
- cctx = preq->cctx;
-
- DEBUG(4, ("pam_reply get called.\n"));
-
- if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
- switch(pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- if ((preq->domain != NULL) &&
- (preq->domain->cache_credentials == true) &&
- (pd->offline_auth == false)) {
-
- /* do auth with offline credentials */
- pd->offline_auth = true;
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for "
- "domain [%s]!\n", preq->domain->name));
- goto done;
- }
-
- pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx,
- struct pam_ctx);
-
- req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb,
- preq->domain, pd->user,
- pd->authtok, pd->authtok_size,
- pctx->rctx->cdb);
- if (req == NULL) {
- DEBUG(1, ("Failed to setup offline auth.\n"));
- /* this error is not fatal, continue */
- } else {
- tevent_req_set_callback(req, pam_cache_auth_done, preq);
- return;
- }
- }
- break;
- case SSS_PAM_CHAUTHTOK_PRELIM:
- case SSS_PAM_CHAUTHTOK:
- DEBUG(5, ("Password change not possible while offline.\n"));
- pd->pam_status = PAM_AUTHTOK_ERR;
- user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
- pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
- (const uint8_t *) &user_info_type);
- break;
-/* TODO: we need the pam session cookie here to make sure that cached
- * authentication was successful */
- case SSS_PAM_SETCRED:
- case SSS_PAM_ACCT_MGMT:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- DEBUG(2, ("Assuming offline authentication setting status for "
- "pam call %d to PAM_SUCCESS.\n", pd->cmd));
- pd->pam_status = PAM_SUCCESS;
- break;
- default:
- DEBUG(1, ("Unknown PAM call [%d].\n", pd->cmd));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- }
- }
-
- if (pd->response_delay > 0) {
- ret = gettimeofday(&tv, NULL);
- if (ret != EOK) {
- DEBUG(1, ("gettimeofday failed [%d][%s].\n",
- errno, strerror(errno)));
- goto done;
- }
- tv.tv_sec += pd->response_delay;
- tv.tv_usec = 0;
- pd->response_delay = 0;
-
- te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
- if (te == NULL) {
- DEBUG(1, ("Failed to add event pam_reply_delay.\n"));
- goto done;
- }
-
- return;
- }
-
- /* If this was a successful login, save the lastLogin time */
- if (pd->cmd == SSS_PAM_AUTHENTICATE &&
- pd->pam_status == PAM_SUCCESS &&
- preq->domain->cache_credentials &&
- !pd->offline_auth &&
- !pd->last_auth_saved &&
- NEED_CHECK_PROVIDER(preq->domain->provider)) {
- ret = set_last_login(preq);
- if (ret != EOK) {
- goto done;
- }
-
- return;
- }
-
- ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- goto done;
- }
-
- if (pd->domain != NULL) {
- pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
- (uint8_t *) pd->domain);
- }
-
- resp_c = 0;
- resp_size = 0;
- resp = pd->resp_list;
- while(resp != NULL) {
- resp_c++;
- resp_size += resp->len;
- resp = resp->next;
- }
-
- ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
- sizeof(int32_t) +
- resp_c * 2* sizeof(int32_t) +
- resp_size);
- if (ret != EOK) {
- goto done;
- }
-
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- DEBUG(4, ("blen: %d\n", blen));
- p = 0;
-
- memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
- p += sizeof(int32_t);
-
- memcpy(&body[p], &resp_c, sizeof(int32_t));
- p += sizeof(int32_t);
-
- resp = pd->resp_list;
- while(resp != NULL) {
- memcpy(&body[p], &resp->type, sizeof(int32_t));
- p += sizeof(int32_t);
- memcpy(&body[p], &resp->len, sizeof(int32_t));
- p += sizeof(int32_t);
- memcpy(&body[p], resp->data, resp->len);
- p += resp->len;
-
- resp = resp->next;
- }
-
-done:
- sss_cmd_done(cctx, preq);
-}
-
-static void pam_cache_auth_done(struct tevent_req *req)
-{
- int ret;
- struct pam_auth_req *preq = tevent_req_callback_data(req,
- struct pam_auth_req);
- uint32_t resp_type;
- size_t resp_len;
- uint8_t *resp;
- time_t expire_date = 0;
- time_t delayed_until = -1;
- long long dummy;
-
- ret = sysdb_cache_auth_recv(req, &expire_date, &delayed_until);
- talloc_zfree(req);
-
- switch (ret) {
- case EOK:
- preq->pd->pam_status = PAM_SUCCESS;
-
- resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
- resp_len = sizeof(uint32_t) + sizeof(long long);
- resp = talloc_size(preq->pd, resp_len);
- if (resp == NULL) {
- DEBUG(1, ("talloc_size failed, cannot prepare user info.\n"));
- } else {
- memcpy(resp, &resp_type, sizeof(uint32_t));
- dummy = (long long) expire_date;
- memcpy(resp+sizeof(uint32_t), &dummy, sizeof(long long));
- ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
- (const uint8_t *) resp);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- }
- break;
- case ENOENT:
- preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- break;
- case EINVAL:
- preq->pd->pam_status = PAM_AUTH_ERR;
- break;
- case EACCES:
- preq->pd->pam_status = PAM_PERM_DENIED;
- if (delayed_until >= 0) {
- resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
- resp_len = sizeof(uint32_t) + sizeof(long long);
- resp = talloc_size(preq->pd, resp_len);
- if (resp == NULL) {
- DEBUG(1, ("talloc_size failed, cannot prepare user info.\n"));
- } else {
- memcpy(resp, &resp_type, sizeof(uint32_t));
- dummy = (long long) delayed_until;
- memcpy(resp+sizeof(uint32_t), &dummy, sizeof(long long));
- ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
- (const uint8_t *) resp);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- }
- }
- break;
- default:
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
-
- pam_reply(preq);
- return;
-}
-
-static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-static void pam_check_user_callback(void *ptr, int status,
- struct ldb_result *res);
-static void pam_dom_forwarder(struct pam_auth_req *preq);
-
-/* TODO: we should probably return some sort of cookie that is set in the
- * PAM_ENVIRONMENT, so that we can save performing some calls and cache
- * data. */
-
-static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-{
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct pam_auth_req *preq;
- struct pam_data *pd;
- uint8_t *body;
- size_t blen;
- int timeout;
- int ret;
- uint32_t terminator = SSS_END_OF_PAM_REQUEST;
- preq = talloc_zero(cctx, struct pam_auth_req);
- if (!preq) {
- return ENOMEM;
- }
- preq->cctx = cctx;
-
- preq->pd = talloc_zero(preq, struct pam_data);
- if (!preq->pd) {
- talloc_free(preq);
- return ENOMEM;
- }
- pd = preq->pd;
-
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen >= sizeof(uint32_t) &&
- memcmp(&body[blen - sizeof(uint32_t)], &terminator, sizeof(uint32_t)) != 0) {
- DEBUG(1, ("Received data not terminated.\n"));
- ret = EINVAL;
- goto done;
- }
-
- pd->cmd = pam_cmd;
- pd->priv = cctx->priv;
-
- switch (cctx->cli_protocol_version->version) {
- case 1:
- ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
- break;
- case 2:
- ret = pam_parse_in_data_v2(cctx->rctx->names, pd, body, blen);
- break;
- case 3:
- ret = pam_parse_in_data_v3(cctx->rctx->names, pd, body, blen);
- break;
- default:
- DEBUG(1, ("Illegal protocol version [%d].\n",
- cctx->cli_protocol_version->version));
- ret = EINVAL;
- }
- if (ret != EOK) {
- ret = EINVAL;
- goto done;
- }
-
- /* now check user is valid */
- if (pd->domain) {
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- if (strcasecmp(dom->name, pd->domain) == 0) break;
- }
- if (!dom) {
- ret = ENOENT;
- goto done;
- }
- preq->domain = dom;
- }
- else {
- for (dom = preq->cctx->rctx->domains; dom; dom = dom->next) {
- if (dom->fqnames) continue;
-
-/* FIXME: need to support negative cache */
-#if HAVE_NEG_CACHE
- ncret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-#endif
- break;
- }
- if (!dom) {
- ret = ENOENT;
- goto done;
- }
- preq->domain = dom;
- }
-
- if (preq->domain->provider == NULL) {
- DEBUG(1, ("Domain [%s] has no auth provider.\n", preq->domain->name));
- ret = EINVAL;
- goto done;
- }
-
- /* When auth is requested always search the provider first,
- * do not rely on cached data unless the provider is completely
- * offline */
- if (NEED_CHECK_PROVIDER(preq->domain->provider) &&
- (pam_cmd == SSS_PAM_AUTHENTICATE || pam_cmd == SSS_PAM_SETCRED)) {
-
- /* no need to re-check later on */
- preq->check_provider = false;
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback, preq,
- timeout, preq->domain->name,
- false, SSS_DP_INITGROUPS,
- preq->pd->user, 0);
- }
- else {
- preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- goto done;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
- }
-
-done:
- if (ret != EOK) {
- switch (ret) {
- case ENOENT:
- pd->pam_status = PAM_USER_UNKNOWN;
- default:
- pd->pam_status = PAM_SYSTEM_ERR;
- }
- pam_reply(preq);
- }
- return EOK;
-}
-
-static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req);
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
- }
-
- /* always try to see if we have the user in cache even if the provider
- * returned an error */
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- goto done;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
-
-done:
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static void pam_check_user_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req);
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- uint64_t cacheExpire;
- bool call_provider = false;
- time_t timeout;
- int ret;
-
- if (status != LDB_SUCCESS) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
-
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- if (preq->check_provider) {
- switch (res->count) {
- case 0:
- call_provider = true;
- break;
-
- case 1:
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
- if (cacheExpire < time(NULL)) {
- call_provider = true;
- }
- break;
-
- default:
- DEBUG(1, ("check user call returned more than one result !?!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
- }
-
- if (call_provider) {
-
- /* dont loop forever :-) */
- preq->check_provider = false;
-
- /* keep around current data in case backend is offline */
- if (res->count) {
- preq->data = talloc_steal(preq, res);
- }
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback, preq,
- timeout, preq->domain->name,
- false, SSS_DP_USER,
- preq->pd->user, 0);
- if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
- return;
- }
-
- switch (res->count) {
- case 0:
- if (!preq->pd->domain) {
- /* search next as the domain was unknown */
-
- ret = EOK;
-
- /* skip domains that require FQnames or have negative caches */
- for (dom = preq->domain->next; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
-#if HAVE_NEG_CACHE
- ncret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
-#endif
- break;
- }
-#if HAVE_NEG_CACHE
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
- cmdctx->name));
- ret = ENOENT;
- }
-#endif
- if (dom == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n",
- preq->pd->user));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- preq->domain = dom;
- preq->data = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- preq->pd->user, preq->domain->name));
-
- /* When auth is requested always search the provider first,
- * do not rely on cached data unless the provider is
- * completely offline */
- if (NEED_CHECK_PROVIDER(preq->domain->provider) &&
- (preq->pd->cmd == SSS_PAM_AUTHENTICATE ||
- preq->pd->cmd == SSS_PAM_SETCRED)) {
-
- /* no need to re-check later on */
- preq->check_provider = false;
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback,
- preq, timeout,
- preq->domain->name,
- false, SSS_DP_USER,
- preq->pd->user, 0);
- }
- else {
- preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
- }
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
- else {
- ret = ENOENT;
- }
-
- DEBUG(2, ("No results for check user call\n"));
-
-#if HAVE_NEG_CACHE
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_user(nctx->ncache, false,
- dctx->domain->name, cmdctx->name);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-#endif
-
- if (ret != EOK) {
- if (ret == ENOENT) {
- preq->pd->pam_status = PAM_USER_UNKNOWN;
- } else {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
- pam_reply(preq);
- return;
- }
- break;
-
- case 1:
-
- /* BINGO */
- preq->pd->pw_uid =
- ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_UIDNUM, -1);
- if (preq->pd->pw_uid == -1) {
- DEBUG(1, ("Failed to find uid for user [%s] in domain [%s].\n",
- preq->pd->user, preq->pd->domain));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-
- preq->pd->gr_gid =
- ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_GIDNUM, -1);
- if (preq->pd->gr_gid == -1) {
- DEBUG(1, ("Failed to find gid for user [%s] in domain [%s].\n",
- preq->pd->user, preq->pd->domain));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-
- pam_dom_forwarder(preq);
- return;
-
- default:
- DEBUG(1, ("check user call returned more than one result !?!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static void pam_dom_forwarder(struct pam_auth_req *preq)
-{
- int ret;
-
- if (!preq->pd->domain) {
- preq->pd->domain = preq->domain->name;
- }
-
- if (!NEED_CHECK_PROVIDER(preq->domain->provider)) {
- preq->callback = pam_reply;
- ret = LOCAL_pam_handler(preq);
- }
- else {
- preq->callback = pam_reply;
- ret = pam_dp_send_req(preq, SSS_CLI_SOCKET_TIMEOUT/2);
- DEBUG(4, ("pam_dp_send_req returned %d\n", ret));
- }
-
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static int pam_cmd_authenticate(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_authenticate\n"));
- return pam_forwarder(cctx, SSS_PAM_AUTHENTICATE);
-}
-
-static int pam_cmd_setcred(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_setcred\n"));
- return pam_forwarder(cctx, SSS_PAM_SETCRED);
-}
-
-static int pam_cmd_acct_mgmt(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_acct_mgmt\n"));
- return pam_forwarder(cctx, SSS_PAM_ACCT_MGMT);
-}
-
-static int pam_cmd_open_session(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_open_session\n"));
- return pam_forwarder(cctx, SSS_PAM_OPEN_SESSION);
-}
-
-static int pam_cmd_close_session(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_close_session\n"));
- return pam_forwarder(cctx, SSS_PAM_CLOSE_SESSION);
-}
-
-static int pam_cmd_chauthtok(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_chauthtok\n"));
- return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK);
-}
-
-static int pam_cmd_chauthtok_prelim(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_chauthtok_prelim\n"));
- return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK_PRELIM);
-}
-
-struct cli_protocol_version *register_cli_protocol_version(void)
-{
- static struct cli_protocol_version pam_cli_protocol_version[] = {
- {3, "2009-09-14", "make cli_pid mandatory"},
- {2, "2009-05-12", "new format <type><size><data>"},
- {1, "2008-09-05", "initial version, \\0 terminated strings"},
- {0, NULL, NULL}
- };
-
- return pam_cli_protocol_version;
-}
-
-struct sss_cmd_table *get_pam_cmds(void)
-{
- static struct sss_cmd_table sss_cmds[] = {
- {SSS_GET_VERSION, sss_cmd_get_version},
- {SSS_PAM_AUTHENTICATE, pam_cmd_authenticate},
- {SSS_PAM_SETCRED, pam_cmd_setcred},
- {SSS_PAM_ACCT_MGMT, pam_cmd_acct_mgmt},
- {SSS_PAM_OPEN_SESSION, pam_cmd_open_session},
- {SSS_PAM_CLOSE_SESSION, pam_cmd_close_session},
- {SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok},
- {SSS_PAM_CHAUTHTOK_PRELIM, pam_cmd_chauthtok_prelim},
- {SSS_CLI_NULL, NULL}
- };
-
- return sss_cmds;
-}
diff --git a/server/responder/pam/pamsrv_dp.c b/server/responder/pam/pamsrv_dp.c
deleted file mode 100644
index 071d09b8e..000000000
--- a/server/responder/pam/pamsrv_dp.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- SSSD
-
- NSS Responder - Data Provider Interfaces
-
- 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 <sys/time.h>
-#include <time.h>
-
-#include <talloc.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "sbus/sbus_client.h"
-#include "responder/pam/pamsrv.h"
-
-static void pam_dp_process_reply(DBusPendingCall *pending, void *ptr)
-{
- DBusError dbus_error;
- DBusMessage* msg;
- int ret;
- int type;
- struct pam_auth_req *preq;
-
- preq = talloc_get_type(ptr, struct pam_auth_req);
-
- dbus_error_init(&dbus_error);
-
- dbus_pending_call_block(pending);
- msg = dbus_pending_call_steal_reply(pending);
- if (msg == NULL) {
- DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
-
-
- type = dbus_message_get_type(msg);
- switch (type) {
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- ret = dp_unpack_pam_response(msg, preq->pd, &dbus_error);
- if (!ret) {
- DEBUG(0, ("Failed to parse reply.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- DEBUG(4, ("received: [%d][%s]\n", preq->pd->pam_status, preq->pd->domain));
- break;
- case DBUS_MESSAGE_TYPE_ERROR:
- DEBUG(0, ("Reply error.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- break;
- default:
- DEBUG(0, ("Default... what now?.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
-
-
-done:
- dbus_pending_call_unref(pending);
- dbus_message_unref(msg);
- preq->callback(preq);
-}
-
-int pam_dp_send_req(struct pam_auth_req *preq, int timeout)
-{
- struct pam_data *pd = preq->pd;
- struct be_conn *be_conn;
- DBusMessage *msg;
- DBusPendingCall *pending_reply;
- DBusConnection *dbus_conn;
- dbus_bool_t ret;
- int res;
-
- /* double check dp_ctx has actually been initialized.
- * in some pathological cases it may happen that nss starts up before
- * dp connection code is actually able to establish a connection.
- */
- res = sss_dp_get_domain_conn(preq->cctx->rctx,
- preq->domain->name, &be_conn);
- if (res != EOK) {
- DEBUG(1, ("The Data Provider connection for %s is not available!"
- " This maybe a bug, it shouldn't happen!\n", preq->domain));
- return EIO;
- }
- dbus_conn = sbus_get_connection(be_conn->conn);
-
- msg = dbus_message_new_method_call(NULL,
- DP_PATH,
- DP_INTERFACE,
- DP_METHOD_PAMHANDLER);
- if (msg == NULL) {
- DEBUG(0,("Out of memory?!\n"));
- return ENOMEM;
- }
-
-
- DEBUG(4, ("Sending request with the following data:\n"));
- DEBUG_PAM_DATA(4, pd);
-
- ret = dp_pack_pam_request(msg, pd);
- if (!ret) {
- DEBUG(1,("Failed to build message\n"));
- return EIO;
- }
-
- ret = dbus_connection_send_with_reply(dbus_conn, msg, &pending_reply, timeout);
- if (!ret || pending_reply == NULL) {
- /*
- * Critical Failure
- * We can't communicate on this connection
- * We'll drop it using the default destructor.
- */
- DEBUG(0, ("D-BUS send failed.\n"));
- dbus_message_unref(msg);
- return EIO;
- }
-
- dbus_pending_call_set_notify(pending_reply,
- pam_dp_process_reply, preq, NULL);
- dbus_message_unref(msg);
-
- return EOK;
-}
-