diff options
Diffstat (limited to 'server/responder/pam/pam_LOCAL_domain.c')
-rw-r--r-- | server/responder/pam/pam_LOCAL_domain.c | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c deleted file mode 100644 index 34f0c8dd..00000000 --- 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; -} |