From b8919e480b4ad25fa03fa3961043e6dcfa28991b Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Fri, 6 Mar 2009 13:33:40 +0100 Subject: added generic PAM return messages and a false login delay --- server/responder/common/responder_common.c | 2 +- server/responder/pam/pam_LOCAL_domain.c | 56 ++++-------------- server/responder/pam/pamsrv.h | 17 +++++- server/responder/pam/pamsrv_cmd.c | 93 +++++++++++++++++++++++++++--- server/responder/pam/pamsrv_dp.c | 27 ++++++--- server/responder/pam/pamsrv_util.c | 21 ++++++- sss_client/pam_sss.c | 74 +++++++++++++++++++----- sss_client/sss_cli.h | 5 ++ 8 files changed, 215 insertions(+), 80 deletions(-) diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c index 18d2f3da..66140f03 100644 --- a/server/responder/common/responder_common.c +++ b/server/responder/common/responder_common.c @@ -350,7 +350,7 @@ static int set_unix_socket(struct nss_ctx *nctx) } talloc_free(default_pipe); - default_pipe = talloc_asprintf(nctx, "%s/private/%s.priv", PIPE_PATH, + default_pipe = talloc_asprintf(nctx, "%s/private/%s", PIPE_PATH, nctx->sss_pipe_name); if (!default_pipe) { return ENOMEM; diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c index ce74884d..c307a1b9 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 349e2892..4bb49c97 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 932f226e..56e997e3 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 5abe0e5d..a679acd3 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 5dab9b67..f43783a6 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; +} diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c index 5b56bb0a..f045602b 100644 --- a/sss_client/pam_sss.c +++ b/sss_client/pam_sss.c @@ -11,7 +11,8 @@ #include #include -#include "sss_cli.h" +#include "sss_cli.h" +#include "sss/responder.h" struct pam_items { const char* pam_service; @@ -34,8 +35,44 @@ struct pam_items { int pam_newauthtok_size; }; +static int eval_response(pam_handle_t *pamh, int buflen, uint8_t *buf) +{ + int p=0; + int32_t *c; + int32_t *type; + int32_t *len; + int32_t *pam_status; + + pam_status = ((int32_t *)(buf+p)); + p += sizeof(int32_t); + + + c = ((int32_t *)(buf+p)); + p += sizeof(int32_t); + + while(*c>0) { + type = ((int32_t *)(buf+p)); + p += sizeof(int32_t); + len = ((int32_t *)(buf+p)); + p += sizeof(int32_t); + switch(*type) { + case PAM_USER_INFO: + D(("user info: [%s]", &buf[p])); + break; + case PAM_DOMAIN_NAME: + D(("domain name: [%s]", &buf[p])); + break; + } + p += *len; + + --(*c); + } + + return 0; +} -static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) { +static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) +{ int ret; ret = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pi->pam_service)); @@ -74,7 +111,8 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) { return PAM_SUCCESS; } -static void print_pam_items(struct pam_items pi) { +static void print_pam_items(struct pam_items pi) +{ D(("Service: %s", *pi.pam_service!='\0' ? pi.pam_service : "(not available)")); D(("User: %s", *pi.pam_user!='\0' ? pi.pam_user : "(not available)")); D(("Tty: %s", *pi.pam_tty!='\0' ? pi.pam_tty : "(not available)")); @@ -85,7 +123,8 @@ static void print_pam_items(struct pam_items pi) { } static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc, - const char **argv) { + const char **argv) +{ int ret; int errnop; int c; @@ -99,7 +138,6 @@ static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc, struct pam_message *mesg[1]; struct pam_response *resp=NULL; int pam_status; - char *domain; char *newpwd[2]; D(("Hello pam_sssd: %d", task)); @@ -277,16 +315,16 @@ static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc, goto done; } - if (replen