diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2010-02-18 07:49:04 -0500 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-02-18 13:48:45 -0500 |
commit | 1c48b5a62f73234ed26bb20f0ab345ab61cda0ab (patch) | |
tree | 0b6cddd567a862e1a7b5df23764869782a62ca78 /server/providers/ldap | |
parent | 8c56df3176f528fe0260974b3bf934173c4651ea (diff) | |
download | sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.gz sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.bz2 sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.zip |
Rename server/ directory to src/
Also update BUILD.txt
Diffstat (limited to 'server/providers/ldap')
-rw-r--r-- | server/providers/ldap/ldap_auth.c | 1055 | ||||
-rw-r--r-- | server/providers/ldap/ldap_child.c | 429 | ||||
-rw-r--r-- | server/providers/ldap/ldap_common.c | 589 | ||||
-rw-r--r-- | server/providers/ldap/ldap_common.h | 115 | ||||
-rw-r--r-- | server/providers/ldap/ldap_id.c | 795 | ||||
-rw-r--r-- | server/providers/ldap/ldap_id_cleanup.c | 555 | ||||
-rw-r--r-- | server/providers/ldap/ldap_id_enum.c | 608 | ||||
-rw-r--r-- | server/providers/ldap/ldap_init.c | 179 | ||||
-rw-r--r-- | server/providers/ldap/sdap.c | 388 | ||||
-rw-r--r-- | server/providers/ldap/sdap.h | 258 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async.c | 1018 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async.h | 126 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async_accounts.c | 2065 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async_connection.c | 1141 | ||||
-rw-r--r-- | server/providers/ldap/sdap_async_private.h | 68 | ||||
-rw-r--r-- | server/providers/ldap/sdap_child_helpers.c | 462 |
16 files changed, 0 insertions, 9851 deletions
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c deleted file mode 100644 index cfe8adb9..00000000 --- a/server/providers/ldap/ldap_auth.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* - SSSD - - LDAP Backend Module - - Authors: - Sumit Bose <sbose@redhat.com> - - Copyright (C) 2008 Red Hat - - 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/>. -*/ - -#ifdef WITH_MOZLDAP -#define LDAP_OPT_SUCCESS LDAP_SUCCESS -#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) -#define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U) -#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) -#endif - -#define _XOPEN_SOURCE 500 /* for strptime() */ -#include <time.h> -#undef _XOPEN_SOURCE -#include <errno.h> -#include <sys/time.h> -#include <strings.h> - -#include <shadow.h> -#include <security/pam_modules.h> - -#include "util/util.h" -#include "util/user_info_msg.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -enum pwexpire { - PWEXPIRE_NONE = 0, - PWEXPIRE_LDAP_PASSWORD_POLICY, - PWEXPIRE_KERBEROS, - PWEXPIRE_SHADOW -}; - -static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, - enum sdap_result *result) -{ - char *end; - struct tm tm = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - time_t expire_time; - - *result = SDAP_AUTH_FAILED; - - end = strptime(expire_date, "%Y%m%d%H%M%SZ", &tm); - if (end == NULL) { - DEBUG(1, ("Kerberos expire date [%s] invalid.\n", expire_date)); - return EINVAL; - } - if (*end != '\0') { - DEBUG(1, ("Kerberos expire date [%s] contains extra characters.\n", - expire_date)); - return EINVAL; - } - - expire_time = mktime(&tm); - if (expire_time == -1) { - DEBUG(1, ("mktime failed to convert [%s].\n", expire_date)); - return EINVAL; - } - - tzset(); - expire_time -= timezone; - DEBUG(9, ("Time info: tzname[0] [%s] tzname[1] [%s] timezone [%d] " - "daylight [%d] now [%d] expire_time [%d].\n", tzname[0], - tzname[1], timezone, daylight, now, expire_time)); - - if (difftime(now, expire_time) > 0.0) { - DEBUG(4, ("Kerberos password expired.\n")); - *result = SDAP_AUTH_PW_EXPIRED; - } else { - *result = SDAP_AUTH_SUCCESS; - } - - return EOK; -} - -static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, - enum sdap_result *result) -{ - long today; - long password_age; - - if (spwd->sp_lstchg <= 0) { - DEBUG(4, ("Last change day is not set, new password needed.\n")); - *result = SDAP_AUTH_PW_EXPIRED; - return EOK; - } - - today = (long) (now / (60 * 60 *24)); - password_age = today - spwd->sp_lstchg; - if (password_age < 0) { - DEBUG(2, ("The last password change time is in the future!.\n")); - *result = SDAP_AUTH_SUCCESS; - return EOK; - } - - if ((spwd->sp_expire != -1 && today > spwd->sp_expire) || - (spwd->sp_max != -1 && spwd->sp_inact != -1 && - password_age > spwd->sp_max + spwd->sp_inact)) - { - DEBUG(4, ("Account expired.\n")); - *result = SDAP_ACCT_EXPIRED; - return EOK; - } - - if (spwd->sp_max != -1 && password_age > spwd->sp_max) { - DEBUG(4, ("Password expired.\n")); - *result = SDAP_AUTH_PW_EXPIRED; - return EOK; - } - -/* TODO: evaluate spwd->min and spwd->warn */ - - *result = SDAP_AUTH_SUCCESS; - return EOK; -} - -static errno_t string_to_shadowpw_days(const char *s, long *d) -{ - long l; - char *endptr; - - if (s == NULL || *s == '\0') { - *d = -1; - return EOK; - } - - errno = 0; - l = strtol(s, &endptr, 10); - if (errno != 0) { - DEBUG(1, ("strtol failed [%d][%s].\n", errno, strerror(errno))); - return errno; - } - - if (*endptr != '\0') { - DEBUG(1, ("Input string [%s] is invalid.\n", s)); - return EINVAL; - } - - if (*d < -1) { - DEBUG(1, ("Input string contains not allowed negative value [%d].\n", - *d)); - return EINVAL; - } - - *d = l; - - return EOK; -} - -static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, - const struct ldb_message *msg, - struct dp_option *opts, - enum pwexpire *type, void **data) -{ - const char *mark; - const char *val; - struct spwd *spwd; - const char *pwd_policy; - int ret; - - *type = PWEXPIRE_NONE; - *data = NULL; - - pwd_policy = dp_opt_get_string(opts, SDAP_PWD_POLICY); - if (pwd_policy == NULL) { - DEBUG(1, ("Missing password policy.\n")); - return EINVAL; - } - - mark = ldb_msg_find_attr_as_string(msg, SYSDB_PWD_ATTRIBUTE, NULL); - if (mark != NULL) { - DEBUG(9, ("Found pwdAttribute, " - "assuming LDAP password policies are active.\n")); - - *type = PWEXPIRE_LDAP_PASSWORD_POLICY; - return EOK; - } - - if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) == 0) { - DEBUG(9, ("No password policy requested.\n")); - return EOK; - } else if (strcasecmp(pwd_policy, PWD_POL_OPT_MIT) == 0) { - mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL); - if (mark != NULL) { - DEBUG(9, ("Found Kerberos password expiration attributes.\n")) - val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION, - NULL); - if (val != NULL) { - *data = talloc_strdup(mem_ctx, val); - if (*data == NULL) { - DEBUG(1, ("talloc_strdup failed.\n")); - return ENOMEM; - } - *type = PWEXPIRE_KERBEROS; - - return EOK; - } - } else { - DEBUG(1, ("No Kerberos password expiration attributes found, " - "but MIT Kerberos password policy was requested.\n")); - return EINVAL; - } - } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) { - mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); - if (mark != NULL) { - DEBUG(9, ("Found shadow password expiration attributes.\n")) - spwd = talloc_zero(mem_ctx, struct spwd); - if (spwd == NULL) { - DEBUG(1, ("talloc failed.\n")); - return ENOMEM; - } - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_lstchg); - if (ret != EOK) goto shadow_fail; - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_min); - if (ret != EOK) goto shadow_fail; - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_max); - if (ret != EOK) goto shadow_fail; - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_warn); - if (ret != EOK) goto shadow_fail; - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_inact); - if (ret != EOK) goto shadow_fail; - - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_expire); - if (ret != EOK) goto shadow_fail; - - *data = spwd; - *type = PWEXPIRE_SHADOW; - - return EOK; - } else { - DEBUG(1, ("No shadow password attributes found, " - "but shadow password policy was requested.\n")); - return EINVAL; - } - } - - DEBUG(9, ("No password expiration attributes found.\n")); - return EOK; - -shadow_fail: - talloc_free(spwd); - return ret; -} - -/* ==Get-User-DN========================================================== */ - -struct get_user_dn_state { - struct tevent_context *ev; - struct sdap_auth_ctx *ctx; - struct sdap_handle *sh; - - const char **attrs; - const char *name; - - char *dn; - enum pwexpire pw_expire_type; - void *pw_expire_data; -}; - -static void get_user_dn_done(void *pvt, int err, struct ldb_result *res); - -struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_auth_ctx *ctx, - struct sdap_handle *sh, - const char *username) -{ - struct tevent_req *req; - struct get_user_dn_state *state; - int ret; - - req = tevent_req_create(memctx, &state, struct get_user_dn_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->sh = sh; - state->name = username; - - state->attrs = talloc_array(state, const char *, 11); - if (!state->attrs) { - talloc_zfree(req); - return NULL; - } - state->attrs[0] = SYSDB_ORIG_DN; - state->attrs[1] = SYSDB_SHADOWPW_LASTCHANGE; - state->attrs[2] = SYSDB_SHADOWPW_MIN; - state->attrs[3] = SYSDB_SHADOWPW_MAX; - state->attrs[4] = SYSDB_SHADOWPW_WARNING; - state->attrs[5] = SYSDB_SHADOWPW_INACTIVE; - state->attrs[6] = SYSDB_SHADOWPW_EXPIRE; - state->attrs[7] = SYSDB_KRBPW_LASTCHANGE; - state->attrs[8] = SYSDB_KRBPW_EXPIRATION; - state->attrs[9] = SYSDB_PWD_ATTRIBUTE; - state->attrs[10] = NULL; - - /* this sysdb call uses a sysdn operation, which means it will be - * schedule only after we return, no timer hack needed */ - ret = sysdb_get_user_attr(state, state->ctx->be->sysdb, - state->ctx->be->domain, state->name, - state->attrs, get_user_dn_done, req); - if (ret) { - tevent_req_error(req, ret); - tevent_req_post(req, ev); - } - - return req; -} - -static void get_user_dn_done(void *pvt, int err, struct ldb_result *res) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct get_user_dn_state *state = tevent_req_data(req, - struct get_user_dn_state); - const char *dn; - int ret; - - if (err != LDB_SUCCESS) { - tevent_req_error(req, EIO); - return; - } - - switch (res->count) { - case 0: - /* FIXME: not in cache, needs a true search */ - tevent_req_error(req, ENOENT); - break; - - case 1: - dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL); - if (!dn) { - /* TODO: try to search ldap server ? */ - - /* FIXME: remove once we store originalDN on every call - * NOTE: this is wrong, works only with some DITs */ - dn = talloc_asprintf(state, "%s=%s,%s", - state->ctx->opts->user_map[SDAP_AT_USER_NAME].name, - state->name, - dp_opt_get_string(state->ctx->opts->basic, - SDAP_USER_SEARCH_BASE)); - if (!dn) { - tevent_req_error(req, ENOMEM); - break; - } - } - - state->dn = talloc_strdup(state, dn); - if (!state->dn) { - tevent_req_error(req, ENOMEM); - break; - } - - ret = find_password_expiration_attributes(state, res->msgs[0], - state->ctx->opts->basic, - &state->pw_expire_type, - &state->pw_expire_data); - if (ret != EOK) { - DEBUG(1, ("find_password_expiration_attributes failed.\n")); - tevent_req_error(req, ENOMEM); - break; - } - - tevent_req_done(req); - break; - - default: - DEBUG(1, ("A user search by name (%s) returned > 1 results!\n", - state->name)); - tevent_req_error(req, EFAULT); - break; - } -} - -static int get_user_dn_recv(struct tevent_req *req, - TALLOC_CTX *memctx, char **dn, - enum pwexpire *pw_expire_type, - void **pw_expire_data) -{ - struct get_user_dn_state *state = tevent_req_data(req, - struct get_user_dn_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *dn = talloc_steal(memctx, state->dn); - if (!*dn) return ENOMEM; - - /* state->pw_expire_data may be NULL */ - *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); - - *pw_expire_type = state->pw_expire_type; - - return EOK; -} - -/* ==Authenticate-User==================================================== */ - -struct auth_state { - struct tevent_context *ev; - struct sdap_auth_ctx *ctx; - const char *username; - struct dp_opt_blob password; - - struct sdap_handle *sh; - - enum sdap_result result; - char *dn; - enum pwexpire pw_expire_type; - void *pw_expire_data; - - struct fo_server *srv; -}; - -static void auth_resolve_done(struct tevent_req *subreq); -static void auth_connect_done(struct tevent_req *subreq); -static void auth_get_user_dn_done(struct tevent_req *subreq); -static void auth_bind_user_done(struct tevent_req *subreq); - -static struct tevent_req *auth_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_auth_ctx *ctx, - const char *username, - struct dp_opt_blob password) -{ - struct tevent_req *req, *subreq; - struct auth_state *state; - - req = tevent_req_create(memctx, &state, struct auth_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->username = username; - state->password = password; - state->srv = NULL; - - subreq = be_resolve_server_send(state, ev, ctx->be, ctx->service->name); - if (!subreq) goto fail; - - tevent_req_set_callback(subreq, auth_resolve_done, req); - - return req; - -fail: - talloc_zfree(req); - return NULL; -} - -static void auth_resolve_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct auth_state *state = tevent_req_data(req, - struct auth_state); - int ret; - - ret = be_resolve_server_recv(subreq, &state->srv); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sdap_connect_send(state, state->ev, state->ctx->opts, - state->ctx->service->uri, true); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, auth_connect_done, req); -} - -static void auth_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct auth_state *state = tevent_req_data(req, - struct auth_state); - int ret; - - ret = sdap_connect_recv(subreq, state, &state->sh); - talloc_zfree(subreq); - if (ret) { - if (state->srv) { - /* mark this server as bad if connection failed */ - fo_set_port_status(state->srv, PORT_NOT_WORKING); - } - - tevent_req_error(req, ret); - return; - } else if (state->srv) { - fo_set_port_status(state->srv, PORT_WORKING); - } - - subreq = get_user_dn_send(state, state->ev, - state->ctx, state->sh, - state->username); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, auth_get_user_dn_done, req); -} - -static void auth_get_user_dn_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct auth_state *state = tevent_req_data(req, - struct auth_state); - int ret; - - ret = get_user_dn_recv(subreq, state, &state->dn, &state->pw_expire_type, - &state->pw_expire_data); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sdap_auth_send(state, state->ev, state->sh, - NULL, NULL, state->dn, - "password", state->password); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(subreq, auth_bind_user_done, req); -} - -static void auth_bind_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct auth_state *state = tevent_req_data(req, - struct auth_state); - int ret; - - ret = sdap_auth_recv(subreq, &state->result); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int auth_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **sh, - enum sdap_result *result, char **dn, - enum pwexpire *pw_expire_type, void **pw_expire_data) -{ - struct auth_state *state = tevent_req_data(req, struct auth_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(req, &tstate, &err)) { - switch (tstate) { - case TEVENT_REQ_USER_ERROR: - if (err == ETIMEDOUT) *result = SDAP_UNAVAIL; - else *result = SDAP_ERROR; - return err; - default: - *result = SDAP_ERROR; - return EIO; - } - } - - if (sh != NULL) { - *sh = talloc_steal(memctx, state->sh); - if (*sh == NULL) return ENOMEM; - } - - if (dn != NULL) { - *dn = talloc_steal(memctx, state->dn); - if (*dn == NULL) return ENOMEM; - } - - if (pw_expire_data != NULL) { - *pw_expire_data = talloc_steal(memctx, state->pw_expire_data); - } - - *pw_expire_type = state->pw_expire_type; - - *result = state->result; - return EOK; -} - -/* ==Perform-Password-Change===================== */ - -struct sdap_pam_chpass_state { - struct be_req *breq; - struct pam_data *pd; - const char *username; - char *dn; - char *password; - char *new_password; - struct sdap_handle *sh; -}; - -static void sdap_auth4chpass_done(struct tevent_req *req); -static void sdap_pam_chpass_done(struct tevent_req *req); -static void sdap_pam_auth_reply(struct be_req *breq, int dp_err, int result); - -void sdap_pam_chpass_handler(struct be_req *breq) -{ - struct sdap_pam_chpass_state *state; - struct sdap_auth_ctx *ctx; - struct tevent_req *subreq; - struct pam_data *pd; - struct dp_opt_blob authtok; - int dp_err = DP_ERR_FATAL; - - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data, - struct sdap_auth_ctx); - pd = talloc_get_type(breq->req_data, struct pam_data); - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - pd->pam_status = PAM_AUTHINFO_UNAVAIL; - dp_err = DP_ERR_OFFLINE; - goto done; - } - - DEBUG(2, ("starting password change request for user [%s].\n", pd->user)); - - pd->pam_status = PAM_SYSTEM_ERR; - - if (pd->cmd != SSS_PAM_CHAUTHTOK && pd->cmd != SSS_PAM_CHAUTHTOK_PRELIM) { - DEBUG(2, ("chpass target was called by wrong pam command.\n")); - goto done; - } - - state = talloc_zero(breq, struct sdap_pam_chpass_state); - if (!state) goto done; - - state->breq = breq; - state->pd = pd; - state->username = pd->user; - state->password = talloc_strndup(state, - (char *)pd->authtok, pd->authtok_size); - if (!state->password) goto done; - talloc_set_destructor((TALLOC_CTX *)state->password, - password_destructor); - - if (pd->cmd == SSS_PAM_CHAUTHTOK) { - state->new_password = talloc_strndup(state, - (char *)pd->newauthtok, - pd->newauthtok_size); - if (!state->new_password) goto done; - talloc_set_destructor((TALLOC_CTX *)state->new_password, - password_destructor); - } - - authtok.data = (uint8_t *)state->password; - authtok.length = strlen(state->password); - subreq = auth_send(breq, breq->be_ctx->ev, - ctx, state->username, authtok); - if (!subreq) goto done; - - tevent_req_set_callback(subreq, sdap_auth4chpass_done, state); - return; - -done: - sdap_pam_auth_reply(breq, dp_err, pd->pam_status); -} - -static void sdap_auth4chpass_done(struct tevent_req *req) -{ - struct sdap_pam_chpass_state *state = - tevent_req_callback_data(req, struct sdap_pam_chpass_state); - struct tevent_req *subreq; - enum sdap_result result; - enum pwexpire pw_expire_type; - void *pw_expire_data; - int dp_err = DP_ERR_FATAL; - int ret; - - ret = auth_recv(req, state, &state->sh, - &result, &state->dn, - &pw_expire_type, &pw_expire_data); - talloc_zfree(req); - if (ret) { - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - - if (result == SDAP_AUTH_SUCCESS && - state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) { - DEBUG(9, ("Initial authentication for change password operation " - "successful.\n")); - state->pd->pam_status = PAM_SUCCESS; - goto done; - } - - if (result == SDAP_AUTH_SUCCESS) { - switch (pw_expire_type) { - case PWEXPIRE_SHADOW: - ret = check_pwexpire_shadow(pw_expire_data, time(NULL), - &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_shadow failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_KERBEROS: - ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), - &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_kerberos failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - - if (result == SDAP_AUTH_PW_EXPIRED) { - DEBUG(1, ("LDAP provider cannot change kerberos " - "passwords.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_LDAP_PASSWORD_POLICY: - case PWEXPIRE_NONE: - break; - default: - DEBUG(1, ("Unknow pasword expiration type.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - } - - switch (result) { - case SDAP_AUTH_SUCCESS: - case SDAP_AUTH_PW_EXPIRED: - DEBUG(7, ("user [%s] successfully authenticated.\n", state->dn)); - if (pw_expire_type == PWEXPIRE_SHADOW) { -/* TODO: implement async ldap modify request */ - DEBUG(1, ("Changing shadow password attributes not implemented.\n")); - state->pd->pam_status = PAM_MODULE_UNKNOWN; - goto done; - } else { - subreq = sdap_exop_modify_passwd_send(state, - state->breq->be_ctx->ev, - state->sh, - state->dn, - state->password, - state->new_password); - - if (!subreq) { - DEBUG(2, ("Failed to change password for %s\n", state->username)); - goto done; - } - - tevent_req_set_callback(subreq, sdap_pam_chpass_done, state); - return; - } - break; - case SDAP_AUTH_FAILED: - state->pd->pam_status = PAM_AUTH_ERR; - break; - default: - state->pd->pam_status = PAM_SYSTEM_ERR; - } - -done: - sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} - -static void sdap_pam_chpass_done(struct tevent_req *req) -{ - struct sdap_pam_chpass_state *state = - tevent_req_callback_data(req, struct sdap_pam_chpass_state); - enum sdap_result result; - int dp_err = DP_ERR_FATAL; - int ret; - char *user_error_message = NULL; - size_t msg_len; - uint8_t *msg; - - ret = sdap_exop_modify_passwd_recv(req, state, &result, &user_error_message); - talloc_zfree(req); - if (ret) { - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - - switch (result) { - case SDAP_SUCCESS: - state->pd->pam_status = PAM_SUCCESS; - dp_err = DP_ERR_OK; - break; - default: - state->pd->pam_status = PAM_AUTHTOK_ERR; - if (user_error_message != NULL) { - ret = pack_user_info_chpass_error(state->pd, user_error_message, - &msg_len, &msg); - if (ret != EOK) { - DEBUG(1, ("pack_user_info_chpass_error failed.\n")); - } else { - ret = pam_add_response(state->pd, SSS_PAM_USER_INFO, msg_len, - msg); - if (ret != EOK) { - DEBUG(1, ("pam_add_response failed.\n")); - } - } - } - } - -done: - sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} -/* ==Perform-User-Authentication-and-Password-Caching===================== */ - -struct sdap_pam_auth_state { - struct be_req *breq; - struct pam_data *pd; - const char *username; - struct dp_opt_blob password; -}; - -static void sdap_pam_auth_done(struct tevent_req *req); -static void sdap_password_cache_done(struct tevent_req *req); - -void sdap_pam_auth_handler(struct be_req *breq) -{ - struct sdap_pam_auth_state *state; - struct sdap_auth_ctx *ctx; - struct tevent_req *subreq; - struct pam_data *pd; - int dp_err = DP_ERR_FATAL; - - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_AUTH].pvt_bet_data, - struct sdap_auth_ctx); - pd = talloc_get_type(breq->req_data, struct pam_data); - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - pd->pam_status = PAM_AUTHINFO_UNAVAIL; - dp_err = DP_ERR_OFFLINE; - goto done; - } - - pd->pam_status = PAM_SYSTEM_ERR; - - switch (pd->cmd) { - case SSS_PAM_AUTHENTICATE: - case SSS_PAM_CHAUTHTOK_PRELIM: - - state = talloc_zero(breq, struct sdap_pam_auth_state); - if (!state) goto done; - - state->breq = breq; - state->pd = pd; - state->username = pd->user; - state->password.data = pd->authtok; - state->password.length = pd->authtok_size; - - subreq = auth_send(breq, breq->be_ctx->ev, ctx, - state->username, state->password); - if (!subreq) goto done; - - tevent_req_set_callback(subreq, sdap_pam_auth_done, state); - return; - - case SSS_PAM_CHAUTHTOK: - break; - - case SSS_PAM_ACCT_MGMT: - case SSS_PAM_SETCRED: - case SSS_PAM_OPEN_SESSION: - case SSS_PAM_CLOSE_SESSION: - pd->pam_status = PAM_SUCCESS; - dp_err = DP_ERR_OK; - break; - default: - pd->pam_status = PAM_MODULE_UNKNOWN; - dp_err = DP_ERR_OK; - } - -done: - sdap_pam_auth_reply(breq, dp_err, 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 *subreq; - enum sdap_result result; - enum pwexpire pw_expire_type; - void *pw_expire_data; - int dp_err = DP_ERR_OK; - int ret; - - ret = auth_recv(req, state, NULL, - &result, NULL, - &pw_expire_type, &pw_expire_data); - talloc_zfree(req); - if (ret) { - state->pd->pam_status = PAM_SYSTEM_ERR; - dp_err = DP_ERR_FATAL; - goto done; - } - - if (result == SDAP_AUTH_SUCCESS) { - switch (pw_expire_type) { - case PWEXPIRE_SHADOW: - ret = check_pwexpire_shadow(pw_expire_data, time(NULL), - &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_shadow failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_KERBEROS: - ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), - &result); - if (ret != EOK) { - DEBUG(1, ("check_pwexpire_kerberos failed.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - break; - case PWEXPIRE_LDAP_PASSWORD_POLICY: - case PWEXPIRE_NONE: - break; - default: - DEBUG(1, ("Unknow pasword expiration type.\n")); - state->pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } - } - - switch (result) { - case SDAP_AUTH_SUCCESS: - state->pd->pam_status = PAM_SUCCESS; - break; - case SDAP_AUTH_FAILED: - state->pd->pam_status = PAM_PERM_DENIED; - break; - case SDAP_UNAVAIL: - state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; - break; - case SDAP_ACCT_EXPIRED: - state->pd->pam_status = PAM_ACCT_EXPIRED; - break; - case SDAP_AUTH_PW_EXPIRED: - state->pd->pam_status = PAM_AUTHTOK_EXPIRED; - break; - default: - state->pd->pam_status = PAM_SYSTEM_ERR; - dp_err = DP_ERR_FATAL; - } - - if (result == SDAP_UNAVAIL) { - be_mark_offline(state->breq->be_ctx); - dp_err = DP_ERR_OFFLINE; - goto done; - } - - if (result == SDAP_AUTH_SUCCESS && - state->breq->be_ctx->domain->cache_credentials) { - - char *password = talloc_strndup(state, (char *) - state->password.data, - state->password.length); - /* password caching failures are not fatal errors */ - if (!password) { - DEBUG(2, ("Failed to cache password for %s\n", state->username)); - goto done; - } - talloc_set_destructor((TALLOC_CTX *)password, password_destructor); - - subreq = sysdb_cache_password_send(state, - state->breq->be_ctx->ev, - state->breq->be_ctx->sysdb, - NULL, - state->breq->be_ctx->domain, - state->username, password); - - /* password caching failures are not fatal errors */ - if (!subreq) { - DEBUG(2, ("Failed to cache password for %s\n", state->username)); - goto done; - } - - tevent_req_set_callback(subreq, sdap_password_cache_done, state); - return; - } - -done: - sdap_pam_auth_reply(state->breq, dp_err, state->pd->pam_status); -} - -static void sdap_password_cache_done(struct tevent_req *subreq) -{ - struct sdap_pam_auth_state *state = tevent_req_callback_data(subreq, - struct sdap_pam_auth_state); - int ret; - - 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)); - } else { - DEBUG(4, ("Password successfully cached for %s\n", state->username)); - } - - sdap_pam_auth_reply(state->breq, DP_ERR_OK, state->pd->pam_status); -} - -static void sdap_pam_auth_reply(struct be_req *req, int dp_err, int result) -{ - req->fn(req, dp_err, result, NULL); -} - diff --git a/server/providers/ldap/ldap_child.c b/server/providers/ldap/ldap_child.c deleted file mode 100644 index 0d34be2c..00000000 --- a/server/providers/ldap/ldap_child.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - SSSD - - LDAP Backend Module -- prime ccache with TGT in a child process - - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 <sys/types.h> -#include <unistd.h> -#include <sys/stat.h> -#include <popt.h> - -#include <security/pam_modules.h> - -#include "util/util.h" -#include "util/sss_krb5.h" -#include "providers/child_common.h" -#include "providers/dp_backend.h" - -static krb5_context krb5_error_ctx; - -struct input_buffer { - const char *realm_str; - const char *princ_str; - const char *keytab_name; -}; - -static errno_t unpack_buffer(uint8_t *buf, size_t size, - struct input_buffer *ibuf) -{ - size_t p = 0; - uint32_t len; - - DEBUG(7, ("total buffer size: %d\n", size)); - - /* realm_str size and length */ - COPY_UINT32_CHECK(&len, buf + p, p, size); - - DEBUG(7, ("realm_str size: %d\n", len)); - if (len) { - if ((p + len ) > size) return EINVAL; - ibuf->realm_str = talloc_strndup(ibuf, (char *)(buf + p), len); - DEBUG(7, ("got realm_str: %s\n", ibuf->realm_str)); - if (ibuf->realm_str == NULL) return ENOMEM; - p += len; - } - - /* princ_str size and length */ - COPY_UINT32_CHECK(&len, buf + p, p, size); - - DEBUG(7, ("princ_str size: %d\n", len)); - if (len) { - if ((p + len ) > size) return EINVAL; - ibuf->princ_str = talloc_strndup(ibuf, (char *)(buf + p), len); - DEBUG(7, ("got princ_str: %s\n", ibuf->princ_str)); - if (ibuf->princ_str == NULL) return ENOMEM; - p += len; - } - - /* keytab_name size and length */ - COPY_UINT32_CHECK(&len, buf + p, p, size); - - DEBUG(7, ("keytab_name size: %d\n", len)); - if (len) { - if ((p + len ) > size) return EINVAL; - ibuf->keytab_name = talloc_strndup(ibuf, (char *)(buf + p), len); - DEBUG(7, ("got keytab_name: %s\n", ibuf->keytab_name)); - if (ibuf->keytab_name == NULL) return ENOMEM; - p += len; - } - - return EOK; -} - -static int pack_buffer(struct response *r, int result, const char *msg) -{ - int len; - int p = 0; - - len = strlen(msg); - r->size = 2 * sizeof(uint32_t) + len; - - /* result */ - COPY_UINT32_VALUE(&r->buf[p], result, p); - - /* message size */ - COPY_UINT32_VALUE(&r->buf[p], len, p); - - /* message itself */ - COPY_MEM(&r->buf[p], msg, p, len); - - return EOK; -} - -static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - const char **ccname_out) -{ - char *ccname; - char *realm_name = NULL; - char *full_princ = NULL; - krb5_context context = NULL; - krb5_keytab keytab = NULL; - krb5_ccache ccache = NULL; - krb5_principal kprinc; - krb5_creds my_creds; - krb5_get_init_creds_opt options; - krb5_error_code krberr; - int ret; - - krberr = krb5_init_context(&context); - if (krberr) { - DEBUG(2, ("Failed to init kerberos context\n")); - return EFAULT; - } - - if (!realm_str) { - krberr = krb5_get_default_realm(context, &realm_name); - if (krberr) { - DEBUG(2, ("Failed to get default realm name: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - } else { - realm_name = talloc_strdup(memctx, realm_str); - if (!realm_name) { - ret = ENOMEM; - goto done; - } - } - - if (princ_str) { - if (!strchr(princ_str, '@')) { - full_princ = talloc_asprintf(memctx, "%s@%s", - princ_str, realm_name); - } else { - full_princ = talloc_strdup(memctx, princ_str); - } - } else { - char hostname[512]; - - ret = gethostname(hostname, 511); - if (ret == -1) { - ret = errno; - goto done; - } - hostname[511] = '\0'; - - full_princ = talloc_asprintf(memctx, "host/%s@%s", - hostname, realm_name); - } - if (!full_princ) { - ret = ENOMEM; - goto done; - } - DEBUG(4, ("Principal name is: [%s]\n", full_princ)); - - krberr = krb5_parse_name(context, full_princ, &kprinc); - if (krberr) { - DEBUG(2, ("Unable to build principal: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - if (keytab_name) { - krberr = krb5_kt_resolve(context, keytab_name, &keytab); - } else { - krberr = krb5_kt_default(context, &keytab); - } - if (krberr) { - DEBUG(2, ("Failed to read keytab file: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - ccname = talloc_asprintf(memctx, "FILE:%s/ccache_%s", DB_PATH, realm_name); - if (!ccname) { - ret = ENOMEM; - goto done; - } - - krberr = krb5_cc_resolve(context, ccname, &ccache); - if (krberr) { - DEBUG(2, ("Failed to set cache name: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - memset(&my_creds, 0, sizeof(my_creds)); - memset(&options, 0, sizeof(options)); - - krb5_get_init_creds_opt_set_address_list(&options, NULL); - krb5_get_init_creds_opt_set_forwardable(&options, 0); - krb5_get_init_creds_opt_set_proxiable(&options, 0); - /* set a very short lifetime, we don't keep the ticket around */ - krb5_get_init_creds_opt_set_tkt_life(&options, 300); - - krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc, - keytab, 0, NULL, &options); - - if (krberr) { - DEBUG(2, ("Failed to init credentials: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - krberr = krb5_cc_initialize(context, ccache, kprinc); - if (krberr) { - DEBUG(2, ("Failed to init ccache: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - krberr = krb5_cc_store_cred(context, ccache, &my_creds); - if (krberr) { - DEBUG(2, ("Failed to store creds: %s\n", - sss_krb5_get_error_message(context, krberr))); - ret = EFAULT; - goto done; - } - - ret = EOK; - *ccname_out = ccname; - -done: - if (keytab) krb5_kt_close(context, keytab); - if (context) krb5_free_context(context); - return ret; -} - -static int prepare_response(TALLOC_CTX *mem_ctx, - const char *ccname, - krb5_error_code kerr, - struct response **rsp) -{ - int ret; - struct response *r = NULL; - const char *krb5_msg = NULL; - - r = talloc_zero(mem_ctx, struct response); - if (!r) return ENOMEM; - - r->buf = talloc_size(mem_ctx, MAX_CHILD_MSG_SIZE); - if (r->buf == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - return ENOMEM; - } - r->max_size = MAX_CHILD_MSG_SIZE; - r->size = 0; - - if (kerr == 0) { - ret = pack_buffer(r, EOK, ccname); - } else { - krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr); - if (krb5_msg == NULL) { - DEBUG(1, ("sss_krb5_get_error_message failed.\n")); - return ENOMEM; - } - - ret = pack_buffer(r, EFAULT, krb5_msg); - sss_krb5_free_error_message(krb5_error_ctx, krb5_msg); - } - - if (ret != EOK) { - DEBUG(1, ("pack_buffer failed\n")); - return ret; - } - - *rsp = r; - return EOK; -} - -int main(int argc, const char *argv[]) -{ - int ret; - int kerr; - int opt; - int debug_fd = -1; - poptContext pc; - TALLOC_CTX *main_ctx; - uint8_t *buf = NULL; - ssize_t len = 0; - const char *ccname = NULL; - struct input_buffer *ibuf = NULL; - struct response *resp = NULL; - size_t written; - - struct poptOption long_options[] = { - POPT_AUTOHELP - {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, - _("Debug level"), NULL}, - {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0, - _("Add debug timestamps"), NULL}, - {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, - _("An open file descriptor for the debug logs"), NULL}, - POPT_TABLEEND - }; - - pc = poptGetContext(argv[0], argc, argv, long_options, 0); - while((opt = poptGetNextOpt(pc)) != -1) { - switch(opt) { - default: - fprintf(stderr, "\nInvalid option %s: %s\n\n", - poptBadOption(pc, 0), poptStrerror(opt)); - poptPrintUsage(pc, stderr, 0); - _exit(-1); - } - } - - poptFreeContext(pc); - - DEBUG(7, ("ldap_child started.\n")); - - main_ctx = talloc_new(NULL); - if (main_ctx == NULL) { - DEBUG(1, ("talloc_new failed.\n")); - _exit(-1); - } - - debug_prg_name = talloc_asprintf(main_ctx, "[sssd[ldap_child[%d]]]", getpid()); - - if (debug_fd != -1) { - ret = set_debug_file_from_fd(debug_fd); - if (ret != EOK) { - DEBUG(1, ("set_debug_file_from_fd failed.\n")); - } - } - - buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE); - if (buf == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - goto fail; - } - - ibuf = talloc_zero(main_ctx, struct input_buffer); - if (ibuf == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - goto fail; - } - - while ((ret = read(STDIN_FILENO, buf + len, IN_BUF_SIZE - len)) != 0) { - if (ret == -1) { - if (errno == EINTR || errno == EAGAIN) { - continue; - } - DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno))); - goto fail; - } else if (ret > 0) { - len += ret; - if (len > IN_BUF_SIZE) { - DEBUG(1, ("read too much, this should never happen.\n")); - goto fail; - } - continue; - } else { - DEBUG(1, ("unexpected return code of read [%d].\n", ret)); - goto fail; - } - } - close(STDIN_FILENO); - - ret = unpack_buffer(buf, len, ibuf); - if (ret != EOK) { - DEBUG(1, ("unpack_buffer failed.[%d][%s].\n", ret, strerror(ret))); - goto fail; - } - - kerr = ldap_child_get_tgt_sync(main_ctx, - ibuf->realm_str, ibuf->princ_str, - ibuf->keytab_name, &ccname); - if (kerr != EOK) { - DEBUG(1, ("ldap_child_get_tgt_sync failed.\n")); - /* Do not return, must report failure */ - } - - ret = prepare_response(main_ctx, ccname, kerr, &resp); - if (ret != EOK) { - DEBUG(1, ("prepare_response failed. [%d][%s].\n", ret, strerror(ret))); - return ENOMEM; - } - - written = 0; - while (written < resp->size) { - ret = write(STDOUT_FILENO, resp->buf + written, resp->size - written); - if (ret == -1) { - if (errno == EAGAIN || errno == EINTR) { - continue; - } - ret = errno; - DEBUG(1, ("write failed [%d][%s].\n", ret, strerror(ret))); - return ret; - } - written += ret; - } - - close(STDOUT_FILENO); - talloc_free(main_ctx); - _exit(0); - -fail: - close(STDOUT_FILENO); - talloc_free(main_ctx); - _exit(-1); -} diff --git a/server/providers/ldap/ldap_common.c b/server/providers/ldap/ldap_common.c deleted file mode 100644 index bd4294f8..00000000 --- a/server/providers/ldap/ldap_common.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - SSSD - - LDAP Provider Common Functions - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2008-2009 Red Hat - - 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 "providers/ldap/ldap_common.h" -#include "providers/fail_over.h" - -#include "util/sss_krb5.h" - -/* a fd the child process would log into */ -int ldap_child_debug_fd = -1; - -struct dp_option default_basic_opts[] = { - { "ldap_uri", DP_OPT_STRING, { "ldap://localhost" }, NULL_STRING }, - { "ldap_search_base", DP_OPT_STRING, { "dc=example,dc=com" }, NULL_STRING }, - { "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_default_authtok_type", DP_OPT_STRING, NULL_STRING, NULL_STRING}, - { "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB }, - { "ldap_search_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, - { "ldap_network_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER }, - { "ldap_opt_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER }, - { "ldap_tls_reqcert", DP_OPT_STRING, { "hard" }, NULL_STRING }, - { "ldap_user_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_user_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING }, - { "ldap_user_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_group_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_group_search_scope", DP_OPT_STRING, { "sub" }, NULL_STRING }, - { "ldap_group_search_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_schema", DP_OPT_STRING, { "rfc2307" }, NULL_STRING }, - { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER }, - { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "ldap_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER }, - { "ldap_purge_cache_timeout", DP_OPT_NUMBER, { .number = 3600 }, NULL_NUMBER }, - { "entry_cache_timoeut", DP_OPT_NUMBER, { .number = 1800 }, NULL_NUMBER }, - { "ldap_tls_cacert", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_tls_cacertdir", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_id_use_start_tls", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "ldap_sasl_mech", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, - /* use the same parm name as the krb5 module so we set it only once */ - { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ldap_pwd_policy", DP_OPT_STRING, { "none" } , NULL_STRING }, - { "ldap_referrals", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE } -}; - -struct sdap_attr_map generic_attr_map[] = { - { "ldap_entry_usn", NULL, SYSDB_USN, NULL }, - { "ldap_rootdse_last_usn", NULL, SYSDB_USN, NULL } -}; - -struct sdap_attr_map gen_ipa_attr_map[] = { - { "ldap_entry_usn", "entryUSN", SYSDB_USN, NULL }, - { "ldap_rootdse_last_usn", "lastUSN", SYSDB_HIGH_USN, NULL } -}; - -struct sdap_attr_map gen_ad_attr_map[] = { - { "ldap_entry_usn", "uSNChanged", SYSDB_USN, NULL }, - { "ldap_rootdse_last_usn", "highestCommittedUSN", SYSDB_HIGH_USN, NULL } -}; - -struct sdap_attr_map rfc2307_user_map[] = { - { "ldap_user_object_class", "posixAccount", SYSDB_USER_CLASS, NULL }, - { "ldap_user_name", "uid", SYSDB_NAME, NULL }, - { "ldap_user_pwd", "userPassword", SYSDB_PWD, NULL }, - { "ldap_user_uid_number", "uidNumber", SYSDB_UIDNUM, NULL }, - { "ldap_user_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, - { "ldap_user_gecos", "gecos", SYSDB_GECOS, NULL }, - { "ldap_user_home_directory", "homeDirectory", SYSDB_HOMEDIR, NULL }, - { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL }, - { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL }, - { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL }, - { "ldap_user_member_of", NULL, SYSDB_MEMBEROF, NULL }, - { "ldap_user_uuid", NULL, SYSDB_UUID, NULL }, - { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, - { "ldap_user_shadow_last_change", "shadowLastChange", SYSDB_SHADOWPW_LASTCHANGE, NULL }, - { "ldap_user_shadow_min", "shadowMin", SYSDB_SHADOWPW_MIN, NULL }, - { "ldap_user_shadow_max", "shadowMax", SYSDB_SHADOWPW_MAX, NULL }, - { "ldap_user_shadow_warning", "shadowWarning", SYSDB_SHADOWPW_WARNING, NULL }, - { "ldap_user_shadow_inactive", "shadowInactive", SYSDB_SHADOWPW_INACTIVE, NULL }, - { "ldap_user_shadow_expire", "shadowExpire", SYSDB_SHADOWPW_EXPIRE, NULL }, - { "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL }, - { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, - { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, - { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL } -}; - -struct sdap_attr_map rfc2307_group_map[] = { - { "ldap_group_object_class", "posixGroup", SYSDB_GROUP_CLASS, NULL }, - { "ldap_group_name", "cn", SYSDB_NAME, NULL }, - { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL }, - { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, - { "ldap_group_member", "memberuid", SYSDB_MEMBER, NULL }, - { "ldap_group_uuid", NULL, SYSDB_UUID, NULL }, - { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL } -}; - -struct sdap_attr_map rfc2307bis_user_map[] = { - { "ldap_user_object_class", "posixAccount", SYSDB_USER_CLASS, NULL }, - { "ldap_user_name", "uid", SYSDB_NAME, NULL }, - { "ldap_user_pwd", "userPassword", SYSDB_PWD, NULL }, - { "ldap_user_uid_number", "uidNumber", SYSDB_UIDNUM, NULL }, - { "ldap_user_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, - { "ldap_user_gecos", "gecos", SYSDB_GECOS, NULL }, - { "ldap_user_home_directory", "homeDirectory", SYSDB_HOMEDIR, NULL }, - { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL }, - { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL }, - { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL }, - { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL }, - /* FIXME: this is 389ds specific */ - { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL }, - { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, - { "ldap_user_shadow_last_change", "shadowLastChange", SYSDB_SHADOWPW_LASTCHANGE, NULL }, - { "ldap_user_shadow_min", "shadowMin", SYSDB_SHADOWPW_MIN, NULL }, - { "ldap_user_shadow_max", "shadowMax", SYSDB_SHADOWPW_MAX, NULL }, - { "ldap_user_shadow_warning", "shadowWarning", SYSDB_SHADOWPW_WARNING, NULL }, - { "ldap_user_shadow_inactive", "shadowInactive", SYSDB_SHADOWPW_INACTIVE, NULL }, - { "ldap_user_shadow_expire", "shadowExpire", SYSDB_SHADOWPW_EXPIRE, NULL }, - { "ldap_user_shadow_flag", "shadowFlag", SYSDB_SHADOWPW_FLAG, NULL }, - { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, - { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, - { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL } -}; - -struct sdap_attr_map rfc2307bis_group_map[] = { - { "ldap_group_object_class", "posixGroup", SYSDB_GROUP_CLASS, NULL }, - { "ldap_group_name", "cn", SYSDB_NAME, NULL }, - { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL }, - { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL }, - { "ldap_group_member", "member", SYSDB_MEMBER, NULL }, - /* FIXME: this is 389ds specific */ - { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL }, - { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL } -}; - -int ldap_get_options(TALLOC_CTX *memctx, - struct confdb_ctx *cdb, - const char *conf_path, - struct sdap_options **_opts) -{ - struct sdap_attr_map *default_attr_map; - struct sdap_attr_map *default_user_map; - struct sdap_attr_map *default_group_map; - struct sdap_options *opts; - char *schema; - const char *pwd_policy; - int ret; - - opts = talloc_zero(memctx, struct sdap_options); - if (!opts) return ENOMEM; - - ret = dp_get_options(opts, cdb, conf_path, - default_basic_opts, - SDAP_OPTS_BASIC, - &opts->basic); - if (ret != EOK) { - goto done; - } - - /* set user/group search bases if they are not */ - if (NULL == dp_opt_get_string(opts->basic, SDAP_USER_SEARCH_BASE)) { - ret = dp_opt_set_string(opts->basic, SDAP_USER_SEARCH_BASE, - dp_opt_get_string(opts->basic, - SDAP_SEARCH_BASE)); - if (ret != EOK) { - goto done; - } - DEBUG(6, ("Option %s set to %s\n", - opts->basic[SDAP_USER_SEARCH_BASE].opt_name, - dp_opt_get_string(opts->basic, SDAP_USER_SEARCH_BASE))); - } - - if (NULL == dp_opt_get_string(opts->basic, SDAP_GROUP_SEARCH_BASE)) { - ret = dp_opt_set_string(opts->basic, SDAP_GROUP_SEARCH_BASE, - dp_opt_get_string(opts->basic, - SDAP_SEARCH_BASE)); - if (ret != EOK) { - goto done; - } - DEBUG(6, ("Option %s set to %s\n", - opts->basic[SDAP_GROUP_SEARCH_BASE].opt_name, - dp_opt_get_string(opts->basic, SDAP_GROUP_SEARCH_BASE))); - } - - pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY); - if (pwd_policy == NULL) { - DEBUG(1, ("Missing password policy, this may not happen.\n")); - ret = EINVAL; - goto done; - } - if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) != 0 && - strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) != 0 && - strcasecmp(pwd_policy, PWD_POL_OPT_MIT) != 0) { - DEBUG(1, ("Unsupported password policy [%s].\n", pwd_policy)); - ret = EINVAL; - goto done; - } - - -#ifndef HAVE_LDAP_CONNCB - bool ldap_referrals; - - ldap_referrals = dp_opt_get_bool(opts->basic, SDAP_REFERRALS); - if (ldap_referrals) { - DEBUG(1, ("LDAP referrals are not supported, because the LDAP library " - "is too old, see sssd-ldap(5) for details.\n")); - ret = dp_opt_set_bool(opts->basic, SDAP_REFERRALS, false); - } -#endif - - /* schema type */ - schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA); - if (strcasecmp(schema, "rfc2307") == 0) { - opts->schema_type = SDAP_SCHEMA_RFC2307; - default_attr_map = generic_attr_map; - default_user_map = rfc2307_user_map; - default_group_map = rfc2307_group_map; - } else - if (strcasecmp(schema, "rfc2307bis") == 0) { - opts->schema_type = SDAP_SCHEMA_RFC2307BIS; - default_attr_map = generic_attr_map; - default_user_map = rfc2307bis_user_map; - default_group_map = rfc2307bis_group_map; - } else - if (strcasecmp(schema, "IPA") == 0) { - opts->schema_type = SDAP_SCHEMA_IPA_V1; - default_attr_map = gen_ipa_attr_map; - default_user_map = rfc2307bis_user_map; - default_group_map = rfc2307bis_group_map; - } else - if (strcasecmp(schema, "AD") == 0) { - opts->schema_type = SDAP_SCHEMA_AD; - default_attr_map = gen_ad_attr_map; - default_user_map = rfc2307bis_user_map; - default_group_map = rfc2307bis_group_map; - } else { - DEBUG(0, ("Unrecognized schema type: %s\n", schema)); - ret = EINVAL; - goto done; - } - - ret = sdap_get_map(opts, cdb, conf_path, - default_attr_map, - SDAP_AT_GENERAL, - &opts->gen_map); - if (ret != EOK) { - goto done; - } - - ret = sdap_get_map(opts, cdb, conf_path, - default_user_map, - SDAP_OPTS_USER, - &opts->user_map); - if (ret != EOK) { - goto done; - } - - ret = sdap_get_map(opts, cdb, conf_path, - default_group_map, - SDAP_OPTS_GROUP, - &opts->group_map); - if (ret != EOK) { - goto done; - } - - ret = EOK; - *_opts = opts; - -done: - if (ret != EOK) { - talloc_zfree(opts); - } - return ret; -} - -void sdap_handler_done(struct be_req *req, int dp_err, - int error, const char *errstr) -{ - return req->fn(req, dp_err, error, errstr); -} - -bool sdap_connected(struct sdap_id_ctx *ctx) -{ - if (ctx->gsh) { - return ctx->gsh->connected; - } - - return false; -} - -void sdap_mark_offline(struct sdap_id_ctx *ctx) -{ - if (ctx->gsh) { - /* make sure we mark the connection as gone when we go offline so that - * we do not try to reuse a bad connection by mistale later */ - talloc_zfree(ctx->gsh); - } - - be_mark_offline(ctx->be); -} - -bool sdap_check_gssapi_reconnect(struct sdap_id_ctx *ctx) -{ - int ret; - bool result = false; - const char *mech; - const char *realm; - char *ccname = NULL; - krb5_context context = NULL; - krb5_ccache ccache = NULL; - krb5_error_code krberr; - TALLOC_CTX *tmp_ctx = NULL; - krb5_creds mcred; - krb5_creds cred; - char *server_name = NULL; - char *client_princ_str = NULL; - char *full_princ = NULL; - krb5_principal client_principal = NULL; - krb5_principal server_principal = NULL; - char hostname[512]; - int l_errno; - - - mech = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_MECH); - if (mech == NULL || strcasecmp(mech, "GSSAPI") != 0) { - return false; - } - - realm = dp_opt_get_string(ctx->opts->basic, SDAP_KRB5_REALM); - if (realm == NULL) { - DEBUG(3, ("Kerberos realm not available.\n")); - return false; - } - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(1, ("talloc_new failed.\n")); - return false; - } - - ccname = talloc_asprintf(tmp_ctx, "FILE:%s/ccache_%s", DB_PATH, realm); - if (ccname == NULL) { - DEBUG(1, ("talloc_asprintf failed.\n")); - goto done; - } - - krberr = krb5_init_context(&context); - if (krberr) { - DEBUG(1, ("Failed to init kerberos context\n")); - goto done; - } - - krberr = krb5_cc_resolve(context, ccname, &ccache); - if (krberr != 0) { - DEBUG(1, ("krb5_cc_resolve failed.\n")); - goto done; - } - - server_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm); - if (server_name == NULL) { - DEBUG(1, ("talloc_asprintf failed.\n")); - goto done; - } - - krberr = krb5_parse_name(context, server_name, &server_principal); - if (krberr != 0) { - DEBUG(1, ("krb5_parse_name failed.\n")); - goto done; - } - - client_princ_str = dp_opt_get_string(ctx->opts->basic, SDAP_SASL_AUTHID); - if (client_princ_str) { - if (!strchr(client_princ_str, '@')) { - full_princ = talloc_asprintf(tmp_ctx, "%s@%s", client_princ_str, - realm); - } else { - full_princ = talloc_strdup(tmp_ctx, client_princ_str); - } - } else { - ret = gethostname(hostname, sizeof(hostname)-1); - if (ret == -1) { - l_errno = errno; - DEBUG(1, ("gethostname failed [%d][%s].\n", l_errno, - strerror(l_errno))); - goto done; - } - hostname[sizeof(hostname)-1] = '\0'; - - full_princ = talloc_asprintf(tmp_ctx, "host/%s@%s", hostname, realm); - } - if (!full_princ) { - DEBUG(1, ("Client principal not available.\n")); - goto done; - } - DEBUG(7, ("Client principal name is: [%s]\n", full_princ)); - krberr = krb5_parse_name(context, full_princ, &client_principal); - if (krberr != 0) { - DEBUG(1, ("krb5_parse_name failed.\n")); - goto done; - } - - memset(&mcred, 0, sizeof(mcred)); - memset(&cred, 0, sizeof(mcred)); - mcred.client = client_principal; - mcred.server = server_principal; - - krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred); - if (krberr != 0) { - DEBUG(1, ("krb5_cc_retrieve_cred failed.\n")); - goto done; - } - - DEBUG(7, ("TGT end time [%d].\n", cred.times.endtime)); - - if (cred.times.endtime <= time(NULL)) { - DEBUG(3, ("TGT is expired.\n")); - result = true; - } - krb5_free_cred_contents(context, &cred); - -done: - if (client_principal != NULL) { - krb5_free_principal(context, client_principal); - } - if (server_principal != NULL) { - krb5_free_principal(context, server_principal); - } - if (ccache != NULL) { - if (result) { - krb5_cc_destroy(context, ccache); - } else { - krb5_cc_close(context, ccache); - } - } - if (context != NULL) krb5_free_context(context); - talloc_free(tmp_ctx); - return result; -} - -int sdap_id_setup_tasks(struct sdap_id_ctx *ctx) -{ - struct timeval tv; - int ret = EOK; - - /* set up enumeration task */ - if (ctx->be->domain->enumerate) { - /* run the first one in a couple of seconds so that we have time to - * finish initializations first*/ - tv = tevent_timeval_current_ofs(10, 0); - ret = ldap_id_enumerate_set_timer(ctx, tv); - } else { - /* the enumeration task, runs the cleanup process by itself, - * but if enumeration is not runnig we need to schedule it */ - - /* run the first one in a couple of seconds so that we have time to - * finish initializations first*/ - tv = tevent_timeval_current_ofs(10, 0); - ret = ldap_id_cleanup_set_timer(ctx, tv); - } - - return ret; -} - -static void sdap_uri_callback(void *private_data, struct fo_server *server) -{ - struct sdap_service *service; - const char *tmp; - char *new_uri; - - service = talloc_get_type(private_data, struct sdap_service); - if (!service) return; - - tmp = (const char *)fo_get_server_user_data(server); - if (tmp && ldap_is_ldap_url(tmp)) { - new_uri = talloc_strdup(service, tmp); - } else { - new_uri = talloc_asprintf(service, "ldap://%s", - fo_get_server_name(server)); - } - if (!new_uri) { - DEBUG(2, ("Failed to copy URI ...\n")); - return; - } - - /* free old one and replace with new one */ - talloc_zfree(service->uri); - service->uri = new_uri; -} - -int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, - const char *service_name, const char *urls, - struct sdap_service **_service) -{ - TALLOC_CTX *tmp_ctx; - struct sdap_service *service; - LDAPURLDesc *lud; - char **list = NULL; - int ret; - int i; - - tmp_ctx = talloc_new(memctx); - if (!tmp_ctx) { - return ENOMEM; - } - - service = talloc_zero(tmp_ctx, struct sdap_service); - if (!service) { - ret = ENOMEM; - goto done; - } - - ret = be_fo_add_service(ctx, service_name); - if (ret != EOK) { - DEBUG(1, ("Failed to create failover service!\n")); - goto done; - } - - service->name = talloc_strdup(service, service_name); - if (!service->name) { - ret = ENOMEM; - goto done; - } - - /* split server parm into a list */ - ret = split_on_separator(tmp_ctx, urls, ',', true, &list, NULL); - if (ret != EOK) { - DEBUG(1, ("Failed to parse server list!\n")); - goto done; - } - - /* now for each URI add a new server to the failover service */ - for (i = 0; list[i]; i++) { - ret = ldap_url_parse(list[i], &lud); - if (ret != LDAP_SUCCESS) { - DEBUG(0, ("Failed to parse ldap URI (%s)!\n", list[i])); - ret = EINVAL; - goto done; - } - - DEBUG(6, ("Added URI %s\n", list[i])); - - talloc_steal(service, list[i]); - - ret = be_fo_add_server(ctx, service->name, - lud->lud_host, lud->lud_port, list[i]); - if (ret) { - goto done; - } - ldap_free_urldesc(lud); - } - - ret = be_fo_service_add_callback(memctx, ctx, service->name, - sdap_uri_callback, service); - if (ret != EOK) { - DEBUG(1, ("Failed to add failover callback!\n")); - goto done; - } - - ret = EOK; - -done: - if (ret == EOK) { - *_service = talloc_steal(memctx, service); - } - talloc_zfree(tmp_ctx); - return ret; -} - diff --git a/server/providers/ldap/ldap_common.h b/server/providers/ldap/ldap_common.h deleted file mode 100644 index ff1ffb72..00000000 --- a/server/providers/ldap/ldap_common.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - SSSD - - LDAP Common utility code - - Copyright (C) Simo Sorce <ssorce@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/>. -*/ - -#ifndef _LDAP_COMMON_H_ -#define _LDAP_COMMON_H_ - -#include "providers/dp_backend.h" -#include "providers/ldap/sdap.h" -#include "providers/fail_over.h" - -#define PWD_POL_OPT_NONE "none" -#define PWD_POL_OPT_SHADOW "shadow" -#define PWD_POL_OPT_MIT "mit_kerberos" - -/* a fd the child process would log into */ -extern int ldap_child_debug_fd; - -struct sdap_id_ctx { - struct be_ctx *be; - struct sdap_options *opts; - struct fo_service *fo_service; - struct sdap_service *service; - - /* what rootDSE returns */ - struct sysdb_attrs *rootDSE; - - /* global sdap handler */ - struct sdap_handle *gsh; - - /* enumeration loop timer */ - struct timeval last_enum; - /* cleanup loop timer */ - struct timeval last_purge; - - char *max_user_timestamp; - char *max_group_timestamp; -}; - -struct sdap_auth_ctx { - struct be_ctx *be; - struct sdap_options *opts; - struct fo_service *fo_service; - struct sdap_service *service; -}; - -/* id */ -void sdap_account_info_handler(struct be_req *breq); -int sdap_id_setup_tasks(struct sdap_id_ctx *ctx); - -/* auth */ -void sdap_pam_auth_handler(struct be_req *breq); - -/* chpass */ -void sdap_pam_chpass_handler(struct be_req *breq); - - - -void sdap_handler_done(struct be_req *req, int dp_err, - int error, const char *errstr); - -int sdap_service_init(TALLOC_CTX *mmectx, struct be_ctx *ctx, - const char *service_name, const char *urls, - struct sdap_service **service); - -/* options parser */ -int ldap_get_options(TALLOC_CTX *memctx, - struct confdb_ctx *cdb, - const char *conf_path, - struct sdap_options **_opts); - -int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); -int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); - -bool sdap_connected(struct sdap_id_ctx *ctx); -void sdap_mark_offline(struct sdap_id_ctx *ctx); -bool sdap_check_gssapi_reconnect(struct sdap_id_ctx *ctx); - -struct tevent_req *users_get_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - const char *name, - int filter_type, - int attrs_type); -int users_get_recv(struct tevent_req *req); - -struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - const char *name, - int filter_type, - int attrs_type); -int groups_get_recv(struct tevent_req *req); - -/* setup child logging */ -int setup_child(struct sdap_id_ctx *ctx); - -#endif /* _LDAP_COMMON_H_ */ diff --git a/server/providers/ldap/ldap_id.c b/server/providers/ldap/ldap_id.c deleted file mode 100644 index 4bbc07a6..00000000 --- a/server/providers/ldap/ldap_id.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - SSSD - - LDAP Identity Backend Module - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2008 Red Hat - - 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 <time.h> -#include <sys/time.h> - -#include "util/util.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -/* =Users-Related-Functions-(by-name,by-uid)============================== */ - -struct users_get_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - const char *name; - int filter_type; - - char *filter; - const char **attrs; -}; - -static void users_get_connect_done(struct tevent_req *subreq); -static void users_get_done(struct tevent_req *subreq); -static void users_get_delete(struct tevent_req *subreq); - -struct tevent_req *users_get_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - const char *name, - int filter_type, - int attrs_type) -{ - struct tevent_req *req, *subreq; - struct users_get_state *state; - const char *attr_name; - int ret; - - req = tevent_req_create(memctx, &state, struct users_get_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = state->ctx->be->domain; - state->name = name; - state->filter_type = filter_type; - - switch (filter_type) { - case BE_FILTER_NAME: - attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name; - break; - case BE_FILTER_IDNUM: - attr_name = ctx->opts->user_map[SDAP_AT_USER_UID].name; - break; - default: - ret = EINVAL; - goto fail; - } - - state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", - attr_name, name, - ctx->opts->user_map[SDAP_OC_USER].name); - if (!state->filter) { - DEBUG(2, ("Failed to build filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->user_map, - SDAP_OPTS_USER, &state->attrs); - if (ret != EOK) goto fail; - - if (!sdap_connected(ctx)) { - - if (ctx->gsh) talloc_zfree(ctx->gsh); - - /* FIXME: add option to decide if tls should be used - * or SASL/GSSAPI, etc ... */ - subreq = sdap_cli_connect_send(state, ev, ctx->opts, - ctx->be, ctx->service, - &ctx->rootDSE); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, users_get_connect_done, req); - - return req; - } - - subreq = sdap_get_users_send(state, state->ev, - state->domain, state->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, users_get_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void users_get_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - int ret; - - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOTSUP) { - DEBUG(0, ("Authentication mechanism not Supported by server")); - } - tevent_req_error(req, ret); - return; - } - - subreq = sdap_get_users_send(state, state->ev, - state->domain, state->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, users_get_done, req); -} - -static void users_get_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - char *endptr; - uid_t uid; - int ret; - - ret = sdap_get_users_recv(subreq, NULL, NULL); - talloc_zfree(subreq); - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - - if (ret == ENOENT) { - if (strchr(state->name, '*')) { - /* it was an enumeration */ - tevent_req_error(req, ret); - return; - } - - switch (state->filter_type) { - case BE_FILTER_NAME: - subreq = sysdb_delete_user_send(state, state->ev, - state->sysdb, NULL, - state->domain, state->name, 0); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, users_get_delete, req); - return; - - case BE_FILTER_IDNUM: - errno = 0; - uid = (uid_t)strtol(state->name, &endptr, 0); - if (errno || *endptr || (state->name == endptr)) { - tevent_req_error(req, errno); - return; - } - - subreq = sysdb_delete_user_send(state, state->ev, - state->sysdb, NULL, - state->domain, NULL, uid); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, users_get_delete, req); - return; - - default: - tevent_req_error(req, EINVAL); - return; - } - } - - tevent_req_done(req); -} - -static void users_get_delete(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - int ret; - - ret = sysdb_delete_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("User (%s) delete returned %d (%s)\n", - state->name, ret, strerror(ret))); - } - - tevent_req_done(req); -} - -int users_get_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* =Groups-Related-Functions-(by-name,by-uid)============================= */ - -struct groups_get_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - const char *name; - int filter_type; - - char *filter; - const char **attrs; -}; - -static void groups_get_connect_done(struct tevent_req *subreq); -static void groups_get_done(struct tevent_req *subreq); -static void groups_get_delete(struct tevent_req *subreq); - -struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - const char *name, - int filter_type, - int attrs_type) -{ - struct tevent_req *req, *subreq; - struct groups_get_state *state; - const char *attr_name; - int ret; - - req = tevent_req_create(memctx, &state, struct groups_get_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = state->ctx->be->domain; - state->name = name; - state->filter_type = filter_type; - - switch(filter_type) { - case BE_FILTER_NAME: - attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name; - break; - case BE_FILTER_IDNUM: - attr_name = ctx->opts->group_map[SDAP_AT_GROUP_GID].name; - break; - default: - ret = EINVAL; - goto fail; - } - - state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", - attr_name, name, - ctx->opts->group_map[SDAP_OC_GROUP].name); - if (!state->filter) { - DEBUG(2, ("Failed to build filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->group_map, - SDAP_OPTS_GROUP, &state->attrs); - if (ret != EOK) goto fail; - - if (!sdap_connected(ctx)) { - - if (ctx->gsh) talloc_zfree(ctx->gsh); - - /* FIXME: add option to decide if tls should be used - * or SASL/GSSAPI, etc ... */ - subreq = sdap_cli_connect_send(state, ev, ctx->opts, - ctx->be, ctx->service, - &ctx->rootDSE); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, groups_get_connect_done, req); - - return req; - } - - subreq = sdap_get_groups_send(state, state->ev, - state->domain, state->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, groups_get_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void groups_get_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - int ret; - - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOTSUP) { - DEBUG(0, ("Authentication mechanism not Supported by server")); - } - tevent_req_error(req, ret); - return; - } - - subreq = sdap_get_groups_send(state, state->ev, - state->domain, state->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, groups_get_done, req); -} - -static void groups_get_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - char *endptr; - gid_t gid; - int ret; - - ret = sdap_get_groups_recv(subreq, NULL, NULL); - talloc_zfree(subreq); - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - - if (ret == ENOENT) { - if (strchr(state->name, '*')) { - /* it was an enumeration */ - tevent_req_error(req, ret); - return; - } - - switch (state->filter_type) { - case BE_FILTER_NAME: - subreq = sysdb_delete_group_send(state, state->ev, - state->sysdb, NULL, - state->domain, state->name, 0); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, groups_get_delete, req); - return; - - case BE_FILTER_IDNUM: - errno = 0; - gid = (gid_t)strtol(state->name, &endptr, 0); - if (errno || *endptr || (state->name == endptr)) { - tevent_req_error(req, errno); - return; - } - - subreq = sysdb_delete_group_send(state, state->ev, - state->sysdb, NULL, - state->domain, NULL, gid); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, groups_get_delete, req); - return; - - default: - tevent_req_error(req, EINVAL); - return; - } - } - - tevent_req_done(req); -} - -static void groups_get_delete(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - int ret; - - ret = sysdb_delete_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Group (%s) delete returned %d (%s)\n", - state->name, ret, strerror(ret))); - } - - tevent_req_done(req); -} - -int groups_get_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* =Get-Groups-for-User================================================== */ - -struct groups_by_user_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - const char *name; - const char **attrs; -}; - -static void groups_by_user_connect_done(struct tevent_req *subreq); -static void groups_by_user_done(struct tevent_req *subreq); - -static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - const char *name) -{ - struct tevent_req *req, *subreq; - struct groups_by_user_state *state; - int ret; - - req = tevent_req_create(memctx, &state, struct groups_by_user_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->name = name; - - ret = build_attrs_from_map(state, ctx->opts->group_map, - SDAP_OPTS_GROUP, &state->attrs); - if (ret != EOK) goto fail; - - if (!sdap_connected(ctx)) { - - if (ctx->gsh) talloc_zfree(ctx->gsh); - - /* FIXME: add option to decide if tls should be used - * or SASL/GSSAPI, etc ... */ - subreq = sdap_cli_connect_send(state, ev, ctx->opts, - ctx->be, ctx->service, - &ctx->rootDSE); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, groups_by_user_connect_done, req); - - return req; - } - - subreq = sdap_get_initgr_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, state->ctx->gsh, - state->name, state->attrs); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, groups_by_user_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void groups_by_user_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct groups_by_user_state *state = tevent_req_data(req, - struct groups_by_user_state); - int ret; - - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOTSUP) { - DEBUG(0, ("Authentication mechanism not Supported by server")); - } - tevent_req_error(req, ret); - return; - } - - subreq = sdap_get_initgr_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, state->ctx->gsh, - state->name, state->attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, groups_by_user_done, req); -} - -static void groups_by_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sdap_get_initgr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int groups_by_user_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - - -/* =Get-Account-Info-Call================================================= */ - -/* FIXME: embed this function in sssd_be and only call out - * specific functions from modules ? */ - -static void sdap_account_info_users_done(struct tevent_req *req); -static void sdap_account_info_groups_done(struct tevent_req *req); -static void sdap_account_info_initgr_done(struct tevent_req *req); - -void sdap_account_info_handler(struct be_req *breq) -{ - struct sdap_id_ctx *ctx; - struct be_acct_req *ar; - struct tevent_req *req; - const char *err = "Unknown Error"; - int ret = EOK; - - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, struct sdap_id_ctx); - - if (be_is_offline(ctx->be)) { - return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline"); - } - - ar = talloc_get_type(breq->req_data, struct be_acct_req); - - switch (ar->entry_type & 0xFFF) { - case BE_REQ_USER: /* user */ - - /* skip enumerations on demand */ - if (strcmp(ar->filter_value, "*") == 0) { - return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success"); - } - - req = users_get_send(breq, breq->be_ctx->ev, ctx, - ar->filter_value, - ar->filter_type, - ar->attr_type); - if (!req) { - return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory"); - } - - tevent_req_set_callback(req, sdap_account_info_users_done, breq); - - break; - - case BE_REQ_GROUP: /* group */ - - if (strcmp(ar->filter_value, "*") == 0) { - return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success"); - } - - /* skip enumerations on demand */ - req = groups_get_send(breq, breq->be_ctx->ev, ctx, - ar->filter_value, - ar->filter_type, - ar->attr_type); - if (!req) { - return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory"); - } - - tevent_req_set_callback(req, sdap_account_info_groups_done, breq); - - break; - - case BE_REQ_INITGROUPS: /* init groups for user */ - if (ar->filter_type != BE_FILTER_NAME) { - ret = EINVAL; - err = "Invalid filter type"; - break; - } - if (ar->attr_type != BE_ATTR_CORE) { - ret = EINVAL; - err = "Invalid attr type"; - break; - } - if (strchr(ar->filter_value, '*')) { - ret = EINVAL; - err = "Invalid filter value"; - break; - } - req = groups_by_user_send(breq, breq->be_ctx->ev, ctx, - ar->filter_value); - if (!req) ret = ENOMEM; - /* tevent_req_set_callback(req, groups_by_user_done, breq); */ - - tevent_req_set_callback(req, sdap_account_info_initgr_done, breq); - - break; - - default: /*fail*/ - ret = EINVAL; - err = "Invalid request type"; - } - - if (ret != EOK) return sdap_handler_done(breq, DP_ERR_FATAL, ret, err); -} - -static void sdap_account_info_users_done(struct tevent_req *req) -{ - struct be_req *breq = tevent_req_callback_data(req, struct be_req); - struct sdap_id_ctx *ctx; - int dp_err = DP_ERR_OK; - const char *error = NULL; - int ret; - - ret = users_get_recv(req); - talloc_zfree(req); - - if (ret) { - dp_err = DP_ERR_FATAL; - error = "Enum Users Failed"; - - if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) { - dp_err = DP_ERR_OFFLINE; - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, - struct sdap_id_ctx); - if (sdap_check_gssapi_reconnect(ctx)) { - talloc_zfree(ctx->gsh); - sdap_account_info_handler(breq); - return; - } - sdap_mark_offline(ctx); - } - } - - sdap_handler_done(breq, dp_err, ret, error); -} - -static void sdap_account_info_groups_done(struct tevent_req *req) -{ - struct be_req *breq = tevent_req_callback_data(req, struct be_req); - struct sdap_id_ctx *ctx; - int dp_err = DP_ERR_OK; - const char *error = NULL; - int ret; - - ret = groups_get_recv(req); - talloc_zfree(req); - - if (ret) { - dp_err = DP_ERR_FATAL; - error = "Enum Groups Failed"; - - if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) { - dp_err = DP_ERR_OFFLINE; - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, - struct sdap_id_ctx); - if (sdap_check_gssapi_reconnect(ctx)) { - talloc_zfree(ctx->gsh); - sdap_account_info_handler(breq); - return; - } - sdap_mark_offline(ctx); - } - } - - return sdap_handler_done(breq, dp_err, ret, error); -} - -static void sdap_account_info_initgr_done(struct tevent_req *req) -{ - struct be_req *breq = tevent_req_callback_data(req, struct be_req); - struct sdap_id_ctx *ctx; - int dp_err = DP_ERR_OK; - const char *error = NULL; - int ret; - - ret = groups_by_user_recv(req); - talloc_zfree(req); - - if (ret) { - dp_err = DP_ERR_FATAL; - error = "Init Groups Failed"; - - if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) { - dp_err = DP_ERR_OFFLINE; - ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, - struct sdap_id_ctx); - if (sdap_check_gssapi_reconnect(ctx)) { - talloc_zfree(ctx->gsh); - sdap_account_info_handler(breq); - return; - } - sdap_mark_offline(ctx); - } - } - - return sdap_handler_done(breq, dp_err, ret, error); -} - diff --git a/server/providers/ldap/ldap_id_cleanup.c b/server/providers/ldap/ldap_id_cleanup.c deleted file mode 100644 index f3fb4443..00000000 --- a/server/providers/ldap/ldap_id_cleanup.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - SSSD - - LDAP Identity Cleanup Functions - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 <time.h> -#include <sys/time.h> - -#include "util/util.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -/* ==Cleanup-Task========================================================= */ - -struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_reschedule(struct tevent_req *req); - -static void ldap_id_cleanup_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); - -static void ldap_id_cleanup_timer(struct tevent_context *ev, - struct tevent_timer *tt, - struct timeval tv, void *pvt) -{ - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); - struct tevent_timer *timeout; - struct tevent_req *req; - int delay; - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); - return; - } - - req = ldap_id_cleanup_send(ctx, ev, ctx); - if (!req) { - DEBUG(1, ("Failed to schedule cleanup, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); - return; - } - tevent_req_set_callback(req, ldap_id_cleanup_reschedule, ctx); - - /* if cleanup takes so long, either we try to cleanup too - * frequently, or something went seriously wrong */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - timeout = tevent_add_timer(ctx->be->ev, req, tv, - ldap_id_cleanup_timeout, req); - return; -} - -static void ldap_id_cleanup_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - int delay; - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - DEBUG(1, ("Cleanup timed out! Timeout too small? (%ds)!\n", delay)); - - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - - talloc_zfree(req); -} - -static void ldap_id_cleanup_reschedule(struct tevent_req *req) -{ - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - enum tevent_req_state tstate; - uint64_t err; - struct timeval tv; - int delay; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* On error schedule starting from now, not the last run */ - tv = tevent_timeval_current(); - } else { - tv = ctx->last_purge; - } - talloc_zfree(req); - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); -} - - - -int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) -{ - struct tevent_timer *cleanup_task; - - DEBUG(6, ("Scheduling next cleanup at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - cleanup_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_cleanup_timer, ctx); - if (!cleanup_task) { - DEBUG(0, ("FATAL: failed to setup cleanup task!\n")); - return EFAULT; - } - - return EOK; -} - - - -struct global_cleanup_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; -}; - -static struct tevent_req *cleanup_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_users_done(struct tevent_req *subreq); -static struct tevent_req *cleanup_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_groups_done(struct tevent_req *subreq); - -struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct global_cleanup_state *state; - struct tevent_req *req, *subreq; - - req = tevent_req_create(memctx, &state, struct global_cleanup_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - subreq = cleanup_users_send(state, ev, ctx); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ldap_id_cleanup_users_done, req); - - ctx->last_purge = tevent_timeval_current(); - - return req; -} - -static void ldap_id_cleanup_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_cleanup_state *state = tevent_req_data(req, - struct global_cleanup_state); - enum tevent_req_state tstate; - uint64_t err = 0; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - subreq = cleanup_groups_send(state, state->ev, state->ctx); - if (!subreq) { - goto fail; - } - tevent_req_set_callback(subreq, ldap_id_cleanup_groups_done, req); - - return; - -fail: - if (err) { - DEBUG(9, ("User cleanup failed with: (%d)[%s]\n", - (int)err, strerror(err))); - - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = cleanup_users_send(state, state->ev, state->ctx); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_cleanup_users_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - } - - DEBUG(1, ("Failed to cleanup users, retrying later!\n")); - tevent_req_done(req); -} - -static void ldap_id_cleanup_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_cleanup_state *state = tevent_req_data(req, - struct global_cleanup_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - tevent_req_done(req); - return; - -fail: - /* check if credentials are expired otherwise go offline on failures */ - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = cleanup_groups_send(state, state->ev, state->ctx); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_cleanup_groups_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - DEBUG(1, ("Failed to cleanup groups (%d [%s]), retrying later!\n", - (int)err, strerror(err))); - tevent_req_done(req); -} - - -/* ==User-Cleanup-Process================================================= */ - -struct cleanup_users_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - struct sysdb_handle *handle; - - struct ldb_message **msgs; - size_t count; - int cur; -}; - -static void cleanup_users_process(struct tevent_req *subreq); -static void cleanup_users_update(struct tevent_req *req); -static void cleanup_users_up_done(struct tevent_req *subreq); - -static struct tevent_req *cleanup_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct cleanup_users_state *state; - static const char *attrs[] = { SYSDB_NAME, NULL }; - time_t now = time(NULL); - char *subfilter; - - req = tevent_req_create(memctx, &state, struct cleanup_users_state); - if (!req) { - return NULL; - } - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = ctx->be->domain; - state->msgs = NULL; - state->count = 0; - state->cur = 0; - - subfilter = talloc_asprintf(state, "(&(!(%s=0))(%s<=%ld))", - SYSDB_CACHE_EXPIRE, - SYSDB_CACHE_EXPIRE, (long)now); - if (!subfilter) { - DEBUG(2, ("Failed to build filter\n")); - talloc_zfree(req); - return NULL; - } - - subreq = sysdb_search_users_send(state, state->ev, - state->sysdb, NULL, - state->domain, subfilter, attrs); - if (!subreq) { - DEBUG(2, ("Failed to send entry search\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, cleanup_users_process, req); - - return req; -} - -static void cleanup_users_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - int ret; - - ret = sysdb_search_users_recv(subreq, state, &state->count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOENT) { - tevent_req_done(req); - return; - } - tevent_req_error(req, ret); - return; - } - - DEBUG(4, ("Found %d expired user entries!\n", state->count)); - - if (state->count == 0) { - tevent_req_done(req); - } - - cleanup_users_update(req); -} - -static void cleanup_users_update(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - const char *str; - - str = ldb_msg_find_attr_as_string(state->msgs[state->cur], - SYSDB_NAME, NULL); - if (!str) { - DEBUG(2, ("Entry %s has no Name Attribute ?!?\n", - ldb_dn_get_linearized(state->msgs[state->cur]->dn))); - tevent_req_error(req, EFAULT); - return; - } - - subreq = users_get_send(state, state->ev, state->ctx, - str, BE_FILTER_NAME, BE_ATTR_CORE); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, cleanup_users_up_done, req); -} - -static void cleanup_users_up_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - int ret; - - ret = users_get_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("User check returned: %d(%s)\n", - ret, strerror(ret))); - } - - /* if the entry doesn't need to be purged, remove it from the list */ - if (ret != ENOENT) { - talloc_zfree(state->msgs[state->cur]); - } - - state->cur++; - if (state->cur < state->count) { - cleanup_users_update(req); - return; - } - - tevent_req_done(req); -} - -/* ==Group-Cleanup-Process================================================ */ - -struct cleanup_groups_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - struct sysdb_handle *handle; - - struct ldb_message **msgs; - size_t count; - int cur; -}; - -static void cleanup_groups_process(struct tevent_req *subreq); -static void cleanup_groups_update(struct tevent_req *req); -static void cleanup_groups_up_done(struct tevent_req *subreq); - -static struct tevent_req *cleanup_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct cleanup_groups_state *state; - static const char *attrs[] = { SYSDB_NAME, NULL }; - time_t now = time(NULL); - char *subfilter; - - req = tevent_req_create(memctx, &state, struct cleanup_groups_state); - if (!req) { - return NULL; - } - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = ctx->be->domain; - state->msgs = NULL; - state->count = 0; - state->cur = 0; - - subfilter = talloc_asprintf(state, "(&(!(%s=0))(%s<=%ld))", - SYSDB_CACHE_EXPIRE, - SYSDB_CACHE_EXPIRE, (long)now); - if (!subfilter) { - DEBUG(2, ("Failed to build filter\n")); - talloc_zfree(req); - return NULL; - } - - subreq = sysdb_search_groups_send(state, state->ev, - state->sysdb, NULL, - state->domain, subfilter, attrs); - if (!subreq) { - DEBUG(2, ("Failed to send entry search\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, cleanup_groups_process, req); - - return req; -} - -static void cleanup_groups_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - int ret; - - ret = sysdb_search_groups_recv(subreq, state, &state->count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOENT) { - tevent_req_done(req); - return; - } - tevent_req_error(req, ret); - return; - } - - DEBUG(4, ("Found %d expired group entries!\n", state->count)); - - if (state->count == 0) { - tevent_req_done(req); - } - - cleanup_groups_update(req); -} - -static void cleanup_groups_update(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - const char *str; - - str = ldb_msg_find_attr_as_string(state->msgs[state->cur], - SYSDB_NAME, NULL); - if (!str) { - DEBUG(2, ("Entry %s has no Name Attribute ?!?\n", - ldb_dn_get_linearized(state->msgs[state->cur]->dn))); - tevent_req_error(req, EFAULT); - return; - } - - subreq = groups_get_send(state, state->ev, state->ctx, - str, BE_FILTER_NAME, BE_ATTR_CORE); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, cleanup_groups_up_done, req); -} - -static void cleanup_groups_up_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - int ret; - - ret = groups_get_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("User check returned: %d(%s)\n", - ret, strerror(ret))); - } - - state->cur++; - if (state->cur < state->count) { - cleanup_groups_update(req); - return; - } - - tevent_req_done(req); -} - diff --git a/server/providers/ldap/ldap_id_enum.c b/server/providers/ldap/ldap_id_enum.c deleted file mode 100644 index bc06e8bd..00000000 --- a/server/providers/ldap/ldap_id_enum.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - SSSD - - LDAP Identity Enumeration - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 <time.h> -#include <sys/time.h> - -#include "util/util.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); - -/* ==Enumeration-Task===================================================== */ - -static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev, - struct sdap_id_ctx *ctx); - -static void ldap_id_enumerate_reschedule(struct tevent_req *req); - -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); - -static void ldap_id_enumerate_timer(struct tevent_context *ev, - struct tevent_timer *tt, - struct timeval tv, void *pvt) -{ - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); - struct tevent_timer *timeout; - struct tevent_req *req; - int delay; - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - return; - } - - req = ldap_id_enumerate_send(ev, ctx); - if (!req) { - DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - return; - } - tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx); - - /* if enumeration takes so long, either we try to enumerate too - * frequently, or something went seriously wrong */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - timeout = tevent_add_timer(ctx->be->ev, req, tv, - ldap_id_enumerate_timeout, req); - return; -} - -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - int delay; - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay)); - - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - - talloc_zfree(req); -} - -static void ldap_id_enumerate_reschedule(struct tevent_req *req) -{ - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - enum tevent_req_state tstate; - uint64_t err; - struct timeval tv; - int delay; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* On error schedule starting from now, not the last run */ - tv = tevent_timeval_current(); - } else { - tv = ctx->last_enum; - } - talloc_zfree(req); - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); -} - - - -int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) -{ - struct tevent_timer *enum_task; - - DEBUG(6, ("Scheduling next enumeration at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - enum_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_enumerate_timer, ctx); - if (!enum_task) { - DEBUG(0, ("FATAL: failed to setup enumeration task!\n")); - return EFAULT; - } - - return EOK; -} - - -struct global_enum_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - - bool purge; -}; - -static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - bool purge); -static void ldap_id_enum_users_done(struct tevent_req *subreq); -static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - bool purge); -static void ldap_id_enum_groups_done(struct tevent_req *subreq); -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq); - -static struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct global_enum_state *state; - struct tevent_req *req, *subreq; - int t; - - req = tevent_req_create(ctx, &state, struct global_enum_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - ctx->last_enum = tevent_timeval_current(); - - t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - if ((ctx->last_purge.tv_sec + t) < ctx->last_enum.tv_sec) { - state->purge = true; - } else { - state->purge = false; - } - - subreq = enum_users_send(state, ev, ctx, state->purge); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ldap_id_enum_users_done, req); - - return req; -} - -static void ldap_id_enum_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - enum tevent_req_state tstate; - uint64_t err = 0; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - subreq = enum_groups_send(state, state->ev, state->ctx, state->purge); - if (!subreq) { - goto fail; - } - tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req); - - return; - -fail: - if (err) { - DEBUG(9, ("User enumeration failed with: (%d)[%s]\n", - (int)err, strerror(err))); - - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = enum_users_send(state, state->ev, state->ctx, state->purge); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_enum_users_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - } - - DEBUG(1, ("Failed to enumerate users, retrying later!\n")); - tevent_req_done(req); -} - -static void ldap_id_enum_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_enum_state *state = tevent_req_data(req, - struct global_enum_state); - enum tevent_req_state tstate; - uint64_t err = 0; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - if (state->purge) { - - subreq = ldap_id_cleanup_send(state, state->ev, state->ctx); - if (!subreq) { - goto fail; - } - tevent_req_set_callback(subreq, ldap_id_enum_cleanup_done, req); - - return; - } - - tevent_req_done(req); - return; - -fail: - /* check if credentials are expired otherwise go offline on failures */ - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = enum_groups_send(state, state->ev, state->ctx, state->purge); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_enum_groups_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - DEBUG(1, ("Failed to enumerate groups (%d [%s]), retrying later!\n", - (int)err, strerror(err))); - tevent_req_done(req); -} - -static void ldap_id_enum_cleanup_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - talloc_zfree(subreq); - tevent_req_done(req); -} - - -/* ==User-Enumeration===================================================== */ - -struct enum_users_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - - char *filter; - const char **attrs; -}; - -static void enum_users_connect_done(struct tevent_req *subreq); -static void enum_users_op_done(struct tevent_req *subreq); - -static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - bool purge) -{ - struct tevent_req *req, *subreq; - struct enum_users_state *state; - int ret; - - req = tevent_req_create(memctx, &state, struct enum_users_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - if (ctx->max_user_timestamp && !purge) { - - state->filter = talloc_asprintf(state, - "(&(%s=*)(objectclass=%s)(%s>=%s)(!(%s=%s)))", - ctx->opts->user_map[SDAP_AT_USER_NAME].name, - ctx->opts->user_map[SDAP_OC_USER].name, - ctx->opts->user_map[SDAP_AT_USER_MODSTAMP].name, - ctx->max_user_timestamp, - ctx->opts->user_map[SDAP_AT_USER_MODSTAMP].name, - ctx->max_user_timestamp); - } else { - state->filter = talloc_asprintf(state, - "(&(%s=*)(objectclass=%s))", - ctx->opts->user_map[SDAP_AT_USER_NAME].name, - ctx->opts->user_map[SDAP_OC_USER].name); - } - if (!state->filter) { - DEBUG(2, ("Failed to build filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->user_map, - SDAP_OPTS_USER, &state->attrs); - if (ret != EOK) goto fail; - - if (!sdap_connected(ctx)) { - - if (ctx->gsh) talloc_zfree(ctx->gsh); - - /* FIXME: add option to decide if tls should be used - * or SASL/GSSAPI, etc ... */ - subreq = sdap_cli_connect_send(state, ev, ctx->opts, - ctx->be, ctx->service, - &ctx->rootDSE); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, enum_users_connect_done, req); - - return req; - } - - subreq = sdap_get_users_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, - state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, enum_users_op_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void enum_users_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_users_state *state = tevent_req_data(req, - struct enum_users_state); - int ret; - - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOTSUP) { - DEBUG(0, ("Authentication mechanism not Supported by server")); - } - tevent_req_error(req, ret); - return; - } - - subreq = sdap_get_users_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, enum_users_op_done, req); -} - -static void enum_users_op_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_users_state *state = tevent_req_data(req, - struct enum_users_state); - char *timestamp; - int ret; - - ret = sdap_get_users_recv(subreq, state, ×tamp); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (timestamp) { - talloc_zfree(state->ctx->max_user_timestamp); - state->ctx->max_user_timestamp = talloc_steal(state->ctx, timestamp); - } - - DEBUG(4, ("Users higher timestamp: [%s]\n", - state->ctx->max_user_timestamp)); - - tevent_req_done(req); -} - -/* =Group-Enumeration===================================================== */ - -struct enum_groups_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - - char *filter; - const char **attrs; -}; - -static void enum_groups_connect_done(struct tevent_req *subreq); -static void enum_groups_op_done(struct tevent_req *subreq); - -static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, - bool purge) -{ - struct tevent_req *req, *subreq; - struct enum_groups_state *state; - const char *attr_name; - int ret; - - req = tevent_req_create(memctx, &state, struct enum_groups_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name; - - if (ctx->max_group_timestamp && !purge) { - - state->filter = talloc_asprintf(state, - "(&(%s=*)(objectclass=%s)(%s>=%s)(!(%s=%s)))", - ctx->opts->group_map[SDAP_AT_GROUP_NAME].name, - ctx->opts->group_map[SDAP_OC_GROUP].name, - ctx->opts->group_map[SDAP_AT_GROUP_MODSTAMP].name, - ctx->max_group_timestamp, - ctx->opts->group_map[SDAP_AT_GROUP_MODSTAMP].name, - ctx->max_group_timestamp); - } else { - state->filter = talloc_asprintf(state, - "(&(%s=*)(objectclass=%s))", - ctx->opts->group_map[SDAP_AT_GROUP_NAME].name, - ctx->opts->group_map[SDAP_OC_GROUP].name); - } - if (!state->filter) { - DEBUG(2, ("Failed to build filter\n")); - ret = ENOMEM; - goto fail; - } - - /* TODO: handle attrs_type */ - ret = build_attrs_from_map(state, ctx->opts->group_map, - SDAP_OPTS_GROUP, &state->attrs); - if (ret != EOK) goto fail; - - if (!sdap_connected(ctx)) { - - if (ctx->gsh) talloc_zfree(ctx->gsh); - - /* FIXME: add option to decide if tls should be used - * or SASL/GSSAPI, etc ... */ - subreq = sdap_cli_connect_send(state, ev, ctx->opts, - ctx->be, ctx->service, - &ctx->rootDSE); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, enum_groups_connect_done, req); - - return req; - } - - subreq = sdap_get_groups_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, enum_groups_op_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void enum_groups_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_groups_state *state = tevent_req_data(req, - struct enum_groups_state); - int ret; - - ret = sdap_cli_connect_recv(subreq, state->ctx, - &state->ctx->gsh, &state->ctx->rootDSE); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOTSUP) { - DEBUG(0, ("Authentication mechanism not Supported by server")); - } - tevent_req_error(req, ret); - return; - } - - subreq = sdap_get_groups_send(state, state->ev, - state->ctx->be->domain, - state->ctx->be->sysdb, - state->ctx->opts, state->ctx->gsh, - state->attrs, state->filter); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, enum_groups_op_done, req); -} - -static void enum_groups_op_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct enum_groups_state *state = tevent_req_data(req, - struct enum_groups_state); - char *timestamp; - int ret; - - ret = sdap_get_groups_recv(subreq, state, ×tamp); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (timestamp) { - talloc_zfree(state->ctx->max_group_timestamp); - state->ctx->max_group_timestamp = talloc_steal(state->ctx, timestamp); - } - - DEBUG(4, ("Groups higher timestamp: [%s]\n", - state->ctx->max_group_timestamp)); - - tevent_req_done(req); -} - diff --git a/server/providers/ldap/ldap_init.c b/server/providers/ldap/ldap_init.c deleted file mode 100644 index b1f053fb..00000000 --- a/server/providers/ldap/ldap_init.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - SSSD - - LDAP Provider Initialization functions - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 "providers/child_common.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async_private.h" - -static void sdap_shutdown(struct be_req *req); - -/* Id Handler */ -struct bet_ops sdap_id_ops = { - .handler = sdap_account_info_handler, - .finalize = sdap_shutdown -}; - -/* Auth Handler */ -struct bet_ops sdap_auth_ops = { - .handler = sdap_pam_auth_handler, - .finalize = sdap_shutdown -}; - -/* Chpass Handler */ -struct bet_ops sdap_chpass_ops = { - .handler = sdap_pam_chpass_handler, - .finalize = sdap_shutdown -}; - -int sssm_ldap_init(struct be_ctx *bectx, - struct bet_ops **ops, - void **pvt_data) -{ - struct sdap_id_ctx *ctx; - const char *urls; - int ret; - - ctx = talloc_zero(bectx, struct sdap_id_ctx); - if (!ctx) return ENOMEM; - - ctx->be = bectx; - - ret = ldap_get_options(ctx, bectx->cdb, - bectx->conf_path, &ctx->opts); - if (ret != EOK) { - goto done; - } - - urls = dp_opt_get_string(ctx->opts->basic, SDAP_URI); - if (!urls) { - DEBUG(0, ("Missing ldap_uri\n")); - ret = EINVAL; - goto done; - } - - ret = sdap_service_init(ctx, ctx->be, "LDAP", urls, &ctx->service); - if (ret != EOK) { - DEBUG(1, ("Failed to initialize failover service!\n")); - goto done; - } - - ret = setup_tls_config(ctx->opts->basic); - if (ret != EOK) { - DEBUG(1, ("setup_tls_config failed [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - ret = sdap_id_setup_tasks(ctx); - if (ret != EOK) { - goto done; - } - - ret = setup_child(ctx); - if (ret != EOK) { - DEBUG(1, ("setup_child failed [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - *ops = &sdap_id_ops; - *pvt_data = ctx; - ret = EOK; - -done: - if (ret != EOK) { - talloc_free(ctx); - } - return ret; -} - -int sssm_ldap_auth_init(struct be_ctx *bectx, - struct bet_ops **ops, - void **pvt_data) -{ - struct sdap_auth_ctx *ctx; - const char *urls; - int ret; - - ctx = talloc(bectx, struct sdap_auth_ctx); - if (!ctx) return ENOMEM; - - ctx->be = bectx; - - ret = ldap_get_options(ctx, bectx->cdb, - bectx->conf_path, &ctx->opts); - if (ret != EOK) { - goto done; - } - - urls = dp_opt_get_string(ctx->opts->basic, SDAP_URI); - if (!urls) { - DEBUG(0, ("Missing ldap_uri\n")); - ret = EINVAL; - goto done; - } - - ret = sdap_service_init(ctx, ctx->be, "LDAP", urls, &ctx->service); - if (ret != EOK) { - DEBUG(1, ("Failed to initialize failover service!\n")); - goto done; - } - - ret = setup_tls_config(ctx->opts->basic); - if (ret != EOK) { - DEBUG(1, ("setup_tls_config failed [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - *ops = &sdap_auth_ops; - *pvt_data = ctx; - ret = EOK; - -done: - if (ret != EOK) { - talloc_free(ctx); - } - return ret; -} - -int sssm_ldap_chpass_init(struct be_ctx *bectx, - struct bet_ops **ops, - void **pvt_data) -{ - int ret; - - ret = sssm_ldap_auth_init(bectx, ops, pvt_data); - - *ops = &sdap_chpass_ops; - - return ret; -} - -static void sdap_shutdown(struct be_req *req) -{ - /* TODO: Clean up any internal data */ - sdap_handler_done(req, DP_ERR_OK, EOK, NULL); -} - diff --git a/server/providers/ldap/sdap.c b/server/providers/ldap/sdap.c deleted file mode 100644 index 39c67cc9..00000000 --- a/server/providers/ldap/sdap.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - SSSD - - LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@redhat.com> - - 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/>. -*/ - -#define LDAP_DEPRECATED 1 -#include "util/util.h" -#include "confdb/confdb.h" -#include "providers/ldap/sdap.h" - -/* =Retrieve-Options====================================================== */ - -int sdap_get_map(TALLOC_CTX *memctx, - struct confdb_ctx *cdb, - const char *conf_path, - struct sdap_attr_map *def_map, - int num_entries, - struct sdap_attr_map **_map) -{ - struct sdap_attr_map *map; - int i, ret; - - map = talloc_array(memctx, struct sdap_attr_map, num_entries); - if (!map) { - return ENOMEM; - } - - for (i = 0; i < num_entries; i++) { - - map[i].opt_name = def_map[i].opt_name; - map[i].def_name = def_map[i].def_name; - map[i].sys_name = def_map[i].sys_name; - - ret = confdb_get_string(cdb, map, conf_path, - map[i].opt_name, - map[i].def_name, - &map[i].name); - if ((ret != EOK) || (map[i].def_name && !map[i].name)) { - DEBUG(0, ("Failed to retrieve value for %s\n", map[i].opt_name)); - if (ret != EOK) { - talloc_zfree(map); - return EINVAL; - } - } - - DEBUG(5, ("Option %s has value %s\n", map[i].opt_name, map[i].name)); - } - - *_map = map; - return EOK; -} - -/* =Parse-msg============================================================= */ - -int sdap_parse_entry(TALLOC_CTX *memctx, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sdap_attr_map *map, int attrs_num, - struct sysdb_attrs **_attrs, char **_dn) -{ - struct sysdb_attrs *attrs; - BerElement *ber = NULL; - struct berval **vals; - struct ldb_val v; - char *str; - int lerrno; - int a, i, ret; - const char *name; - bool store; - - lerrno = 0; - ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - - attrs = sysdb_new_attrs(memctx); - if (!attrs) return ENOMEM; - - str = ldap_get_dn(sh->ldap, sm->msg); - if (!str) { - ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - DEBUG(1, ("ldap_get_dn failed: %d(%s)\n", - lerrno, ldap_err2string(lerrno))); - ret = EIO; - goto fail; - } - - DEBUG(9, ("OriginalDN: [%s].\n", str)); - ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str); - if (ret) goto fail; - if (_dn) { - *_dn = talloc_strdup(memctx, str); - if (!*_dn) { - ret = ENOMEM; - ldap_memfree(str); - goto fail; - } - } - ldap_memfree(str); - - if (map) { - vals = ldap_get_values_len(sh->ldap, sm->msg, "objectClass"); - if (!vals) { - DEBUG(1, ("Unknown entry type, no objectClasses found!\n")); - ret = EINVAL; - goto fail; - } - - for (i = 0; vals[i]; i++) { - /* the objectclass is always the first name in the map */ - if (strncasecmp(map[0].name, - vals[i]->bv_val, vals[i]->bv_len) == 0) { - /* ok it's an entry of the right type */ - break; - } - } - if (!vals[i]) { - DEBUG(1, ("objectClass not matching: %s\n", - map[0].name)); - ldap_value_free_len(vals); - ret = EINVAL; - goto fail; - } - ldap_value_free_len(vals); - } - - str = ldap_first_attribute(sh->ldap, sm->msg, &ber); - if (!str) { - ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - DEBUG(1, ("Entry has no attributes [%d(%s)]!?\n", - lerrno, ldap_err2string(lerrno))); - if (map) { - ret = EINVAL; - goto fail; - } - } - while (str) { - if (map) { - for (a = 1; a < attrs_num; a++) { - /* check if this attr is valid with the chosen schema */ - if (!map[a].name) continue; - /* check if it is an attr we are interested in */ - if (strcasecmp(str, map[a].name) == 0) break; - } - /* interesting attr */ - if (a < attrs_num) { - store = true; - name = map[a].sys_name; - } else { - store = false; - } - } else { - name = str; - store = true; - } - - if (store) { - vals = ldap_get_values_len(sh->ldap, sm->msg, str); - if (!vals) { - ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - DEBUG(1, ("LDAP Library error: %d(%s)", - lerrno, ldap_err2string(lerrno))); - ret = EIO; - goto fail; - } - if (!vals[0]) { - DEBUG(1, ("Missing value after ldap_get_values() ??\n")); - ret = EINVAL; - goto fail; - } - for (i = 0; vals[i]; i++) { - v.data = (uint8_t *)vals[i]->bv_val; - v.length = vals[i]->bv_len; - - ret = sysdb_attrs_add_val(attrs, name, &v); - if (ret) goto fail; - } - ldap_value_free_len(vals); - } - - ldap_memfree(str); - str = ldap_next_attribute(sh->ldap, sm->msg, ber); - } - ber_free(ber, 0); - - ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - if (lerrno) { - DEBUG(1, ("LDAP Library error: %d(%s)", - lerrno, ldap_err2string(lerrno))); - ret = EIO; - goto fail; - } - - *_attrs = attrs; - return EOK; - -fail: - if (ber) ber_free(ber, 0); - talloc_free(attrs); - return ret; -} - -/* This function converts an ldap message into a sysdb_attrs structure. - * It converts only known user attributes, the rest are ignored. - * If the entry is not that of an user an error is returned. - * The original DN is stored as an attribute named originalDN */ - -int sdap_parse_user(TALLOC_CTX *memctx, struct sdap_options *opts, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sysdb_attrs **_attrs, char **_dn) -{ - - return sdap_parse_entry(memctx, sh, sm, opts->user_map, - SDAP_OPTS_USER, _attrs, _dn); -} - -/* This function converts an ldap message into a sysdb_attrs structure. - * It converts only known group attributes, the rest are ignored. - * If the entry is not that of an user an error is returned. - * The original DN is stored as an attribute named originalDN */ - -int sdap_parse_group(TALLOC_CTX *memctx, struct sdap_options *opts, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sysdb_attrs **_attrs, char **_dn) -{ - - return sdap_parse_entry(memctx, sh, sm, opts->group_map, - SDAP_OPTS_GROUP, _attrs, _dn); -} - -/* =Get-DN-from-message=================================================== */ - -int sdap_get_msg_dn(TALLOC_CTX *memctx, struct sdap_handle *sh, - struct sdap_msg *sm, char **_dn) -{ - char *str; - int lerrno; - - lerrno = 0; - ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - - str = ldap_get_dn(sh->ldap, sm->msg); - if (!str) { - ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); - DEBUG(1, ("ldap_get_dn failed: %d(%s)\n", - lerrno, ldap_err2string(lerrno))); - return EIO; - } - - *_dn = talloc_strdup(memctx, str); - ldap_memfree(str); - if (!*_dn) return ENOMEM; - - return EOK; -} - -errno_t setup_tls_config(struct dp_option *basic_opts) -{ - int ret; - int ldap_opt_x_tls_require_cert; - const char *tls_opt; - tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_REQCERT); - if (tls_opt) { - if (strcasecmp(tls_opt, "never") == 0) { - ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_NEVER; - } - else if (strcasecmp(tls_opt, "allow") == 0) { - ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_ALLOW; - } - else if (strcasecmp(tls_opt, "try") == 0) { - ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_TRY; - } - else if (strcasecmp(tls_opt, "demand") == 0) { - ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_DEMAND; - } - else if (strcasecmp(tls_opt, "hard") == 0) { - ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_HARD; - } - else { - DEBUG(1, ("Unknown value for tls_reqcert.\n")); - return EINVAL; - } - /* LDAP_OPT_X_TLS_REQUIRE_CERT has to be set as a global option, - * because the SSL/TLS context is initialized from this value. */ - ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, - &ldap_opt_x_tls_require_cert); - if (ret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("ldap_set_option failed: %s\n", ldap_err2string(ret))); - return EIO; - } - } - - tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERT); - if (tls_opt) { - ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_opt); - if (ret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("ldap_set_option failed: %s\n", ldap_err2string(ret))); - return EIO; - } - } - - tls_opt = dp_opt_get_string(basic_opts, SDAP_TLS_CACERTDIR); - if (tls_opt) { - ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, tls_opt); - if (ret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("ldap_set_option failed: %s\n", ldap_err2string(ret))); - return EIO; - } - } - - return EOK; -} - - -bool sdap_rootdse_sasl_mech_is_supported(struct sysdb_attrs *rootdse, - const char *sasl_mech) -{ - struct ldb_message_element *el = NULL; - struct ldb_val *val; - int i; - - if (!sasl_mech) return false; - - for (i = 0; i < rootdse->num; i++) { - if (strcasecmp(rootdse->a[i].name, "supportedSASLMechanisms")) { - continue; - } - el = &rootdse->a[i]; - break; - } - - if (!el) { - /* no supported SASL Mechanism at all ? */ - return false; - } - - for (i = 0; i < el->num_values; i++) { - val = &el->values[i]; - if (strncasecmp(sasl_mech, (const char *)val->data, val->length)) { - continue; - } - return true; - } - - return false; -} - -int build_attrs_from_map(TALLOC_CTX *memctx, - struct sdap_attr_map *map, - size_t size, const char ***_attrs) -{ - char **attrs; - int i, j; - - attrs = talloc_array(memctx, char *, size + 1); - if (!attrs) return ENOMEM; - - /* first attribute is "objectclass" not the specifc one */ - attrs[0] = talloc_strdup(memctx, "objectClass"); - if (!attrs[0]) return ENOMEM; - - /* add the others */ - for (i = j = 1; i < size; i++) { - if (map[i].name) { - attrs[j] = map[i].name; - j++; - } - } - attrs[j] = NULL; - - *_attrs = (const char **)attrs; - - return EOK; -} - diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h deleted file mode 100644 index 16dbb784..00000000 --- a/server/providers/ldap/sdap.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - SSSD - - LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@redhat.com> - - 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/>. -*/ - -#ifndef _SDAP_H_ -#define _SDAP_H_ - -#include "providers/dp_backend.h" -#include <ldap.h> -#include "util/sss_ldap.h" - -struct sdap_msg { - struct sdap_msg *next; - LDAPMessage *msg; -}; - -struct sdap_op; - -typedef void (sdap_op_callback_t)(struct sdap_op *op, - struct sdap_msg *, int, void *); - -struct sdap_handle; - -struct sdap_op { - struct sdap_op *prev, *next; - struct sdap_handle *sh; - - int msgid; - bool done; - - sdap_op_callback_t *callback; - void *data; - - struct tevent_context *ev; - struct sdap_msg *list; - struct sdap_msg *last; -}; - -struct fd_event_item { - struct fd_event_item *prev; - struct fd_event_item *next; - - int fd; - struct tevent_fd *fde; -}; - -struct ldap_cb_data { - struct sdap_handle *sh; - struct tevent_context *ev; - struct fd_event_item *fd_list; -}; - -struct sdap_handle { - LDAP *ldap; - bool connected; - -#ifdef HAVE_LDAP_CONNCB - struct ldap_conncb *conncb; -#else - struct tevent_fd *fde; -#endif - - struct sdap_op *ops; -}; - -struct sdap_service { - char *name; - char *uri; -}; - -#define SYSDB_SHADOWPW_LASTCHANGE "shadowLastChange" -#define SYSDB_SHADOWPW_MIN "shadowMin" -#define SYSDB_SHADOWPW_MAX "shadowMax" -#define SYSDB_SHADOWPW_WARNING "shadowWarning" -#define SYSDB_SHADOWPW_INACTIVE "shadowInactive" -#define SYSDB_SHADOWPW_EXPIRE "shadowExpire" -#define SYSDB_SHADOWPW_FLAG "shadowFlag" - -#define SYSDB_KRBPW_LASTCHANGE "krbLastPwdChange" -#define SYSDB_KRBPW_EXPIRATION "krbPasswordExpiration" - -#define SYSDB_PWD_ATTRIBUTE "pwdAttribute" - -enum sdap_result { - SDAP_SUCCESS, - SDAP_NOT_FOUND, - SDAP_UNAVAIL, - SDAP_RETRY, - SDAP_ERROR, - SDAP_AUTH_SUCCESS, - SDAP_AUTH_FAILED, - SDAP_AUTH_PW_EXPIRED, - SDAP_ACCT_EXPIRED -}; - -enum sdap_basic_opt { - SDAP_URI = 0, - SDAP_SEARCH_BASE, - SDAP_DEFAULT_BIND_DN, - SDAP_DEFAULT_AUTHTOK_TYPE, - SDAP_DEFAULT_AUTHTOK, - SDAP_SEARCH_TIMEOUT, - SDAP_NETWORK_TIMEOUT, - SDAP_OPT_TIMEOUT, - SDAP_TLS_REQCERT, - SDAP_USER_SEARCH_BASE, - SDAP_USER_SEARCH_SCOPE, - SDAP_USER_SEARCH_FILTER, - SDAP_GROUP_SEARCH_BASE, - SDAP_GROUP_SEARCH_SCOPE, - SDAP_GROUP_SEARCH_FILTER, - SDAP_SCHEMA, - SDAP_OFFLINE_TIMEOUT, - SDAP_FORCE_UPPER_CASE_REALM, - SDAP_ENUM_REFRESH_TIMEOUT, - SDAP_CACHE_PURGE_TIMEOUT, - SDAP_ENTRY_CACHE_TIMEOUT, - SDAP_TLS_CACERT, - SDAP_TLS_CACERTDIR, - SDAP_ID_TLS, - SDAP_SASL_MECH, - SDAP_SASL_AUTHID, - SDAP_KRB5_KEYTAB, - SDAP_KRB5_KINIT, - SDAP_KRB5_REALM, - SDAP_PWD_POLICY, - SDAP_REFERRALS, - - SDAP_OPTS_BASIC /* opts counter */ -}; - -enum sdap_gen_attrs { - SDAP_AT_ENTRY_USN = 0, - SDAP_AT_LAST_USN, - - SDAP_AT_GENERAL /* attrs counter */ -}; - -/* the objectclass must be the first attribute. - * Functions depend on this */ -enum sdap_user_attrs { - SDAP_OC_USER = 0, - SDAP_AT_USER_NAME, - SDAP_AT_USER_PWD, - SDAP_AT_USER_UID, - SDAP_AT_USER_GID, - SDAP_AT_USER_GECOS, - SDAP_AT_USER_HOME, - SDAP_AT_USER_SHELL, - SDAP_AT_USER_PRINC, - SDAP_AT_USER_FULLNAME, - SDAP_AT_USER_MEMBEROF, - SDAP_AT_USER_UUID, - SDAP_AT_USER_MODSTAMP, - SDAP_AT_SP_LSTCHG, - SDAP_AT_SP_MIN, - SDAP_AT_SP_MAX, - SDAP_AT_SP_WARN, - SDAP_AT_SP_INACT, - SDAP_AT_SP_EXPIRE, - SDAP_AT_SP_FLAG, - SDAP_AT_KP_LASTCHANGE, - SDAP_AT_KP_EXPIRATION, - SDAP_AT_PWD_ATTRIBUTE, - - SDAP_OPTS_USER /* attrs counter */ -}; - -#define SDAP_FIRST_EXTRA_USER_AT SDAP_AT_SP_LSTCHG - -/* the objectclass must be the first attribute. - * Functions depend on this */ -enum sdap_group_attrs { - SDAP_OC_GROUP = 0, - SDAP_AT_GROUP_NAME, - SDAP_AT_GROUP_PWD, - SDAP_AT_GROUP_GID, - SDAP_AT_GROUP_MEMBER, - SDAP_AT_GROUP_UUID, - SDAP_AT_GROUP_MODSTAMP, - - SDAP_OPTS_GROUP /* attrs counter */ -}; - -struct sdap_attr_map { - const char *opt_name; - const char *def_name; - const char *sys_name; - char *name; -}; - -struct sdap_options { - struct dp_option *basic; - struct sdap_attr_map *gen_map; - struct sdap_attr_map *user_map; - struct sdap_attr_map *group_map; - - /* supported schema types */ - enum schema_type { - SDAP_SCHEMA_RFC2307 = 1, /* memberUid = uid */ - SDAP_SCHEMA_RFC2307BIS = 2, /* member = dn */ - SDAP_SCHEMA_IPA_V1 = 3, /* member/memberof */ - SDAP_SCHEMA_AD = 4 /* AD's member/memberof */ - } schema_type; - - struct ldb_dn *users_base; - struct ldb_dn *groups_base; -}; - -int sdap_get_map(TALLOC_CTX *memctx, - struct confdb_ctx *cdb, - const char *conf_path, - struct sdap_attr_map *def_map, - int num_entries, - struct sdap_attr_map **_map); - -int sdap_parse_entry(TALLOC_CTX *memctx, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sdap_attr_map *map, int attrs_num, - struct sysdb_attrs **_attrs, char **_dn); - -int sdap_parse_user(TALLOC_CTX *memctx, struct sdap_options *opts, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sysdb_attrs **_attrs, char **_dn); - -int sdap_parse_group(TALLOC_CTX *memctx, struct sdap_options *opts, - struct sdap_handle *sh, struct sdap_msg *sm, - struct sysdb_attrs **_attrs, char **_dn); - -int sdap_get_msg_dn(TALLOC_CTX *memctx, struct sdap_handle *sh, - struct sdap_msg *sm, char **_dn); - -errno_t setup_tls_config(struct dp_option *basic_opts); - -bool sdap_rootdse_sasl_mech_is_supported(struct sysdb_attrs *rootdse, - const char *sasl_mech); - -int build_attrs_from_map(TALLOC_CTX *memctx, - struct sdap_attr_map *map, - size_t size, const char ***_attrs); -#endif /* _SDAP_H_ */ diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c deleted file mode 100644 index 959c08a6..00000000 --- a/server/providers/ldap/sdap_async.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* - SSSD - - Async LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@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 <ctype.h> -#include "util/util.h" -#include "providers/ldap/sdap_async_private.h" - -#define REALM_SEPARATOR '@' -#define REPLY_REALLOC_INCREMENT 10 - -void make_realm_upper_case(const char *upn) -{ - char *c; - - c = strchr(upn, REALM_SEPARATOR); - if (c == NULL) { - DEBUG(9, ("No realm delimiter found in upn [%s].\n", upn)); - return; - } - - while(*(++c) != '\0') { - c[0] = toupper(*c); - } - - return; -} - -/* ==LDAP-Memory-Handling================================================= */ - -static int lmsg_destructor(void *mem) -{ - ldap_msgfree((LDAPMessage *)mem); - return 0; -} - -static int sdap_msg_attach(TALLOC_CTX *memctx, LDAPMessage *msg) -{ - void *h; - - if (!msg) return EINVAL; - - h = sss_mem_attach(memctx, msg, lmsg_destructor); - if (!h) return ENOMEM; - - return EOK; -} - -/* ==sdap-hanlde-utility-functions======================================== */ - -static inline void sdap_handle_release(struct sdap_handle *sh); -static int sdap_handle_destructor(void *mem); - -struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx) -{ - struct sdap_handle *sh; - - sh = talloc_zero(memctx, struct sdap_handle); - if (!sh) return NULL; - - talloc_set_destructor((TALLOC_CTX *)sh, sdap_handle_destructor); - - return sh; -} - -static int sdap_handle_destructor(void *mem) -{ - struct sdap_handle *sh = talloc_get_type(mem, struct sdap_handle); - - sdap_handle_release(sh); - - return 0; -} - -static void sdap_handle_release(struct sdap_handle *sh) -{ - DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n", - sh, (int)sh->connected, sh->ops, sh->ldap)); - - if (sh->connected) { - struct sdap_op *op; - -#ifdef HAVE_LDAP_CONNCB - /* remove all related fd events from the event loop */ - talloc_zfree(sh->conncb->lc_arg); -#else - talloc_zfree(sh->fde); -#endif - - while (sh->ops) { - op = sh->ops; - op->callback(op, NULL, EIO, op->data); - /* calling the callback may result in freeing the op */ - /* check if it is still the same or avoid freeing */ - if (op == sh->ops) talloc_free(op); - } - - if (sh->ldap) { - ldap_unbind_ext(sh->ldap, NULL, NULL); - } -#ifdef HAVE_LDAP_CONNCB - talloc_zfree(sh->conncb); -#endif - sh->connected = false; - sh->ldap = NULL; - sh->ops = NULL; - } -} - -/* ==Parse-Results-And-Handle-Disconnections============================== */ -static void sdap_process_message(struct tevent_context *ev, - struct sdap_handle *sh, LDAPMessage *msg); -static void sdap_process_result(struct tevent_context *ev, void *pvt); -static void sdap_process_next_reply(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); - -static void sdap_ldap_result(struct tevent_context *ev, - struct tevent_fd *fde, - uint16_t flags, void *pvt) -{ - sdap_process_result(ev, pvt); -} - -static void sdap_ldap_next_result(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - sdap_process_result(ev, pvt); -} - -static void sdap_process_result(struct tevent_context *ev, void *pvt) -{ - struct sdap_handle *sh = talloc_get_type(pvt, struct sdap_handle); - struct timeval no_timeout = {0, 0}; - struct tevent_timer *te; - LDAPMessage *msg; - int ret; - - DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n", - sh, (int)sh->connected, sh->ops, sh->ldap)); - - if (!sh->connected || !sh->ldap) { - DEBUG(2, ("ERROR: LDAP connection is not connected!\n")); - return; - } - - ret = ldap_result(sh->ldap, LDAP_RES_ANY, 0, &no_timeout, &msg); - if (ret == 0) { - /* this almost always means we have reached the end of - * the list of received messages */ - DEBUG(8, ("Trace: ldap_result found nothing!\n")); - return; - } - - if (ret == -1) { - DEBUG(4, ("ldap_result gave -1, something bad happend!\n")); - sdap_handle_release(sh); - return; - } - - /* We don't know if this will be the last result. - * - * important: we must do this before actually processing the message - * because the message processing might even free the sdap_handler - * so it must be the last operation. - * FIXME: use tevent_immediate/tevent_queues, when avilable */ - memset(&no_timeout, 0, sizeof(struct timeval)); - - te = tevent_add_timer(ev, sh, no_timeout, sdap_ldap_next_result, sh); - if (!te) { - DEBUG(1, ("Failed to add critical timer to fetch next result!\n")); - } - - /* now process this message */ - sdap_process_message(ev, sh, msg); -} - -/* process a messgae calling the right operation callback. - * msg is completely taken care of (including freeeing it) - * NOTE: this function may even end up freeing the sdap_handle - * so sdap_hanbdle must not be used after this function is called - */ -static void sdap_process_message(struct tevent_context *ev, - struct sdap_handle *sh, LDAPMessage *msg) -{ - struct sdap_msg *reply; - struct sdap_op *op; - int msgid; - int msgtype; - int ret; - - msgid = ldap_msgid(msg); - if (msgid == -1) { - DEBUG(2, ("can't fire callback, message id invalid!\n")); - ldap_msgfree(msg); - return; - } - - msgtype = ldap_msgtype(msg); - - for (op = sh->ops; op; op = op->next) { - if (op->msgid == msgid) break; - } - - if (op == NULL) { - DEBUG(2, ("Unmatched msgid, discarding message (type: %0x)\n", - msgtype)); - ldap_msgfree(msg); - return; - } - - /* shouldn't happen */ - if (op->done) { - DEBUG(2, ("Operation [%p] already handled (type: %0x)\n", op, msgtype)); - ldap_msgfree(msg); - return; - } - - switch (msgtype) { - case LDAP_RES_SEARCH_ENTRY: - /* go and process entry */ - break; - - case LDAP_RES_SEARCH_REFERENCE: - /* more ops to come with this msgid */ - /* just ignore */ - ldap_msgfree(msg); - return; - - case LDAP_RES_BIND: - case LDAP_RES_SEARCH_RESULT: - case LDAP_RES_MODIFY: - case LDAP_RES_ADD: - case LDAP_RES_DELETE: - case LDAP_RES_MODDN: - case LDAP_RES_COMPARE: - case LDAP_RES_EXTENDED: - case LDAP_RES_INTERMEDIATE: - /* no more results expected with this msgid */ - op->done = true; - break; - - default: - /* unkwon msg type ?? */ - DEBUG(1, ("Couldn't figure out the msg type! [%0x]\n", msgtype)); - ldap_msgfree(msg); - return; - } - - reply = talloc_zero(op, struct sdap_msg); - if (!reply) { - ldap_msgfree(msg); - ret = ENOMEM; - } else { - reply->msg = msg; - ret = sdap_msg_attach(reply, msg); - if (ret != EOK) { - ldap_msgfree(msg); - talloc_zfree(reply); - } - } - - if (op->list) { - /* list exist, queue it */ - - op->last->next = reply; - op->last = reply; - - } else { - /* create list, then call callback */ - op->list = op->last = reply; - - /* must be the last operation as it may end up freeing all memory - * including all ops handlers */ - op->callback(op, reply, ret, op->data); - } -} - -static void sdap_unlock_next_reply(struct sdap_op *op) -{ - struct timeval tv; - struct tevent_timer *te; - struct sdap_msg *next_reply; - - if (op->list) { - next_reply = op->list->next; - /* get rid of the previous reply, it has been processed already */ - talloc_zfree(op->list); - op->list = next_reply; - } - - /* if there are still replies to parse, queue a new operation */ - if (op->list) { - /* use a very small timeout, so that fd operations have a chance to be - * served while processing a long reply */ - tv = tevent_timeval_current(); - - /* wait 5 microsecond */ - tv.tv_usec += 5; - tv.tv_sec += tv.tv_usec / 1000000; - tv.tv_usec = tv.tv_usec % 1000000; - - te = tevent_add_timer(op->ev, op, tv, - sdap_process_next_reply, op); - if (!te) { - DEBUG(1, ("Failed to add critical timer for next reply!\n")); - op->callback(op, NULL, EFAULT, op->data); - } - } -} - -static void sdap_process_next_reply(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct sdap_op *op = talloc_get_type(pvt, struct sdap_op); - - op->callback(op, op->list, EOK, op->data); -} - -#ifdef HAVE_LDAP_CONNCB -int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, - struct sockaddr *addr, struct ldap_conncb *ctx) -{ - int ret; - ber_socket_t ber_fd; - struct fd_event_item *fd_event_item; - struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg, - struct ldap_cb_data); - - ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd); - if (ret == -1) { - DEBUG(1, ("ber_sockbuf_ctrl failed.\n")); - return EINVAL; - } - DEBUG(9, ("New LDAP connection to [%s] with fd [%d].\n", - ldap_url_desc2str(srv), ber_fd)); - - fd_event_item = talloc_zero(cb_data, struct fd_event_item); - if (fd_event_item == NULL) { - DEBUG(1, ("talloc failed.\n")); - return ENOMEM; - } - - fd_event_item->fde = tevent_add_fd(cb_data->ev, fd_event_item, ber_fd, - TEVENT_FD_READ, sdap_ldap_result, - cb_data->sh); - if (fd_event_item->fde == NULL) { - DEBUG(1, ("tevent_add_fd failed.\n")); - talloc_free(fd_event_item); - return ENOMEM; - } - fd_event_item->fd = ber_fd; - - DLIST_ADD(cb_data->fd_list, fd_event_item); - - return LDAP_SUCCESS; -} - -void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb, - struct ldap_conncb *ctx) -{ - int ret; - ber_socket_t ber_fd; - struct fd_event_item *fd_event_item; - struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg, - struct ldap_cb_data); - - if (sb == NULL || cb_data == NULL) { - return; - } - - ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd); - if (ret == -1) { - DEBUG(1, ("ber_sockbuf_ctrl failed.\n")); - return; - } - DEBUG(9, ("Closing LDAP connection with fd [%d].\n", ber_fd)); - - DLIST_FOR_EACH(fd_event_item, cb_data->fd_list) { - if (fd_event_item->fd == ber_fd) { - break; - } - } - if (fd_event_item == NULL) { - DEBUG(1, ("No event for fd [%d] found.\n", ber_fd)); - return; - } - - DLIST_REMOVE(cb_data->fd_list, fd_event_item); - talloc_zfree(fd_event_item); - - return; -} - -#else - -static int get_fd_from_ldap(LDAP *ldap, int *fd) -{ - int ret; - - ret = ldap_get_option(ldap, LDAP_OPT_DESC, fd); - if (ret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to get fd from ldap!!\n")); - *fd = -1; - return EIO; - } - - return EOK; -} - -int sdap_install_ldap_callbacks(struct sdap_handle *sh, - struct tevent_context *ev) -{ - int fd; - int ret; - - ret = get_fd_from_ldap(sh->ldap, &fd); - if (ret) return ret; - - sh->fde = tevent_add_fd(ev, sh, fd, TEVENT_FD_READ, sdap_ldap_result, sh); - if (!sh->fde) return ENOMEM; - - DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n", - sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap)); - - return EOK; -} - -#endif - - -/* ==LDAP-Operations-Helpers============================================== */ - -static int sdap_op_destructor(void *mem) -{ - struct sdap_op *op = (struct sdap_op *)mem; - - DLIST_REMOVE(op->sh->ops, op); - - if (op->done) return 0; - - /* we don't check the result here, if a message was really abandoned, - * hopefully the server will get an abandon. - * If the operation was already fully completed, this is going to be - * just a noop */ - ldap_abandon_ext(op->sh->ldap, op->msgid, NULL, NULL); - - return 0; -} - -static void sdap_op_timeout(struct tevent_req *req) -{ - struct sdap_op *op = tevent_req_callback_data(req, struct sdap_op); - - /* should never happen, but just in case */ - if (op->done) { - DEBUG(2, ("Timeout happened after op was finished !?\n")); - return; - } - - /* signal the caller that we have a timeout */ - op->callback(op, NULL, ETIMEDOUT, op->data); -} - -int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev, - struct sdap_handle *sh, int msgid, - sdap_op_callback_t *callback, void *data, - int timeout, struct sdap_op **_op) -{ - struct sdap_op *op; - - op = talloc_zero(memctx, struct sdap_op); - if (!op) return ENOMEM; - - op->sh = sh; - op->msgid = msgid; - op->callback = callback; - op->data = data; - op->ev = ev; - - /* check if we need to set a timeout */ - if (timeout) { - struct tevent_req *req; - struct timeval tv; - - tv = tevent_timeval_current(); - tv = tevent_timeval_add(&tv, timeout, 0); - - /* allocate on op, so when it get freed the timeout is removed */ - req = tevent_wakeup_send(op, ev, tv); - if (!req) { - talloc_zfree(op); - return ENOMEM; - } - tevent_req_set_callback(req, sdap_op_timeout, op); - } - - DLIST_ADD(sh->ops, op); - - talloc_set_destructor((TALLOC_CTX *)op, sdap_op_destructor); - - *_op = op; - return EOK; -} - -/* ==Modify-Password====================================================== */ - -struct sdap_exop_modify_passwd_state { - struct sdap_handle *sh; - - struct sdap_op *op; - - int result; - char *user_error_message; -}; - -static void sdap_exop_modify_passwd_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); - -struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - char *user_dn, - char *password, - char *new_password) -{ - struct tevent_req *req = NULL; - struct sdap_exop_modify_passwd_state *state; - int ret; - BerElement *ber = NULL; - struct berval *bv = NULL; - int msgid; - LDAPControl *request_controls[2]; - - req = tevent_req_create(memctx, &state, - struct sdap_exop_modify_passwd_state); - if (!req) return NULL; - - state->sh = sh; - state->user_error_message = NULL; - - ber = ber_alloc_t( LBER_USE_DER ); - if (ber == NULL) { - DEBUG(7, ("ber_alloc_t failed.\n")); - talloc_zfree(req); - return NULL; - } - - ret = ber_printf( ber, "{tststs}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, - user_dn, - LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, password, - LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, new_password); - if (ret == -1) { - DEBUG(1, ("ber_printf failed.\n")); - ber_free(ber, 1); - talloc_zfree(req); - return NULL; - } - - ret = ber_flatten(ber, &bv); - ber_free(ber, 1); - if (ret == -1) { - DEBUG(1, ("ber_flatten failed.\n")); - talloc_zfree(req); - return NULL; - } - - ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST, - 0, NULL, 0, &request_controls[0]); - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("sss_ldap_control_create failed.\n")); - goto fail; - } - request_controls[1] = NULL; - - DEBUG(4, ("Executing extended operation\n")); - - ret = ldap_extended_operation(state->sh->ldap, LDAP_EXOP_MODIFY_PASSWD, - bv, request_controls, NULL, &msgid); - ber_bvfree(bv); - ldap_control_free(request_controls[0]); - if (ret == -1 || msgid == -1) { - DEBUG(1, ("ldap_extended_operation failed\n")); - goto fail; - } - DEBUG(8, ("ldap_extended_operation sent, msgid = %d\n", msgid)); - - /* FIXME: get timeouts from configuration, for now 5 secs. */ - ret = sdap_op_add(state, ev, state->sh, msgid, - sdap_exop_modify_passwd_done, req, 5, &state->op); - if (ret) { - DEBUG(1, ("Failed to set up operation!\n")); - goto fail; - } - - return req; - -fail: - tevent_req_error(req, EIO); - tevent_req_post(req, ev); - return req; -} - -static void sdap_exop_modify_passwd_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_exop_modify_passwd_state *state = tevent_req_data(req, - struct sdap_exop_modify_passwd_state); - char *errmsg = NULL; - int ret; - LDAPControl **response_controls = NULL; - int c; - ber_int_t pp_grace; - ber_int_t pp_expire; - LDAPPasswordPolicyError pp_error; - - if (error) { - tevent_req_error(req, error); - return; - } - - ret = ldap_parse_result(state->sh->ldap, reply->msg, - &state->result, NULL, &errmsg, NULL, - &response_controls, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - ret = EIO; - goto done; - } - - if (response_controls == NULL) { - DEBUG(5, ("Server returned no controls.\n")); - } else { - for (c = 0; response_controls[c] != NULL; c++) { - DEBUG(9, ("Server returned control [%s].\n", - response_controls[c]->ldctl_oid)); - if (strcmp(response_controls[c]->ldctl_oid, - LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { - ret = ldap_parse_passwordpolicy_control(state->sh->ldap, - response_controls[c], - &pp_expire, &pp_grace, - &pp_error); - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("ldap_parse_passwordpolicy_control failed.\n")); - ret = EIO; - goto done; - } - - DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] " - "error [%s].\n", pp_expire, pp_grace, - ldap_passwordpolicy_err2txt(pp_error))); - } - } - } - - if (state->result != LDAP_SUCCESS) { - state->user_error_message = talloc_strdup(state, errmsg); - if (state->user_error_message == NULL) { - DEBUG(1, ("talloc_strdup failed.\n")); - } - } - - DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n", - ldap_err2string(state->result), state->result, errmsg)); - - ret = LDAP_SUCCESS; -done: - ldap_controls_free(response_controls); - ldap_memfree(errmsg); - - if (ret == LDAP_SUCCESS) { - tevent_req_done(req); - } else { - tevent_req_error(req, ret); - } -} - -int sdap_exop_modify_passwd_recv(struct tevent_req *req, - TALLOC_CTX * mem_ctx, - enum sdap_result *result, - char **user_error_message) -{ - struct sdap_exop_modify_passwd_state *state = tevent_req_data(req, - struct sdap_exop_modify_passwd_state); - - *result = SDAP_ERROR; - *user_error_message = talloc_steal(mem_ctx, state->user_error_message); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (state->result == LDAP_SUCCESS) { - *result = SDAP_SUCCESS; - } - - return EOK; -} - -/* ==Fetch-RootDSE============================================= */ - -struct sdap_get_rootdse_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - - struct sysdb_attrs *rootdse; -}; - -static void sdap_get_rootdse_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sdap_handle *sh) -{ - struct tevent_req *req, *subreq; - struct sdap_get_rootdse_state *state; - - DEBUG(9, ("Getting rootdse\n")); - - req = tevent_req_create(memctx, &state, struct sdap_get_rootdse_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sh = sh; - state->rootdse = NULL; - - subreq = sdap_get_generic_send(state, ev, opts, sh, - "", LDAP_SCOPE_BASE, - "(objectclass=*)", NULL, NULL, 0); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_get_rootdse_done, req); - - return req; -} - -static void sdap_get_rootdse_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_rootdse_state *state = tevent_req_data(req, - struct sdap_get_rootdse_state); - struct sysdb_attrs **results; - size_t num_results; - int ret; - - ret = sdap_get_generic_recv(subreq, state, &num_results, &results); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (num_results == 0 || !results) { - DEBUG(2, ("No RootDSE for server ?!\n")); - tevent_req_error(req, ENOENT); - return; - } - - if (num_results > 1) { - DEBUG(2, ("Multiple replies when searching for RootDSE ??\n")); - tevent_req_error(req, EIO); - return; - } - - state->rootdse = talloc_steal(state, results[0]); - talloc_zfree(results); - - DEBUG(9, ("Got rootdse\n")); - - tevent_req_done(req); -} - -int sdap_get_rootdse_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sysdb_attrs **rootdse) -{ - struct sdap_get_rootdse_state *state = tevent_req_data(req, - struct sdap_get_rootdse_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *rootdse = talloc_steal(memctx, state->rootdse); - - return EOK; -} - -/* ==Generic Search============================================ */ - -struct sdap_get_generic_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - const char *search_base; - int scope; - const char *filter; - const char **attrs; - struct sdap_attr_map *map; - int map_num_attrs; - - struct sdap_op *op; - - size_t reply_max; - size_t reply_count; - struct sysdb_attrs **reply; -}; - -static errno_t add_to_reply(struct sdap_get_generic_state *state, - struct sysdb_attrs *msg); - -static void sdap_get_generic_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); - -struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sdap_handle *sh, - const char *search_base, - int scope, - const char *filter, - const char **attrs, - struct sdap_attr_map *map, - int map_num_attrs) -{ - struct tevent_req *req = NULL; - struct sdap_get_generic_state *state = NULL; - int lret; - int ret; - int msgid; - - req = tevent_req_create(memctx, &state, struct sdap_get_generic_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sh = sh; - state->search_base = search_base; - state->scope = scope; - state->filter = filter; - state->attrs = attrs; - state->map = map; - state->map_num_attrs = map_num_attrs; - state->op = NULL; - state->reply_max = 0; - state->reply_count = 0; - state->reply = NULL; - - DEBUG(6, ("calling ldap_search_ext with [%s][%s].\n", state->filter, - state->search_base)); - if (debug_level >= 7) { - int i; - - if (state->attrs) { - for (i = 0; state->attrs[i]; i++) { - DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i])); - } - } - } - - lret = ldap_search_ext(state->sh->ldap, state->search_base, - state->scope, state->filter, - discard_const(state->attrs), - false, NULL, NULL, NULL, 0, &msgid); - if (lret != LDAP_SUCCESS) { - DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret))); - ret = EIO; - goto fail; - } - DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid)); - - ret = sdap_op_add(state, state->ev, state->sh, msgid, - sdap_get_generic_done, req, - dp_opt_get_int(state->opts->basic, - SDAP_SEARCH_TIMEOUT), - &state->op); - if (ret != EOK) { - DEBUG(1, ("Failed to set up operation!\n")); - goto fail; - } - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - - -static void sdap_get_generic_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_get_generic_state *state = tevent_req_data(req, - struct sdap_get_generic_state); - struct sysdb_attrs *attrs; - char *errmsg; - int result; - int ret; - - if (error) { - tevent_req_error(req, error); - return; - } - - switch (ldap_msgtype(reply->msg)) { - case LDAP_RES_SEARCH_REFERENCE: - /* ignore references for now */ - talloc_free(reply); - - /* unlock the operation so that we can proceed with the next result */ - sdap_unlock_next_reply(state->op); - break; - - case LDAP_RES_SEARCH_ENTRY: - ret = sdap_parse_entry(state, state->sh, reply, - state->map, state->map_num_attrs, - &attrs, NULL); - if (ret != EOK) { - DEBUG(1, ("sdap_parse_generic_entry failed.\n")); - tevent_req_error(req, ENOMEM); - return; - } - - ret = add_to_reply(state, attrs); - if (ret != EOK) { - DEBUG(1, ("add_to_reply failed.\n")); - tevent_req_error(req, ret); - return; - } - - sdap_unlock_next_reply(state->op); - break; - - case LDAP_RES_SEARCH_RESULT: - ret = ldap_parse_result(state->sh->ldap, reply->msg, - &result, NULL, &errmsg, NULL, NULL, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - tevent_req_error(req, EIO); - return; - } - - DEBUG(6, ("Search result: %s(%d), %s\n", - ldap_err2string(result), result, errmsg)); - - tevent_req_done(req); - return; - - default: - /* what is going on here !? */ - tevent_req_error(req, EIO); - return; - } -} - -static errno_t add_to_reply(struct sdap_get_generic_state *state, - struct sysdb_attrs *msg) -{ - if (state->reply == NULL || state->reply_max == state->reply_count) { - state->reply_max += REPLY_REALLOC_INCREMENT; - state->reply = talloc_realloc(state, state->reply, - struct sysdb_attrs *, - state->reply_max); - if (state->reply == NULL) { - DEBUG(1, ("talloc_realloc failed.\n")); - return ENOMEM; - } - } - - state->reply[state->reply_count++] = talloc_steal(state->reply, msg); - - return EOK; -} - -int sdap_get_generic_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - size_t *reply_count, - struct sysdb_attrs ***reply) -{ - struct sdap_get_generic_state *state = tevent_req_data(req, - struct sdap_get_generic_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *reply_count = state->reply_count; - *reply = talloc_steal(mem_ctx, state->reply); - - return EOK; -} - diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h deleted file mode 100644 index 3c52d236..00000000 --- a/server/providers/ldap/sdap_async.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - SSSD - - Async LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@redhat.com> - - 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/>. -*/ - -#ifndef _SDAP_ASYNC_H_ -#define _SDAP_ASYNC_H_ - -#include <talloc.h> -#include <tevent.h> -#include "providers/dp_backend.h" -#include "providers/ldap/sdap.h" -#include "providers/fail_over.h" - -struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - const char *uri, - bool use_start_tls); -int sdap_connect_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **sh); - -struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char **attrs, - const char *wildcard); -int sdap_get_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp); - -struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char **attrs, - const char *wildcard); -int sdap_get_groups_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp); - -struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - int timeout, - const char *keytab, - const char *principal, - const char *realm); -int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result); - -struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - const char *sasl_mech, - const char *sasl_user, - const char *user_dn, - const char *authtok_type, - struct dp_opt_blob authtok); -int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result); - -struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char *name, - const char **grp_attrs); -int sdap_get_initgr_recv(struct tevent_req *req); - -struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - char *user_dn, - char *password, - char *new_password); -int sdap_exop_modify_passwd_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - enum sdap_result *result, - char **user_error_msg); - -struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct be_ctx *be, - struct sdap_service *service, - struct sysdb_attrs **rootdse); -int sdap_cli_connect_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **gsh, - struct sysdb_attrs **rootdse); - -struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sdap_handle *sh, - const char *search_base, - int scope, - const char *filter, - const char **attrs, - struct sdap_attr_map *map, - int map_num_attrs); -int sdap_get_generic_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, size_t *reply_count, - struct sysdb_attrs ***reply_list); - -#endif /* _SDAP_ASYNC_H_ */ diff --git a/server/providers/ldap/sdap_async_accounts.c b/server/providers/ldap/sdap_async_accounts.c deleted file mode 100644 index abebe288..00000000 --- a/server/providers/ldap/sdap_async_accounts.c +++ /dev/null @@ -1,2065 +0,0 @@ -/* - SSSD - - Async LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@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 "util/util.h" -#include "db/sysdb.h" -#include "providers/ldap/sdap_async_private.h" - -/* ==Save-User-Entry====================================================== */ - -struct sdap_save_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sdap_options *opts; - - struct sss_domain_info *dom; - - const char *name; - struct sysdb_attrs *attrs; - char *timestamp; -}; - -static void sdap_save_user_done(struct tevent_req *subreq); - - /* FIXME: support storing additional attributes */ - -static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs, - bool is_initgr) -{ - struct tevent_req *req, *subreq; - struct sdap_save_user_state *state; - struct ldb_message_element *el; - int ret; - const char *pwd; - const char *gecos; - const char *homedir; - const char *shell; - long int l; - uid_t uid; - gid_t gid; - struct sysdb_attrs *user_attrs; - char *upn = NULL; - int i; - char *val = NULL; - int cache_timeout; - - DEBUG(9, ("Save user\n")); - - req = tevent_req_create(memctx, &state, struct sdap_save_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->dom = dom; - state->opts = opts; - state->attrs = attrs; - state->timestamp = NULL; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_NAME].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) { - ret = EINVAL; - goto fail; - } - state->name = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_PWD].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) pwd = NULL; - else pwd = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_GECOS].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) gecos = NULL; - else gecos = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_HOME].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) homedir = NULL; - else homedir = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_SHELL].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) shell = NULL; - else shell = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_UID].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) { - DEBUG(1, ("no uid provided for [%s] in domain [%s].\n", - state->name, dom->name)); - ret = EINVAL; - goto fail; - } - errno = 0; - l = strtol((const char *)el->values[0].data, NULL, 0); - if (errno) { - ret = EINVAL; - goto fail; - } - uid = l; - - /* check that the uid is valid for this domain */ - if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); - ret = EINVAL; - goto fail; - } - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_GID].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) { - DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", - state->name, dom->name)); - ret = EINVAL; - goto fail; - } - errno = 0; - l = strtol((const char *)el->values[0].data, NULL, 0); - if (errno) { - ret = EINVAL; - goto fail; - } - gid = l; - - /* check that the gid is valid for this domain */ - if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("User [%s] filtered out! (id out of range)\n", - state->name)); - ret = EINVAL; - goto fail; - } - - user_attrs = sysdb_new_attrs(state); - if (user_attrs == NULL) { - ret = ENOMEM; - goto fail; - } - - ret = sysdb_attrs_get_el(state->attrs, SYSDB_ORIG_DN, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("Original DN is not available for [%s].\n", state->name)); - } else { - DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n", - el->values[0].data, state->name)); - ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_DN, - (const char *) el->values[0].data); - if (ret) { - goto fail; - } - } - - ret = sysdb_attrs_get_el(state->attrs, SYSDB_MEMBEROF, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("Original memberOf is not available for [%s].\n", - state->name)); - } else { - DEBUG(7, ("Adding original memberOf attributes to [%s].\n", - state->name)); - for (i = 0; i < el->num_values; i++) { - ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF, - (const char *) el->values[i].data); - if (ret) { - goto fail; - } - } - } - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n", - state->name)); - } else { - ret = sysdb_attrs_add_string(user_attrs, - opts->user_map[SDAP_AT_USER_MODSTAMP].sys_name, - (const char*)el->values[0].data); - if (ret) { - goto fail; - } - state->timestamp = talloc_strdup(state, - (const char*)el->values[0].data); - if (!state->timestamp) { - ret = ENOMEM; - goto fail; - } - } - - ret = sysdb_attrs_get_el(state->attrs, - opts->user_map[SDAP_AT_USER_PRINC].sys_name, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("User principle is not available for [%s].\n", state->name)); - } else { - upn = talloc_strdup(user_attrs, (const char*) el->values[0].data); - if (!upn) { - ret = ENOMEM; - goto fail; - } - if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { - make_realm_upper_case(upn); - } - DEBUG(7, ("Adding user principle [%s] to attributes of [%s].\n", - upn, state->name)); - ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); - if (ret) { - goto fail; - } - } - - for (i = SDAP_FIRST_EXTRA_USER_AT; i < SDAP_OPTS_USER; i++) { - ret = sysdb_attrs_get_el(state->attrs, opts->user_map[i].sys_name, &el); - if (ret) { - goto fail; - } - if (el->num_values > 0) { - DEBUG(9, ("Adding [%s]=[%s] to user attributes.\n", - opts->user_map[i].sys_name, - (const char*) el->values[0].data)); - val = talloc_strdup(user_attrs, (const char*) el->values[0].data); - if (val == NULL) { - ret = ENOMEM; - goto fail; - } - ret = sysdb_attrs_add_string(user_attrs, - opts->user_map[i].sys_name, val); - if (ret) { - goto fail; - } - } - } - - cache_timeout = dp_opt_get_int(opts->basic, SDAP_ENTRY_CACHE_TIMEOUT); - - if (is_initgr) { - ret = sysdb_attrs_add_time_t(user_attrs, SYSDB_INITGR_EXPIRE, - (cache_timeout ? - (time(NULL) + cache_timeout) : 0)); - if (ret) { - goto fail; - } - } - - DEBUG(6, ("Storing info for user %s\n", state->name)); - - subreq = sysdb_store_user_send(state, state->ev, state->handle, - state->dom, state->name, pwd, - uid, gid, gecos, homedir, shell, - user_attrs, cache_timeout); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_save_user_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_save_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_save_user_state *state = tevent_req_data(req, - struct sdap_save_user_state); - int ret; - - ret = sysdb_store_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to save user %s\n", state->name)); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_save_user_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_save_user_state *state = tevent_req_data(req, - struct sdap_save_user_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->timestamp); - } - - return EOK; -} - - -/* ==Generic-Function-to-save-multiple-users============================= */ - -struct sdap_save_users_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - - struct sysdb_attrs **users; - int count; - int cur; - - struct sysdb_handle *handle; - - char *higher_timestamp; -}; - -static void sdap_save_users_trans(struct tevent_req *subreq); -static void sdap_save_users_store(struct tevent_req *req); -static void sdap_save_users_process(struct tevent_req *subreq); -struct tevent_req *sdap_save_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sysdb_attrs **users, - int num_users) -{ - struct tevent_req *req, *subreq; - struct sdap_save_users_state *state; - - req = tevent_req_create(memctx, &state, struct sdap_save_users_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; - state->users = users; - state->count = num_users; - state->cur = 0; - state->handle = NULL; - state->higher_timestamp = NULL; - - subreq = sysdb_transaction_send(state, state->ev, state->sysdb); - if (!subreq) { - tevent_req_error(req, ENOMEM); - tevent_req_post(req, ev); - return req; - } - tevent_req_set_callback(subreq, sdap_save_users_trans, req); - - return req; -} - -static void sdap_save_users_trans(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_users_state *state; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_users_state); - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - sdap_save_users_store(req); -} - -static void sdap_save_users_store(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_save_users_state *state; - - state = tevent_req_data(req, struct sdap_save_users_state); - - subreq = sdap_save_user_send(state, state->ev, state->handle, - state->opts, state->dom, - state->users[state->cur], false); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_save_users_process, req); -} - -static void sdap_save_users_process(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_users_state *state; - char *timestamp = NULL; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_users_state); - - ret = sdap_save_user_recv(subreq, state, ×tamp); - talloc_zfree(subreq); - - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - if (ret) { - DEBUG(2, ("Failed to store user %d. Ignoring.\n", state->cur)); - } else { - DEBUG(9, ("User %d processed!\n", state->cur)); - } - - if (timestamp) { - if (state->higher_timestamp) { - if (strcmp(timestamp, state->higher_timestamp) > 0) { - talloc_zfree(state->higher_timestamp); - state->higher_timestamp = timestamp; - } else { - talloc_zfree(timestamp); - } - } else { - state->higher_timestamp = timestamp; - } - } - - state->cur++; - if (state->cur < state->count) { - sdap_save_users_store(req); - } else { - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - } -} - -static int sdap_save_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_save_users_state *state = tevent_req_data(req, - struct sdap_save_users_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); - } - - return EOK; -} - - -/* ==Search-Users-with-filter============================================= */ - -struct sdap_get_users_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - struct sss_domain_info *dom; - struct sysdb_ctx *sysdb; - const char **attrs; - const char *filter; - - char *higher_timestamp; - struct sysdb_attrs **users; - size_t count; -}; - -static void sdap_get_users_process(struct tevent_req *subreq); -static void sdap_get_users_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char **attrs, - const char *filter) -{ - struct tevent_req *req, *subreq; - struct sdap_get_users_state *state; - - req = tevent_req_create(memctx, &state, struct sdap_get_users_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->dom = dom; - state->sh = sh; - state->sysdb = sysdb; - state->filter = filter; - state->attrs = attrs; - state->higher_timestamp = NULL; - state->users = NULL; - state->count = 0; - - subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_USER_SEARCH_BASE), - LDAP_SCOPE_SUBTREE, - state->filter, state->attrs, - state->opts->user_map, SDAP_OPTS_USER); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_get_users_process, req); - - return req; -} - -static void sdap_get_users_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); - int ret; - - ret = sdap_get_generic_recv(subreq, state, - &state->count, &state->users); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - DEBUG(6, ("Search for users, returned %d results.\n", state->count)); - - if (state->count == 0) { - tevent_req_error(req, ENOENT); - return; - } - - subreq = sdap_save_users_send(state, state->ev, state->dom, - state->sysdb, state->opts, - state->users, state->count); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_users_done, req); -} - -static void sdap_get_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); - int ret; - - DEBUG(9, ("Saving %d Users - Done\n", state->count)); - - ret = sdap_save_users_recv(subreq, state, &state->higher_timestamp); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to store users.\n")); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sdap_get_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_get_users_state *state = tevent_req_data(req, - struct sdap_get_users_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); - } - - return EOK; -} - -/* ==Group-Parsing Routines=============================================== */ - -struct sdap_orig_entry_state { - int done; -}; - -static void sdap_find_entry_by_origDN_done(struct tevent_req *req) -{ - struct sdap_orig_entry_state *state = tevent_req_callback_data(req, - struct sdap_orig_entry_state); - state->done = 1; -} - -/* WARNING: this is a sync routine for now */ -static int sdap_find_entry_by_origDN(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *orig_dn, - char **localdn) -{ - struct tevent_req *req; - struct sdap_orig_entry_state *state; - static const char *attrs[] = { NULL }; - struct ldb_dn *base_dn; - char *filter; - struct ldb_message **msgs; - size_t num_msgs; - int ret; - - state = talloc_zero(memctx, struct sdap_orig_entry_state); - if (!state) { - ret = ENOMEM; - goto done; - } - - filter = talloc_asprintf(state, "%s=%s", SYSDB_ORIG_DN, orig_dn); - if (!filter) { - ret = ENOMEM; - goto done; - } - - base_dn = sysdb_domain_dn(sysdb_handle_get_ctx(handle), - state, domain->name); - if (!base_dn) { - ret = ENOMEM; - goto done; - } - - req = sysdb_search_entry_send(state, ev, handle, base_dn, - LDB_SCOPE_SUBTREE, filter, attrs); - if (!req) { - ret = ENOMEM; - goto done; - } - tevent_req_set_callback(req, sdap_find_entry_by_origDN_done, state); - - /* WARNING: SYNC LOOP HERE */ - tevent_loop_allow_nesting(ev); - while (state->done == 0) { - tevent_loop_once(ev); - } - - ret = sysdb_search_entry_recv(req, state, &num_msgs, &msgs); - if (ret) { - goto done; - } - if (num_msgs != 1) { - ret = ENOENT; - goto done; - } - - *localdn = talloc_strdup(memctx, ldb_dn_get_linearized(msgs[0]->dn)); - if (!*localdn) { - ret = ENOENT; - goto done; - } - - ret = EOK; - -done: - talloc_zfree(state); - return ret; -} - -static int sdap_fill_memberships(struct sysdb_attrs *group_attrs, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *domain, - struct ldb_val *values, - int num_values) -{ - struct ldb_message_element *el; - int i, j; - int ret; - - switch (opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - DEBUG(9, ("[RFC2307 Schema]\n")); - - ret = sysdb_attrs_users_from_ldb_vals(group_attrs, SYSDB_MEMBER, - domain->name, - values, num_values); - if (ret) { - goto done; - } - - break; - - case SDAP_SCHEMA_RFC2307BIS: - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - DEBUG(9, ("[IPA or AD Schema]\n")); - - ret = sysdb_attrs_get_el(group_attrs, SYSDB_MEMBER, &el); - if (ret) { - goto done; - } - - /* Just allocate both big enough to contain all members for now */ - el->values = talloc_realloc(el, el->values, struct ldb_val, - el->num_values + num_values); - if (!el->values) { - ret = ENOMEM; - goto done; - } - - for (i = 0, j = el->num_values; i < num_values; i++) { - - /* sync search entry with this as origDN */ - ret = sdap_find_entry_by_origDN(el->values, ev, - handle, domain, - (char *)values[i].data, - (char **)&el->values[j].data); - if (ret != EOK) { - if (ret != ENOENT) { - goto done; - } - - DEBUG(7, (" member #%d (%s): not found!\n", - i, (char *)values[i].data)); - } else { - DEBUG(7, (" member #%d (%s): [%s]\n", - i, (char *)values[i].data, - (char *)el->values[j].data)); - - el->values[j].length = strlen((char *)el->values[j].data); - j++; - } - } - el->num_values = j; - - break; - - default: - DEBUG(0, ("FATAL ERROR: Unhandled schema type! (%d)\n", - opts->schema_type)); - ret = EFAULT; - goto done; - } - - ret = EOK; - -done: - return ret; -} - -/* ==Save-Group-Entry===================================================== */ - -struct sdap_save_group_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sdap_options *opts; - - struct sss_domain_info *dom; - - const char *name; - char *timestamp; -}; - -static void sdap_save_group_done(struct tevent_req *subreq); - - /* FIXME: support non legacy */ - /* FIXME: support storing additional attributes */ - -static struct tevent_req *sdap_save_group_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs, - bool store_members) -{ - struct tevent_req *req, *subreq; - struct sdap_save_group_state *state; - struct ldb_message_element *el; - struct sysdb_attrs *group_attrs; - long int l; - gid_t gid; - int ret; - - req = tevent_req_create(memctx, &state, struct sdap_save_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->dom = dom; - state->opts = opts; - state->timestamp = NULL; - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_NAME].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) { - ret = EINVAL; - goto fail; - } - state->name = (const char *)el->values[0].data; - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_GID].sys_name, &el); - if (ret) goto fail; - if (el->num_values == 0) { - DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", - state->name, dom->name)); - ret = EINVAL; - goto fail; - } - errno = 0; - l = strtol((const char *)el->values[0].data, NULL, 0); - if (errno) { - ret = EINVAL; - goto fail; - } - gid = l; - - /* check that the gid is valid for this domain */ - if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { - DEBUG(2, ("Group [%s] filtered out! (id out of range)\n", - state->name)); - ret = EINVAL; - goto fail; - } - - group_attrs = sysdb_new_attrs(state); - if (!group_attrs) { - ret = ENOMEM; - goto fail; - } - - ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("Original DN is not available for [%s].\n", state->name)); - } else { - DEBUG(7, ("Adding original DN [%s] to attributes of [%s].\n", - el->values[0].data, state->name)); - ret = sysdb_attrs_add_string(group_attrs, SYSDB_ORIG_DN, - (const char *)el->values[0].data); - if (ret) { - goto fail; - } - } - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_MODSTAMP].sys_name, &el); - if (ret) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("Original mod-Timestamp is not available for [%s].\n", - state->name)); - } else { - ret = sysdb_attrs_add_string(group_attrs, - opts->group_map[SDAP_AT_GROUP_MODSTAMP].sys_name, - (const char*)el->values[0].data); - if (ret) { - goto fail; - } - state->timestamp = talloc_strdup(state, - (const char*)el->values[0].data); - if (!state->timestamp) { - ret = ENOMEM; - goto fail; - } - } - - if (store_members) { - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); - if (ret != EOK) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("No members for group [%s]\n", state->name)); - - } else { - DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - - ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, - el->values, el->num_values); - if (ret) { - goto fail; - } - } - } - - DEBUG(6, ("Storing info for group %s\n", state->name)); - - subreq = sysdb_store_group_send(state, state->ev, - state->handle, state->dom, - state->name, gid, - group_attrs, - dp_opt_get_int(opts->basic, - SDAP_ENTRY_CACHE_TIMEOUT)); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_save_group_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_save_group_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_save_group_state *state = tevent_req_data(req, - struct sdap_save_group_state); - int ret; - - ret = sysdb_store_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to save group %s [%d]\n", state->name, ret)); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_save_group_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_save_group_state *state = tevent_req_data(req, - struct sdap_save_group_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if ( timestamp ) { - *timestamp = talloc_steal(mem_ctx, state->timestamp); - } - - return EOK; -} - - -/* ==Save-Group-Memebrs=================================================== */ - -struct sdap_save_grpmem_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sdap_options *opts; - - struct sss_domain_info *dom; - - const char *name; -}; - -static void sdap_save_grpmem_done(struct tevent_req *subreq); - - /* FIXME: support non legacy */ - /* FIXME: support storing additional attributes */ - -static struct tevent_req *sdap_save_grpmem_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sdap_options *opts, - struct sss_domain_info *dom, - struct sysdb_attrs *attrs) -{ - struct tevent_req *req, *subreq; - struct sdap_save_grpmem_state *state; - struct ldb_message_element *el; - struct sysdb_attrs *group_attrs = NULL; - int ret; - - req = tevent_req_create(memctx, &state, struct sdap_save_grpmem_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->dom = dom; - state->opts = opts; - - ret = sysdb_attrs_get_string(attrs, - opts->group_map[SDAP_AT_GROUP_NAME].sys_name, - &state->name); - if (ret != EOK) { - goto fail; - } - - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el); - if (ret != EOK) { - goto fail; - } - if (el->num_values == 0) { - DEBUG(7, ("No members for group [%s]\n", state->name)); - - } else { - DEBUG(7, ("Adding member users to group [%s]\n", state->name)); - - group_attrs = sysdb_new_attrs(state); - if (!group_attrs) { - ret = ENOMEM; - goto fail; - } - - ret = sdap_fill_memberships(group_attrs, ev, handle, opts, dom, - el->values, el->num_values); - if (ret) { - goto fail; - } - } - - DEBUG(6, ("Storing members for group %s\n", state->name)); - - subreq = sysdb_store_group_send(state, state->ev, - state->handle, state->dom, - state->name, 0, - group_attrs, - dp_opt_get_int(opts->basic, - SDAP_ENTRY_CACHE_TIMEOUT)); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_save_grpmem_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_save_grpmem_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_save_grpmem_state *state = tevent_req_data(req, - struct sdap_save_grpmem_state); - int ret; - - ret = sysdb_store_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to save group members for %s [%d]\n", - state->name, ret)); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_save_grpmem_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* ==Generic-Function-to-save-multiple-groups============================= */ - -struct sdap_save_groups_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - - struct sysdb_attrs **groups; - int count; - int cur; - bool twopass; - - struct sysdb_handle *handle; - - char *higher_timestamp; -}; - -static void sdap_save_groups_trans(struct tevent_req *subreq); -static void sdap_save_groups_save(struct tevent_req *req); -static void sdap_save_groups_loop(struct tevent_req *subreq); -static void sdap_save_groups_mem_save(struct tevent_req *req); -static void sdap_save_groups_mem_loop(struct tevent_req *subreq); -struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sysdb_attrs **groups, - int num_groups) -{ - struct tevent_req *req, *subreq; - struct sdap_save_groups_state *state; - - req = tevent_req_create(memctx, &state, struct sdap_save_groups_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; - state->groups = groups; - state->count = num_groups; - state->cur = 0; - state->handle = NULL; - state->higher_timestamp = NULL; - - switch (opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - state->twopass = false; - break; - - case SDAP_SCHEMA_RFC2307BIS: - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - state->twopass = true; - break; - - default: - tevent_req_error(req, EINVAL); - tevent_req_post(req, ev); - return req; - } - - subreq = sysdb_transaction_send(state, state->ev, state->sysdb); - if (!subreq) { - tevent_req_error(req, ENOMEM); - tevent_req_post(req, ev); - return req; - } - tevent_req_set_callback(subreq, sdap_save_groups_trans, req); - - return req; -} - -static void sdap_save_groups_trans(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_groups_state *state; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_groups_state); - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - sdap_save_groups_save(req); -} - -static void sdap_save_groups_save(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_save_groups_state *state; - - state = tevent_req_data(req, struct sdap_save_groups_state); - - /* if 2 pass savemembers = false */ - subreq = sdap_save_group_send(state, state->ev, state->handle, - state->opts, state->dom, - state->groups[state->cur], - (!state->twopass)); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_save_groups_loop, req); -} - -static void sdap_save_groups_loop(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_groups_state *state; - char *timestamp = NULL; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_groups_state); - - ret = sdap_save_group_recv(subreq, state, ×tamp); - talloc_zfree(subreq); - - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - if (ret) { - DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur)); - } else { - DEBUG(9, ("Group %d processed!\n", state->cur)); - } - - if (timestamp) { - if (state->higher_timestamp) { - if (strcmp(timestamp, state->higher_timestamp) > 0) { - talloc_zfree(state->higher_timestamp); - state->higher_timestamp = timestamp; - } else { - talloc_zfree(timestamp); - } - } else { - state->higher_timestamp = timestamp; - } - } - - state->cur++; - if (state->cur < state->count) { - - sdap_save_groups_save(req); - - } else if (state->twopass) { - - state->cur = 0; - sdap_save_groups_mem_save(req); - - } else { - - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - } -} - -static void sdap_save_groups_mem_save(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_save_groups_state *state; - - state = tevent_req_data(req, struct sdap_save_groups_state); - - subreq = sdap_save_grpmem_send(state, state->ev, state->handle, - state->opts, state->dom, - state->groups[state->cur]); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_save_groups_mem_loop, req); -} - -static void sdap_save_groups_mem_loop(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_save_groups_state *state; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_save_groups_state); - - ret = sdap_save_grpmem_recv(subreq); - talloc_zfree(subreq); - - /* Do not fail completely on errors. - * Just report the failure to save and go on */ - if (ret) { - DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur)); - } - - state->cur++; - if (state->cur < state->count) { - - sdap_save_groups_mem_save(req); - - } else { - - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - /* sysdb_transaction_complete will call tevent_req_done(req) */ - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - } -} - -static int sdap_save_groups_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_save_groups_state *state = tevent_req_data(req, - struct sdap_save_groups_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); - } - - return EOK; -} - - -/* ==Search-Groups-with-filter============================================ */ - -struct sdap_get_groups_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - struct sss_domain_info *dom; - struct sysdb_ctx *sysdb; - const char **attrs; - const char *filter; - - char *higher_timestamp; - struct sysdb_attrs **groups; - size_t count; -}; - -static void sdap_get_groups_process(struct tevent_req *subreq); -static void sdap_get_groups_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char **attrs, - const char *filter) -{ - struct tevent_req *req, *subreq; - struct sdap_get_groups_state *state; - - req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->dom = dom; - state->sh = sh; - state->sysdb = sysdb; - state->filter = filter; - state->attrs = attrs; - state->higher_timestamp = NULL; - state->groups = NULL; - state->count = 0; - - subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - LDAP_SCOPE_SUBTREE, - state->filter, state->attrs, - state->opts->group_map, SDAP_OPTS_GROUP); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_get_groups_process, req); - - return req; -} - -static void sdap_get_groups_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_groups_state *state = tevent_req_data(req, - struct sdap_get_groups_state); - int ret; - - ret = sdap_get_generic_recv(subreq, state, - &state->count, &state->groups); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - DEBUG(6, ("Search for groups, returned %d results.\n", state->count)); - - if (state->count == 0) { - tevent_req_error(req, ENOENT); - return; - } - - subreq = sdap_save_groups_send(state, state->ev, state->dom, - state->sysdb, state->opts, - state->groups, state->count); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_groups_done, req); -} - -static void sdap_get_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_groups_state *state = tevent_req_data(req, - struct sdap_get_groups_state); - int ret; - - DEBUG(9, ("Saving %d Groups - Done\n", state->count)); - - ret = sdap_save_groups_recv(subreq, state, &state->higher_timestamp); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Failed to store groups.\n")); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sdap_get_groups_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp) -{ - struct sdap_get_groups_state *state = tevent_req_data(req, - struct sdap_get_groups_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (timestamp) { - *timestamp = talloc_steal(mem_ctx, state->higher_timestamp); - } - - return EOK; -} - - -/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */ - -struct sdap_initgr_rfc2307_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - struct sdap_handle *sh; - - struct sdap_op *op; -}; - -static void sdap_initgr_rfc2307_process(struct tevent_req *subreq); -static void sdap_initgr_rfc2307_done(struct tevent_req *subreq); -struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, - struct sdap_handle *sh, - const char *base_dn, - const char *name, - const char **grp_attrs) -{ - struct tevent_req *req, *subreq; - struct sdap_initgr_rfc2307_state *state; - const char *filter; - - req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; - state->sh = sh; - state->op = NULL; - - filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", - opts->group_map[SDAP_AT_GROUP_MEMBER].name, - name, opts->group_map[SDAP_OC_GROUP].name); - if (!filter) { - talloc_zfree(req); - return NULL; - } - - subreq = sdap_get_generic_send(state, state->ev, state->opts, - state->sh, base_dn, LDAP_SCOPE_SUBTREE, - filter, grp_attrs, - state->opts->group_map, SDAP_OPTS_GROUP); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_initgr_rfc2307_process, req); - - return req; -} - -static void sdap_initgr_rfc2307_process(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_initgr_rfc2307_state *state; - struct sysdb_attrs **groups; - size_t count; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_initgr_rfc2307_state); - - ret = sdap_get_generic_recv(subreq, state, &count, &groups); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (count == 0) { - tevent_req_done(req); - return; - } - - subreq = sdap_save_groups_send(state, state->ev, state->dom, - state->sysdb, state->opts, - groups, count); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_initgr_rfc2307_done, req); -} - -static void sdap_initgr_rfc2307_done(struct tevent_req *subreq) -{ - struct tevent_req *req; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - - ret = sdap_save_groups_recv(subreq, NULL, NULL); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_initgr_rfc2307_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* ==Initgr-call-(groups-a-user-is-member-of)-nested-groups=============== */ - -struct sdap_initgr_nested_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - struct sdap_handle *sh; - - const char **grp_attrs; - - char *filter; - char **group_dns; - int count; - int cur; - - struct sdap_op *op; - - struct sysdb_attrs **groups; - int groups_cur; -}; - -static void sdap_initgr_nested_search(struct tevent_req *subreq); -static void sdap_initgr_nested_store(struct tevent_req *req); -static void sdap_initgr_nested_done(struct tevent_req *subreq); -static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *dom, - struct sdap_handle *sh, - struct sysdb_attrs *user, - const char **grp_attrs) -{ - struct tevent_req *req, *subreq; - struct sdap_initgr_nested_state *state; - struct ldb_message_element *el; - int i, ret; - - req = tevent_req_create(memctx, &state, struct sdap_initgr_nested_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; - state->sh = sh; - state->grp_attrs = grp_attrs; - state->op = NULL; - - state->filter = talloc_asprintf(state, "(objectclass=%s)", - opts->group_map[SDAP_OC_GROUP].name); - if (!state->filter) { - talloc_zfree(req); - return NULL; - } - - /* TODO: test rootDSE for deref support and use it if available */ - /* TODO: or test rootDSE for ASQ support and use it if available */ - - ret = sysdb_attrs_get_el(user, SYSDB_MEMBEROF, &el); - if (ret || !el || el->num_values == 0) { - DEBUG(4, ("User entry lacks original memberof ?\n")); - /* user with no groups ? */ - tevent_req_error(req, ENOENT); - tevent_req_post(req, ev); - } - state->count = el->num_values; - - state->groups = talloc_zero_array(state, struct sysdb_attrs *, - state->count + 1);; - if (!state->groups) { - talloc_zfree(req); - return NULL; - } - state->groups_cur = 0; - - state->group_dns = talloc_array(state, char *, state->count + 1); - if (!state->group_dns) { - talloc_zfree(req); - return NULL; - } - for (i = 0; i < state->count; i++) { - state->group_dns[i] = talloc_strdup(state->group_dns, - (char *)el->values[i].data); - if (!state->group_dns[i]) { - talloc_zfree(req); - return NULL; - } - } - state->group_dns[i] = NULL; /* terminate */ - state->cur = 0; - - subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh, - state->group_dns[state->cur], - LDAP_SCOPE_BASE, - state->filter, state->grp_attrs, - state->opts->group_map, SDAP_OPTS_GROUP); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_initgr_nested_search, req); - - return req; -} - -static void sdap_initgr_nested_search(struct tevent_req *subreq) -{ - struct tevent_req *req; - struct sdap_initgr_nested_state *state; - struct sysdb_attrs **groups; - size_t count; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - state = tevent_req_data(req, struct sdap_initgr_nested_state); - - ret = sdap_get_generic_recv(subreq, state, &count, &groups); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (count == 1) { - state->groups[state->groups_cur] = groups[0]; - state->groups_cur++; - } else { - DEBUG(2, ("Search for group %s, returned %d results. Skipping\n", - state->group_dns[state->cur], count)); - } - - state->cur++; - if (state->cur < state->count) { - subreq = sdap_get_generic_send(state, state->ev, - state->opts, state->sh, - state->group_dns[state->cur], - LDAP_SCOPE_BASE, - state->filter, state->grp_attrs, - state->opts->group_map, - SDAP_OPTS_GROUP); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_initgr_nested_search, req); - } else { - sdap_initgr_nested_store(req); - } -} - -static void sdap_initgr_nested_store(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct sdap_initgr_nested_state *state; - - state = tevent_req_data(req, struct sdap_initgr_nested_state); - - subreq = sdap_save_groups_send(state, state->ev, state->dom, - state->sysdb, state->opts, - state->groups, state->groups_cur); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_initgr_nested_done, req); -} - -static void sdap_initgr_nested_done(struct tevent_req *subreq) -{ - struct tevent_req *req; - int ret; - - req = tevent_req_callback_data(subreq, struct tevent_req); - - ret = sdap_save_groups_recv(subreq, NULL, NULL); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static int sdap_initgr_nested_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* ==Initgr-call-(groups-a-user-is-member-of)============================= */ - -struct sdap_get_initgr_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sdap_options *opts; - struct sss_domain_info *dom; - struct sdap_handle *sh; - const char *name; - const char **grp_attrs; - - struct sysdb_attrs *orig_user; - - struct sysdb_handle *handle; -}; - -static void sdap_get_initgr_user(struct tevent_req *subreq); -static void sdap_get_initgr_store(struct tevent_req *subreq); -static void sdap_get_initgr_commit(struct tevent_req *subreq); -static void sdap_get_initgr_process(struct tevent_req *subreq); -static void sdap_get_initgr_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, - struct sysdb_ctx *sysdb, - struct sdap_options *opts, - struct sdap_handle *sh, - const char *name, - const char **grp_attrs) -{ - struct tevent_req *req, *subreq; - struct sdap_get_initgr_state *state; - const char *base_dn; - char *filter; - const char **attrs; - int ret; - - DEBUG(9, ("Retrieving info for initgroups call\n")); - - req = tevent_req_create(memctx, &state, struct sdap_get_initgr_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->sysdb = sysdb; - state->dom = dom; - state->sh = sh; - state->name = name; - state->grp_attrs = grp_attrs; - state->orig_user = NULL; - - filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", - state->opts->user_map[SDAP_AT_USER_NAME].name, - state->name, - state->opts->user_map[SDAP_OC_USER].name); - if (!filter) { - talloc_zfree(req); - return NULL; - } - - base_dn = dp_opt_get_string(state->opts->basic, - SDAP_USER_SEARCH_BASE); - if (!base_dn) { - talloc_zfree(req); - return NULL; - } - - ret = build_attrs_from_map(state, state->opts->user_map, - SDAP_OPTS_USER, &attrs); - if (ret) { - talloc_zfree(req); - return NULL; - } - - subreq = sdap_get_generic_send(state, state->ev, - state->opts, state->sh, - base_dn, LDAP_SCOPE_SUBTREE, - filter, attrs, - state->opts->user_map, SDAP_OPTS_USER); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_get_initgr_user, req); - - return req; -} - -static void sdap_get_initgr_user(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - struct sysdb_attrs **usr_attrs; - size_t count; - int ret; - - DEBUG(9, ("Receiving info for the user\n")); - - ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (count != 1) { - DEBUG(2, ("Expected one user entry and got %d\n", count)); - tevent_req_error(req, ENOENT); - return; - } - - state->orig_user = usr_attrs[0]; - - subreq = sysdb_transaction_send(state, state->ev, state->sysdb); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_store, req); -} - -static void sdap_get_initgr_store(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - - DEBUG(9, ("Storing the user\n")); - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - subreq = sdap_save_user_send(state, state->ev, state->handle, - state->opts, state->dom, - state->orig_user, true); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_commit, req); -} - -static void sdap_get_initgr_commit(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - - DEBUG(9, ("Commit change\n")); - - ret = sdap_save_user_recv(subreq, NULL, NULL); - 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, sdap_get_initgr_process, req); -} - -static void sdap_get_initgr_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - - DEBUG(9, ("Process user's groups\n")); - - ret = sysdb_transaction_commit_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - switch (state->opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts, - state->sysdb, state->dom, state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_GROUP_SEARCH_BASE), - state->name, state->grp_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - break; - - case SDAP_SCHEMA_RFC2307BIS: - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - /* TODO: AD uses a different member/memberof schema - * We need an AD specific call that is able to unroll - * nested groups by doing extensive recursive searches */ - - subreq = sdap_initgr_nested_send(state, state->ev, state->opts, - state->sysdb, state->dom, state->sh, - state->orig_user, state->grp_attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_initgr_done, req); - return; - - default: - tevent_req_error(req, EINVAL); - return; - } -} - -static void sdap_get_initgr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_initgr_state *state = tevent_req_data(req, - struct sdap_get_initgr_state); - int ret; - - DEBUG(9, ("Initgroups done\n")); - - switch (state->opts->schema_type) { - case SDAP_SCHEMA_RFC2307: - - ret = sdap_initgr_rfc2307_recv(subreq); - break; - - case SDAP_SCHEMA_RFC2307BIS: - case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - - ret = sdap_initgr_nested_recv(subreq); - break; - - default: - - ret = EINVAL; - break; - } - - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sdap_get_initgr_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - diff --git a/server/providers/ldap/sdap_async_connection.c b/server/providers/ldap/sdap_async_connection.c deleted file mode 100644 index 18e47d3b..00000000 --- a/server/providers/ldap/sdap_async_connection.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* - SSSD - - Async LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@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 <sasl/sasl.h> -#include "util/util.h" -#include "util/sss_krb5.h" -#include "providers/ldap/sdap_async_private.h" - -#define LDAP_X_SSSD_PASSWORD_EXPIRED 0x555D - -/* ==Connect-to-LDAP-Server=============================================== */ - -struct sdap_connect_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - - struct sdap_op *op; - - struct sdap_msg *reply; - int result; -}; - -static void sdap_connect_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); - -struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - const char *uri, - bool use_start_tls) -{ - struct tevent_req *req; - struct sdap_connect_state *state; - struct timeval tv; - int ver; - int lret; - int ret = EOK; - int msgid; - bool ldap_referrals; - - req = tevent_req_create(memctx, &state, struct sdap_connect_state); - if (!req) return NULL; - - state->reply = talloc(state, struct sdap_msg); - if (!state->reply) { - talloc_zfree(req); - return NULL; - } - - state->ev = ev; - state->opts = opts; - state->sh = sdap_handle_create(state); - if (!state->sh) { - talloc_zfree(req); - return NULL; - } - /* Initialize LDAP handler */ - lret = ldap_initialize(&state->sh->ldap, uri); - if (lret != LDAP_SUCCESS) { - DEBUG(1, ("ldap_initialize failed: %s\n", ldap_err2string(lret))); - goto fail; - } - - /* Force ldap version to 3 */ - ver = LDAP_VERSION3; - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_PROTOCOL_VERSION, &ver); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set ldap version to 3\n")); - goto fail; - } - - /* Set Network Timeout */ - tv.tv_sec = dp_opt_get_int(opts->basic, SDAP_NETWORK_TIMEOUT); - tv.tv_usec = 0; - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_NETWORK_TIMEOUT, &tv); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set network timeout to %d\n", - dp_opt_get_int(opts->basic, SDAP_NETWORK_TIMEOUT))); - goto fail; - } - - /* Set Default Timeout */ - tv.tv_sec = dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT); - tv.tv_usec = 0; - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_TIMEOUT, &tv); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set default timeout to %d\n", - dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT))); - goto fail; - } - - /* Set Referral chasing */ - ldap_referrals = dp_opt_get_bool(opts->basic, SDAP_REFERRALS); - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_REFERRALS, - (ldap_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF)); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set referral chasing to %s\n", - (ldap_referrals ? "LDAP_OPT_ON" : "LDAP_OPT_OFF"))); - goto fail; - } - -#ifdef HAVE_LDAP_CONNCB - struct ldap_cb_data *cb_data; - - /* add connection callback */ - state->sh->conncb = talloc_zero(state->sh, struct ldap_conncb); - if (state->sh->conncb == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto fail; - } - - cb_data = talloc_zero(state->sh->conncb, struct ldap_cb_data); - if (cb_data == NULL) { - DEBUG(1, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto fail; - } - cb_data->sh = state->sh; - cb_data->ev = state->ev; - - state->sh->conncb->lc_add = sdap_ldap_connect_callback_add; - state->sh->conncb->lc_del = sdap_ldap_connect_callback_del; - state->sh->conncb->lc_arg = cb_data; - - lret = ldap_set_option(state->sh->ldap, LDAP_OPT_CONNECT_CB, - state->sh->conncb); - if (lret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("Failed to set connection callback\n")); - goto fail; - } -#endif - - /* if we do not use start_tls the connection is not really connected yet - * just fake an async procedure and leave connection to the bind call */ - if (!use_start_tls) { - tevent_req_post(req, ev); - return req; - } - - DEBUG(4, ("Executing START TLS\n")); - - lret = ldap_start_tls(state->sh->ldap, NULL, NULL, &msgid); - if (lret != LDAP_SUCCESS) { - DEBUG(3, ("ldap_start_tls failed: [%s]", ldap_err2string(ret))); - goto fail; - } - - state->sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(state->sh, state->ev); - if (ret) goto fail; -#endif - - /* FIXME: get timeouts from configuration, for now 5 secs. */ - ret = sdap_op_add(state, ev, state->sh, msgid, - sdap_connect_done, req, 5, &state->op); - if (ret) { - DEBUG(1, ("Failed to set up operation!\n")); - goto fail; - } - - return req; - -fail: - if (ret) { - tevent_req_error(req, ret); - } else { - if (lret == LDAP_SERVER_DOWN) { - tevent_req_error(req, ETIMEDOUT); - } else { - tevent_req_error(req, EIO); - } - } - tevent_req_post(req, ev); - return req; -} - -static void sdap_connect_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_connect_state *state = tevent_req_data(req, - struct sdap_connect_state); - char *errmsg; - int ret; - - if (error) { - tevent_req_error(req, error); - return; - } - - state->reply = talloc_steal(state, reply); - - ret = ldap_parse_result(state->sh->ldap, state->reply->msg, - &state->result, NULL, &errmsg, NULL, NULL, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - tevent_req_error(req, EIO); - return; - } - - DEBUG(3, ("START TLS result: %s(%d), %s\n", - ldap_err2string(state->result), state->result, errmsg)); - - if (ldap_tls_inplace(state->sh->ldap)) { - DEBUG(9, ("SSL/TLS handler already in place.\n")); - tevent_req_done(req); - return; - } - -/* FIXME: take care that ldap_install_tls might block */ - ret = ldap_install_tls(state->sh->ldap); - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("ldap_install_tls failed: [%d][%s]\n", ret, - ldap_err2string(ret))); - state->result = ret; - tevent_req_error(req, EIO); - return; - } - - tevent_req_done(req); -} - -int sdap_connect_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **sh) -{ - struct sdap_connect_state *state = tevent_req_data(req, - struct sdap_connect_state); - enum tevent_req_state tstate; - uint64_t err = EIO; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* if tstate shows in progress, it is because - * we did not ask to perform tls, just pretend all is fine */ - if (tstate != TEVENT_REQ_IN_PROGRESS) { - return err; - } - } - - *sh = talloc_steal(memctx, state->sh); - if (!*sh) { - return ENOMEM; - } - return EOK; -} - -/* ==Simple-Bind========================================================== */ - -struct simple_bind_state { - struct tevent_context *ev; - struct sdap_handle *sh; - const char *user_dn; - struct berval *pw; - - struct sdap_op *op; - - struct sdap_msg *reply; - int result; -}; - -static void simple_bind_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt); - -static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - const char *user_dn, - struct berval *pw) -{ - struct tevent_req *req; - struct simple_bind_state *state; - int ret = EOK; - int msgid; - int ldap_err; - LDAPControl *request_controls[2]; - - req = tevent_req_create(memctx, &state, struct simple_bind_state); - if (!req) return NULL; - - state->reply = talloc(state, struct sdap_msg); - if (!state->reply) { - talloc_zfree(req); - return NULL; - } - - state->ev = ev; - state->sh = sh; - state->user_dn = user_dn; - state->pw = pw; - - ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST, - 0, NULL, 0, &request_controls[0]); - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("sss_ldap_control_create failed.\n")); - goto fail; - } - request_controls[1] = NULL; - - DEBUG(4, ("Executing simple bind as: %s\n", state->user_dn)); - - ret = ldap_sasl_bind(state->sh->ldap, state->user_dn, LDAP_SASL_SIMPLE, - state->pw, request_controls, NULL, &msgid); - ldap_control_free(request_controls[0]); - if (ret == -1 || msgid == -1) { - ret = ldap_get_option(state->sh->ldap, - LDAP_OPT_RESULT_CODE, &ldap_err); - if (ret != LDAP_OPT_SUCCESS) { - DEBUG(1, ("ldap_bind failed (couldn't get ldap error)\n")); - ret = LDAP_LOCAL_ERROR; - } else { - DEBUG(1, ("ldap_bind failed (%d)[%s]\n", - ldap_err, ldap_err2string(ldap_err))); - ret = ldap_err; - } - goto fail; - } - DEBUG(8, ("ldap simple bind sent, msgid = %d\n", msgid)); - - if (!sh->connected) { - sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(sh, ev); - if (ret) goto fail; -#endif - } - - /* FIXME: get timeouts from configuration, for now 5 secs. */ - ret = sdap_op_add(state, ev, sh, msgid, - simple_bind_done, req, 5, &state->op); - if (ret) { - DEBUG(1, ("Failed to set up operation!\n")); - goto fail; - } - - return req; - -fail: - if (ret == LDAP_SERVER_DOWN) { - tevent_req_error(req, ETIMEDOUT); - } else { - tevent_req_error(req, EIO); - } - tevent_req_post(req, ev); - return req; -} - -static void simple_bind_done(struct sdap_op *op, - struct sdap_msg *reply, - int error, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct simple_bind_state *state = tevent_req_data(req, - struct simple_bind_state); - char *errmsg; - int ret; - LDAPControl **response_controls; - int c; - ber_int_t pp_grace; - ber_int_t pp_expire; - LDAPPasswordPolicyError pp_error; - - if (error) { - tevent_req_error(req, error); - return; - } - - state->reply = talloc_steal(state, reply); - - ret = ldap_parse_result(state->sh->ldap, state->reply->msg, - &state->result, NULL, &errmsg, NULL, - &response_controls, 0); - if (ret != LDAP_SUCCESS) { - DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid)); - ret = EIO; - goto done; - } - - if (response_controls == NULL) { - DEBUG(5, ("Server returned no controls.\n")); - } else { - for (c = 0; response_controls[c] != NULL; c++) { - DEBUG(9, ("Server returned control [%s].\n", - response_controls[c]->ldctl_oid)); - if (strcmp(response_controls[c]->ldctl_oid, - LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { - ret = ldap_parse_passwordpolicy_control(state->sh->ldap, - response_controls[c], - &pp_expire, &pp_grace, - &pp_error); - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("ldap_parse_passwordpolicy_control failed.\n")); - ret = EIO; - goto done; - } - - DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] " - "error [%s].\n", pp_expire, pp_grace, - ldap_passwordpolicy_err2txt(pp_error))); - - if (state->result == LDAP_SUCCESS && - (pp_error == PP_changeAfterReset || pp_grace > 0)) { - DEBUG(4, ("User must set a new password.\n")); - state->result = LDAP_X_SSSD_PASSWORD_EXPIRED; - } - } - } - } - - DEBUG(3, ("Bind result: %s(%d), %s\n", - ldap_err2string(state->result), state->result, errmsg)); - - ret = LDAP_SUCCESS; -done: - ldap_controls_free(response_controls); - - if (ret == LDAP_SUCCESS) { - tevent_req_done(req); - } else { - tevent_req_error(req, ret); - } -} - -static int simple_bind_recv(struct tevent_req *req, int *ldaperr) -{ - struct simple_bind_state *state = tevent_req_data(req, - struct simple_bind_state); - - *ldaperr = LDAP_OTHER; - TEVENT_REQ_RETURN_ON_ERROR(req); - - *ldaperr = state->result; - return EOK; -} - -/* ==SASL-Bind============================================================ */ - -struct sasl_bind_state { - struct tevent_context *ev; - struct sdap_handle *sh; - - const char *sasl_mech; - const char *sasl_user; - struct berval *sasl_cred; - - int result; -}; - -static int sdap_sasl_interact(LDAP *ld, unsigned flags, - void *defaults, void *interact); - -static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - const char *sasl_mech, - const char *sasl_user, - struct berval *sasl_cred) -{ - struct tevent_req *req; - struct sasl_bind_state *state; - int ret = EOK; - - req = tevent_req_create(memctx, &state, struct sasl_bind_state); - if (!req) return NULL; - - state->ev = ev; - state->sh = sh; - state->sasl_mech = sasl_mech; - state->sasl_user = sasl_user; - state->sasl_cred = sasl_cred; - - DEBUG(4, ("Executing sasl bind mech: %s, user: %s\n", - sasl_mech, sasl_user)); - - /* FIXME: Warning, this is a sync call! - * No async variant exist in openldap libraries yet */ - - ret = ldap_sasl_interactive_bind_s(state->sh->ldap, NULL, - sasl_mech, NULL, NULL, - LDAP_SASL_QUIET, - (*sdap_sasl_interact), state); - state->result = ret; - if (ret != LDAP_SUCCESS) { - DEBUG(1, ("ldap_sasl_bind failed (%d)[%s]\n", - ret, ldap_err2string(ret))); - goto fail; - } - - if (!sh->connected) { - sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - ret = sdap_install_ldap_callbacks(sh, ev); - if (ret) goto fail; -#endif - } - - tevent_req_post(req, ev); - return req; - -fail: - if (ret == LDAP_SERVER_DOWN) { - tevent_req_error(req, ETIMEDOUT); - } else { - tevent_req_error(req, EIO); - } - tevent_req_post(req, ev); - return req; -} - -static int sdap_sasl_interact(LDAP *ld, unsigned flags, - void *defaults, void *interact) -{ - struct sasl_bind_state *state = talloc_get_type(defaults, - struct sasl_bind_state); - sasl_interact_t *in = (sasl_interact_t *)interact; - - if (!ld) return LDAP_PARAM_ERROR; - - while (in->id != SASL_CB_LIST_END) { - - switch (in->id) { - case SASL_CB_GETREALM: - case SASL_CB_AUTHNAME: - case SASL_CB_PASS: - if (in->defresult) { - in->result = in->defresult; - } else { - in->result = ""; - } - in->len = strlen(in->result); - break; - case SASL_CB_USER: - if (state->sasl_user) { - in->result = state->sasl_user; - } else if (in->defresult) { - in->result = in->defresult; - } else { - in->result = ""; - } - in->len = strlen(in->result); - break; - case SASL_CB_NOECHOPROMPT: - case SASL_CB_ECHOPROMPT: - goto fail; - } - - in++; - } - - return LDAP_SUCCESS; - -fail: - return LDAP_UNAVAILABLE; -} - -static int sasl_bind_recv(struct tevent_req *req, int *ldaperr) -{ - struct sasl_bind_state *state = tevent_req_data(req, - struct sasl_bind_state); - enum tevent_req_state tstate; - uint64_t err = EIO; - - if (tevent_req_is_error(req, &tstate, &err)) { - if (tstate != TEVENT_REQ_IN_PROGRESS) { - *ldaperr = LDAP_OTHER; - return err; - } - } - - *ldaperr = state->result; - return EOK; -} - -/* ==Perform-Kinit-given-keytab-and-principal============================= */ - -struct sdap_kinit_state { - int result; -}; - -static void sdap_kinit_done(struct tevent_req *subreq); - -struct tevent_req *sdap_kinit_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - int timeout, - const char *keytab, - const char *principal, - const char *realm) -{ - struct tevent_req *req; - struct tevent_req *subreq; - struct sdap_kinit_state *state; - int ret; - - DEBUG(6, ("Attempting kinit (%s, %s, %s)\n", keytab, principal, realm)); - - req = tevent_req_create(memctx, &state, struct sdap_kinit_state); - if (!req) return NULL; - - state->result = SDAP_AUTH_FAILED; - - if (keytab) { - ret = setenv("KRB5_KTNAME", keytab, 1); - if (ret == -1) { - DEBUG(2, ("Failed to set KRB5_KTNAME to %s\n", keytab)); - return NULL; - } - } - - subreq = sdap_get_tgt_send(state, ev, realm, principal, keytab, timeout); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_kinit_done, req); - - return req; -} - -static void sdap_kinit_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_kinit_state *state = tevent_req_data(req, - struct sdap_kinit_state); - - int ret; - int result; - char *ccname = NULL; - - ret = sdap_get_tgt_recv(subreq, state, &result, &ccname); - talloc_zfree(subreq); - if (ret != EOK) { - state->result = SDAP_AUTH_FAILED; - DEBUG(1, ("child failed (%d [%s])\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (result == EOK) { - ret = setenv("KRB5CCNAME", ccname, 1); - if (ret == -1) { - DEBUG(2, ("Unable to set env. variable KRB5CCNAME!\n")); - state->result = SDAP_AUTH_FAILED; - tevent_req_error(req, EFAULT); - } - - state->result = SDAP_AUTH_SUCCESS; - tevent_req_done(req); - return; - } - - DEBUG(4, ("Could not get TGT: %d [%s]\n", result, strerror(result))); - state->result = SDAP_AUTH_FAILED; - tevent_req_error(req, EIO); -} - -int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result) -{ - struct sdap_kinit_state *state = tevent_req_data(req, - struct sdap_kinit_state); - enum tevent_req_state tstate; - uint64_t err = EIO; - - if (tevent_req_is_error(req, &tstate, &err)) { - if (tstate != TEVENT_REQ_IN_PROGRESS) { - *result = SDAP_ERROR; - return err; - } - } - - *result = state->result; - return EOK; -} - - -/* ==Authenticaticate-User-by-DN========================================== */ - -struct sdap_auth_state { - const char *user_dn; - struct berval pw; - - int result; - bool is_sasl; -}; - -static void sdap_auth_done(struct tevent_req *subreq); - -/* TODO: handle sasl_cred */ -struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_handle *sh, - const char *sasl_mech, - const char *sasl_user, - const char *user_dn, - const char *authtok_type, - struct dp_opt_blob authtok) -{ - struct tevent_req *req, *subreq; - struct sdap_auth_state *state; - - if (authtok_type != NULL && strcasecmp(authtok_type,"password") != 0) { - DEBUG(1,("Authentication token type [%s] is not supported")); - return NULL; - } - - req = tevent_req_create(memctx, &state, struct sdap_auth_state); - if (!req) return NULL; - - state->user_dn = user_dn; - state->pw.bv_val = (char *)authtok.data; - state->pw.bv_len = authtok.length; - - if (sasl_mech) { - state->is_sasl = true; - subreq = sasl_bind_send(state, ev, sh, sasl_mech, sasl_user, NULL); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return tevent_req_post(req, ev); - } - } else { - state->is_sasl = false; - subreq = simple_bind_send(state, ev, sh, user_dn, &state->pw); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return tevent_req_post(req, ev); - } - } - - tevent_req_set_callback(subreq, sdap_auth_done, req); - return req; -} - -static void sdap_auth_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_auth_state *state = tevent_req_data(req, - struct sdap_auth_state); - int ret; - - if (state->is_sasl) { - ret = sasl_bind_recv(subreq, &state->result); - } else { - ret = simple_bind_recv(subreq, &state->result); - } - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result) -{ - struct sdap_auth_state *state = tevent_req_data(req, - struct sdap_auth_state); - - *result = SDAP_ERROR; - TEVENT_REQ_RETURN_ON_ERROR(req); - - switch (state->result) { - case LDAP_SUCCESS: - *result = SDAP_AUTH_SUCCESS; - break; - case LDAP_INVALID_CREDENTIALS: - *result = SDAP_AUTH_FAILED; - break; - case LDAP_X_SSSD_PASSWORD_EXPIRED: - *result = SDAP_AUTH_PW_EXPIRED; - break; - default: - break; - } - - return EOK; -} - -/* ==Client connect============================================ */ - -struct sdap_cli_connect_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_service *service; - - bool use_rootdse; - struct sysdb_attrs *rootdse; - - struct sdap_handle *sh; - - struct fo_server *srv; -}; - -static void sdap_cli_resolve_done(struct tevent_req *subreq); -static void sdap_cli_connect_done(struct tevent_req *subreq); -static void sdap_cli_rootdse_step(struct tevent_req *req); -static void sdap_cli_rootdse_done(struct tevent_req *subreq); -static void sdap_cli_kinit_step(struct tevent_req *req); -static void sdap_cli_kinit_done(struct tevent_req *subreq); -static void sdap_cli_auth_step(struct tevent_req *req); -static void sdap_cli_auth_done(struct tevent_req *subreq); - -struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct be_ctx *be, - struct sdap_service *service, - struct sysdb_attrs **rootdse) -{ - struct tevent_req *req, *subreq; - struct sdap_cli_connect_state *state; - - req = tevent_req_create(memctx, &state, struct sdap_cli_connect_state); - if (!req) return NULL; - - state->ev = ev; - state->opts = opts; - state->service = service; - state->srv = NULL; - - if (rootdse) { - state->use_rootdse = true; - state->rootdse = *rootdse; - } else { - state->use_rootdse = false; - state->rootdse = NULL; - } - - /* NOTE: this call may cause service->uri to be refreshed - * with a new valid server. Do not use service->uri before */ - subreq = be_resolve_server_send(state, ev, be, service->name); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sdap_cli_resolve_done, req); - - return req; -} - -static void sdap_cli_resolve_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - int ret; - - ret = be_resolve_server_recv(subreq, &state->srv); - talloc_zfree(subreq); - if (ret) { - /* all servers have been tried and none - * was found good, go offline */ - tevent_req_error(req, EIO); - return; - } - - subreq = sdap_connect_send(state, state->ev, state->opts, - state->service->uri, - dp_opt_get_bool(state->opts->basic, - SDAP_ID_TLS)); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_cli_connect_done, req); -} - -static void sdap_cli_connect_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - const char *sasl_mech; - int ret; - - ret = sdap_connect_recv(subreq, state, &state->sh); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->use_rootdse && !state->rootdse) { - /* fetch the rootDSE this time */ - sdap_cli_rootdse_step(req); - return; - } - - sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH); - - if (sasl_mech && state->use_rootdse) { - /* check if server claims to support GSSAPI */ - if (!sdap_rootdse_sasl_mech_is_supported(state->rootdse, - sasl_mech)) { - tevent_req_error(req, ENOTSUP); - return; - } - } - - if (sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) { - if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) { - sdap_cli_kinit_step(req); - return; - } - } - - sdap_cli_auth_step(req); -} - -static void sdap_cli_rootdse_step(struct tevent_req *req) -{ - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - struct tevent_req *subreq; - - subreq = sdap_get_rootdse_send(state, state->ev, state->opts, state->sh); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_cli_rootdse_done, req); - - if (!state->sh->connected) { - /* this rootdse search is performed before we actually do a bind, - * so we need to set up the callbacks or we will never get notified - * of a reply */ - state->sh->connected = true; -#ifndef HAVE_LDAP_CONNCB - int ret; - - ret = sdap_install_ldap_callbacks(state->sh, state->ev); - if (ret) { - tevent_req_error(req, ret); - } -#endif - } -} - -static void sdap_cli_rootdse_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - const char *sasl_mech; - int ret; - - ret = sdap_get_rootdse_recv(subreq, state, &state->rootdse); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH); - - if (sasl_mech && state->use_rootdse) { - /* check if server claims to support GSSAPI */ - if (!sdap_rootdse_sasl_mech_is_supported(state->rootdse, - sasl_mech)) { - tevent_req_error(req, ENOTSUP); - return; - } - } - - if (sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) { - if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) { - sdap_cli_kinit_step(req); - return; - } - } - - sdap_cli_auth_step(req); -} - -static void sdap_cli_kinit_step(struct tevent_req *req) -{ - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - struct tevent_req *subreq; - - subreq = sdap_kinit_send(state, state->ev, - state->sh, - dp_opt_get_int(state->opts->basic, - SDAP_OPT_TIMEOUT), - dp_opt_get_string(state->opts->basic, - SDAP_KRB5_KEYTAB), - dp_opt_get_string(state->opts->basic, - SDAP_SASL_AUTHID), - dp_opt_get_string(state->opts->basic, - SDAP_KRB5_REALM)); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_cli_kinit_done, req); -} - -static void sdap_cli_kinit_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - enum sdap_result result; - int ret; - - ret = sdap_kinit_recv(subreq, &result); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - if (result != SDAP_AUTH_SUCCESS) { - tevent_req_error(req, EACCES); - return; - } - - sdap_cli_auth_step(req); -} - -static void sdap_cli_auth_step(struct tevent_req *req) -{ - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - struct tevent_req *subreq; - - subreq = sdap_auth_send(state, - state->ev, - state->sh, - dp_opt_get_string(state->opts->basic, - SDAP_SASL_MECH), - dp_opt_get_string(state->opts->basic, - SDAP_SASL_AUTHID), - dp_opt_get_string(state->opts->basic, - SDAP_DEFAULT_BIND_DN), - dp_opt_get_string(state->opts->basic, - SDAP_DEFAULT_AUTHTOK_TYPE), - dp_opt_get_blob(state->opts->basic, - SDAP_DEFAULT_AUTHTOK)); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_cli_auth_done, req); -} - -static void sdap_cli_auth_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - enum sdap_result result; - int ret; - - ret = sdap_auth_recv(subreq, &result); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - if (result != SDAP_AUTH_SUCCESS) { - tevent_req_error(req, EACCES); - return; - } - - tevent_req_done(req); -} - -int sdap_cli_connect_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sdap_handle **gsh, - struct sysdb_attrs **rootdse) -{ - struct sdap_cli_connect_state *state = tevent_req_data(req, - struct sdap_cli_connect_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* mark the server as bad if connection failed */ - if (state->srv) { - fo_set_port_status(state->srv, PORT_NOT_WORKING); - } - - if (tstate == TEVENT_REQ_USER_ERROR) { - return err; - } - return EIO; - } else if (state->srv) { - fo_set_port_status(state->srv, PORT_WORKING); - } - - if (gsh) { - *gsh = talloc_steal(memctx, state->sh); - if (!*gsh) { - return ENOMEM; - } - } else { - talloc_zfree(state->sh); - } - - if (rootdse) { - if (state->use_rootdse) { - *rootdse = talloc_steal(memctx, state->rootdse); - if (!*rootdse) { - return ENOMEM; - } - } else { - *rootdse = NULL; - } - } else { - talloc_zfree(rootdse); - } - - return EOK; -} - diff --git a/server/providers/ldap/sdap_async_private.h b/server/providers/ldap/sdap_async_private.h deleted file mode 100644 index 55f76ed7..00000000 --- a/server/providers/ldap/sdap_async_private.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - SSSD - - Async LDAP Helper routines - - Copyright (C) Simo Sorce <ssorce@redhat.com> - - 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/>. -*/ - -#ifndef _SDAP_ASYNC_PRIVATE_H_ -#define _SDAP_ASYNC_PRIVATE_H_ - -#include "config.h" -#include "providers/ldap/sdap_async.h" - -void make_realm_upper_case(const char *upn); -struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx); - -#ifdef HAVE_LDAP_CONNCB -int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv, - struct sockaddr *addr, struct ldap_conncb *ctx); -void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb, - struct ldap_conncb *ctx); -#else -int sdap_install_ldap_callbacks(struct sdap_handle *sh, - struct tevent_context *ev); -#endif - -int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev, - struct sdap_handle *sh, int msgid, - sdap_op_callback_t *callback, void *data, - int timeout, struct sdap_op **_op); - -struct tevent_req *sdap_get_rootdse_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, - struct sdap_handle *sh); -int sdap_get_rootdse_recv(struct tevent_req *req, - TALLOC_CTX *memctx, - struct sysdb_attrs **rootdse); - -/* from sdap_child_helpers.c */ - -struct tevent_req *sdap_get_tgt_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - int timeout); - -int sdap_get_tgt_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - int *result, - char **ccname); - -#endif /* _SDAP_ASYNC_PRIVATE_H_ */ diff --git a/server/providers/ldap/sdap_child_helpers.c b/server/providers/ldap/sdap_child_helpers.c deleted file mode 100644 index 0a95c8a0..00000000 --- a/server/providers/ldap/sdap_child_helpers.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - SSSD - - LDAP Backend Module -- child helpers - - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 <sys/types.h> -#include <sys/wait.h> -#include <pwd.h> -#include <unistd.h> -#include <fcntl.h> - -#include "util/util.h" -#include "providers/ldap/ldap_common.h" -#include "providers/child_common.h" - -#ifndef SSSD_LIBEXEC_PATH -#error "SSSD_LIBEXEC_PATH not defined" -#else -#define LDAP_CHILD SSSD_LIBEXEC_PATH"/ldap_child" -#endif - -#ifndef LDAP_CHILD_USER -#define LDAP_CHILD_USER "nobody" -#endif - -struct sdap_child { - /* child info */ - pid_t pid; - int read_from_child_fd; - int write_to_child_fd; -}; - -static void sdap_close_fd(int *fd) -{ - int ret; - - if (*fd == -1) { - DEBUG(6, ("fd already closed\n")); - return; - } - - ret = close(*fd); - if (ret) { - ret = errno; - DEBUG(2, ("Closing fd %d, return error %d (%s)\n", - *fd, ret, strerror(ret))); - } - - *fd = -1; -} - -static int sdap_child_destructor(void *ptr) -{ - struct sdap_child *child = talloc_get_type(ptr, struct sdap_child); - - child_cleanup(child->read_from_child_fd, child->write_to_child_fd); - - return 0; -} - -static errno_t sdap_fork_child(struct sdap_child *child) -{ - int pipefd_to_child[2]; - int pipefd_from_child[2]; - pid_t pid; - int ret; - errno_t err; - - ret = pipe(pipefd_from_child); - if (ret == -1) { - err = errno; - DEBUG(1, ("pipe failed [%d][%s].\n", err, strerror(err))); - return err; - } - ret = pipe(pipefd_to_child); - if (ret == -1) { - err = errno; - DEBUG(1, ("pipe failed [%d][%s].\n", err, strerror(err))); - return err; - } - - pid = fork(); - - if (pid == 0) { /* child */ - err = exec_child(child, - pipefd_to_child, pipefd_from_child, - LDAP_CHILD, ldap_child_debug_fd); - if (err != EOK) { - DEBUG(1, ("Could not exec LDAP child: [%d][%s].\n", - err, strerror(err))); - return err; - } - } else if (pid > 0) { /* parent */ - child->pid = pid; - child->read_from_child_fd = pipefd_from_child[0]; - close(pipefd_from_child[1]); - child->write_to_child_fd = pipefd_to_child[1]; - close(pipefd_to_child[0]); - fd_nonblocking(child->read_from_child_fd); - fd_nonblocking(child->write_to_child_fd); - - } else { /* error */ - err = errno; - DEBUG(1, ("fork failed [%d][%s].\n", err, strerror(err))); - return err; - } - - return EOK; -} - -static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - struct io_buffer **io_buf) -{ - struct io_buffer *buf; - size_t rp; - - buf = talloc(mem_ctx, struct io_buffer); - if (buf == NULL) { - DEBUG(1, ("talloc failed.\n")); - return ENOMEM; - } - - buf->size = 3 * sizeof(uint32_t); - if (realm_str) { - buf->size += strlen(realm_str); - } - if (princ_str) { - buf->size += strlen(princ_str); - } - if (keytab_name) { - buf->size += strlen(keytab_name); - } - - DEBUG(7, ("buffer size: %d\n", buf->size)); - - buf->data = talloc_size(buf, buf->size); - if (buf->data == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - talloc_free(buf); - return ENOMEM; - } - - rp = 0; - - /* realm */ - if (realm_str) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(realm_str), rp); - COPY_MEM(&buf->data[rp], realm_str, rp, strlen(realm_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - /* principal */ - if (princ_str) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(princ_str), rp); - COPY_MEM(&buf->data[rp], princ_str, rp, strlen(princ_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - /* keytab */ - if (keytab_name) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(keytab_name), rp); - COPY_MEM(&buf->data[rp], keytab_name, rp, strlen(realm_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - *io_buf = buf; - return EOK; -} - -static int parse_child_response(TALLOC_CTX *mem_ctx, - uint8_t *buf, ssize_t size, - int *result, char **ccache) -{ - size_t p = 0; - uint32_t len; - uint32_t res; - char *ccn; - - /* operation result code */ - COPY_UINT32_CHECK(&res, buf + p, p, size); - - /* ccache name size */ - COPY_UINT32_CHECK(&len, buf + p, p, size); - - if ((p + len ) > size) return EINVAL; - - ccn = talloc_size(mem_ctx, sizeof(char) * (len + 1)); - if (ccn == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - return ENOMEM; - } - memcpy(ccn, buf+p, sizeof(char) * (len + 1)); - ccn[len] = '\0'; - - *result = res; - *ccache = ccn; - return EOK; -} - -/* ==The-public-async-interface============================================*/ - -struct sdap_get_tgt_state { - struct tevent_context *ev; - struct sdap_child *child; - ssize_t len; - uint8_t *buf; -}; - -static errno_t set_tgt_child_timeout(struct tevent_req *req, - struct tevent_context *ev, - int timeout); -static void sdap_get_tgt_step(struct tevent_req *subreq); -static void sdap_get_tgt_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_tgt_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - int timeout) -{ - struct tevent_req *req, *subreq; - struct sdap_get_tgt_state *state; - struct io_buffer *buf; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sdap_get_tgt_state); - if (!req) { - return NULL; - } - - state->ev = ev; - - state->child = talloc_zero(state, struct sdap_child); - if (!state->child) { - ret = ENOMEM; - goto fail; - } - - state->child->read_from_child_fd = -1; - state->child->write_to_child_fd = -1; - talloc_set_destructor((TALLOC_CTX *)state->child, sdap_child_destructor); - - /* prepare the data to pass to child */ - ret = create_tgt_req_send_buffer(state, - realm_str, princ_str, keytab_name, - &buf); - if (ret != EOK) { - DEBUG(1, ("create_tgt_req_send_buffer failed.\n")); - goto fail; - } - - ret = sdap_fork_child(state->child); - if (ret != EOK) { - DEBUG(1, ("sdap_fork_child failed.\n")); - goto fail; - } - - ret = set_tgt_child_timeout(req, ev, timeout); - if (ret != EOK) { - DEBUG(1, ("activate_child_timeout_handler failed.\n")); - goto fail; - } - - subreq = write_pipe_send(state, ev, buf->data, buf->size, - state->child->write_to_child_fd); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_get_tgt_step, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_get_tgt_step(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - ret = write_pipe_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - sdap_close_fd(&state->child->write_to_child_fd); - - subreq = read_pipe_send(state, state->ev, - state->child->read_from_child_fd); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_tgt_done, req); -} - -static void sdap_get_tgt_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - ret = read_pipe_recv(subreq, state, &state->buf, &state->len); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - sdap_close_fd(&state->child->read_from_child_fd); - - tevent_req_done(req); -} - -int sdap_get_tgt_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - int *result, - char **ccname) -{ - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - char *ccn; - int res; - int ret; - - TEVENT_REQ_RETURN_ON_ERROR(req); - - ret = parse_child_response(mem_ctx, state->buf, state->len, &res, &ccn); - if (ret != EOK) { - DEBUG(1, ("Cannot parse child response: [%d][%s]\n", ret, strerror(ret))); - return ret; - } - - DEBUG(6, ("Child responded: %d [%s]\n", res, ccn)); - *result = res; - *ccname = ccn; - return EOK; -} - - - -static void get_tgt_timeout_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - DEBUG(9, ("timeout for tgt child [%d] reached.\n", state->child->pid)); - - ret = kill(state->child->pid, SIGKILL); - if (ret == -1) { - DEBUG(1, ("kill failed [%d][%s].\n", errno, strerror(errno))); - } - - tevent_req_error(req, ETIMEDOUT); -} - -static errno_t set_tgt_child_timeout(struct tevent_req *req, - struct tevent_context *ev, - int timeout) -{ - struct tevent_timer *te; - struct timeval tv; - - DEBUG(6, ("Setting %d seconds timeout for tgt child\n", timeout)); - - tv = tevent_timeval_current_ofs(timeout, 0); - - te = tevent_add_timer(ev, req, tv, get_tgt_timeout_handler, req); - if (te == NULL) { - DEBUG(1, ("tevent_add_timer failed.\n")); - return ENOMEM; - } - - return EOK; -} - - - -/* Setup child logging */ -int setup_child(struct sdap_id_ctx *ctx) -{ - int ret; - const char *mech; - struct tevent_signal *sige; - unsigned v; - FILE *debug_filep; - - mech = dp_opt_get_string(ctx->opts->basic, - SDAP_SASL_MECH); - if (!mech) { - return EOK; - } - - sige = tevent_add_signal(ctx->be->ev, ctx, SIGCHLD, SA_SIGINFO, - child_sig_handler, NULL); - if (sige == NULL) { - DEBUG(1, ("tevent_add_signal failed.\n")); - return ENOMEM; - } - - if (debug_to_file != 0 && ldap_child_debug_fd == -1) { - ret = open_debug_file_ex("ldap_child", &debug_filep); - if (ret != EOK) { - DEBUG(0, ("Error setting up logging (%d) [%s]\n", - ret, strerror(ret))); - return ret; - } - - ldap_child_debug_fd = fileno(debug_filep); - if (ldap_child_debug_fd == -1) { - DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno))); - ret = errno; - return ret; - } - - v = fcntl(ldap_child_debug_fd, F_GETFD, 0); - fcntl(ldap_child_debug_fd, F_SETFD, v & ~FD_CLOEXEC); - } - - return EOK; -} |