From f255b943157f76b53eb55c279e29e40a6c41a97a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 3 Jul 2009 19:35:27 -0400 Subject: Unify password caching ops in sysdb --- server/db/sysdb.c | 20 +++++ server/db/sysdb.h | 27 +++++-- server/db/sysdb_ops.c | 113 +++++++++++++++++++++------ server/providers/ldap/ldap_auth.c | 48 ++++++------ server/providers/ldap/sdap_async.c | 97 ----------------------- server/providers/ldap/sdap_async.h | 9 --- server/providers/proxy.c | 155 +++++++------------------------------ 7 files changed, 178 insertions(+), 291 deletions(-) (limited to 'server') diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 1951a9b3b..0cac339ed 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -443,6 +443,26 @@ int sysdb_transaction_commit_recv(struct tevent_req *req) return EOK; } +/* default transaction commit receive function. + * This function does not use the request state so it is safe to use + * from any caller */ +void sysdb_transaction_complete(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + int ret; + + ret = sysdb_transaction_commit_recv(subreq); + talloc_zfree(subreq); + if (ret) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + + /* =Operations============================================================ */ struct sysdb_operation_state { diff --git a/server/db/sysdb.h b/server/db/sysdb.h index aa1aaf4cd..a81f46301 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -195,6 +195,13 @@ struct tevent_req *sysdb_transaction_commit_send(TALLOC_CTX *mem_ctx, struct sysdb_handle *handle); int sysdb_transaction_commit_recv(struct tevent_req *req); + +/* default transaction commit receive function. + * This function does not use the request state so it is safe to use + * from any caller */ +void sysdb_transaction_complete(struct tevent_req *subreq); + + /* Sysdb initialization. * call this function *only* once to initialize the database and get * the sysdb ctx */ @@ -457,13 +464,19 @@ struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx, const char *member); int sysdb_remove_group_member_recv(struct tevent_req *req); -struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *user, - const char *password); -int sysdb_set_cached_password_recv(struct tevent_req *req); +/* Password caching function. + * If you are in a transaction ignore sysdb and pass in the handle. + * If you are not in a transaction pass NULL in handle and provide sysdb, + * in this case a transaction will be automatically started and the + * function will be completely wrapped in it's own sysdb transaction */ +struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *username, + const char *password); +int sysdb_cache_password_recv(struct tevent_req *req); /* TODO: remove later * These functions are available in the latest tevent and are the ones that diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c index 24d90b129..c53d6720c 100644 --- a/server/db/sysdb_ops.c +++ b/server/db/sysdb_ops.c @@ -2919,20 +2919,32 @@ int sysdb_remove_group_member_recv(struct tevent_req *req) } -/* ======================================================================= */ +/* =Password-Caching====================================================== */ -static void sysdb_set_cached_password_done(struct tevent_req *subreq); +struct sysdb_cache_pw_state { + struct tevent_context *ev; + struct sss_domain_info *domain; -struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *user, - const char *password) + const char *username; + struct sysdb_attrs *attrs; + + struct sysdb_handle *handle; + bool commit; +}; + +static void sysdb_cache_password_trans(struct tevent_req *subreq); +static void sysdb_cache_password_done(struct tevent_req *subreq); + +struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sysdb_ctx *sysdb, + struct sysdb_handle *handle, + struct sss_domain_info *domain, + const char *username, + const char *password) { struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct sysdb_attrs *attrs; + struct sysdb_cache_pw_state *state; char *hash = NULL; char *salt; int ret; @@ -2941,9 +2953,8 @@ struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx, if (!req) return NULL; state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; + state->domain = domain; + state->username = username; ret = s3crypt_gen_salt(state, &salt); if (ret) { @@ -2957,25 +2968,42 @@ struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx, goto fail; } - attrs = sysdb_new_attrs(state); - if (!attrs) { + state->attrs = sysdb_new_attrs(state); + if (!state->attrs) { ERROR_OUT(ret, ENOMEM, fail); } - ret = sysdb_attrs_add_string(attrs, SYSDB_CACHEDPWD, hash); + ret = sysdb_attrs_add_string(state->attrs, SYSDB_CACHEDPWD, hash); if (ret) goto fail; /* FIXME: should we use a different attribute for chache passwords ?? */ - ret = sysdb_attrs_add_long(attrs, "lastCachedPasswordChange", + ret = sysdb_attrs_add_long(state->attrs, "lastCachedPasswordChange", (long)time(NULL)); if (ret) goto fail; - subreq = sysdb_set_user_attr_send(state, ev, handle, domain, - user, attrs, SYSDB_MOD_REP); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); + state->handle = NULL; + + if (handle) { + state->handle = handle; + state->commit = false; + + subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, + state->domain, state->username, + state->attrs, SYSDB_MOD_REP); + if (!subreq) { + ERROR_OUT(ret, ENOMEM, fail); + } + tevent_req_set_callback(subreq, sysdb_cache_password_done, req); + } else { + state->commit = true; + + subreq = sysdb_transaction_send(state, state->ev, sysdb); + if (!subreq) { + ret = ENOMEM; + goto fail; + } + tevent_req_set_callback(subreq, sysdb_cache_password_trans, req); } - tevent_req_set_callback(subreq, sysdb_set_cached_password_done, req); return req; @@ -2985,10 +3013,36 @@ fail: return req; } -static void sysdb_set_cached_password_done(struct tevent_req *subreq) +static void sysdb_cache_password_trans(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sysdb_cache_pw_state *state = tevent_req_data(req, + struct sysdb_cache_pw_state); + int ret; + + ret = sysdb_transaction_recv(req, state, &state->handle); + if (ret) { + tevent_req_error(req, ret); + return; + } + + subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, + state->domain, state->username, + state->attrs, SYSDB_MOD_REP); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sysdb_cache_password_done, req); +} + +static void sysdb_cache_password_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct sysdb_cache_pw_state *state = tevent_req_data(req, + struct sysdb_cache_pw_state); int ret; ret = sysdb_set_user_attr_recv(subreq); @@ -2998,10 +3052,21 @@ static void sysdb_set_cached_password_done(struct tevent_req *subreq) return; } + if (state->commit) { + subreq = sysdb_transaction_commit_send(state, state->ev, + state->handle); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, sysdb_transaction_complete, req); + return; + } + tevent_req_done(req); } -int sysdb_set_cached_password_recv(struct tevent_req *req) +int sysdb_cache_password_recv(struct tevent_req *req) { return sysdb_op_default_recv(req); } diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c index c176cb4ee..e36338577 100644 --- a/server/providers/ldap/ldap_auth.c +++ b/server/providers/ldap/ldap_auth.c @@ -312,7 +312,7 @@ struct sdap_pam_auth_state { static void sdap_pam_auth_done(struct tevent_req *req); static void sdap_password_cache_done(struct tevent_req *req); -static void sdap_pam_auth_reply(struct be_req *breq, int result, const char *err); +static void sdap_pam_auth_reply(struct be_req *breq, int result); /* FIXME: convert caller to tevent_req too ?*/ static void sdap_pam_auth_send(struct be_req *breq) @@ -356,22 +356,16 @@ static void sdap_pam_auth_send(struct be_req *breq) default: pd->pam_status = PAM_SUCCESS; } - tevent_req_set_callback(req, sdap_cache_pw_done, data); - - return; - -fail: - DEBUG(2, ("Failed to cache password (%d)[%s]!?\n", ret, strerror(ret))); done: - sdap_pam_auth_reply(breq, pd->pam_status, NULL); + sdap_pam_auth_reply(breq, pd->pam_status); } static void sdap_pam_auth_done(struct tevent_req *req) { struct sdap_pam_auth_state *state = tevent_req_callback_data(req, struct sdap_pam_auth_state); - struct tevent_req *preq; + struct tevent_req *subreq; enum sdap_result result; int ret; @@ -399,34 +393,35 @@ static void sdap_pam_auth_done(struct tevent_req *req) if (result == SDAP_AUTH_SUCCESS && state->breq->be_ctx->domain->cache_credentials) { - preq = sdap_cache_pw_send(state, - state->breq->be_ctx->ev, - state->breq->be_ctx->sysdb, - state->breq->be_ctx->domain, - state->username, - state->password); + subreq = sysdb_cache_password_send(state, + state->breq->be_ctx->ev, + state->breq->be_ctx->sysdb, + NULL, + state->breq->be_ctx->domain, + state->username, state->password); /* password caching failures are not fatal errors */ - if (!preq) { + if (!subreq) { DEBUG(2, ("Failed to cache password for %s\n", state->username)); goto done; } - tevent_req_set_callback(preq, sdap_password_cache_done, state); + tevent_req_set_callback(subreq, sdap_password_cache_done, state); return; } done: - sdap_pam_auth_reply(state->breq, state->pd->pam_status, NULL); + sdap_pam_auth_reply(state->breq, state->pd->pam_status); } -static void sdap_password_cache_done(struct tevent_req *req) +static void sdap_password_cache_done(struct tevent_req *subreq) { - struct sdap_pam_auth_state *state = - tevent_req_callback_data(req, struct sdap_pam_auth_state); + struct sdap_pam_auth_state *state = tevent_req_callback_data(subreq, + struct sdap_pam_auth_state); int ret; - ret = sdap_cache_pw_recv(req); + ret = sysdb_cache_password_recv(subreq); + talloc_zfree(subreq); if (ret) { /* password caching failures are not fatal errors */ DEBUG(2, ("Failed to cache password for %s\n", state->username)); @@ -434,13 +429,14 @@ static void sdap_password_cache_done(struct tevent_req *req) DEBUG(4, ("Password successfully cached for %s\n", state->username)); } - talloc_zfree(req); - sdap_pam_auth_reply(state->breq, state->pd->pam_status, NULL); + sdap_pam_auth_reply(state->breq, state->pd->pam_status); } -static void sdap_pam_auth_reply(struct be_req *req, int result, const char *err) +static void sdap_pam_auth_reply(struct be_req *req, int result) { - req->fn(req, result, err); + const char *errstr = NULL; + if (result) errstr = "Operation failed"; + req->fn(req, result, errstr); } /* ==Module-Initialization-and-Dispose==================================== */ diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c index e618824de..2aba33c19 100644 --- a/server/providers/ldap/sdap_async.c +++ b/server/providers/ldap/sdap_async.c @@ -520,103 +520,6 @@ int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result) return EOK; } -/* ==Password=Caching===================================================== */ - -struct sdap_cache_pw_state { - struct sss_domain_info *domain; - const char *username; - const char *password; - - struct sysdb_req *sysreq; - - int result; -}; - -static void sdap_cache_pw_op(struct sysdb_req *req, void *pvt); -static void sdap_cache_pw_callback(void *pvt, int error, struct ldb_result *r); - -struct tevent_req *sdap_cache_pw_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *username, - const char *password) -{ - struct tevent_req *req; - struct sdap_cache_pw_state *state; - int ret; - - req = tevent_req_create(memctx, &state, struct sdap_cache_pw_state); - if (!req) return NULL; - - state->domain = domain; - state->username = username; - state->password = password; - - ret = sysdb_transaction(state, sysdb, sdap_cache_pw_op, req); - - if (ret != EOK) { - DEBUG(1, ("Failed to start sysydb transaction (%d)[%s]!?\n", - ret, strerror(ret))); - goto fail; - } - - return req; - -fail: - tevent_req_error(req, EIO); - tevent_req_post(req, ev); - return req; -} - -static void sdap_cache_pw_op(struct sysdb_req *sysreq, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_cache_pw_state *state = tevent_req_data(req, - struct sdap_cache_pw_state); - int ret; - - state->sysreq = sysreq; - - ret = sysdb_set_cached_password(sysreq, - state->domain, - state->username, - state->password, - sdap_cache_pw_callback, req); - if (ret != EOK) { - state->result = ret; - tevent_req_done(req); - } -} - -static void sdap_cache_pw_callback(void *pvt, int e, struct ldb_result *r) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_cache_pw_state *state = tevent_req_data(req, - struct sdap_cache_pw_state); - sysdb_transaction_done(state->sysreq, e); - - if (e != EOK) { - DEBUG(2, ("Failed to cache password (%d)[%s]!?\n", e, strerror(e))); - state->result = e; - } - - state->result = EOK; - tevent_req_done(req); -} - -int sdap_cache_pw_recv(struct tevent_req *req) -{ - struct sdap_cache_pw_state *state = tevent_req_data(req, - struct sdap_cache_pw_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(req, &tstate, &err)) { - return err; - } - return state->result; -} /* ==Save-User-Entry====================================================== */ diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h index 6b72ac04d..37c307a0e 100644 --- a/server/providers/ldap/sdap_async.h +++ b/server/providers/ldap/sdap_async.h @@ -79,12 +79,3 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, const char *password); int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result); - -struct tevent_req *sdap_cache_pw_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *username, - const char *password); - -int sdap_cache_pw_recv(struct tevent_req *req); diff --git a/server/providers/proxy.c b/server/providers/proxy.c index 58d52d540..23360945b 100644 --- a/server/providers/proxy.c +++ b/server/providers/proxy.c @@ -158,12 +158,6 @@ failed: } static void proxy_pam_handler_cache_done(struct tevent_req *treq); -static struct tevent_req *cache_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *username, - struct authtok_conv *ac); static void proxy_reply(struct be_req *req, int error, const char *errstr); @@ -257,32 +251,46 @@ static void proxy_pam_handler(struct be_req *req) { pd->pam_status = pam_status; if (cache_auth_data) { - struct tevent_req *treq; + struct tevent_req *subreq; + char *password; - treq = cache_password_send(req, req->be_ctx->ev, - req->be_ctx->sysdb, - req->be_ctx->domain, - pd->user, auth_data); - if (!treq) { + password = talloc_size(req, auth_data->authtok_size + 1); + if (!password) { /* password caching failures are not fatal errors */ return proxy_reply(req, EOK, NULL); } - tevent_req_set_callback(treq, proxy_pam_handler_cache_done, req); - - return; + memcpy(password, auth_data->authtok, auth_data->authtok_size); + password[auth_data->authtok_size] = '\0'; + talloc_set_destructor((TALLOC_CTX *)password, password_destructor); + + subreq = sysdb_cache_password_send(req, req->be_ctx->ev, + req->be_ctx->sysdb, NULL, + req->be_ctx->domain, + pd->user, password); + if (!subreq) { + /* password caching failures are not fatal errors */ + return proxy_reply(req, EOK, NULL); + } + tevent_req_set_callback(subreq, proxy_pam_handler_cache_done, req); } proxy_reply(req, EOK, NULL); } -static void proxy_pam_handler_cache_done(struct tevent_req *treq) +static void proxy_pam_handler_cache_done(struct tevent_req *subreq) { - struct be_req *req = tevent_req_callback_data(treq, struct be_req); + struct be_req *req = tevent_req_callback_data(subreq, struct be_req); + int ret; /* password caching failures are not fatal errors */ + ret = sysdb_cache_password_recv(subreq); + talloc_zfree(subreq); - /* so we just ignore any return */ - talloc_zfree(treq); + /* so we just log it any return */ + if (ret) { + DEBUG(2, ("Failed to cache password (%d)[%s]!?\n", + ret, strerror(ret))); + } return proxy_reply(req, EOK, NULL); } @@ -342,115 +350,6 @@ static int proxy_default_recv(struct tevent_req *req) } -/* =Password-Caching======================================================*/ - -struct cache_pw_state { - struct tevent_context *ev; - struct sss_domain_info *domain; - const char *name; - char *passwd; - - struct sysdb_handle *handle; -}; - -static void cache_password_process(struct tevent_req *subreq); -static void cache_password_done(struct tevent_req *subreq); - -static struct tevent_req *cache_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *username, - struct authtok_conv *ac) -{ - struct tevent_req *req, *subreq; - struct cache_pw_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct cache_pw_state); - if (!req) { - ret = ENOMEM; - goto fail; - } - - state->ev = ev; - state->handle = NULL; - state->name = username; - - state->passwd = talloc_size(state, ac->authtok_size + 1); - if (!state->passwd) { - ret = ENOMEM; - goto fail; - } - memcpy(state->passwd, ac->authtok, ac->authtok_size); - state->passwd[ac->authtok_size] = '\0'; - talloc_set_destructor((TALLOC_CTX *)state->passwd, - password_destructor); - - subreq = sysdb_transaction_send(state, state->ev, sysdb); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, cache_password_process, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void cache_password_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cache_pw_state *state = tevent_req_data(req, - struct cache_pw_state); - int ret; - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_cached_password_send(state, state->ev, state->handle, - state->domain, - state->name, - state->passwd); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, cache_password_done, req); -} - -static void cache_password_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cache_pw_state *state = tevent_req_data(req, - struct cache_pw_state); - int ret; - - ret = sysdb_set_cached_password_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, proxy_default_done, req); -} - - /* =Getpwnam-wrapper======================================================*/ static void get_pw_name_process(struct tevent_req *subreq); -- cgit