summaryrefslogtreecommitdiffstats
path: root/src/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/pam/pamsrv_cmd.c')
-rw-r--r--src/responder/pam/pamsrv_cmd.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index 7c13ab11d..ced9df063 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -29,6 +29,7 @@
#include "responder/common/negcache.h"
#include "providers/data_provider.h"
#include "responder/pam/pamsrv.h"
+#include "responder/pam/pam_helpers.h"
#include "db/sysdb.h"
enum pam_verbosity {
@@ -836,6 +837,8 @@ static int pam_check_user_search(struct pam_auth_req *preq)
int ret;
struct tevent_req *dpreq;
struct dp_callback_ctx *cb_ctx;
+ struct pam_ctx *pctx =
+ talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
while (dom) {
/* if it is a domainless search, skip domains that require fully
@@ -858,14 +861,26 @@ static int pam_check_user_search(struct pam_auth_req *preq)
talloc_free(name);
name = dom->case_sensitive ? talloc_strdup(preq, preq->pd->user) :
sss_tc_utf8_str_tolower(preq, preq->pd->user);
+ if (!name) {
+ return ENOMEM;
+ }
/* Refresh the user's cache entry on any PAM query
* We put a timeout in the client context so that we limit
* the number of updates within a reasonable timeout
*/
- if (preq->check_provider && cctx->pam_timeout < time(NULL)) {
- /* Call provider first */
- break;
+ if (preq->check_provider) {
+ ret = pam_initgr_check_timeout(pctx->id_table, name);
+ if (ret != EOK
+ && ret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not look up initgroup timout\n"));
+ return EIO;
+ } else if (ret == ENOENT) {
+ /* Call provider first */
+ break;
+ }
+ /* Entry is still valid, get it from the sysdb */
}
DEBUG(4, ("Requesting info for [%s@%s]\n", name, dom->name));
@@ -1020,6 +1035,7 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
int ret;
struct pam_ctx *pctx =
talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
+ char *name;
if (err_maj) {
DEBUG(2, ("Unable to get information from Data Provider\n"
@@ -1030,7 +1046,25 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
ret = pam_check_user_search(preq);
if (ret == EOK || ret == ENOENT) {
/* Make sure we don't go to the ID provider too often */
- preq->cctx->pam_timeout = time(NULL) + pctx->id_timeout;
+ name = preq->domain->case_sensitive ?
+ talloc_strdup(preq, preq->pd->user) :
+ sss_tc_utf8_str_tolower(preq, preq->pd->user);
+ if (!name) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = pam_initgr_cache_set(pctx->rctx->ev, pctx->id_table,
+ name, pctx->id_timeout);
+ talloc_free(name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not save initgr timestamp. "
+ "Proceeding with PAM actions\n"));
+ /* This is non-fatal, we'll just end up going to the
+ * data provider again next time.
+ */
+ }
}
if (ret == EOK) {
@@ -1038,6 +1072,8 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
}
ret = pam_check_user_done(preq, ret);
+
+done:
if (ret) {
preq->pd->pam_status = PAM_SYSTEM_ERR;
pam_reply(preq);