summaryrefslogtreecommitdiffstats
path: root/server/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-04-11 00:31:50 -0400
committerSimo Sorce <ssorce@redhat.com>2009-04-13 09:07:10 -0400
commit943df8483b9f8a43df72121883ca67f17571d214 (patch)
treea9301004163a7033b4a342057c355da1ea49454b /server/responder/pam/pamsrv_cmd.c
parentf16705ecade500f77b525d1a3df0109196c98ee0 (diff)
downloadsssd-943df8483b9f8a43df72121883ca67f17571d214.tar.gz
sssd-943df8483b9f8a43df72121883ca67f17571d214.tar.xz
sssd-943df8483b9f8a43df72121883ca67f17571d214.zip
Implement credentials caching in pam responder.
Implement credentials caching in pam responder. Currently works only for the proxy backend. Also cleanup pam responder code and mode common code in data provider. (the data provider should never include responder private headers)
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;