summaryrefslogtreecommitdiffstats
path: root/server/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/responder/pam/pamsrv_cmd.c')
-rw-r--r--server/responder/pam/pamsrv_cmd.c123
1 files changed, 95 insertions, 28 deletions
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index db5f064fd..2190b5668 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -1,10 +1,32 @@
+/*
+ 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 <errno.h>
#include <talloc.h>
#include "util/util.h"
#include "confdb/confdb.h"
#include "responder/common/responder_packet.h"
-#include "responder/pam/pam_LOCAL_domain.h"
+#include "providers/data_provider.h"
#include "responder/pam/pamsrv.h"
static int pam_parse_in_data(struct sss_names_ctx *snctx,
@@ -86,19 +108,20 @@ static int pam_parse_in_data(struct sss_names_ctx *snctx,
return EOK;
}
-static void pam_reply(struct pam_data *pd);
+static void pam_reply(struct pam_auth_req *preq);
static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
struct timeval tv, void *pvt)
{
- struct pam_data *pd;
+ struct pam_auth_req *preq;
+
DEBUG(4, ("pam_reply_delay get called.\n"));
- pd = talloc_get_type(pvt, struct pam_data);
+ preq = talloc_get_type(pvt, struct pam_auth_req);
- pam_reply(pd);
+ pam_reply(preq);
}
-static void pam_reply(struct pam_data *pd)
+static void pam_reply(struct pam_auth_req *preq)
{
struct cli_ctx *cctx;
uint8_t *body;
@@ -111,13 +134,48 @@ static void pam_reply(struct pam_data *pd)
int p;
struct timeval tv;
struct tevent_timer *te;
+ struct pam_data *pd;
+
+ pd = preq->pd;
DEBUG(4, ("pam_reply get called.\n"));
+ if ((pd->cmd == SSS_PAM_AUTHENTICATE) &&
+ (preq->domain->cache_credentials == true) &&
+ (pd->offline_auth == false)) {
+
+ if (pd->pam_status == PAM_SUCCESS) {
+ pd->offline_auth = true;
+ preq->callback = pam_reply;
+ ret = pam_cache_credentials(preq);
+ if (ret == EOK) {
+ return;
+ }
+ else {
+ DEBUG(0, ("Failed to cache credentials"));
+ /* this error is not fatal, continue */
+ }
+ }
+
+ 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;
+ }
+ else {
+ DEBUG(1, ("Failed to setup offline auth"));
+ /* this error is not fatal, continue */
+ }
+ }
+ }
+
if (pd->response_delay > 0) {
ret = gettimeofday(&tv, NULL);
if (ret != EOK) {
- DEBUG(0, ("gettimeofday failed [%d][%s].\n",
+ DEBUG(1, ("gettimeofday failed [%d][%s].\n",
errno, strerror(errno)));
err = ret;
goto done;
@@ -126,9 +184,9 @@ static void pam_reply(struct pam_data *pd)
tv.tv_usec = 0;
pd->response_delay = 0;
- te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, pd);
+ te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
if (te == NULL) {
- DEBUG(0, ("Failed to add event pam_reply_delay.\n"));
+ DEBUG(1, ("Failed to add event pam_reply_delay.\n"));
err = ENOMEM;
goto done;
}
@@ -136,7 +194,7 @@ static void pam_reply(struct pam_data *pd)
return;
}
- cctx = pd->cctx;
+ cctx = preq->cctx;
ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -191,8 +249,7 @@ static void pam_reply(struct pam_data *pd)
}
done:
- talloc_free(pd);
- sss_cmd_done(cctx, NULL);
+ sss_cmd_done(cctx, preq);
}
static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
@@ -201,50 +258,60 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
uint8_t *body;
size_t blen;
int ret;
+ struct pam_auth_req *preq;
struct pam_data *pd;
- pd = talloc(cctx, struct pam_data);
- if (pd == NULL) return ENOMEM;
+ 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) &&
((uint32_t *)(&body[blen - sizeof(uint32_t)]))[0] != END_OF_PAM_REQUEST) {
DEBUG(1, ("Received data not terminated.\n"));
- talloc_free(pd);
+ talloc_free(preq);
return EINVAL;
}
pd->cmd = pam_cmd;
- pd->cctx = cctx;
- ret=pam_parse_in_data(cctx->rctx->names, pd, body, blen);
- if( ret != 0 ) {
- talloc_free(pd);
+ ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
+ if (ret != 0) {
+ talloc_free(preq);
return EINVAL;
}
- pd->response_delay = 0;
- pd->resp_list = NULL;
-
if (pd->domain) {
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
if (strcasecmp(dom->name, pd->domain) == 0) break;
}
if (!dom) {
- talloc_free(pd);
+ talloc_free(preq);
return EINVAL;
}
+ preq->domain = dom;
}
else {
DEBUG(4, ("Domain not provided, using default.\n"));
- dom = cctx->rctx->domains;
- pd->domain = dom->name;
+ preq->domain = cctx->rctx->domains;
+ pd->domain = preq->domain->name;
}
- if (!dom->provider) {
- return LOCAL_pam_handler(cctx, pam_reply, dom, pd);
+ if (!preq->domain->provider) {
+ preq->callback = pam_reply;
+ return LOCAL_pam_handler(preq);
};
- ret = pam_dp_send_req(cctx, pam_reply, PAM_DP_TIMEOUT, pd);
+ preq->callback = pam_reply;
+ ret = pam_dp_send_req(preq, PAM_DP_TIMEOUT);
DEBUG(4, ("pam_dp_send_req returned %d\n", ret));
return ret;