summaryrefslogtreecommitdiffstats
path: root/server/responder/pam
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-03-06 13:33:40 +0100
committerSimo Sorce <ssorce@redhat.com>2009-03-10 09:41:15 -0400
commitb8919e480b4ad25fa03fa3961043e6dcfa28991b (patch)
treec0fd30ee68503326a3a9ab331b564c5dc8756c70 /server/responder/pam
parentd0e33c2a035c4c877b9f624b6999899666cb6385 (diff)
downloadsssd-b8919e480b4ad25fa03fa3961043e6dcfa28991b.tar.gz
sssd-b8919e480b4ad25fa03fa3961043e6dcfa28991b.tar.xz
sssd-b8919e480b4ad25fa03fa3961043e6dcfa28991b.zip
added generic PAM return messages and a false login delay
Diffstat (limited to 'server/responder/pam')
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c56
-rw-r--r--server/responder/pam/pamsrv.h17
-rw-r--r--server/responder/pam/pamsrv_cmd.c93
-rw-r--r--server/responder/pam/pamsrv_dp.c27
-rw-r--r--server/responder/pam/pamsrv_util.c21
5 files changed, 150 insertions, 64 deletions
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
index ce74884d4..c307a1b99 100644
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ b/server/responder/pam/pam_LOCAL_domain.c
@@ -34,9 +34,7 @@ struct LOCAL_request {
struct sysdb_attrs *mod_attrs;
struct sysdb_req *sysdb_req;
struct ldb_result *res;
- int pam_status;
int error;
- int callback_delay;
};
static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, char **dest)
@@ -56,46 +54,14 @@ static int authtok2str(const void *mem_ctx, uint8_t *src, const int src_size, ch
return EOK;
}
-static void LOCAL_call_callback(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt) {
-
- struct LOCAL_request *lreq;
- int pam_status;
-
- lreq = talloc_get_type(pvt, struct LOCAL_request);
-
- if (lreq->error != EOK) pam_status = PAM_SYSTEM_ERR;
- else pam_status = lreq->pam_status;
-
- lreq->callback(lreq->cctx, pam_status, "LOCAL");
-
- talloc_free(lreq);
-}
-
static void prepare_reply(struct LOCAL_request *lreq)
{
- int ret;
- struct timeval tv;
- struct tevent_timer *te;
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (lreq->callback_delay > 0) {
- ret = gettimeofday(&tv, NULL);
- if (ret != 0) {
- DEBUG(1, ("gettimeofday failed, continuing.\n"));
- }
- tv.tv_sec += lreq->callback_delay;
- tv.tv_usec = 0;
- }
+ if (lreq->error != EOK && lreq->pd->pam_status == PAM_SUCCESS)
+ lreq->pd->pam_status = PAM_SYSTEM_ERR;
- te = tevent_add_timer(lreq->cctx->ev, lreq, tv, LOCAL_call_callback, lreq);
- if (te == NULL) {
- DEBUG(1, ("Cannot add callback to event loop.\n"));
- return;
- }
+ lreq->callback(lreq->pd);
+
+ talloc_free(lreq);
}
static void set_user_attr_callback(void *pvt, int ldb_status, struct ldb_result *res)
@@ -161,6 +127,7 @@ static void do_successful_login(struct LOCAL_request *lreq)
ret = sysdb_transaction(lreq, lreq->dbctx, set_user_attr_req, lreq);
NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_transaction failed.\n"),
lreq->error, ret, done);
+
return;
done:
@@ -173,9 +140,9 @@ static void do_failed_login(struct LOCAL_request *lreq)
int ret;
int failedLoginAttempts;
- lreq->pam_status = PAM_AUTH_ERR;
+ lreq->pd->pam_status = PAM_AUTH_ERR;
/* TODO: maybe add more inteligent delay calculation */
- lreq->callback_delay = 3;
+ lreq->pd->response_delay = 3;
lreq->mod_attrs = sysdb_new_attrs(lreq);
NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
@@ -215,7 +182,7 @@ static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
if (disabled != NULL &&
strncasecmp(disabled, "false",5)!=0 &&
strncasecmp(disabled, "no",2)!=0 ) {
- lreq->pam_status = PAM_PERM_DENIED;
+ lreq->pd->pam_status = PAM_PERM_DENIED;
}
prepare_reply(lreq);
@@ -290,7 +257,7 @@ static void pam_handler_callback(void *pvt, int ldb_status,
if (res->count < 1) {
DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n",
lreq->pd->user));
- lreq->pam_status = PAM_USER_UNKNOWN;
+ lreq->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"));
@@ -404,9 +371,8 @@ int LOCAL_pam_handler(struct cli_ctx *cctx, pam_dp_callback_t callback,
lreq->cctx = cctx;
lreq->pd = pd;
lreq->callback = callback;
- lreq->pam_status = PAM_SUCCESS;
+ lreq->pd->pam_status = PAM_SUCCESS;
lreq->error = EOK;
- lreq->callback_delay = 0;
DEBUG(4, ("LOCAL pam handler.\n"));
diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h
index 349e2892b..4bb49c978 100644
--- a/server/responder/pam/pamsrv.h
+++ b/server/responder/pam/pamsrv.h
@@ -12,6 +12,13 @@
if (level <= debug_level) pam_print_data(level, pd); \
} while(0);
+struct response_data {
+ int32_t type;
+ int32_t len;
+ uint8_t *data;
+ struct response_data *next;
+};
+
struct pam_data {
int cmd;
uint32_t authtok_type;
@@ -26,12 +33,18 @@ struct pam_data {
char *rhost;
uint8_t *authtok;
uint8_t *newauthtok;
+
+ int pam_status;
+ int response_delay;
+ struct response_data *resp_list;
+ struct cli_ctx *cctx;
};
+int pam_add_response(struct pam_data *pd, enum response_type type,
+ int len, uint8_t *data);
void pam_print_data(int l, struct pam_data *pd);
-typedef void (*pam_dp_callback_t)(struct cli_ctx *cctx,
- int pam_status, const char *domain);
+typedef void (*pam_dp_callback_t)(struct pam_data *pd);
struct sbus_method *register_pam_dp_methods(void);
struct sss_cmd_table *register_sss_cmds(void);
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 932f226e1..56e997e37 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -82,17 +82,58 @@ static int pam_parse_in_data(uint8_t *body, size_t blen, struct pam_data *pd) {
return EOK;
}
-static void pam_reply(struct cli_ctx *cctx,
- int pam_status, const char *domain)
+static void pam_reply(struct pam_data *pd);
+static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
+ struct timeval tv, void *pvt)
{
+ struct pam_data *pd;
+ DEBUG(4, ("pam_reply_delay get called.\n"));
+
+ pd = talloc_get_type(pvt, struct pam_data);
+
+ pam_reply(pd);
+}
+
+static void pam_reply(struct pam_data *pd)
+{
+ struct cli_ctx *cctx;
struct sss_cmd_ctx *nctx;
- int32_t ret_status = pam_status;
uint8_t *body;
size_t blen;
int ret;
int err = EOK;
+ int32_t resp_c;
+ int32_t resp_size;
+ struct response_data *resp;
+ int p;
+ struct timeval tv;
+ struct tevent_timer *te;
DEBUG(4, ("pam_reply get called.\n"));
+
+ if (pd->response_delay > 0) {
+ ret = gettimeofday(&tv, NULL);
+ if (ret != EOK) {
+ DEBUG(0, ("gettimeofday failed [%d][%s].\n",
+ errno, strerror(errno)));
+ err = ret;
+ goto done;
+ }
+ tv.tv_sec += pd->response_delay;
+ tv.tv_usec = 0;
+ pd->response_delay = 0;
+
+ te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, pd);
+ if (te == NULL) {
+ DEBUG(0, ("Failed to add event pam_reply_delay.\n"));
+ err = ENOMEM;
+ goto done;
+ }
+
+ return;
+ }
+
+ cctx = pd->cctx;
nctx = talloc_zero(cctx, struct sss_cmd_ctx);
if (!nctx) {
err = ENOMEM;
@@ -102,13 +143,30 @@ static void pam_reply(struct cli_ctx *cctx,
nctx->check_expiration = true;
ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
+ &cctx->creq->out);
if (ret != EOK) {
err = ret;
goto done;
}
- ret = sss_packet_grow(cctx->creq->out, sizeof(int) + strlen(domain)+1 );
+ if (pd->domain != NULL) {
+ pam_add_response(pd, PAM_DOMAIN_NAME, strlen(pd->domain)+1,
+ (uint8_t *) pd->domain);
+ }
+
+ resp_c = 0;
+ resp_size = 0;
+ resp = pd->resp_list;
+ while(resp != NULL) {
+ resp_c++;
+ resp_size += resp->len;
+ resp = resp->next;
+ }
+
+ ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) + strlen(pd->domain)+1 +
+ sizeof(int32_t) +
+ resp_c * 2* sizeof(int32_t) +
+ resp_size);
if (ret != EOK) {
err = ret;
goto done;
@@ -116,10 +174,28 @@ static void pam_reply(struct cli_ctx *cctx,
sss_packet_get_body(cctx->creq->out, &body, &blen);
DEBUG(4, ("blen: %d\n", blen));
- memcpy(body, &ret_status, sizeof(int32_t));
- memcpy(body+sizeof(int32_t), domain, strlen(domain)+1);
+ p = 0;
+
+ memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
+ p += sizeof(int32_t);
+
+ memcpy(&body[p], &resp_c, sizeof(int32_t));
+ p += sizeof(int32_t);
+
+ resp = pd->resp_list;
+ while(resp != NULL) {
+ memcpy(&body[p], &resp->type, sizeof(int32_t));
+ p += sizeof(int32_t);
+ memcpy(&body[p], &resp->len, sizeof(int32_t));
+ p += sizeof(int32_t);
+ memcpy(&body[p], resp->data, resp->len);
+ p += resp->len;
+
+ resp = resp->next;
+ }
done:
+ talloc_free(pd);
sss_cmd_done(nctx);
}
@@ -143,11 +219,14 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
}
pd->cmd = pam_cmd;
+ pd->cctx = cctx;
ret=pam_parse_in_data(body, blen, pd);
if( ret != 0 ) {
talloc_free(pd);
return EINVAL;
}
+ pd->response_delay = 0;
+ pd->resp_list = NULL;
if (pd->domain == NULL) {
ret = confdb_get_string(cctx->nctx->cdb, cctx, "config/domains",
diff --git a/server/responder/pam/pamsrv_dp.c b/server/responder/pam/pamsrv_dp.c
index 5abe0e5d7..a679acd35 100644
--- a/server/responder/pam/pamsrv_dp.c
+++ b/server/responder/pam/pamsrv_dp.c
@@ -34,10 +34,12 @@
struct pam_reply_ctx {
struct cli_ctx *cctx;
+ struct pam_data *pd;
pam_dp_callback_t callback;
};
-static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr) {
+static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr)
+{
DBusError dbus_error;
DBusMessage* msg;
int ret;
@@ -54,7 +56,7 @@ static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr) {
msg = dbus_pending_call_steal_reply(pending);
if (msg == NULL) {
DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
- pam_status = PAM_SYSTEM_ERR;
+ rctx->pd->pam_status = PAM_SYSTEM_ERR;
goto done;
}
@@ -68,11 +70,13 @@ static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr) {
DBUS_TYPE_INVALID);
if (!ret) {
DEBUG(0, ("Failed to parse reply.\n"));
- pam_status = PAM_SYSTEM_ERR;
- domain = "";
+ rctx->pd->pam_status = PAM_SYSTEM_ERR;
+ domain = NULL;
goto done;
}
DEBUG(4, ("received: [%d][%s]\n", pam_status, domain));
+ rctx->pd->pam_status = pam_status;
+ rctx->pd->domain = talloc_strdup(rctx->cctx, domain);
break;
case DBUS_MESSAGE_TYPE_ERROR:
DEBUG(0, ("Reply error.\n"));
@@ -87,12 +91,15 @@ static void pam_process_dp_reply(DBusPendingCall *pending, void *ptr) {
done:
dbus_pending_call_unref(pending);
dbus_message_unref(msg);
- rctx->callback(rctx->cctx, pam_status, domain);
+ rctx->callback(rctx->pd);
+
+ talloc_free(rctx);
}
int pam_dp_send_req(struct cli_ctx *cctx,
pam_dp_callback_t callback,
- int timeout, struct pam_data *pd) {
+ int timeout, struct pam_data *pd)
+{
DBusMessage *msg;
DBusPendingCall *pending_reply;
DBusConnection *conn;
@@ -105,8 +112,9 @@ int pam_dp_send_req(struct cli_ctx *cctx,
DEBUG(0,("Out of memory?!\n"));
return ENOMEM;
}
- rctx->cctx=cctx;
- rctx->callback=callback;
+ rctx->cctx = cctx;
+ rctx->callback = callback;
+ rctx->pd = pd;
if (pd->domain==NULL ||
pd->user==NULL ||
@@ -204,7 +212,8 @@ static int pam_dp_identity(DBusMessage *message, struct sbus_conn_ctx *sconn)
return EOK;
}
-struct sbus_method *register_pam_dp_methods(void) {
+struct sbus_method *register_pam_dp_methods(void)
+{
static struct sbus_method pam_dp_methods[] = {
{ DP_CLI_METHOD_IDENTITY, pam_dp_identity },
{ NULL, NULL }
diff --git a/server/responder/pam/pamsrv_util.c b/server/responder/pam/pamsrv_util.c
index 5dab9b679..f43783a60 100644
--- a/server/responder/pam/pamsrv_util.c
+++ b/server/responder/pam/pamsrv_util.c
@@ -1,7 +1,8 @@
#include "util/util.h"
#include "responder/pam/pamsrv.h"
-void pam_print_data(int l, struct pam_data *pd) {
+void pam_print_data(int l, struct pam_data *pd)
+{
DEBUG(l, ("command: %d\n", pd->cmd));
DEBUG(l, ("domain: %s\n", pd->domain));
DEBUG(l, ("user: %s\n", pd->user));
@@ -14,3 +15,21 @@ void pam_print_data(int l, struct pam_data *pd) {
DEBUG(l, ("newauthtok type: %d\n", pd->newauthtok_type));
DEBUG(l, ("newauthtok size: %d\n", pd->newauthtok_size));
}
+
+int pam_add_response(struct pam_data *pd, enum response_type type,
+ int len, uint8_t *data)
+{
+ struct response_data *new;
+
+ new = talloc(pd, struct response_data);
+ if (new == NULL) return ENOMEM;
+
+ new->type = type;
+ new->len = len;
+ new->data = talloc_memdup(pd, data, len);
+ if (new->data == NULL) return ENOMEM;
+ new->next = pd->resp_list;
+ pd->resp_list = new;
+
+ return EOK;
+}