From 6e52969c0dc8ac0dfb81e800bd2ef5228b8fea29 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 7 Jan 2010 10:26:50 +0100 Subject: Add sysdb request to authenticate against a cached password The code for authentication against a cached password is moved from the pam responder to a generic sysdb tevent request. The new code can be used by other components of sssd to verify passwords on their own. Tests for the sysdb_cache_password and sysdb_cache_auth request are added and some unneeded or unused code and variables are removed. --- server/responder/pam/pam_LOCAL_domain.c | 31 ++---- server/responder/pam/pamsrv.h | 2 - server/responder/pam/pamsrv_cache.c | 180 -------------------------------- server/responder/pam/pamsrv_cmd.c | 62 +++++++++-- 4 files changed, 59 insertions(+), 216 deletions(-) delete mode 100644 server/responder/pam/pamsrv_cache.c (limited to 'server/responder') diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c index b98459d6..9d3738c5 100644 --- a/server/responder/pam/pam_LOCAL_domain.c +++ b/server/responder/pam/pam_LOCAL_domain.c @@ -58,23 +58,6 @@ struct LOCAL_request { struct pam_auth_req *preq; }; -static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, char **dest) -{ - if ((src == NULL && src_size != 0) || - (src != NULL && *src != '\0' && src_size == 0)) { - return EINVAL; - } - - *dest = talloc_size(mem_ctx, src_size + 1); - if (*dest == NULL) { - return ENOMEM; - } - memcpy(*dest, src, src_size); - (*dest)[src_size]='\0'; - - return EOK; -} - static void prepare_reply(struct LOCAL_request *lreq) { struct pam_data *pd; @@ -273,9 +256,10 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq) pd = lreq->preq->pd; - ret = authtok2str(lreq, pd->newauthtok, pd->newauthtok_size, &newauthtok); - NEQ_CHECK_OR_JUMP(ret, EOK, ("authtok2str failed.\n"), - lreq->error, ret, done); + 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) { @@ -375,9 +359,10 @@ static void local_handler_callback(void *pvt, int ldb_status, DEBUG(4, ("allowing root to reset a password.\n")); break; } - ret = authtok2str(lreq, pd->authtok, pd->authtok_size, &authtok); - NEQ_CHECK_OR_JUMP(ret, EOK, ("authtok2str failed.\n"), - lreq->error, ret, done); + 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); diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h index d87e166f..60f9c66a 100644 --- a/server/responder/pam/pamsrv.h +++ b/server/responder/pam/pamsrv.h @@ -52,8 +52,6 @@ struct sss_cmd_table *get_pam_cmds(void); int pam_dp_send_req(struct pam_auth_req *preq, int timeout); -int pam_cache_auth(struct pam_auth_req *preq); - int LOCAL_pam_handler(struct pam_auth_req *preq); #endif /* __PAMSRV_H__ */ diff --git a/server/responder/pam/pamsrv_cache.c b/server/responder/pam/pamsrv_cache.c deleted file mode 100644 index 1e1c5444..00000000 --- a/server/responder/pam/pamsrv_cache.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - SSSD - - PAM cache credentials - - Copyright (C) Simo Sorce 2009 - Copyright (C) Sumit Bose 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 . -*/ - -#include -#include -#include "util/util.h" -#include "db/sysdb.h" -#include "util/nss_sha512crypt.h" -#include "providers/data_provider.h" -#include "responder/pam/pamsrv.h" - -static int authtok2str(const void *mem_ctx, - uint8_t *src, const int src_size, - char **_dest) -{ - char *dest; - - if ((src == NULL && src_size != 0) || - (src != NULL && *src != '\0' && src_size == 0)) { - return EINVAL; - } - - dest = talloc_size(mem_ctx, src_size + 1); - if (dest == NULL) { - return ENOMEM; - } - - memcpy(dest, src, src_size); - dest[src_size]='\0'; - - *_dest = dest; - return EOK; -} - -static void pam_cache_auth_return(struct pam_auth_req *preq, int error) -{ - preq->pd->pam_status = error; - preq->callback(preq); -} - -static void pam_cache_auth_callback(void *pvt, int ldb_status, - struct ldb_result *res) -{ - struct pam_auth_req *preq; - struct pam_ctx *pctx; - struct pam_data *pd; - const char *userhash; - char *comphash; - char *password = NULL; - int i, ret; - uint64_t lastLogin = 0; - - preq = talloc_get_type(pvt, struct pam_auth_req); - pd = preq->pd; - - pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); - - if (ldb_status != LDB_SUCCESS) { - DEBUG(4, ("User info retrieval failed! (%d [%s])\n", - ldb_status, sysdb_error_to_errno(ldb_status))); - - ret = PAM_SYSTEM_ERR; - goto done; - } - - if (res->count == 0) { - DEBUG(4, ("User [%s@%s] not found.\n", - pd->user, preq->domain->name)); - ret = PAM_USER_UNKNOWN; - goto done; - } - - if (res->count != 1) { - DEBUG(4, ("Too many results for user [%s@%s].\n", - pd->user, preq->domain->name)); - ret = PAM_SYSTEM_ERR; - goto done; - } - - /* Check offline_auth_cache_timeout */ - lastLogin = ldb_msg_find_attr_as_uint64(res->msgs[0], - SYSDB_LAST_ONLINE_AUTH, - 0); - if (pctx->cred_expiration && - lastLogin + (pctx->cred_expiration * 86400) < time(NULL)) { - DEBUG(4, ("Cached user entry is too old.")); - ret = PAM_AUTHINFO_UNAVAIL; - goto done; - } - - /* TODO: verify user account (failed logins, disabled, expired ...) */ - - ret = authtok2str(preq, pd->authtok, pd->authtok_size, &password); - if (ret) { - DEBUG(4, ("Invalid auth token.\n")); - ret = PAM_AUTH_ERR; - goto done; - } - - userhash = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_CACHEDPWD, NULL); - if (userhash == NULL || *userhash == '\0') { - DEBUG(4, ("Cached credentials not available.\n")); - ret = PAM_AUTHINFO_UNAVAIL; - goto done; - } - - ret = s3crypt_sha512(preq, password, userhash, &comphash); - if (ret) { - DEBUG(4, ("Failed to create password hash.\n")); - ret = PAM_SYSTEM_ERR; - goto done; - } - - if (strcmp(userhash, comphash) == 0) { - /* TODO: probable good point for audit logging */ - DEBUG(4, ("Hashes do match!\n")); - ret = PAM_SUCCESS; - goto done; - } - - DEBUG(4, ("Authentication failed.\n")); - ret = PAM_AUTH_ERR; - -done: - if (password) for (i = 0; password[i]; i++) password[i] = 0; - pam_cache_auth_return(preq, ret); -} - -int pam_cache_auth(struct pam_auth_req *preq) -{ - struct sysdb_ctx *sysdb; - int ret; - - static const char *attrs[] = {SYSDB_NAME, - SYSDB_CACHEDPWD, - SYSDB_DISABLED, - SYSDB_LAST_LOGIN, - SYSDB_LAST_ONLINE_AUTH, - "lastCachedPasswordChange", - "accountExpires", - "failedLoginAttempts", - "lastFailedLogin", - NULL}; - - 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")); - return ret; - } - ret = sysdb_get_user_attr(preq, sysdb, - preq->domain, preq->pd->user, attrs, - pam_cache_auth_callback, preq); - - if (ret != EOK) { - DEBUG(2, ("sysdb_get_user_attr failed.\n")); - } - - return ret; -} - diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c index 69cbf55d..ca41d641 100644 --- a/server/responder/pam/pamsrv_cmd.c +++ b/server/responder/pam/pamsrv_cmd.c @@ -465,13 +465,14 @@ static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te, 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; - int err = EOK; int32_t resp_c; int32_t resp_size; struct response_data *resp; @@ -479,6 +480,9 @@ static void pam_reply(struct pam_auth_req *preq) struct timeval tv; struct tevent_timer *te; struct pam_data *pd; + struct tevent_req *req; + struct sysdb_ctx *sysdb; + struct pam_ctx *pctx; pd = preq->pd; @@ -492,14 +496,25 @@ static void pam_reply(struct pam_auth_req *preq) if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) { /* do auth with offline credentials */ pd->offline_auth = true; - preq->callback = pam_reply; - ret = pam_cache_auth(preq); - if (ret == EOK) { - return; + + 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; } - else { + + 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")); /* this error is not fatal, continue */ + } else { + tevent_req_set_callback(req, pam_cache_auth_done, preq); + return; } } } @@ -521,7 +536,6 @@ static void pam_reply(struct pam_auth_req *preq) if (ret != EOK) { DEBUG(1, ("gettimeofday failed [%d][%s].\n", errno, strerror(errno))); - err = ret; goto done; } tv.tv_sec += pd->response_delay; @@ -531,7 +545,6 @@ static void pam_reply(struct pam_auth_req *preq) 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")); - err = ENOMEM; goto done; } @@ -547,7 +560,6 @@ static void pam_reply(struct pam_auth_req *preq) NEED_CHECK_PROVIDER(preq->domain->provider)) { ret = set_last_login(preq); if (ret != EOK) { - err = ret; goto done; } @@ -557,7 +569,6 @@ static void pam_reply(struct pam_auth_req *preq) ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in), &cctx->creq->out); if (ret != EOK) { - err = ret; goto done; } @@ -580,7 +591,6 @@ static void pam_reply(struct pam_auth_req *preq) resp_c * 2* sizeof(int32_t) + resp_size); if (ret != EOK) { - err = ret; goto done; } @@ -610,6 +620,36 @@ 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); + + ret = sysdb_cache_auth_recv(req); + talloc_zfree(req); + + switch (ret) { + case EOK: + preq->pd->pam_status = PAM_SUCCESS; + 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; + 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, -- cgit