summaryrefslogtreecommitdiffstats
path: root/server/providers
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-05-11 09:08:31 -0400
committerSimo Sorce <ssorce@redhat.com>2009-05-18 15:27:48 -0400
commit66c727e0e7b34d19cdb8dbdc0a0fae15d9d5ff25 (patch)
tree35caa2b93baa413e516c1834626a14e36c811017 /server/providers
parent3594dff371450e4530bf26f3bc4b2ea195270bcd (diff)
downloadsssd-66c727e0e7b34d19cdb8dbdc0a0fae15d9d5ff25.tar.gz
sssd-66c727e0e7b34d19cdb8dbdc0a0fae15d9d5ff25.tar.xz
sssd-66c727e0e7b34d19cdb8dbdc0a0fae15d9d5ff25.zip
Move actual password caching into sysdb
Convert auth modules to do the caching themselves
Diffstat (limited to 'server/providers')
-rw-r--r--server/providers/ldap/ldap_auth.c123
-rw-r--r--server/providers/proxy.c124
2 files changed, 230 insertions, 17 deletions
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 6a4dc895f..0c2541f1b 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -283,6 +283,8 @@ static int sdap_bind(struct sdap_req *lr)
return LDAP_SUCCESS;
}
+static void sdap_cache_password(struct sdap_req *lr);
+
static void sdap_pam_loop(struct tevent_context *ev, struct tevent_fd *te,
uint16_t fd, void *pvt)
{
@@ -290,7 +292,6 @@ static void sdap_pam_loop(struct tevent_context *ev, struct tevent_fd *te,
int pam_status=PAM_SUCCESS;
int ldap_ret;
struct sdap_req *lr;
- struct pam_data *pd;
struct be_req *req;
LDAPMessage *result=NULL;
LDAPMessage *msg=NULL;
@@ -573,11 +574,17 @@ done:
talloc_free(filter);
if (lr->ldap != NULL) ldap_unbind_ext(lr->ldap, NULL, NULL);
req = lr->req;
- pd = talloc_get_type(lr->req->req_data, struct pam_data);
- pd->pam_status = pam_status;
+ lr->pd->pam_status = pam_status;
+
+ if (((lr->pd->cmd == SSS_PAM_AUTHENTICATE) ||
+ (lr->pd->cmd == SSS_PAM_CHAUTHTOK)) &&
+ (lr->pd->pam_status == PAM_SUCCESS) &&
+ lr->req->be_ctx->domain->cache_credentials) {
+ sdap_cache_password(lr);
+ return;
+ }
talloc_free(lr);
-
req->fn(req, pam_status, NULL);
}
@@ -617,8 +624,7 @@ static void sdap_start(struct tevent_context *ev, struct tevent_timer *te,
done:
if (lr->ldap != NULL ) ldap_unbind_ext(lr->ldap, NULL, NULL);
req = lr->req;
- pd = talloc_get_type(lr->req->req_data, struct pam_data);
- pd->pam_status = pam_status;
+ lr->pd->pam_status = pam_status;
talloc_free(lr);
@@ -666,6 +672,111 @@ done:
req->fn(req, pam_status, NULL);
}
+struct sdap_pw_cache {
+ struct sysdb_req *sysreq;
+ struct sdap_req *lr;
+};
+
+static int password_destructor(void *memctx)
+{
+ char *password = (char *)memctx;
+ int i;
+
+ /* zero out password */
+ for (i = 0; password[i]; i++) password[i] = '\0';
+
+ return 0;
+}
+
+static void sdap_reply(struct be_req *req, int ret, char *errstr)
+{
+ req->fn(req, ret, errstr);
+}
+
+static void sdap_cache_pw_callback(void *pvt, int error,
+ struct ldb_result *ignore)
+{
+ struct sdap_pw_cache *data = talloc_get_type(pvt, struct sdap_pw_cache);
+ if (error != EOK) {
+ DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
+ error, strerror(error)));
+ }
+
+ sysdb_transaction_done(data->sysreq, error);
+
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+}
+
+static void sdap_cache_pw_op(struct sysdb_req *req, void *pvt)
+{
+ struct sdap_pw_cache *data = talloc_get_type(pvt, struct sdap_pw_cache);
+ struct pam_data *pd;
+ const char *username;
+ const char *password;
+ int ret;
+
+ data->sysreq = req;
+
+ pd = data->lr->pd;
+ username = pd->user;
+
+ if (pd->cmd == SSS_PAM_AUTHENTICATE) {
+ password = talloc_strndup(data, pd->authtok, pd->authtok_size);
+ }
+ else if (pd->cmd == SSS_PAM_CHAUTHTOK) {
+ password = talloc_strndup(data, pd->newauthtok, pd->newauthtok_size);
+ }
+ else {
+ DEBUG(1, ("Attempting password caching on invalid Op!\n"));
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+ return;
+ }
+
+ if (!password) {
+ DEBUG(2, ("Out of Memory!\n"));
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+ return;
+ }
+
+ ret = sysdb_set_cached_password(req,
+ data->lr->req->be_ctx->domain,
+ username,
+ password,
+ sdap_cache_pw_callback, data);
+ if (ret != EOK) {
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+ }
+}
+
+static void sdap_cache_password(struct sdap_req *lr)
+{
+ struct sdap_pw_cache *data;
+ int ret;
+
+ data = talloc_zero(lr, struct sdap_pw_cache);
+ if (!data) {
+ DEBUG(2, ("Out of Memory!\n"));
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, lr->pd->pam_status, NULL);
+ return;
+ }
+ data->lr = lr;
+
+ ret = sysdb_transaction(data, lr->req->be_ctx->sysdb,
+ sdap_cache_pw_op, data);
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, lr->pd->pam_status, NULL);
+ }
+}
+
static void sdap_shutdown(struct be_req *req)
{
/* TODO: Clean up any internal data */
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index 0fea89df9..175670ada 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -70,6 +70,12 @@ struct authtok_conv {
uint8_t *authtok;
};
+static void cache_password(struct be_req *req,
+ char *username,
+ struct authtok_conv *ac);
+static void proxy_reply(struct be_req *req,
+ int error, const char *errstr);
+
static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
struct pam_response **response,
void *appdata_ptr) {
@@ -121,12 +127,13 @@ static void proxy_pam_handler(struct be_req *req) {
struct pam_conv conv;
struct pam_data *pd;
struct proxy_auth_ctx *ctx;;
+ bool cache_auth_data = false;
ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct proxy_auth_ctx);
pd = talloc_get_type(req->req_data, struct pam_data);
conv.conv=proxy_internal_conv;
- auth_data = talloc_zero(req->be_ctx, struct authtok_conv);
+ auth_data = talloc_zero(req, struct authtok_conv);
conv.appdata_ptr=auth_data;
ret = pam_start(ctx->pam_target, pd->user, &conv, &pamh);
@@ -148,7 +155,11 @@ static void proxy_pam_handler(struct be_req *req) {
case SSS_PAM_AUTHENTICATE:
auth_data->authtok_size = pd->authtok_size;
auth_data->authtok = pd->authtok;
- pam_status=pam_authenticate(pamh, 0);
+ pam_status = pam_authenticate(pamh, 0);
+ if ((pam_status == PAM_SUCCESS) &&
+ (req->be_ctx->domain->cache_credentials)) {
+ cache_auth_data = true;
+ }
break;
case SSS_PAM_SETCRED:
pam_status=pam_setcred(pamh, 0);
@@ -166,12 +177,16 @@ static void proxy_pam_handler(struct be_req *req) {
if (pd->priv != 1) {
auth_data->authtok_size = pd->authtok_size;
auth_data->authtok = pd->authtok;
- pam_status=pam_authenticate(pamh, 0);
+ pam_status = pam_authenticate(pamh, 0);
if (pam_status != PAM_SUCCESS) break;
}
auth_data->authtok_size = pd->newauthtok_size;
auth_data->authtok = pd->newauthtok;
- pam_status=pam_chauthtok(pamh, 0);
+ pam_status = pam_chauthtok(pamh, 0);
+ if ((pam_status == PAM_SUCCESS) &&
+ (req->be_ctx->domain->cache_credentials)) {
+ cache_auth_data = true;
+ }
break;
default:
DEBUG(1, ("unknown PAM call"));
@@ -191,15 +206,14 @@ static void proxy_pam_handler(struct be_req *req) {
pam_status = PAM_SYSTEM_ERR;
}
- talloc_free(auth_data);
-
pd->pam_status = pam_status;
- req->fn(req, EOK, NULL);
-}
-static void proxy_reply(struct be_req *req, int error, const char *errstr)
-{
- return req->fn(req, error, errstr);
+ if (cache_auth_data) {
+ cache_password(req, pd->user, auth_data);
+ return;
+ }
+
+ proxy_reply(req, EOK, NULL);
}
struct proxy_data {
@@ -222,6 +236,94 @@ struct proxy_data {
sysdb_callback_t next_fn;
};
+static void proxy_reply(struct be_req *req, int error, const char *errstr)
+{
+ return req->fn(req, error, errstr);
+}
+
+static void cache_pw_return(void *pvt, int error, struct ldb_result *ignore)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ const char *err = "Success";
+
+ if (error != EOK) {
+ DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
+ error, strerror(error)));
+ }
+
+ sysdb_transaction_done(data->sysreq, error);
+
+ /* password caching failures are not fatal errors */
+ return proxy_reply(data->req, EOK, NULL);
+}
+
+static void cache_pw_op(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ int ret;
+
+ data->sysreq = req;
+
+ ret = sysdb_set_cached_password(req,
+ data->req->be_ctx->domain,
+ data->pwd->pw_name,
+ data->pwd->pw_passwd,
+ cache_pw_return, data);
+ if (ret != EOK) {
+ /* password caching failures are not fatal errors */
+ proxy_reply(data->req, EOK, NULL);
+ }
+}
+
+static int password_destructor(void *memctx)
+{
+ char *password = (char *)memctx;
+ int i;
+
+ /* zero out password */
+ for (i = 0; password[i]; i++) password[i] = '\0';
+
+ return 0;
+}
+
+static void cache_password(struct be_req *req,
+ char *username,
+ struct authtok_conv *ac)
+{
+ struct proxy_data *data;
+ struct proxy_ctx *ctx;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
+
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->pwd = talloc(data, struct passwd);
+ if (!data->pwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->pwd->pw_name = username;
+ data->pwd->pw_passwd = talloc_size(data, ac->authtok_size + 1);
+ if (!data->pwd->pw_passwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ memcpy(data->pwd->pw_passwd, ac->authtok, ac->authtok_size);
+ data->pwd->pw_passwd[ac->authtok_size] = '\0';
+
+ talloc_set_destructor((TALLOC_CTX *)data->pwd->pw_passwd,
+ password_destructor);
+
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, cache_pw_op, data);
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ /* password caching failures are not fatal errors */
+ return proxy_reply(req, EOK, NULL);
+ }
+}
+
static void proxy_return(void *pvt, int error, struct ldb_result *ignore)
{
struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);