summaryrefslogtreecommitdiffstats
path: root/server/providers
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-02-18 07:49:04 -0500
committerStephen Gallagher <sgallagh@redhat.com>2010-02-18 13:48:45 -0500
commit1c48b5a62f73234ed26bb20f0ab345ab61cda0ab (patch)
tree0b6cddd567a862e1a7b5df23764869782a62ca78 /server/providers
parent8c56df3176f528fe0260974b3bf934173c4651ea (diff)
downloadsssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.gz
sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.tar.xz
sssd-1c48b5a62f73234ed26bb20f0ab345ab61cda0ab.zip
Rename server/ directory to src/
Also update BUILD.txt
Diffstat (limited to 'server/providers')
-rw-r--r--server/providers/child_common.c416
-rw-r--r--server/providers/child_common.h73
-rw-r--r--server/providers/data_provider.h219
-rw-r--r--server/providers/data_provider_be.c1235
-rw-r--r--server/providers/data_provider_fo.c356
-rw-r--r--server/providers/data_provider_opts.c384
-rw-r--r--server/providers/dp_auth_util.c414
-rw-r--r--server/providers/dp_backend.h142
-rw-r--r--server/providers/dp_sbus.c45
-rw-r--r--server/providers/fail_over.c651
-rw-r--r--server/providers/fail_over.h108
-rw-r--r--server/providers/ipa/ipa_access.c1823
-rw-r--r--server/providers/ipa/ipa_access.h66
-rw-r--r--server/providers/ipa/ipa_auth.c313
-rw-r--r--server/providers/ipa/ipa_auth.h32
-rw-r--r--server/providers/ipa/ipa_common.c597
-rw-r--r--server/providers/ipa/ipa_common.h83
-rw-r--r--server/providers/ipa/ipa_init.c293
-rw-r--r--server/providers/ipa/ipa_timerules.c1186
-rw-r--r--server/providers/ipa/ipa_timerules.h56
-rw-r--r--server/providers/krb5/krb5_auth.c1193
-rw-r--r--server/providers/krb5/krb5_auth.h91
-rw-r--r--server/providers/krb5/krb5_become_user.c61
-rw-r--r--server/providers/krb5/krb5_child.c1030
-rw-r--r--server/providers/krb5/krb5_common.c356
-rw-r--r--server/providers/krb5/krb5_common.h72
-rw-r--r--server/providers/krb5/krb5_init.c152
-rw-r--r--server/providers/krb5/krb5_utils.c145
-rw-r--r--server/providers/krb5/krb5_utils.h39
-rw-r--r--server/providers/ldap/ldap_auth.c1055
-rw-r--r--server/providers/ldap/ldap_child.c429
-rw-r--r--server/providers/ldap/ldap_common.c589
-rw-r--r--server/providers/ldap/ldap_common.h115
-rw-r--r--server/providers/ldap/ldap_id.c795
-rw-r--r--server/providers/ldap/ldap_id_cleanup.c555
-rw-r--r--server/providers/ldap/ldap_id_enum.c608
-rw-r--r--server/providers/ldap/ldap_init.c179
-rw-r--r--server/providers/ldap/sdap.c388
-rw-r--r--server/providers/ldap/sdap.h258
-rw-r--r--server/providers/ldap/sdap_async.c1018
-rw-r--r--server/providers/ldap/sdap_async.h126
-rw-r--r--server/providers/ldap/sdap_async_accounts.c2065
-rw-r--r--server/providers/ldap/sdap_async_connection.c1141
-rw-r--r--server/providers/ldap/sdap_async_private.h68
-rw-r--r--server/providers/ldap/sdap_child_helpers.c462
-rw-r--r--server/providers/providers.h24
-rw-r--r--server/providers/proxy.c2521
-rw-r--r--server/providers/sssd_be.exports4
48 files changed, 0 insertions, 24031 deletions
diff --git a/server/providers/child_common.c b/server/providers/child_common.c
deleted file mode 100644
index 2ad0f04e3..000000000
--- a/server/providers/child_common.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- SSSD
-
- Common helper functions to be used in child processes
-
- Authors:
- Sumit Bose <sbose@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 <fcntl.h>
-#include <tevent.h>
-#include <sys/wait.h>
-#include <errno.h>
-
-#include "util/util.h"
-#include "util/find_uid.h"
-#include "db/sysdb.h"
-#include "providers/child_common.h"
-
-/* Async communication with the child process via a pipe */
-
-struct write_pipe_state {
- int fd;
- uint8_t *buf;
- size_t len;
- size_t written;
-};
-
-static void write_pipe_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt);
-
-struct tevent_req *write_pipe_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- uint8_t *buf, size_t len, int fd)
-{
- struct tevent_req *req;
- struct write_pipe_state *state;
- struct tevent_fd *fde;
-
- req = tevent_req_create(mem_ctx, &state, struct write_pipe_state);
- if (req == NULL) return NULL;
-
- state->fd = fd;
- state->buf = buf;
- state->len = len;
- state->written = 0;
-
- fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE,
- write_pipe_handler, req);
- if (fde == NULL) {
- DEBUG(1, ("tevent_add_fd failed.\n"));
- goto fail;
- }
-
- return req;
-
-fail:
- talloc_zfree(req);
- return NULL;
-}
-
-static void write_pipe_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt)
-{
- struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
- struct write_pipe_state *state = tevent_req_data(req,
- struct write_pipe_state);
- ssize_t size;
-
- if (flags & TEVENT_FD_READ) {
- DEBUG(1, ("write_pipe_done called with TEVENT_FD_READ,"
- " this should not happen.\n"));
- tevent_req_error(req, EINVAL);
- return;
- }
-
- size = write(state->fd,
- state->buf + state->written,
- state->len - state->written);
- if (size == -1) {
- if (errno == EAGAIN || errno == EINTR) return;
- DEBUG(1, ("write failed [%d][%s].\n", errno, strerror(errno)));
- tevent_req_error(req, errno);
- return;
-
- } else if (size >= 0) {
- state->written += size;
- if (state->written > state->len) {
- DEBUG(1, ("write to much, this should never happen.\n"));
- tevent_req_error(req, EINVAL);
- return;
- }
- } else {
- DEBUG(1, ("unexpected return value of write [%d].\n", size));
- tevent_req_error(req, EINVAL);
- return;
- }
-
- if (state->len == state->written) {
- DEBUG(6, ("All data has been sent!\n"));
- tevent_req_done(req);
- return;
- }
-}
-
-int write_pipe_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-struct read_pipe_state {
- int fd;
- uint8_t *buf;
- size_t len;
-};
-
-static void read_pipe_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt);
-
-struct tevent_req *read_pipe_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd)
-{
- struct tevent_req *req;
- struct read_pipe_state *state;
- struct tevent_fd *fde;
-
- req = tevent_req_create(mem_ctx, &state, struct read_pipe_state);
- if (req == NULL) return NULL;
-
- state->fd = fd;
- state->buf = talloc_array(state, uint8_t, MAX_CHILD_MSG_SIZE);
- state->len = 0;
- if (state->buf == NULL) goto fail;
-
- fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ,
- read_pipe_handler, req);
- if (fde == NULL) {
- DEBUG(1, ("tevent_add_fd failed.\n"));
- goto fail;
- }
-
- return req;
-
-fail:
- talloc_zfree(req);
- return NULL;
-}
-
-static void read_pipe_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt)
-{
- struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
- struct read_pipe_state *state = tevent_req_data(req,
- struct read_pipe_state);
- ssize_t size;
- errno_t err;
-
- if (flags & TEVENT_FD_WRITE) {
- DEBUG(1, ("read_pipe_done called with TEVENT_FD_WRITE,"
- " this should not happen.\n"));
- tevent_req_error(req, EINVAL);
- return;
- }
-
- size = read(state->fd,
- state->buf + state->len,
- MAX_CHILD_MSG_SIZE - state->len);
- if (size == -1) {
- err = errno;
- if (err == EAGAIN || err == EINTR) {
- return;
- }
-
- DEBUG(1, ("read failed [%d][%s].\n", err, strerror(err)));
- tevent_req_error(req, err);
- return;
-
- } else if (size > 0) {
- state->len += size;
- if (state->len > MAX_CHILD_MSG_SIZE) {
- DEBUG(1, ("read to much, this should never happen.\n"));
- tevent_req_error(req, EINVAL);
- return;
- }
-
- } else if (size == 0) {
- DEBUG(6, ("EOF received, client finished\n"));
- tevent_req_done(req);
- return;
-
- } else {
- DEBUG(1, ("unexpected return value of read [%d].\n", size));
- tevent_req_error(req, EINVAL);
- return;
- }
-}
-
-int read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- uint8_t **buf, ssize_t *len)
-{
- struct read_pipe_state *state;
- state = tevent_req_data(req, struct read_pipe_state);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *buf = talloc_steal(mem_ctx, state->buf);
- *len = state->len;
-
- return EOK;
-}
-
-/* The pipes to communicate with the child must be nonblocking */
-void fd_nonblocking(int fd)
-{
- int flags;
- int ret;
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags == -1) {
- ret = errno;
- DEBUG(1, ("F_GETFL failed [%d][%s].\n", ret, strerror(ret)));
- return;
- }
-
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
- ret = errno;
- DEBUG(1, ("F_SETFL failed [%d][%s].\n", ret, strerror(ret)));
- }
-
- return;
-}
-
-void child_sig_handler(struct tevent_context *ev,
- struct tevent_signal *sige, int signum,
- int count, void *__siginfo, void *pvt)
-{
- int ret;
- int child_status;
-
- DEBUG(7, ("Waiting for [%d] childeren.\n", count));
- do {
- errno = 0;
- ret = waitpid(-1, &child_status, WNOHANG);
-
- if (ret == -1) {
- DEBUG(1, ("waitpid failed [%d][%s].\n", errno, strerror(errno)));
- } else if (ret == 0) {
- DEBUG(1, ("waitpid did not found a child with changed status.\n"));
- } else {
- if (WEXITSTATUS(child_status) != 0) {
- DEBUG(1, ("child [%d] failed with status [%d].\n", ret,
- child_status));
- } else {
- DEBUG(4, ("child [%d] finished successful.\n", ret));
- }
- }
-
- --count;
- } while (count < 0);
-
- return;
-}
-
-static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
- int child_debug_fd,
- const char *binary,
- char ***_argv)
-{
- uint_t argc = 3; /* program name, debug_level and NULL */
- char ** argv;
- errno_t ret = EINVAL;
-
- /* Save the current state in case an interrupt changes it */
- bool child_debug_to_file = debug_to_file;
- bool child_debug_timestamps = debug_timestamps;
-
- if (child_debug_to_file) argc++;
- if (!child_debug_timestamps) argc++;
-
- /* program name, debug_level,
- * debug_to_file, debug_timestamps
- * and NULL */
- argv = talloc_array(mem_ctx, char *, argc);
- if (argv == NULL) {
- DEBUG(1, ("talloc_array failed.\n"));
- return ENOMEM;
- }
-
- argv[--argc] = NULL;
-
- argv[--argc] = talloc_asprintf(argv, "--debug-level=%d",
- debug_level);
- if (argv[argc] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- if (child_debug_to_file) {
- argv[--argc] = talloc_asprintf(argv, "--debug-fd=%d",
- child_debug_fd);
- if (argv[argc] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- }
-
- if (!child_debug_timestamps) {
- argv[--argc] = talloc_strdup(argv, "--debug-timestamps=0");
- if (argv[argc] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- }
-
- argv[--argc] = talloc_strdup(argv, binary);
- if (argv[argc] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- if (argc != 0) {
- ret = EINVAL;
- goto fail;
- }
-
- *_argv = argv;
-
- return EOK;
-
-fail:
- talloc_free(argv);
- return ret;
-}
-
-errno_t exec_child(TALLOC_CTX *mem_ctx,
- int *pipefd_to_child, int *pipefd_from_child,
- const char *binary, int debug_fd)
-{
- int ret;
- errno_t err;
- char **argv;
-
- close(pipefd_to_child[1]);
- ret = dup2(pipefd_to_child[0], STDIN_FILENO);
- if (ret == -1) {
- err = errno;
- DEBUG(1, ("dup2 failed [%d][%s].\n", err, strerror(err)));
- return err;
- }
-
- close(pipefd_from_child[0]);
- ret = dup2(pipefd_from_child[1], STDOUT_FILENO);
- if (ret == -1) {
- err = errno;
- DEBUG(1, ("dup2 failed [%d][%s].\n", err, strerror(err)));
- return err;
- }
-
- ret = prepare_child_argv(mem_ctx, debug_fd,
- binary, &argv);
- if (ret != EOK) {
- DEBUG(1, ("prepare_child_argv.\n"));
- return ret;
- }
-
- ret = execv(binary, argv);
- if (ret == -1) {
- err = errno;
- DEBUG(1, ("execv failed [%d][%s].\n", err, strerror(err)));
- return err;
- }
-
- return EOK;
-}
-
-void child_cleanup(int readfd, int writefd)
-{
- int ret;
-
- if (readfd != -1) {
- ret = close(readfd);
- if (ret != EOK) {
- ret = errno;
- DEBUG(1, ("close failed [%d][%s].\n", errno, strerror(errno)));
- }
- }
- if (writefd != -1) {
- ret = close(writefd);
- if (ret != EOK) {
- ret = errno;
- DEBUG(1, ("close failed [%d][%s].\n", errno, strerror(errno)));
- }
- }
-}
diff --git a/server/providers/child_common.h b/server/providers/child_common.h
deleted file mode 100644
index a441df3c5..000000000
--- a/server/providers/child_common.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- SSSD
-
- Common helper functions to be used in child processes
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef __CHILD_COMMON_H__
-#define __CHILD_COMMON_H__
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <tevent.h>
-
-#include "util/util.h"
-
-#define IN_BUF_SIZE 512
-#define MAX_CHILD_MSG_SIZE 255
-
-struct response {
- size_t max_size;
- size_t size;
- uint8_t *buf;
-};
-
-struct io_buffer {
- uint8_t *data;
- size_t size;
-};
-
-/* Async communication with the child process via a pipe */
-struct tevent_req *write_pipe_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- uint8_t *buf, size_t len, int fd);
-int write_pipe_recv(struct tevent_req *req);
-
-struct tevent_req *read_pipe_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev, int fd);
-int read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
- uint8_t **buf, ssize_t *len);
-
-/* The pipes to communicate with the child must be nonblocking */
-void fd_nonblocking(int fd);
-
-void child_sig_handler(struct tevent_context *ev,
- struct tevent_signal *sige, int signum,
- int count, void *__siginfo, void *pvt);
-
-errno_t exec_child(TALLOC_CTX *mem_ctx,
- int *pipefd_to_child, int *pipefd_from_child,
- const char *binary, int debug_fd);
-
-void child_cleanup(int readfd, int writefd);
-
-#endif /* __CHILD_COMMON_H__ */
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
deleted file mode 100644
index 76ba4cffb..000000000
--- a/server/providers/data_provider.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- SSSD
-
- Data Provider, private header file
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
-
- 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 __DATA_PROVIDER_H__
-#define __DATA_PROVIDER_H__
-
-#include <stdint.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <stdbool.h>
-#include "talloc.h"
-#include "tevent.h"
-#include "ldb.h"
-#include "util/util.h"
-#include "confdb/confdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "sbus/sbus_client.h"
-#include "sss_client/sss_cli.h"
-
-#define DATA_PROVIDER_VERSION 0x0001
-#define DATA_PROVIDER_SERVICE_NAME "dp"
-#define DATA_PROVIDER_PIPE "private/sbus-dp"
-
-#define DATA_PROVIDER_DB_FILE "sssd.ldb"
-#define DATA_PROVIDER_DB_CONF_SEC "config/services/nss"
-
-#define MOD_OFFLINE 0x0000
-#define MOD_ONLINE 0x0001
-
-#define DP_INTERFACE "org.freedesktop.sssd.dataprovider"
-#define DP_PATH "/org/freedesktop/sssd/dataprovider"
-
-#define BE_PROVIDE_ACC_INFO (1<<8)
-#define BE_PROVIDE_PAM (1<<9)
-#define BE_PROVIDE_POLICY (1<<10)
-
-#define DP_METHOD_REGISTER "RegisterService"
-#define DP_METHOD_ONLINE "getOnline"
-#define DP_METHOD_GETACCTINFO "getAccountInfo"
-#define DP_METHOD_PAMHANDLER "pamHandler"
-
-#define DP_ERR_OK 0
-#define DP_ERR_OFFLINE 1
-#define DP_ERR_TIMEOUT 2
-#define DP_ERR_FATAL 3
-
-#define BE_ATTR_CORE 1
-#define BE_ATTR_MEM 2
-#define BE_ATTR_ALL 3
-
-#define BE_FILTER_NAME 1
-#define BE_FILTER_IDNUM 2
-
-#define BE_REQ_USER 0x0001
-#define BE_REQ_GROUP 0x0002
-#define BE_REQ_INITGROUPS 0x0003
-#define BE_REQ_FAST 0x1000
-
-/* AUTH related common data and functions */
-
-#define DEBUG_PAM_DATA(level, pd) do { \
- if (level <= debug_level) pam_print_data(level, pd); \
-} while(0);
-
-
-struct response_data {
- int32_t type;
- int32_t len;
- uint8_t *data;
- struct response_data *next;
-};
-
-struct pam_data {
- int cmd;
- uint32_t authtok_type;
- uint32_t authtok_size;
- uint32_t newauthtok_type;
- uint32_t newauthtok_size;
- char *domain;
- char *user;
- char *service;
- char *tty;
- char *ruser;
- char *rhost;
- uint8_t *authtok;
- uint8_t *newauthtok;
- uint32_t cli_pid;
-
- int pam_status;
- int response_delay;
- struct response_data *resp_list;
-
- bool offline_auth;
- bool last_auth_saved;
- int priv;
- uid_t pw_uid;
- gid_t gr_gid;
-
- const char *upn;
-};
-
-/* from dp_auth_util.c */
-void pam_print_data(int l, struct pam_data *pd);
-int pam_add_response(struct pam_data *pd,
- enum response_type type,
- int len, const uint8_t *data);
-
-bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd);
-bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd,
- DBusError *dbus_error);
-
-bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd);
-bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd,
- DBusError *dbus_error);
-
-int dp_common_send_id(struct sbus_connection *conn, uint16_t version,
- const char *name, const char *domain);
-
-/* from dp_sbus.c */
-int dp_get_sbus_address(TALLOC_CTX *mem_ctx,
- char **address, const char *domain_name);
-
-
-/* Helpers */
-
-#define NULL_STRING { .string = NULL }
-#define NULL_BLOB { .blob = { NULL, 0 } }
-#define NULL_NUMBER { .number = 0 }
-#define BOOL_FALSE { .boolean = false }
-#define BOOL_TRUE { .boolean = true }
-
-enum dp_opt_type {
- DP_OPT_STRING,
- DP_OPT_BLOB,
- DP_OPT_NUMBER,
- DP_OPT_BOOL
-};
-
-struct dp_opt_blob {
- uint8_t *data;
- size_t length;
-};
-
-union dp_opt_value {
- const char *cstring;
- char *string;
- struct dp_opt_blob blob;
- int number;
- bool boolean;
-};
-
-struct dp_option {
- const char *opt_name;
- enum dp_opt_type type;
- union dp_opt_value def_val;
- union dp_opt_value val;
-};
-
-int dp_get_options(TALLOC_CTX *memctx,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct dp_option *def_opts,
- int num_opts,
- struct dp_option **_opts);
-
-int dp_copy_options(TALLOC_CTX *memctx,
- struct dp_option *src_opts,
- int num_opts,
- struct dp_option **_opts);
-
-const char *_dp_opt_get_cstring(struct dp_option *opts,
- int id, const char *location);
-char *_dp_opt_get_string(struct dp_option *opts,
- int id, const char *location);
-struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
- int id, const char *location);
-int _dp_opt_get_int(struct dp_option *opts,
- int id, const char *location);
-bool _dp_opt_get_bool(struct dp_option *opts,
- int id, const char *location);
-#define dp_opt_get_cstring(o, i) _dp_opt_get_cstring(o, i, __FUNCTION__)
-#define dp_opt_get_string(o, i) _dp_opt_get_string(o, i, __FUNCTION__)
-#define dp_opt_get_blob(o, i) _dp_opt_get_blob(o, i, __FUNCTION__)
-#define dp_opt_get_int(o, i) _dp_opt_get_int(o, i, __FUNCTION__)
-#define dp_opt_get_bool(o, i) _dp_opt_get_bool(o, i, __FUNCTION__)
-
-int _dp_opt_set_string(struct dp_option *opts, int id,
- const char *s, const char *location);
-int _dp_opt_set_blob(struct dp_option *opts, int id,
- struct dp_opt_blob b, const char *location);
-int _dp_opt_set_int(struct dp_option *opts, int id,
- int i, const char *location);
-int _dp_opt_set_bool(struct dp_option *opts, int id,
- bool b, const char *location);
-#define dp_opt_set_string(o, i, v) _dp_opt_set_string(o, i, v, __FUNCTION__)
-#define dp_opt_set_blob(o, i, v) _dp_opt_set_blob(o, i, v, __FUNCTION__)
-#define dp_opt_set_int(o, i, v) _dp_opt_set_int(o, i, v, __FUNCTION__)
-#define dp_opt_set_bool(o, i, v) _dp_opt_set_bool(o, i, v, __FUNCTION__)
-
-#endif /* __DATA_PROVIDER_ */
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
deleted file mode 100644
index 93cae0702..000000000
--- a/server/providers/data_provider_be.c
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- SSSD
-
- Data Provider Process
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
-
- 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 <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <string.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <dlfcn.h>
-
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-
-#include "popt.h"
-#include "util/util.h"
-#include "confdb/confdb.h"
-#include "db/sysdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "providers/dp_backend.h"
-#include "providers/fail_over.h"
-#include "resolv/async_resolv.h"
-#include "monitor/monitor_interfaces.h"
-
-#define MSG_TARGET_NO_CONFIGURED "sssd_be: The requested target is not configured"
-
-#define ACCESS_PERMIT "permit"
-#define ACCESS_DENY "deny"
-#define NO_PROVIDER "none"
-
-static int data_provider_res_init(DBusMessage *message,
- struct sbus_connection *conn);
-static int data_provider_go_offline(DBusMessage *message,
- struct sbus_connection *conn);
-
-struct sbus_method monitor_be_methods[] = {
- { MON_CLI_METHOD_PING, monitor_common_pong },
- { MON_CLI_METHOD_RES_INIT, data_provider_res_init },
- { MON_CLI_METHOD_OFFLINE, data_provider_go_offline },
- { NULL, NULL }
-};
-
-struct sbus_interface monitor_be_interface = {
- MONITOR_INTERFACE,
- MONITOR_PATH,
- SBUS_DEFAULT_VTABLE,
- monitor_be_methods,
- NULL
-};
-
-static int client_registration(DBusMessage *message, struct sbus_connection *conn);
-static int be_check_online(DBusMessage *message, struct sbus_connection *conn);
-static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn);
-static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn);
-
-struct sbus_method be_methods[] = {
- { DP_METHOD_REGISTER, client_registration },
- { DP_METHOD_ONLINE, be_check_online },
- { DP_METHOD_GETACCTINFO, be_get_account_info },
- { DP_METHOD_PAMHANDLER, be_pam_handler },
- { NULL, NULL }
-};
-
-struct sbus_interface be_interface = {
- DP_INTERFACE,
- DP_PATH,
- SBUS_DEFAULT_VTABLE,
- be_methods,
- NULL
-};
-
-static struct bet_data bet_data[] = {
- {BET_NULL, NULL, NULL},
- {BET_ID, CONFDB_DOMAIN_ID_PROVIDER, "sssm_%s_init"},
- {BET_AUTH, CONFDB_DOMAIN_AUTH_PROVIDER, "sssm_%s_auth_init"},
- {BET_ACCESS, CONFDB_DOMAIN_ACCESS_PROVIDER, "sssm_%s_access_init"},
- {BET_CHPASS, CONFDB_DOMAIN_CHPASS_PROVIDER, "sssm_%s_chpass_init"},
- {BET_MAX, NULL, NULL}
-};
-
-struct be_async_req {
- be_req_fn_t fn;
- struct be_req *req;
-};
-
-static void be_async_req_handler(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- struct be_async_req *async_req;
-
- async_req = talloc_get_type(pvt, struct be_async_req);
-
- async_req->fn(async_req->req);
-}
-
-static int be_file_request(struct be_ctx *ctx,
- be_req_fn_t fn,
- struct be_req *req)
-{
- struct be_async_req *areq;
- struct tevent_timer *te;
- struct timeval tv;
-
- if (!fn || !req) return EINVAL;
-
- areq = talloc(req, struct be_async_req);
- if (!areq) {
- return ENOMEM;
- }
- areq->fn = fn;
- areq->req = req;
-
- /* fire immediately */
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- te = tevent_add_timer(ctx->ev, req, tv, be_async_req_handler, areq);
- if (te == NULL) {
- return EIO;
- }
-
- return EOK;
-}
-
-bool be_is_offline(struct be_ctx *ctx)
-{
- time_t now = time(NULL);
-
- /* check if we are past the offline blackout timeout */
- /* FIXME: get offline_timeout from configuration */
- if (ctx->offstat.went_offline + 60 < now) {
- ctx->offstat.offline = false;
- }
-
- return ctx->offstat.offline;
-}
-
-void be_mark_offline(struct be_ctx *ctx)
-{
- DEBUG(8, ("Going offline!\n"));
-
- ctx->offstat.went_offline = time(NULL);
- ctx->offstat.offline = true;
-}
-
-static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
-{
- struct be_client *becli;
- DBusMessage *reply;
- DBusConnection *dbus_conn;
- dbus_bool_t dbret;
- void *user_data;
- dbus_uint16_t online;
- dbus_uint16_t err_maj = 0;
- dbus_uint32_t err_min = 0;
- static const char *err_msg = "Success";
-
- user_data = sbus_conn_get_private_data(conn);
- if (!user_data) return EINVAL;
- becli = talloc_get_type(user_data, struct be_client);
- if (!becli) return EINVAL;
-
- reply = dbus_message_new_method_return(message);
- if (!reply) return ENOMEM;
-
- if (be_is_offline(becli->bectx)) {
- online = MOD_OFFLINE;
- } else {
- online = MOD_ONLINE;
- }
-
- dbret = dbus_message_append_args(reply,
- DBUS_TYPE_UINT16, &online,
- DBUS_TYPE_UINT16, &err_maj,
- DBUS_TYPE_UINT32, &err_min,
- DBUS_TYPE_STRING, &err_msg,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(1, ("Failed to generate dbus reply\n"));
- return EIO;
- }
-
- dbus_conn = sbus_get_connection(becli->conn);
- dbus_connection_send(dbus_conn, reply, NULL);
- dbus_message_unref(reply);
-
- DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
- err_maj, err_min, err_msg));
-
- return EOK;
-}
-
-static char *dp_err_to_string(TALLOC_CTX *memctx, int dp_err_type, int errnum)
-{
- switch (dp_err_type) {
- case DP_ERR_OK:
- return talloc_strdup(memctx, "Success");
- break;
-
- case DP_ERR_OFFLINE:
- return talloc_asprintf(memctx,
- "Provider is Offline (%s)",
- strerror(errnum));
- break;
-
- case DP_ERR_TIMEOUT:
- return talloc_asprintf(memctx,
- "Request timed out (%s)",
- strerror(errnum));
- break;
-
- case DP_ERR_FATAL:
- default:
- return talloc_asprintf(memctx,
- "Internal Error (%s)",
- strerror(errnum));
- break;
- }
-
- return NULL;
-}
-
-
-static void acctinfo_callback(struct be_req *req,
- int dp_err_type,
- int errnum,
- const char *errstr)
-{
- DBusMessage *reply;
- DBusConnection *dbus_conn;
- dbus_bool_t dbret;
- dbus_uint16_t err_maj = 0;
- dbus_uint32_t err_min = 0;
- const char *err_msg = NULL;
-
- reply = (DBusMessage *)req->pvt;
-
- if (reply) {
- /* Return a reply if one was requested
- * There may not be one if this request began
- * while we were offline
- */
-
- err_maj = dp_err_type;
- err_min = errnum;
- if (errstr) {
- err_msg = errstr;
- } else {
- err_msg = dp_err_to_string(req, dp_err_type, errnum);
- }
- if (!err_msg) {
- DEBUG(1, ("Failed to set err_msg, Out of memory?\n"));
- err_msg = "OOM";
- }
-
- dbret = dbus_message_append_args(reply,
- DBUS_TYPE_UINT16, &err_maj,
- DBUS_TYPE_UINT32, &err_min,
- DBUS_TYPE_STRING, &err_msg,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(1, ("Failed to generate dbus reply\n"));
- return;
- }
-
- dbus_conn = sbus_get_connection(req->becli->conn);
- dbus_connection_send(dbus_conn, reply, NULL);
- dbus_message_unref(reply);
-
- DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
- err_maj, err_min, err_msg));
- }
-
- /* finally free the request */
- talloc_free(req);
-}
-
-static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn)
-{
- struct be_acct_req *req;
- struct be_req *be_req;
- struct be_client *becli;
- DBusMessage *reply;
- DBusError dbus_error;
- dbus_bool_t dbret;
- void *user_data;
- uint32_t type;
- char *filter;
- int filter_type;
- uint32_t attr_type;
- char *filter_val;
- int ret;
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
- const char *err_msg;
-
- be_req = NULL;
-
- user_data = sbus_conn_get_private_data(conn);
- if (!user_data) return EINVAL;
- becli = talloc_get_type(user_data, struct be_client);
- if (!becli) return EINVAL;
-
- dbus_error_init(&dbus_error);
-
- ret = dbus_message_get_args(message, &dbus_error,
- DBUS_TYPE_UINT32, &type,
- DBUS_TYPE_UINT32, &attr_type,
- DBUS_TYPE_STRING, &filter,
- DBUS_TYPE_INVALID);
- if (!ret) {
- DEBUG(1,("Failed, to parse message!\n"));
- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
- return EIO;
- }
-
- DEBUG(4, ("Got request for [%u][%d][%s]\n", type, attr_type, filter));
-
- reply = dbus_message_new_method_return(message);
- if (!reply) return ENOMEM;
-
- /* If we are offline and fast reply was requested
- * return offline immediately
- */
- if ((type & BE_REQ_FAST) && becli->bectx->offstat.offline) {
- /* Send back an immediate reply */
- err_maj = DP_ERR_OFFLINE;
- err_min = EAGAIN;
- err_msg = "Fast reply - offline";
-
- dbret = dbus_message_append_args(reply,
- DBUS_TYPE_UINT16, &err_maj,
- DBUS_TYPE_UINT32, &err_min,
- DBUS_TYPE_STRING, &err_msg,
- DBUS_TYPE_INVALID);
- if (!dbret) return EIO;
-
- DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
- err_maj, err_min, err_msg));
-
- sbus_conn_send_reply(conn, reply);
- dbus_message_unref(reply);
- reply = NULL;
- /* This reply will be queued and sent
- * when we reenter the mainloop.
- *
- * Continue processing in case we are
- * going back online.
- */
- }
-
- if ((attr_type != BE_ATTR_CORE) &&
- (attr_type != BE_ATTR_MEM) &&
- (attr_type != BE_ATTR_ALL)) {
- /* Unrecognized attr type */
- err_maj = DP_ERR_FATAL;
- err_min = EINVAL;
- err_msg = "Invalid Attrs Parameter";
- goto done;
- }
-
- if (filter) {
- if (strncmp(filter, "name=", 5) == 0) {
- filter_type = BE_FILTER_NAME;
- filter_val = &filter[5];
- } else if (strncmp(filter, "idnumber=", 9) == 0) {
- filter_type = BE_FILTER_IDNUM;
- filter_val = &filter[9];
- } else {
- err_maj = DP_ERR_FATAL;
- err_min = EINVAL;
- err_msg = "Invalid Filter";
- goto done;
- }
- } else {
- err_maj = DP_ERR_FATAL;
- err_min = EINVAL;
- err_msg = "Missing Filter Parameter";
- goto done;
- }
-
- /* process request */
- be_req = talloc(becli, struct be_req);
- if (!be_req) {
- err_maj = DP_ERR_FATAL;
- err_min = ENOMEM;
- err_msg = "Out of memory";
- goto done;
- }
- be_req->becli = becli;
- be_req->be_ctx = becli->bectx;
- be_req->fn = acctinfo_callback;
- be_req->pvt = reply;
-
- req = talloc(be_req, struct be_acct_req);
- if (!req) {
- err_maj = DP_ERR_FATAL;
- err_min = ENOMEM;
- err_msg = "Out of memory";
- goto done;
- }
- req->entry_type = type;
- req->attr_type = (int)attr_type;
- req->filter_type = filter_type;
- req->filter_value = talloc_strdup(req, filter_val);
-
- be_req->req_data = req;
-
- ret = be_file_request(becli->bectx,
- becli->bectx->bet_info[BET_ID].bet_ops->handler,
- be_req);
- if (ret != EOK) {
- err_maj = DP_ERR_FATAL;
- err_min = ret;
- err_msg = "Failed to file request";
- goto done;
- }
-
- return EOK;
-
-done:
- if (be_req) {
- talloc_free(be_req);
- }
-
- if (reply) {
- dbret = dbus_message_append_args(reply,
- DBUS_TYPE_UINT16, &err_maj,
- DBUS_TYPE_UINT32, &err_min,
- DBUS_TYPE_STRING, &err_msg,
- DBUS_TYPE_INVALID);
- if (!dbret) return EIO;
-
- DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
- err_maj, err_min, err_msg));
-
- /* send reply back */
- sbus_conn_send_reply(conn, reply);
- dbus_message_unref(reply);
- }
-
- return EOK;
-}
-
-static void be_pam_handler_callback(struct be_req *req,
- int dp_err_type,
- int errnum,
- const char *errstr)
-{
- struct pam_data *pd;
- DBusMessage *reply;
- DBusConnection *dbus_conn;
- dbus_bool_t dbret;
-
- DEBUG(4, ("Backend returned: (%d, %d, %s) [%s]\n",
- dp_err_type, errnum, errstr?errstr:"<NULL>",
- dp_err_to_string(req, dp_err_type, 0)));
-
- pd = talloc_get_type(req->req_data, struct pam_data);
-
- DEBUG(4, ("Sending result [%d][%s]\n", pd->pam_status, pd->domain));
- reply = (DBusMessage *)req->pvt;
- dbret = dp_pack_pam_response(reply, pd);
- if (!dbret) {
- DEBUG(1, ("Failed to generate dbus reply\n"));
- dbus_message_unref(reply);
- return;
- }
-
- dbus_conn = sbus_get_connection(req->becli->conn);
- dbus_connection_send(dbus_conn, reply, NULL);
- dbus_message_unref(reply);
-
- DEBUG(4, ("Sent result [%d][%s]\n", pd->pam_status, pd->domain));
-
- talloc_free(req);
-}
-
-static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
-{
- DBusError dbus_error;
- DBusMessage *reply;
- struct be_client *becli;
- dbus_bool_t ret;
- void *user_data;
- struct pam_data *pd = NULL;
- struct be_req *be_req = NULL;
- enum bet_type target = BET_NULL;
-
- user_data = sbus_conn_get_private_data(conn);
- if (!user_data) return EINVAL;
- becli = talloc_get_type(user_data, struct be_client);
- if (!becli) return EINVAL;
-
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- DEBUG(1, ("dbus_message_new_method_return failed, cannot send reply.\n"));
- return ENOMEM;
- }
-
- be_req = talloc_zero(becli, struct be_req);
- if (!be_req) {
- DEBUG(7, ("talloc_zero failed.\n"));
- goto done;
- }
-
- be_req->becli = becli;
- be_req->be_ctx = becli->bectx;
- be_req->fn = be_pam_handler_callback;
- be_req->pvt = reply;
-
- pd = talloc_zero(be_req, struct pam_data);
- if (!pd) {
- talloc_free(be_req);
- return ENOMEM;
- }
-
- pd->pam_status = PAM_SYSTEM_ERR;
- pd->domain = talloc_strdup(pd, becli->bectx->domain->name);
- if (pd->domain == NULL) {
- talloc_free(be_req);
- return ENOMEM;
- }
-
- dbus_error_init(&dbus_error);
-
- ret = dp_unpack_pam_request(message, pd, &dbus_error);
- if (!ret) {
- DEBUG(1,("Failed, to parse message!\n"));
- talloc_free(be_req);
- return EIO;
- }
-
- DEBUG(4, ("Got request with the following data\n"));
- DEBUG_PAM_DATA(4, pd);
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- target = BET_AUTH;
- break;
- case SSS_PAM_ACCT_MGMT:
- target = BET_ACCESS;
- break;
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- target = BET_CHPASS;
- break;
- case SSS_PAM_SETCRED:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- pd->pam_status = PAM_SUCCESS;
- goto done;
- break;
- default:
- DEBUG(7, ("Unsupported PAM command [%d].\n", pd->cmd));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- goto done;
- }
-
- /* return an error if corresponding backend target is not configured */
- if (!becli->bectx->bet_info[target].bet_ops) {
- DEBUG(7, ("Undefined backend target.\n"));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO,
- sizeof(MSG_TARGET_NO_CONFIGURED),
- (const uint8_t *) MSG_TARGET_NO_CONFIGURED);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- goto done;
- }
-
- be_req->req_data = pd;
-
- ret = be_file_request(becli->bectx,
- becli->bectx->bet_info[target].bet_ops->handler,
- be_req);
- if (ret != EOK) {
- DEBUG(7, ("be_file_request failed.\n"));
- goto done;
- }
-
- return EOK;
-
-done:
-
- DEBUG(4, ("Sending result [%d][%s]\n",
- pd->pam_status, pd->domain));
-
- ret = dp_pack_pam_response(reply, pd);
- if (!ret) {
- DEBUG(1, ("Failed to generate dbus reply\n"));
- talloc_free(be_req);
- dbus_message_unref(reply);
- return EIO;
- }
-
- /* send reply back immediately */
- sbus_conn_send_reply(conn, reply);
- dbus_message_unref(reply);
-
- talloc_free(be_req);
-
- return EOK;
-}
-
-static int be_client_destructor(void *ctx)
-{
- struct be_client *becli = talloc_get_type(ctx, struct be_client);
- if (becli->bectx) {
- if (becli->bectx->nss_cli == becli) {
- DEBUG(4, ("Removed NSS client\n"));
- becli->bectx->nss_cli = NULL;
- } else if (becli->bectx->pam_cli == becli) {
- DEBUG(4, ("Removed PAM client\n"));
- becli->bectx->pam_cli = NULL;
- } else {
- DEBUG(2, ("Unknown client removed ...\n"));
- }
- }
- return 0;
-}
-
-static int client_registration(DBusMessage *message,
- struct sbus_connection *conn)
-{
- dbus_uint16_t version = DATA_PROVIDER_VERSION;
- struct be_client *becli;
- DBusMessage *reply;
- DBusError dbus_error;
- dbus_uint16_t cli_ver;
- char *cli_name;
- char *cli_domain;
- dbus_bool_t dbret;
- void *data;
-
- data = sbus_conn_get_private_data(conn);
- becli = talloc_get_type(data, struct be_client);
- if (!becli) {
- DEBUG(0, ("Connection holds no valid init data\n"));
- return EINVAL;
- }
-
- /* First thing, cancel the timeout */
- DEBUG(4, ("Cancel DP ID timeout [%p]\n", becli->timeout));
- talloc_zfree(becli->timeout);
-
- dbus_error_init(&dbus_error);
-
- dbret = dbus_message_get_args(message, &dbus_error,
- DBUS_TYPE_UINT16, &cli_ver,
- DBUS_TYPE_STRING, &cli_name,
- DBUS_TYPE_STRING, &cli_domain,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(1, ("Failed to parse message, killing connection\n"));
- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
- sbus_disconnect(conn);
- /* FIXME: should we just talloc_zfree(conn) ? */
- return EIO;
- }
-
- if (strcasecmp(cli_name, "NSS") == 0) {
- becli->bectx->nss_cli = becli;
- } else if (strcasecmp(cli_name, "PAM") == 0) {
- becli->bectx->pam_cli = becli;
- } else {
- DEBUG(1, ("Unknown client! [%s]\n", cli_name));
- }
- talloc_set_destructor((TALLOC_CTX *)becli, be_client_destructor);
-
- DEBUG(4, ("Added Frontend client [%s]\n", cli_name));
-
- /* reply that all is ok */
- reply = dbus_message_new_method_return(message);
- if (!reply) {
- DEBUG(0, ("Dbus Out of memory!\n"));
- return ENOMEM;
- }
-
- dbret = dbus_message_append_args(reply,
- DBUS_TYPE_UINT16, &version,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(0, ("Failed to build dbus reply\n"));
- dbus_message_unref(reply);
- sbus_disconnect(conn);
- return EIO;
- }
-
- /* send reply back */
- sbus_conn_send_reply(conn, reply);
- dbus_message_unref(reply);
-
- becli->initialized = true;
- return EOK;
-}
-
-static void init_timeout(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval t, void *ptr)
-{
- struct be_client *becli;
-
- DEBUG(2, ("Client timed out before Identification [%p]!\n", te));
-
- becli = talloc_get_type(ptr, struct be_client);
-
- sbus_disconnect(becli->conn);
- talloc_zfree(becli);
-}
-
-static int be_client_init(struct sbus_connection *conn, void *data)
-{
- struct be_ctx *bectx;
- struct be_client *becli;
- struct timeval tv;
-
- bectx = talloc_get_type(data, struct be_ctx);
-
- /* hang off this memory to the connection so that when the connection
- * is freed we can potentially call a destructor */
-
- becli = talloc(conn, struct be_client);
- if (!becli) {
- DEBUG(0,("Out of memory?!\n"));
- talloc_zfree(conn);
- return ENOMEM;
- }
- becli->bectx = bectx;
- becli->conn = conn;
- becli->initialized = false;
-
- /* 5 seconds should be plenty */
- tv = tevent_timeval_current_ofs(5, 0);
-
- becli->timeout = tevent_add_timer(bectx->ev, becli,
- tv, init_timeout, becli);
- if (!becli->timeout) {
- DEBUG(0,("Out of memory?!\n"));
- talloc_zfree(conn);
- return ENOMEM;
- }
- DEBUG(4, ("Set-up Backend ID timeout [%p]\n", becli->timeout));
-
- /* Attach the client context to the connection context, so that it is
- * always available when we need to manage the connection. */
- sbus_conn_set_private_data(conn, becli);
-
- return EOK;
-}
-
-/* be_srv_init
- * set up per-domain sbus channel */
-static int be_srv_init(struct be_ctx *ctx)
-{
- char *sbus_address;
- int ret;
-
- /* Set up SBUS connection to the monitor */
- ret = dp_get_sbus_address(ctx, &sbus_address, ctx->domain->name);
- if (ret != EOK) {
- DEBUG(0, ("Could not get sbus backend address.\n"));
- return ret;
- }
-
- ret = sbus_new_server(ctx, ctx->ev, sbus_address,
- &be_interface, &ctx->sbus_srv,
- be_client_init, ctx);
- if (ret != EOK) {
- DEBUG(0, ("Could not set up sbus server.\n"));
- return ret;
- }
-
- return EOK;
-}
-
-/* mon_cli_init
- * sbus channel to the monitor daemon */
-static int mon_cli_init(struct be_ctx *ctx)
-{
- char *sbus_address;
- int ret;
-
- /* Set up SBUS connection to the monitor */
- ret = monitor_get_sbus_address(ctx, &sbus_address);
- if (ret != EOK) {
- DEBUG(0, ("Could not locate monitor address.\n"));
- return ret;
- }
-
- ret = sbus_client_init(ctx, ctx->ev, sbus_address,
- &monitor_be_interface, &ctx->mon_conn,
- NULL, ctx);
- if (ret != EOK) {
- DEBUG(0, ("Failed to connect to monitor services.\n"));
- return ret;
- }
-
- /* Identify ourselves to the monitor */
- ret = monitor_common_send_id(ctx->mon_conn,
- ctx->identity,
- DATA_PROVIDER_VERSION);
- if (ret != EOK) {
- DEBUG(0, ("Failed to identify to the monitor!\n"));
- return ret;
- }
-
- return EOK;
-}
-
-static void be_target_access_permit(struct be_req *be_req)
-{
- struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data);
- DEBUG(9, ("be_target_access_permit called, returning PAM_SUCCESS.\n"));
-
- pd->pam_status = PAM_SUCCESS;
- be_req->fn(be_req, DP_ERR_OK, PAM_SUCCESS, NULL);
-}
-
-static struct bet_ops be_target_access_permit_ops = {
- .check_online = NULL,
- .handler = be_target_access_permit,
- .finalize = NULL
-};
-
-static void be_target_access_deny(struct be_req *be_req)
-{
- struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data);
- DEBUG(9, ("be_target_access_deny called, returning PAM_PERM_DENIED.\n"));
-
- pd->pam_status = PAM_PERM_DENIED;
- be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL);
-}
-
-static struct bet_ops be_target_access_deny_ops = {
- .check_online = NULL,
- .handler = be_target_access_deny,
- .finalize = NULL
-};
-
-static int load_backend_module(struct be_ctx *ctx,
- enum bet_type bet_type,
- struct bet_info *bet_info,
- const char *default_mod_name)
-{
- TALLOC_CTX *tmp_ctx;
- int ret = EINVAL;
- bool already_loaded = false;
- int lb=0;
- char *mod_name = NULL;
- char *path = NULL;
- void *handle;
- char *mod_init_fn_name = NULL;
- bet_init_fn_t mod_init_fn = NULL;
-
- (*bet_info).mod_name = NULL;
- (*bet_info).bet_ops = NULL;
- (*bet_info).pvt_bet_data = NULL;
-
- if (bet_type <= BET_NULL || bet_type >= BET_MAX ||
- bet_type != bet_data[bet_type].bet_type) {
- DEBUG(2, ("invalid bet_type or bet_data corrupted.\n"));
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(ctx);
- if (!tmp_ctx) {
- DEBUG(7, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- ret = confdb_get_string(ctx->cdb, tmp_ctx, ctx->conf_path,
- bet_data[bet_type].option_name, NULL,
- &mod_name);
- if (ret != EOK) {
- ret = EFAULT;
- goto done;
- }
- if (!mod_name) {
- if (default_mod_name != NULL) {
- DEBUG(5, ("no module name found in confdb, using [%s].\n",
- default_mod_name));
- mod_name = talloc_strdup(ctx, default_mod_name);
- } else {
- ret = ENOENT;
- goto done;
- }
- }
-
- if (strcasecmp(mod_name, NO_PROVIDER) == 0) {
- ret = ENOENT;
- goto done;
- }
-
- if (bet_type == BET_ACCESS) {
- if (strcmp(mod_name, ACCESS_PERMIT) == 0) {
- (*bet_info).bet_ops = &be_target_access_permit_ops;
- (*bet_info).pvt_bet_data = NULL;
- (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_PERMIT);
-
- ret = EOK;
- goto done;
- }
- if (strcmp(mod_name, ACCESS_DENY) == 0) {
- (*bet_info).bet_ops = &be_target_access_deny_ops;
- (*bet_info).pvt_bet_data = NULL;
- (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_DENY);
-
- ret = EOK;
- goto done;
- }
- }
-
- mod_init_fn_name = talloc_asprintf(tmp_ctx,
- bet_data[bet_type].mod_init_fn_name_fmt,
- mod_name);
- if (mod_init_fn_name == NULL) {
- DEBUG(7, ("talloc_asprintf failed\n"));
- ret = ENOMEM;
- goto done;
- }
-
-
- lb = 0;
- while(ctx->loaded_be[lb].be_name != NULL) {
- if (strncmp(ctx->loaded_be[lb].be_name, mod_name,
- strlen(mod_name)) == 0) {
- DEBUG(7, ("Backend [%s] already loaded.\n", mod_name));
- already_loaded = true;
- break;
- }
-
- ++lb;
- if (lb >= BET_MAX) {
- DEBUG(2, ("Backend context corrupted.\n"));
- ret = EINVAL;
- goto done;
- }
- }
-
- if (!already_loaded) {
- path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
- DATA_PROVIDER_PLUGINS_PATH, mod_name);
- if (!path) {
- ret = ENOMEM;
- goto done;
- }
-
- DEBUG(7, ("Loading backend [%s] with path [%s].\n", mod_name, path));
- handle = dlopen(path, RTLD_NOW);
- if (!handle) {
- DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n",
- mod_name, path, dlerror()));
- ret = ELIBACC;
- goto done;
- }
-
- ctx->loaded_be[lb].be_name = talloc_strdup(ctx, mod_name);
- ctx->loaded_be[lb].handle = handle;
- }
-
- mod_init_fn = (bet_init_fn_t)dlsym(ctx->loaded_be[lb].handle,
- mod_init_fn_name);
- if (mod_init_fn == NULL) {
- if (default_mod_name != NULL &&
- strcmp(default_mod_name, mod_name) == 0 ) {
- /* If the default is used and fails we indicate this to the caller
- * by returning ENOENT. Ths way the caller can decide how to
- * handle the different types of error conditions. */
- ret = ENOENT;
- } else {
- DEBUG(0, ("Unable to load init fn %s from module %s, error: %s\n",
- mod_init_fn_name, mod_name, dlerror()));
- ret = ELIBBAD;
- }
- goto done;
- }
-
- ret = mod_init_fn(ctx, &(*bet_info).bet_ops, &(*bet_info).pvt_bet_data);
- if (ret != EOK) {
- DEBUG(0, ("Error (%d) in module (%s) initialization (%s)!\n",
- ret, mod_name, mod_init_fn_name));
- goto done;
- }
-
- (*bet_info).mod_name = talloc_strdup(ctx, mod_name);
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static void signal_be_offline(struct tevent_context *ev,
- struct tevent_signal *se,
- int signum,
- int count,
- void *siginfo,
- void *private_data)
-{
- struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
- be_mark_offline(ctx);
-}
-
-int be_process_init(TALLOC_CTX *mem_ctx,
- const char *be_domain,
- struct tevent_context *ev,
- struct confdb_ctx *cdb)
-{
- struct be_ctx *ctx;
- struct tevent_signal *tes;
- int ret;
-
- ctx = talloc_zero(mem_ctx, struct be_ctx);
- if (!ctx) {
- DEBUG(0, ("fatal error initializing be_ctx\n"));
- return ENOMEM;
- }
- ctx->ev = ev;
- ctx->cdb = cdb;
- ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain);
- ctx->conf_path = talloc_asprintf(ctx, CONFDB_DOMAIN_PATH_TMPL, be_domain);
- if (!ctx->identity || !ctx->conf_path) {
- DEBUG(0, ("Out of memory!?\n"));
- return ENOMEM;
- }
-
- ret = be_init_failover(ctx);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing failover context\n"));
- return ret;
- }
-
- ret = confdb_get_domain(cdb, be_domain, &ctx->domain);
- if (ret != EOK) {
- DEBUG(0, ("fatal error retrieving domain configuration\n"));
- return ret;
- }
-
- ret = sysdb_domain_init(ctx, ev, ctx->domain, DB_PATH, &ctx->sysdb);
- if (ret != EOK) {
- DEBUG(0, ("fatal error opening cache database\n"));
- return ret;
- }
-
- ret = mon_cli_init(ctx);
- if (ret != EOK) {
- DEBUG(0, ("fatal error setting up monitor bus\n"));
- return ret;
- }
-
- ret = be_srv_init(ctx);
- if (ret != EOK) {
- DEBUG(0, ("fatal error setting up server bus\n"));
- return ret;
- }
-
- ret = load_backend_module(ctx, BET_ID,
- &ctx->bet_info[BET_ID], NULL);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing data providers\n"));
- return ret;
- }
- DEBUG(9, ("ID backend target successfully loaded from provider [%s].\n",
- ctx->bet_info[BET_ID].mod_name));
-
- ret = load_backend_module(ctx, BET_AUTH,
- &ctx->bet_info[BET_AUTH],
- ctx->bet_info[BET_ID].mod_name);
- if (ret != EOK) {
- if (ret != ENOENT) {
- DEBUG(0, ("fatal error initializing data providers\n"));
- return ret;
- }
- DEBUG(1, ("No authentication module provided for [%s] !!\n",
- be_domain));
- } else {
- DEBUG(9, ("AUTH backend target successfully loaded "
- "from provider [%s].\n", ctx->bet_info[BET_AUTH].mod_name));
- }
-
- ret = load_backend_module(ctx, BET_ACCESS, &ctx->bet_info[BET_ACCESS],
- ACCESS_PERMIT);
- if (ret != EOK) {
- DEBUG(0, ("Failed to setup ACCESS backend.\n"));
- return ret;
- }
- DEBUG(9, ("ACCESS backend target successfully loaded "
- "from provider [%s].\n", ctx->bet_info[BET_ACCESS].mod_name));
-
- ret = load_backend_module(ctx, BET_CHPASS,
- &ctx->bet_info[BET_CHPASS],
- ctx->bet_info[BET_AUTH].mod_name);
- if (ret != EOK) {
- if (ret != ENOENT) {
- DEBUG(0, ("fatal error initializing data providers\n"));
- return ret;
- }
- DEBUG(1, ("No change password module provided for [%s] !!\n",
- be_domain));
- } else {
- DEBUG(9, ("CHPASS backend target successfully loaded "
- "from provider [%s].\n", ctx->bet_info[BET_CHPASS].mod_name));
- }
-
- /* Handle SIGUSR1 to force offline behavior */
- BlockSignals(false, SIGUSR1);
- tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
- signal_be_offline, ctx);
- if (tes == NULL) {
- return EIO;
- }
-
- return EOK;
-}
-
-int main(int argc, const char *argv[])
-{
- int opt;
- poptContext pc;
- char *be_domain = NULL;
- char *srv_name = NULL;
- char *conf_entry = NULL;
- struct main_context *main_ctx;
- int ret;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- SSSD_MAIN_OPTS
- {"domain", 0, POPT_ARG_STRING, &be_domain, 0,
- _("Domain of the information provider (mandatory)"), 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);
- return 1;
- }
- }
-
- if (be_domain == NULL) {
- fprintf(stderr, "\nMissing option, --domain is a mandatory option.\n\n");
- poptPrintUsage(pc, stderr, 0);
- return 1;
- }
-
- poptFreeContext(pc);
-
-
- /* set up things like debug , signals, daemonization, etc... */
- debug_log_file = talloc_asprintf(NULL, "sssd_%s", be_domain);
- if (!debug_log_file) return 2;
-
- srv_name = talloc_asprintf(NULL, "sssd[be[%s]]", be_domain);
- if (!srv_name) return 2;
-
- conf_entry = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, be_domain);
- if (!conf_entry) return 2;
-
- ret = server_setup(srv_name, 0, conf_entry, &main_ctx);
- if (ret != EOK) {
- DEBUG(0, ("Could not set up mainloop [%d]\n", ret));
- return 2;
- }
-
- ret = die_if_parent_died();
- if (ret != EOK) {
- /* This is not fatal, don't return */
- DEBUG(2, ("Could not set up to exit when parent process does\n"));
- }
-
- ret = be_process_init(main_ctx,
- be_domain,
- main_ctx->event_ctx,
- main_ctx->confdb_ctx);
- if (ret != EOK) {
- DEBUG(0, ("Could not initialize backend [%d]\n", ret));
- return 3;
- }
-
- DEBUG(1, ("Backend provider (%s) started!\n", be_domain));
-
- /* loop on main */
- server_loop(main_ctx);
-
- return 0;
-}
-
-static int data_provider_res_init(DBusMessage *message,
- struct sbus_connection *conn)
-{
- resolv_reread_configuration();
-
- return monitor_common_res_init(message, conn);
-}
-
-static int data_provider_go_offline(DBusMessage *message,
- struct sbus_connection *conn)
-{
- struct be_ctx *be_ctx;
- be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
- be_mark_offline(be_ctx);
- return monitor_common_pong(message, conn);
-}
diff --git a/server/providers/data_provider_fo.c b/server/providers/data_provider_fo.c
deleted file mode 100644
index 7d0240489..000000000
--- a/server/providers/data_provider_fo.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- SSSD
-
- Data Provider Helpers
-
- 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 <netdb.h>
-#include <arpa/inet.h>
-#include "providers/dp_backend.h"
-#include "resolv/async_resolv.h"
-
-struct be_svc_callback {
- struct be_svc_callback *prev;
- struct be_svc_callback *next;
-
- struct be_svc_data *svc;
-
- be_svc_callback_fn_t *fn;
- void *private_data;
-};
-
-struct be_svc_data {
- struct be_svc_data *prev;
- struct be_svc_data *next;
-
- const char *name;
- struct fo_service *fo_service;
-
- struct fo_server *last_good_srv;
-
- struct be_svc_callback *callbacks;
-};
-
-struct be_failover_ctx {
- struct fo_ctx *fo_ctx;
- struct resolv_ctx *resolv;
-
- struct be_svc_data *svcs;
-};
-
-int be_init_failover(struct be_ctx *ctx)
-{
- int ret;
-
- if (ctx->be_fo != NULL) {
- return EOK;
- }
-
- ctx->be_fo = talloc_zero(ctx, struct be_failover_ctx);
- if (!ctx->be_fo) {
- return ENOMEM;
- }
-
- ret = resolv_init(ctx, ctx->ev, 5, &ctx->be_fo->resolv);
- if (ret != EOK) {
- talloc_zfree(ctx->be_fo);
- return ret;
- }
-
- /* todo get timeout from configuration */
- ctx->be_fo->fo_ctx = fo_context_init(ctx->be_fo, 30);
- if (!ctx->be_fo->fo_ctx) {
- talloc_zfree(ctx->be_fo);
- return ENOMEM;
- }
-
- return EOK;
-}
-
-static int be_svc_data_destroy(void *memptr)
-{
- struct be_svc_data *svc;
-
- svc = talloc_get_type(memptr, struct be_svc_data);
-
- while (svc->callbacks) {
- /* callbacks removes themselves from the list,
- * so this while will freem them all and then terminate */
- talloc_free(svc->callbacks);
- }
-
- return 0;
-}
-
-int be_fo_add_service(struct be_ctx *ctx, const char *service_name)
-{
- struct fo_service *service;
- struct be_svc_data *svc;
- int ret;
-
- DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
- if (strcmp(svc->name, service_name) == 0) {
- DEBUG(6, ("Failover service already initialized!\n"));
- /* we already have a service up and configured,
- * can happen when using both id and auth provider
- */
- return EOK;
- }
- }
-
- /* if not in the be service list, try to create new one */
-
- ret = fo_new_service(ctx->be_fo->fo_ctx, service_name, &service);
- if (ret != EOK && ret != EEXIST) {
- DEBUG(1, ("Failed to create failover service!\n"));
- return ret;
- }
-
- svc = talloc_zero(ctx->be_fo, struct be_svc_data);
- if (!svc) {
- return ENOMEM;
- }
- talloc_set_destructor((TALLOC_CTX *)svc, be_svc_data_destroy);
-
- svc->name = talloc_strdup(svc, service_name);
- if (!svc->name) {
- talloc_zfree(svc);
- return ENOMEM;
- }
- svc->fo_service = service;
-
- DLIST_ADD(ctx->be_fo->svcs, svc);
-
- return EOK;
-}
-
-static int be_svc_callback_destroy(void *memptr)
-{
- struct be_svc_callback *callback;
-
- callback = talloc_get_type(memptr, struct be_svc_callback);
-
- if (callback->svc) {
- DLIST_REMOVE(callback->svc->callbacks, callback);
- }
-
- return 0;
-}
-
-int be_fo_service_add_callback(TALLOC_CTX *memctx,
- struct be_ctx *ctx, const char *service_name,
- be_svc_callback_fn_t *fn, void *private_data)
-{
- struct be_svc_callback *callback;
- struct be_svc_data *svc;
-
- DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
- if (strcmp(svc->name, service_name) == 0) {
- break;
- }
- }
- if (NULL == svc) {
- return ENOENT;
- }
-
- callback = talloc_zero(memctx, struct be_svc_callback);
- if (!callback) {
- return ENOMEM;
- }
- talloc_set_destructor((TALLOC_CTX *)callback, be_svc_callback_destroy);
-
- callback->svc = svc;
- callback->fn = fn;
- callback->private_data = private_data;
-
- DLIST_ADD(svc->callbacks, callback);
-
- return EOK;
-}
-
-int be_fo_add_server(struct be_ctx *ctx, const char *service_name,
- const char *server, int port, void *user_data)
-{
- struct be_svc_data *svc;
- int ret;
-
- DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
- if (strcmp(svc->name, service_name) == 0) {
- break;
- }
- }
- if (NULL == svc) {
- return ENOENT;
- }
-
- ret = fo_add_server(svc->fo_service, server, port, user_data);
- if (ret && ret != EEXIST) {
- DEBUG(1, ("Failed to add server to failover service\n"));
- return ret;
- }
-
- return EOK;
-}
-
-struct be_resolve_server_state {
- struct tevent_context *ev;
- struct be_ctx *ctx;
-
- struct be_svc_data *svc;
- int attempts;
-
- struct fo_server *srv;
-};
-
-static void be_resolve_server_done(struct tevent_req *subreq);
-
-struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct be_ctx *ctx,
- const char *service_name)
-{
- struct tevent_req *req, *subreq;
- struct be_resolve_server_state *state;
- struct be_svc_data *svc;
-
- req = tevent_req_create(memctx, &state, struct be_resolve_server_state);
- if (!req) return NULL;
-
- state->ev = ev;
- state->ctx = ctx;
-
- DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
- if (strcmp(svc->name, service_name) == 0) {
- state->svc = svc;
- break;
- }
- }
-
- if (NULL == svc) {
- tevent_req_error(req, EINVAL);
- tevent_req_post(req, ev);
- return req;
- }
-
- state->attempts = 0;
-
- subreq = fo_resolve_service_send(state, ev,
- ctx->be_fo->resolv, svc->fo_service);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, be_resolve_server_done, req);
-
- return req;
-}
-
-static void be_resolve_server_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct be_resolve_server_state *state = tevent_req_data(req,
- struct be_resolve_server_state);
- struct be_svc_callback *callback;
- int ret;
-
- ret = fo_resolve_service_recv(subreq, &state->srv);
- talloc_zfree(subreq);
- switch (ret) {
- case EOK:
- if (!state->srv) {
- tevent_req_error(req, EFAULT);
- return;
- }
- break;
-
- case ENOENT:
- /* all servers have been tried and none
- * was found good, go offline */
- tevent_req_error(req, EIO);
- return;
-
- default:
- /* mark server as bad and retry */
- if (!state->srv) {
- tevent_req_error(req, EFAULT);
- return;
- }
- DEBUG(6, ("Couldn't resolve server (%s), resolver returned (%d)\n",
- fo_get_server_name(state->srv), ret));
-
- state->attempts++;
- if (state->attempts >= 10) {
- DEBUG(2, ("Failed to find a server after 10 attempts\n"));
- tevent_req_error(req, EIO);
- return;
- }
-
- /* now try next one */
- DEBUG(6, ("Trying with the next one!\n"));
- subreq = fo_resolve_service_send(state, state->ev,
- state->ctx->be_fo->resolv,
- state->svc->fo_service);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, be_resolve_server_done, req);
-
- return;
- }
-
- /* all fine we got the server */
-
- if (debug_level >= 4) {
- struct hostent *srvaddr;
- char ipaddr[128];
- srvaddr = fo_get_server_hostent(state->srv);
- inet_ntop(srvaddr->h_addrtype, srvaddr->h_addr_list[0],
- ipaddr, 128);
-
- DEBUG(4, ("Found address for server %s: [%s]\n",
- fo_get_server_name(state->srv), ipaddr));
- }
-
- /* now call all svc callbacks if server changed */
- if (state->srv != state->svc->last_good_srv) {
- state->svc->last_good_srv = state->srv;
-
- DLIST_FOR_EACH(callback, state->svc->callbacks) {
- callback->fn(callback->private_data, state->srv);
- }
- }
-
- tevent_req_done(req);
-}
-
-int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv)
-{
- struct be_resolve_server_state *state = tevent_req_data(req,
- struct be_resolve_server_state);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- if (srv) {
- *srv = state->srv;
- }
-
- return EOK;
-}
-
diff --git a/server/providers/data_provider_opts.c b/server/providers/data_provider_opts.c
deleted file mode 100644
index 98283e430..000000000
--- a/server/providers/data_provider_opts.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- SSSD
-
- Data Provider Helpers
-
- 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 "data_provider.h"
-
-/* =Retrieve-Options====================================================== */
-
-int dp_get_options(TALLOC_CTX *memctx,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct dp_option *def_opts,
- int num_opts,
- struct dp_option **_opts)
-{
- struct dp_option *opts;
- int i, ret;
-
- opts = talloc_zero_array(memctx, struct dp_option, num_opts);
- if (!opts) return ENOMEM;
-
- for (i = 0; i < num_opts; i++) {
- char *tmp;
-
- opts[i].opt_name = def_opts[i].opt_name;
- opts[i].type = def_opts[i].type;
- opts[i].def_val = def_opts[i].def_val;
- ret = EOK;
-
- switch (def_opts[i].type) {
- case DP_OPT_STRING:
- ret = confdb_get_string(cdb, opts, conf_path,
- opts[i].opt_name,
- opts[i].def_val.cstring,
- &opts[i].val.string);
- if (ret != EOK ||
- ((opts[i].def_val.string != NULL) &&
- (opts[i].val.string == NULL))) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- if (ret == EOK) ret = EINVAL;
- goto done;
- }
- DEBUG(6, ("Option %s has value %s\n",
- opts[i].opt_name, opts[i].val.cstring));
- break;
-
- case DP_OPT_BLOB:
- ret = confdb_get_string(cdb, opts, conf_path,
- opts[i].opt_name,
- NULL, &tmp);
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
-
- if (tmp) {
- opts[i].val.blob.data = (uint8_t *)tmp;
- opts[i].val.blob.length = strlen(tmp);
- } else {
- opts[i].val.blob.data = NULL;
- opts[i].val.blob.length = 0;
- }
-
- DEBUG(6, ("Option %s has %s binary value.\n",
- opts[i].opt_name,
- opts[i].val.blob.length?"a":"no"));
- break;
-
- case DP_OPT_NUMBER:
- ret = confdb_get_int(cdb, opts, conf_path,
- opts[i].opt_name,
- opts[i].def_val.number,
- &opts[i].val.number);
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s has value %d\n",
- opts[i].opt_name, opts[i].val.number));
- break;
-
- case DP_OPT_BOOL:
- ret = confdb_get_bool(cdb, opts, conf_path,
- opts[i].opt_name,
- opts[i].def_val.boolean,
- &opts[i].val.boolean);
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s is %s\n",
- opts[i].opt_name,
- opts[i].val.boolean?"TRUE":"FALSE"));
- break;
- }
- }
-
- ret = EOK;
- *_opts = opts;
-
-done:
- if (ret != EOK) talloc_zfree(opts);
- return ret;
-}
-
-/* =Basic-Option-Helpers================================================== */
-
-int dp_copy_options(TALLOC_CTX *memctx,
- struct dp_option *src_opts,
- int num_opts,
- struct dp_option **_opts)
-{
- struct dp_option *opts;
- int i, ret;
-
- opts = talloc_zero_array(memctx, struct dp_option, num_opts);
- if (!opts) return ENOMEM;
-
- for (i = 0; i < num_opts; i++) {
- opts[i].opt_name = src_opts[i].opt_name;
- opts[i].type = src_opts[i].type;
- opts[i].def_val = src_opts[i].def_val;
- ret = EOK;
-
- switch (src_opts[i].type) {
- case DP_OPT_STRING:
- if (src_opts[i].val.string) {
- ret = dp_opt_set_string(opts, i, src_opts[i].val.string);
- } else if (src_opts[i].def_val.string) {
- ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string);
- }
- if (ret != EOK) {
- DEBUG(0, ("Failed to copy value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s has value %s\n",
- opts[i].opt_name, opts[i].val.cstring));
- break;
-
- case DP_OPT_BLOB:
- if (src_opts[i].val.blob.data) {
- ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob);
- } else if (src_opts[i].def_val.blob.data) {
- ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob);
- }
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s has %s binary value.\n",
- opts[i].opt_name,
- opts[i].val.blob.length?"a":"no"));
- break;
-
- case DP_OPT_NUMBER:
- if (src_opts[i].val.number) {
- ret = dp_opt_set_int(opts, i, src_opts[i].val.number);
- } else if (src_opts[i].def_val.number) {
- ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number);
- }
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s has value %d\n",
- opts[i].opt_name, opts[i].val.number));
- break;
-
- case DP_OPT_BOOL:
- if (src_opts[i].val.boolean) {
- ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean);
- } else if (src_opts[i].def_val.boolean) {
- ret = dp_opt_set_int(opts, i, src_opts[i].def_val.boolean);
- }
- if (ret != EOK) {
- DEBUG(0, ("Failed to retrieve value for option (%s)\n",
- opts[i].opt_name));
- goto done;
- }
- DEBUG(6, ("Option %s is %s\n",
- opts[i].opt_name,
- opts[i].val.boolean?"TRUE":"FALSE"));
- break;
- }
- }
-
- *_opts = opts;
-
-done:
- if (ret != EOK) talloc_zfree(opts);
- return ret;
-}
-
-static const char *dp_opt_type_to_string(enum dp_opt_type type)
-{
- switch (type) {
- case DP_OPT_STRING:
- return "String";
- case DP_OPT_BLOB:
- return "Blob";
- case DP_OPT_NUMBER:
- return "Number";
- case DP_OPT_BOOL:
- return "Boolean";
- }
- return NULL;
-}
-
-/* Getters */
-const char *_dp_opt_get_cstring(struct dp_option *opts,
- int id, const char *location)
-{
- if (opts[id].type != DP_OPT_STRING) {
- DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
- " but value is of type '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return NULL;
- }
- return opts[id].val.cstring;
-}
-
-char *_dp_opt_get_string(struct dp_option *opts,
- int id, const char *location)
-{
- if (opts[id].type != DP_OPT_STRING) {
- DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
- " but value is of type '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return NULL;
- }
- return opts[id].val.string;
-}
-
-struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
- int id, const char *location)
-{
- struct dp_opt_blob null_blob = { NULL, 0 };
- if (opts[id].type != DP_OPT_BLOB) {
- DEBUG(0, ("[%s] Requested type 'Blob' for option '%s'"
- " but value is of type '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return null_blob;
- }
- return opts[id].val.blob;
-}
-
-int _dp_opt_get_int(struct dp_option *opts,
- int id, const char *location)
-{
- if (opts[id].type != DP_OPT_NUMBER) {
- DEBUG(0, ("[%s] Requested type 'Number' for option '%s'"
- " but value is of type '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return 0;
- }
- return opts[id].val.number;
-}
-
-bool _dp_opt_get_bool(struct dp_option *opts,
- int id, const char *location)
-{
- if (opts[id].type != DP_OPT_BOOL) {
- DEBUG(0, ("[%s] Requested type 'Boolean' for option '%s'"
- " but value is of type '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return false;
- }
- return opts[id].val.boolean;
-}
-
-/* Setters */
-int _dp_opt_set_string(struct dp_option *opts, int id,
- const char *s, const char *location)
-{
- if (opts[id].type != DP_OPT_STRING) {
- DEBUG(0, ("[%s] Requested type 'String' for option '%s'"
- " but type is '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return EINVAL;
- }
-
- if (opts[id].val.string) {
- talloc_zfree(opts[id].val.string);
- }
- if (s) {
- opts[id].val.string = talloc_strdup(opts, s);
- if (!opts[id].val.string) {
- DEBUG(0, ("talloc_strdup() failed!\n"));
- return ENOMEM;
- }
- }
-
- return EOK;
-}
-
-int _dp_opt_set_blob(struct dp_option *opts, int id,
- struct dp_opt_blob b, const char *location)
-{
- if (opts[id].type != DP_OPT_BLOB) {
- DEBUG(0, ("[%s] Requested type 'Blob' for option '%s'"
- " but type is '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return EINVAL;
- }
-
- if (opts[id].val.blob.data) {
- talloc_zfree(opts[id].val.blob.data);
- opts[id].val.blob.length = 0;
- }
- if (b.data) {
- opts[id].val.blob.data = talloc_memdup(opts, b.data, b.length);
- if (!opts[id].val.blob.data) {
- DEBUG(0, ("talloc_memdup() failed!\n"));
- return ENOMEM;
- }
- }
- opts[id].val.blob.length = b.length;
-
- return EOK;
-}
-
-int _dp_opt_set_int(struct dp_option *opts, int id,
- int i, const char *location)
-{
- if (opts[id].type != DP_OPT_NUMBER) {
- DEBUG(0, ("[%s] Requested type 'Number' for option '%s'"
- " but type is '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return EINVAL;
- }
-
- opts[id].val.number = i;
-
- return EOK;
-}
-
-int _dp_opt_set_bool(struct dp_option *opts, int id,
- bool b, const char *location)
-{
- if (opts[id].type != DP_OPT_BOOL) {
- DEBUG(0, ("[%s] Requested type 'Boolean' for option '%s'"
- " but type is '%s'!\n",
- location, opts[id].opt_name,
- dp_opt_type_to_string(opts[id].type)));
- return EINVAL;
- }
-
- opts[id].val.boolean = b;
-
- return EOK;
-}
-
diff --git a/server/providers/dp_auth_util.c b/server/providers/dp_auth_util.c
deleted file mode 100644
index 39cc0f60f..000000000
--- a/server/providers/dp_auth_util.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- SSSD
-
- Data Provider, auth utils
-
- Copyright (C) Sumit Bose <sbose@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 "data_provider.h"
-
-void pam_print_data(int l, struct pam_data *pd)
-{
- DEBUG(l, ("command: %d\n", pd->cmd));
- DEBUG(l, ("domain: %s\n", pd->domain));
- DEBUG(l, ("user: %s\n", pd->user));
- DEBUG(l, ("service: %s\n", pd->service));
- DEBUG(l, ("tty: %s\n", pd->tty));
- DEBUG(l, ("ruser: %s\n", pd->ruser));
- DEBUG(l, ("rhost: %s\n", pd->rhost));
- DEBUG(l, ("authtok type: %d\n", pd->authtok_type));
- DEBUG(l, ("authtok size: %d\n", pd->authtok_size));
- DEBUG(l, ("newauthtok type: %d\n", pd->newauthtok_type));
- DEBUG(l, ("newauthtok size: %d\n", pd->newauthtok_size));
- DEBUG(l, ("priv: %d\n", pd->priv));
- DEBUG(l, ("pw_uid: %d\n", pd->pw_uid));
- DEBUG(l, ("gr_gid: %d\n", pd->gr_gid));
- DEBUG(l, ("cli_pid: %d\n", pd->cli_pid));
-}
-
-int pam_add_response(struct pam_data *pd, enum response_type type,
- int len, const uint8_t *data)
-{
- struct response_data *new;
-
- new = talloc(pd, struct response_data);
- if (new == NULL) return ENOMEM;
-
- new->type = type;
- new->len = len;
- new->data = talloc_memdup(pd, data, len);
- if (new->data == NULL) return ENOMEM;
- new->next = pd->resp_list;
- pd->resp_list = new;
-
- return EOK;
-}
-
-bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
-{
- int ret;
-
- if (pd->user == NULL || pd->domain == NULL) return false;
- if (pd->service == NULL) pd->service = talloc_strdup(pd, "");
- if (pd->tty == NULL) pd->tty = talloc_strdup(pd, "");
- if (pd->ruser == NULL) pd->ruser = talloc_strdup(pd, "");
- if (pd->rhost == NULL) pd->rhost = talloc_strdup(pd, "");
-
-
- ret = dbus_message_append_args(msg,
- DBUS_TYPE_INT32, &(pd->cmd),
- DBUS_TYPE_STRING, &(pd->domain),
- DBUS_TYPE_STRING, &(pd->user),
- DBUS_TYPE_STRING, &(pd->service),
- DBUS_TYPE_STRING, &(pd->tty),
- DBUS_TYPE_STRING, &(pd->ruser),
- DBUS_TYPE_STRING, &(pd->rhost),
- DBUS_TYPE_UINT32, &(pd->authtok_type),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->authtok),
- (pd->authtok_size),
- DBUS_TYPE_UINT32, &(pd->newauthtok_type),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->newauthtok),
- pd->newauthtok_size,
- DBUS_TYPE_INT32, &(pd->priv),
- DBUS_TYPE_INT32, &(pd->pw_uid),
- DBUS_TYPE_INT32, &(pd->gr_gid),
- DBUS_TYPE_UINT32, &(pd->cli_pid),
- DBUS_TYPE_INVALID);
-
- return ret;
-}
-
-bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
-{
- int ret;
-
- ret = dbus_message_get_args(msg, dbus_error,
- DBUS_TYPE_INT32, &(pd->cmd),
- DBUS_TYPE_STRING, &(pd->domain),
- DBUS_TYPE_STRING, &(pd->user),
- DBUS_TYPE_STRING, &(pd->service),
- DBUS_TYPE_STRING, &(pd->tty),
- DBUS_TYPE_STRING, &(pd->ruser),
- DBUS_TYPE_STRING, &(pd->rhost),
- DBUS_TYPE_UINT32, &(pd->authtok_type),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->authtok),
- &(pd->authtok_size),
- DBUS_TYPE_UINT32, &(pd->newauthtok_type),
- DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &(pd->newauthtok),
- &(pd->newauthtok_size),
- DBUS_TYPE_INT32, &(pd->priv),
- DBUS_TYPE_INT32, &(pd->pw_uid),
- DBUS_TYPE_INT32, &(pd->gr_gid),
- DBUS_TYPE_UINT32, &(pd->cli_pid),
- DBUS_TYPE_INVALID);
-
- return ret;
-}
-
-bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd)
-{
- dbus_bool_t dbret;
- struct response_data *resp;
- DBusMessageIter iter;
- DBusMessageIter array_iter;
- DBusMessageIter struct_iter;
- DBusMessageIter data_iter;
-
- dbus_message_iter_init_append(msg, &iter);
-
- /* Append the PAM status */
- dbret = dbus_message_iter_append_basic(&iter,
- DBUS_TYPE_UINT32, &(pd->pam_status));
- if (!dbret) {
- return false;
- }
-
- /* Append the domain */
- dbret = dbus_message_iter_append_basic(&iter,
- DBUS_TYPE_STRING, &(pd->domain));
- if (!dbret) {
- return false;
- }
-
- /* Create an array of response structures */
- dbret = dbus_message_iter_open_container(&iter,
- DBUS_TYPE_ARRAY, "(uay)",
- &array_iter);
- if (!dbret) {
- return false;
- }
-
- resp = pd->resp_list;
- while (resp != NULL) {
- /* Create a DBUS struct */
- dbret = dbus_message_iter_open_container(&array_iter,
- DBUS_TYPE_STRUCT, NULL,
- &struct_iter);
- if (!dbret) {
- return false;
- }
-
- /* Add the response type */
- dbret = dbus_message_iter_append_basic(&struct_iter,
- DBUS_TYPE_UINT32,
- &(resp->type));
- if (!dbret) {
- return false;
- }
-
- /* Add the response message */
- dbret = dbus_message_iter_open_container(&struct_iter,
- DBUS_TYPE_ARRAY, "y",
- &data_iter);
- if (!dbret) {
- return false;
- }
- dbret = dbus_message_iter_append_fixed_array(&data_iter,
- DBUS_TYPE_BYTE, &(resp->data), resp->len);
- if (!dbret) {
- return false;
- }
- dbret = dbus_message_iter_close_container(&struct_iter, &data_iter);
- if (!dbret) {
- return false;
- }
-
- resp = resp->next;
- dbret = dbus_message_iter_close_container(&array_iter, &struct_iter);
- if (!dbret) {
- return false;
- }
- }
-
- /* Close the struct array */
- dbret = dbus_message_iter_close_container(&iter, &array_iter);
- if (!dbret) {
- return false;
- }
-
- return true;
-}
-
-bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *dbus_error)
-{
- DBusMessageIter iter;
- DBusMessageIter array_iter;
- DBusMessageIter struct_iter;
- DBusMessageIter sub_iter;
- int type;
- int len;
- const uint8_t *data;
-
- if (!dbus_message_iter_init(msg, &iter)) {
- DEBUG(1, ("pam response has no arguments.\n"));
- return false;
- }
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
- dbus_message_iter_get_basic(&iter, &(pd->pam_status));
-
- if (!dbus_message_iter_next(&iter)) {
- DEBUG(1, ("pam response has too few arguments.\n"));
- return false;
- }
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
- dbus_message_iter_get_basic(&iter, &(pd->domain));
-
- if (!dbus_message_iter_next(&iter)) {
- DEBUG(1, ("pam response has too few arguments.\n"));
- return false;
- }
-
- /* After this point will be an array of pam data */
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
- DEBUG(1, ("pam response format error.\n"));
- DEBUG(1, ("Type was %c\n", (char)dbus_message_iter_get_arg_type(&iter)));
- return false;
- }
-
- if (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
-
- dbus_message_iter_recurse(&iter, &array_iter);
- while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID) {
- /* Read in a pam data struct */
- if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
-
- dbus_message_iter_recurse(&array_iter, &struct_iter);
-
- /* PAM data struct contains a type and a byte-array of data */
-
- /* Get the pam data type */
- if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_UINT32) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
- dbus_message_iter_get_basic(&struct_iter, &type);
-
- if (!dbus_message_iter_next(&struct_iter)) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
-
- /* Get the byte array */
- if (dbus_message_iter_get_arg_type(&struct_iter) != DBUS_TYPE_ARRAY ||
- dbus_message_iter_get_element_type(&struct_iter) != DBUS_TYPE_BYTE) {
- DEBUG(1, ("pam response format error.\n"));
- return false;
- }
-
- dbus_message_iter_recurse(&struct_iter, &sub_iter);
- dbus_message_iter_get_fixed_array(&sub_iter, &data, &len);
-
- pam_add_response(pd, type, len, data);
- dbus_message_iter_next(&array_iter);
- }
-
- return true;
-}
-
-static void id_callback(DBusPendingCall *pending, void *ptr)
-{
- DBusMessage *reply;
- DBusError dbus_error;
- dbus_bool_t ret;
- dbus_uint16_t dp_ver;
- int type;
-
- dbus_error_init(&dbus_error);
-
- reply = dbus_pending_call_steal_reply(pending);
- if (!reply) {
- /* reply should never be null. This function shouldn't be called
- * until reply is valid or timeout has occurred. If reply is NULL
- * here, something is seriously wrong and we should bail out.
- */
- DEBUG(0, ("Severe error. A reply callback was called but no"
- " reply was received and no timeout occurred\n"));
-
- /* FIXME: Destroy this connection ? */
- goto done;
- }
-
- type = dbus_message_get_type(reply);
- switch (type) {
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- ret = dbus_message_get_args(reply, &dbus_error,
- DBUS_TYPE_UINT16, &dp_ver,
- DBUS_TYPE_INVALID);
- if (!ret) {
- DEBUG(1, ("Failed to parse message\n"));
- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
- /* FIXME: Destroy this connection ? */
- goto done;
- }
-
- DEBUG(4, ("Got id ack and version (%d) from DP\n", dp_ver));
-
- break;
-
- case DBUS_MESSAGE_TYPE_ERROR:
- DEBUG(0,("The Monitor returned an error [%s]\n",
- dbus_message_get_error_name(reply)));
- /* Falling through to default intentionally*/
- default:
- /*
- * Timeout or other error occurred or something
- * unexpected happened.
- * It doesn't matter which, because either way we
- * know that this connection isn't trustworthy.
- * We'll destroy it now.
- */
-
- /* FIXME: Destroy this connection ? */
- break;
- }
-
-done:
- dbus_pending_call_unref(pending);
- dbus_message_unref(reply);
-}
-
-int dp_common_send_id(struct sbus_connection *conn, uint16_t version,
- const char *name, const char *domain)
-{
- DBusPendingCall *pending_reply;
- DBusConnection *dbus_conn;
- DBusMessage *msg;
- dbus_bool_t ret;
-
- dbus_conn = sbus_get_connection(conn);
-
- /* create the message */
- msg = dbus_message_new_method_call(NULL,
- DP_PATH,
- DP_INTERFACE,
- DP_METHOD_REGISTER);
- if (msg == NULL) {
- DEBUG(0, ("Out of memory?!\n"));
- return ENOMEM;
- }
-
- DEBUG(4, ("Sending ID to DP: (%d,%s,%s)\n",
- version, name, domain));
-
- ret = dbus_message_append_args(msg,
- DBUS_TYPE_UINT16, &version,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &domain,
- DBUS_TYPE_INVALID);
- if (!ret) {
- DEBUG(1, ("Failed to build message\n"));
- return EIO;
- }
-
- ret = dbus_connection_send_with_reply(dbus_conn, msg, &pending_reply,
- 30000 /* TODO: set timeout */);
- if (!ret || !pending_reply) {
- /*
- * Critical Failure
- * We can't communicate on this connection
- * We'll drop it using the default destructor.
- */
- DEBUG(0, ("D-BUS send failed.\n"));
- dbus_message_unref(msg);
- return EIO;
- }
-
- /* Set up the reply handler */
- dbus_pending_call_set_notify(pending_reply, id_callback, NULL, NULL);
- dbus_message_unref(msg);
-
- return EOK;
-}
-
diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h
deleted file mode 100644
index f1069d0db..000000000
--- a/server/providers/dp_backend.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- SSSD
-
- Data Provider, private header file
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
-
- 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 __DP_BACKEND_H__
-#define __DP_BACKEND_H__
-
-#include "providers/data_provider.h"
-#include "providers/fail_over.h"
-#include "db/sysdb.h"
-
-struct be_ctx;
-struct bet_ops;
-struct be_req;
-
-typedef int (*bet_init_fn_t)(TALLOC_CTX *, struct bet_ops **, void **);
-typedef void (*be_shutdown_fn)(void *);
-typedef void (*be_req_fn_t)(struct be_req *);
-typedef void (*be_async_callback_t)(struct be_req *, int, int, const char *);
-
-enum bet_type {
- BET_NULL = 0,
- BET_ID,
- BET_AUTH,
- BET_ACCESS,
- BET_CHPASS,
- BET_MAX
-};
-
-struct bet_data {
- enum bet_type bet_type;
- const char *option_name;
- const char *mod_init_fn_name_fmt;
-};
-
-struct loaded_be {
- char *be_name;
- void *handle;
-};
-
-struct bet_info {
- enum bet_type bet_type;
- struct bet_ops *bet_ops;
- void *pvt_bet_data;
- char *mod_name;
-};
-
-struct be_offline_status {
- time_t went_offline;
- bool offline;
-};
-
-struct be_client {
- struct be_ctx *bectx;
- struct sbus_connection *conn;
- struct tevent_timer *timeout;
- bool initialized;
-};
-
-struct be_failover_ctx;
-
-struct be_ctx {
- struct tevent_context *ev;
- struct confdb_ctx *cdb;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *domain;
- const char *identity;
- const char *conf_path;
- struct be_failover_ctx *be_fo;
-
- struct be_offline_status offstat;
-
- struct sbus_connection *mon_conn;
- struct sbus_connection *sbus_srv;
-
- struct be_client *nss_cli;
- struct be_client *pam_cli;
-
- struct loaded_be loaded_be[BET_MAX];
- struct bet_info bet_info[BET_MAX];
-};
-
-struct bet_ops {
- be_req_fn_t check_online;
- be_req_fn_t handler;
- be_req_fn_t finalize;
-};
-
-struct be_req {
- struct be_client *becli;
- struct be_ctx *be_ctx;
- void *req_data;
-
- be_async_callback_t fn;
- void *pvt;
-};
-
-struct be_acct_req {
- int entry_type;
- int attr_type;
- int filter_type;
- char *filter_value;
-};
-
-bool be_is_offline(struct be_ctx *ctx);
-void be_mark_offline(struct be_ctx *ctx);
-
-/* from data_provider_fo.c */
-typedef void (be_svc_callback_fn_t)(void *, struct fo_server *);
-
-int be_init_failover(struct be_ctx *ctx);
-int be_fo_add_service(struct be_ctx *ctx, const char *service_name);
-int be_fo_service_add_callback(TALLOC_CTX *memctx,
- struct be_ctx *ctx, const char *service_name,
- be_svc_callback_fn_t *fn, void *private_data);
-int be_fo_add_server(struct be_ctx *ctx, const char *service_name,
- const char *server, int port, void *user_data);
-
-struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct be_ctx *ctx,
- const char *service_name);
-int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
-
-#endif /* __DP_BACKEND_H___ */
diff --git a/server/providers/dp_sbus.c b/server/providers/dp_sbus.c
deleted file mode 100644
index f9dd28216..000000000
--- a/server/providers/dp_sbus.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- SSSD
-
- Data Provider Helpers
-
- Copyright (C) Stephen Gallagher <sgallagh@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 "config.h"
-#include "talloc.h"
-#include "tevent.h"
-#include "confdb/confdb.h"
-#include "sbus/sssd_dbus.h"
-#include "providers/data_provider.h"
-
-int dp_get_sbus_address(TALLOC_CTX *mem_ctx,
- char **address, const char *domain_name)
-{
- char *default_address;
-
- *address = NULL;
- default_address = talloc_asprintf(mem_ctx, "unix:path=%s/%s_%s",
- PIPE_PATH, DATA_PROVIDER_PIPE,
- domain_name);
- if (default_address == NULL) {
- return ENOMEM;
- }
-
- *address = default_address;
- return EOK;
-}
-
diff --git a/server/providers/fail_over.c b/server/providers/fail_over.c
deleted file mode 100644
index 7560b89ee..000000000
--- a/server/providers/fail_over.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- SSSD
-
- Fail over helper functions.
-
- Authors:
- Martin Nagy <mnagy@redhat.com>
-
- Copyright (C) Red Hat, Inc 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 <sys/time.h>
-
-#include <errno.h>
-#include <stdbool.h>
-#include <strings.h>
-#include <talloc.h>
-
-#include "util/dlinklist.h"
-#include "util/refcount.h"
-#include "util/util.h"
-#include "providers/fail_over.h"
-#include "resolv/async_resolv.h"
-
-#define STATUS_DIFF(p, now) ((now).tv_sec - (p)->last_status_change.tv_sec)
-#define SERVER_NAME(s) ((s)->common ? (s)->common->name : "(no name)")
-
-#define DEFAULT_PORT_STATUS PORT_NEUTRAL
-#define DEFAULT_SERVER_STATUS SERVER_NAME_NOT_RESOLVED
-
-struct fo_ctx {
- struct fo_service *service_list;
- struct server_common *server_common_list;
-
- /* Settings. */
- time_t retry_timeout;
-};
-
-struct fo_service {
- struct fo_service *prev;
- struct fo_service *next;
-
- struct fo_ctx *ctx;
- char *name;
- struct fo_server *active_server;
- struct fo_server *last_tried_server;
- struct fo_server *server_list;
-};
-
-struct fo_server {
- struct fo_server *prev;
- struct fo_server *next;
-
- void *user_data;
- int port;
- int port_status;
- struct fo_service *service;
- struct timeval last_status_change;
- struct server_common *common;
-};
-
-struct server_common {
- REFCOUNT_COMMON;
-
- struct server_common *prev;
- struct server_common *next;
-
- char *name;
- struct hostent *hostent;
- struct resolve_service_request *request_list;
- int server_status;
- struct timeval last_status_change;
-};
-
-struct resolve_service_request {
- struct resolve_service_request *prev;
- struct resolve_service_request *next;
-
- struct server_common *server_common;
- struct tevent_req *req;
-};
-
-struct status {
- int value;
- struct timeval last_change;
-};
-
-struct fo_ctx *
-fo_context_init(TALLOC_CTX *mem_ctx, time_t retry_timeout)
-{
- struct fo_ctx *ctx;
-
- ctx = talloc_zero(mem_ctx, struct fo_ctx);
- if (ctx == NULL) {
- DEBUG(1, ("No memory\n"));
- return NULL;
- }
-
- ctx->retry_timeout = retry_timeout;
-
- DEBUG(3, ("Created new fail over context, retry timeout is %d\n",
- retry_timeout));
- return ctx;
-}
-
-static const char *
-str_port_status(enum port_status status)
-{
- switch (status) {
- case PORT_NEUTRAL:
- return "neutral";
- case PORT_WORKING:
- return "working";
- case PORT_NOT_WORKING:
- return "not working";
- }
-
- return "unknown port status";
-}
-
-static const char *
-str_server_status(enum server_status status)
-{
- switch (status) {
- case SERVER_NAME_NOT_RESOLVED:
- return "name not resolved";
- case SERVER_RESOLVING_NAME:
- return "resolving name";
- case SERVER_NAME_RESOLVED:
- return "name resolved";
- case SERVER_WORKING:
- return "working";
- case SERVER_NOT_WORKING:
- return "not working";
- }
-
- return "unknown server status";
-}
-
-/*
- * This function will return the status of the server. If the status was
- * last updated a long time ago, we will first reset the status.
- */
-static enum server_status
-get_server_status(struct fo_server *server)
-{
- struct timeval tv;
- time_t timeout;
-
- if (server->common == NULL)
- return SERVER_NAME_RESOLVED;
-
- DEBUG(7, ("Status of server '%s' is '%s'\n", SERVER_NAME(server),
- str_server_status(server->common->server_status)));
-
- timeout = server->service->ctx->retry_timeout;
- if (timeout != 0 && server->common->server_status == SERVER_NOT_WORKING) {
- gettimeofday(&tv, NULL);
- if (STATUS_DIFF(server->common, tv) > timeout) {
- DEBUG(4, ("Reseting the server status of '%s'\n",
- SERVER_NAME(server)));
- server->common->server_status = SERVER_NAME_NOT_RESOLVED;
- server->last_status_change.tv_sec = 0;
- }
- }
-
- return server->common->server_status;
-}
-
-/*
- * This function will return the status of the service. If the status was
- * last updated a long time ago, we will first reset the status.
- */
-static enum port_status
-get_port_status(struct fo_server *server)
-{
- struct timeval tv;
- time_t timeout;
-
- DEBUG(7, ("Port status of port %d for server '%s' is '%s'\n", server->port,
- SERVER_NAME(server), str_port_status(server->port_status)));
-
- timeout = server->service->ctx->retry_timeout;
- if (timeout != 0 && server->port_status == PORT_NOT_WORKING) {
- gettimeofday(&tv, NULL);
- if (STATUS_DIFF(server, tv) > timeout) {
- DEBUG(4, ("Reseting the status of port %d for server '%s'\n",
- server->port, SERVER_NAME(server)));
- server->port_status = PORT_NEUTRAL;
- server->last_status_change.tv_sec = tv.tv_sec;
- }
- }
-
- return server->port_status;
-}
-
-static int
-server_works(struct fo_server *server)
-{
- if (get_server_status(server) == SERVER_NOT_WORKING)
- return 0;
-
- return 1;
-}
-
-static int
-service_works(struct fo_server *server)
-{
- if (!server_works(server))
- return 0;
- if (get_port_status(server) == PORT_NOT_WORKING)
- return 0;
-
- return 1;
-}
-
-static int
-service_destructor(struct fo_service *service)
-{
- DLIST_REMOVE(service->ctx->service_list, service);
- return 0;
-}
-
-int
-fo_new_service(struct fo_ctx *ctx, const char *name,
- struct fo_service **_service)
-{
- struct fo_service *service;
- int ret;
-
- DEBUG(3, ("Creating new service '%s'\n", name));
- ret = fo_get_service(ctx, name, &service);
- if (ret == EOK) {
- DEBUG(5, ("Service '%s' already exists\n", name));
- if (_service) {
- *_service = service;
- }
- return EEXIST;
- } else if (ret != ENOENT) {
- return ret;
- }
-
- service = talloc_zero(ctx, struct fo_service);
- if (service == NULL)
- return ENOMEM;
-
- service->name = talloc_strdup(service, name);
- if (service->name == NULL) {
- talloc_free(service);
- return ENOMEM;
- }
-
- service->ctx = ctx;
- DLIST_ADD(ctx->service_list, service);
-
- talloc_set_destructor(service, service_destructor);
- if (_service) {
- *_service = service;
- }
-
- return EOK;
-}
-
-int
-fo_get_service(struct fo_ctx *ctx, const char *name,
- struct fo_service **_service)
-{
- struct fo_service *service;
-
- DLIST_FOR_EACH(service, ctx->service_list) {
- if (!strcmp(name, service->name)) {
- *_service = service;
- return EOK;
- }
- }
-
- return ENOENT;
-}
-
-static int
-get_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name,
- struct server_common **_common)
-{
- struct server_common *common;
-
- DLIST_FOR_EACH(common, ctx->server_common_list) {
- if (!strcmp(name, common->name)) {
- *_common = rc_reference(mem_ctx, struct server_common, common);
- if (_common == NULL)
- return ENOMEM;
- return EOK;
- }
- }
-
- return ENOENT;
-}
-
-static struct server_common *
-create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
-{
- struct server_common *common;
-
- common = rc_alloc(mem_ctx, struct server_common);
- if (common == NULL)
- return NULL;
-
- common->name = talloc_strdup(common, name);
- if (common->name == NULL) {
- talloc_free(common);
- return NULL;
- }
-
- common->prev = NULL;
- common->next = NULL;
- common->hostent = NULL;
- common->request_list = NULL;
- common->server_status = DEFAULT_SERVER_STATUS;
- common->last_status_change.tv_sec = 0;
- common->last_status_change.tv_usec = 0;
-
- DLIST_ADD_END(ctx->server_common_list, common, struct server_common *);
- return common;
-}
-
-int
-fo_add_server(struct fo_service *service, const char *name, int port,
- void *user_data)
-{
- struct fo_server *server;
- int ret;
-
- DEBUG(3, ("Adding new server '%s', to service '%s'\n",
- name ? name : "(no name)", service->name));
- DLIST_FOR_EACH(server, service->server_list) {
- if (server->port != port || server->user_data != user_data)
- continue;
- if (name == NULL && server->common == NULL) {
- return EEXIST;
- } else if (name != NULL && server->common != NULL) {
- if (!strcmp(name, server->common->name))
- return EEXIST;
- }
- }
-
- server = talloc_zero(service, struct fo_server);
- if (server == NULL)
- return ENOMEM;
-
- server->port = port;
- server->user_data = user_data;
- server->service = service;
- server->port_status = DEFAULT_PORT_STATUS;
-
- if (name != NULL) {
- ret = get_server_common(server, service->ctx, name, &server->common);
- if (ret == ENOENT) {
- server->common = create_server_common(server, service->ctx, name);
- if (server->common == NULL) {
- talloc_free(server);
- return ENOMEM;
- }
- } else if (ret != EOK) {
- talloc_free(server);
- return ret;
- }
- }
-
- DLIST_ADD_END(service->server_list, server, struct fo_server *);
-
- return EOK;
-}
-
-static int
-get_first_server_entity(struct fo_service *service, struct fo_server **_server)
-{
- struct fo_server *server;
-
- /* If we already have a working server, use that one. */
- server = service->active_server;
- if (server != NULL) {
- if (service_works(server)) {
- goto done;
- }
- service->active_server = NULL;
- }
-
- /*
- * Otherwise iterate through the server list.
- */
-
- /* First, try servers after the last one we tried. */
- if (service->last_tried_server != NULL) {
- DLIST_FOR_EACH(server, service->last_tried_server->next) {
- if (service_works(server)) {
- goto done;
- }
- }
- }
-
- /* If none were found, try at the start. */
- DLIST_FOR_EACH(server, service->server_list) {
- if (service_works(server)) {
- goto done;
- }
- if (server == service->last_tried_server) {
- break;
- }
- }
-
- service->last_tried_server = NULL;
- return ENOENT;
-
-done:
- service->last_tried_server = server;
- *_server = server;
- return EOK;
-}
-
-static int
-resolve_service_request_destructor(struct resolve_service_request *request)
-{
- DLIST_REMOVE(request->server_common->request_list, request);
- return 0;
-}
-
-static int
-set_lookup_hook(struct fo_server *server, struct tevent_req *req)
-{
- struct resolve_service_request *request;
-
- request = talloc(req, struct resolve_service_request);
- if (request == NULL) {
- DEBUG(1, ("No memory\n"));
- talloc_free(request);
- return ENOMEM;
- }
- request->server_common = server->common;
- request->req = req;
- DLIST_ADD(server->common->request_list, request);
- talloc_set_destructor(request, resolve_service_request_destructor);
-
- return EOK;
-}
-
-/*******************************************************************
- * Get server to connect to. *
- *******************************************************************/
-
-struct resolve_service_state {
- struct fo_server *server;
-};
-
-static void fo_resolve_service_done(struct tevent_req *subreq);
-
-struct tevent_req *
-fo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- struct resolv_ctx *resolv, struct fo_service *service)
-{
- int ret;
- struct fo_server *server;
- struct tevent_req *req;
- struct tevent_req *subreq;
- struct resolve_service_state *state;
-
- DEBUG(4, ("Trying to resolve service '%s'\n", service->name));
- req = tevent_req_create(mem_ctx, &state, struct resolve_service_state);
- if (req == NULL)
- return NULL;
-
- ret = get_first_server_entity(service, &server);
- if (ret != EOK) {
- DEBUG(1, ("No available servers for service '%s'\n", service->name));
- goto done;
- }
-
- state->server = server;
-
- if (server->common == NULL) {
- /* This server doesn't have a name, we don't do name resolution. */
- tevent_req_done(req);
- tevent_req_post(req, ev);
- return req;
- }
-
- switch (get_server_status(server)) {
- case SERVER_NAME_NOT_RESOLVED: /* Request name resolution. */
- subreq = resolv_gethostbyname_send(server->common, ev, resolv,
- server->common->name);
- if (subreq == NULL) {
- ret = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(subreq, fo_resolve_service_done, server->common);
- fo_set_server_status(server, SERVER_RESOLVING_NAME);
- /* FALLTHROUGH */
- case SERVER_RESOLVING_NAME:
- /* Name resolution is already under way. Just add ourselves into the
- * waiting queue so we get notified after the operation is finished. */
- ret = set_lookup_hook(server, req);
- if (ret != EOK)
- goto done;
- break;
- default: /* The name is already resolved. Return immediately. */
- tevent_req_done(req);
- tevent_req_post(req, ev);
- break;
- }
-
-done:
- if (ret != EOK) {
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- }
- return req;
-}
-
-static void set_server_common_status(struct server_common *common,
- enum server_status status);
-
-static void
-fo_resolve_service_done(struct tevent_req *subreq)
-{
- int resolv_status;
- struct resolve_service_request *request;
- struct server_common *common;
- int ret;
-
- common = tevent_req_callback_data(subreq, struct server_common);
-
- if (common->hostent != NULL) {
- talloc_zfree(common->hostent);
- }
-
- ret = resolv_gethostbyname_recv(subreq, common,
- &resolv_status, NULL, &common->hostent);
- talloc_free(subreq);
- if (ret != EOK) {
- DEBUG(1, ("Failed to resolve server '%s': %s\n", common->name,
- resolv_strerror(resolv_status)));
- set_server_common_status(common, SERVER_NOT_WORKING);
- } else {
- set_server_common_status(common, SERVER_NAME_RESOLVED);
- }
-
- /* Take care of all requests for this server. */
- while ((request = common->request_list) != NULL) {
- DLIST_REMOVE(common->request_list, request);
- if (resolv_status) {
- /* FIXME FIXME: resolv_status is an ARES error.
- * but any caller will expect classic error codes.
- * also the send() function may return ENOENT, so this mix
- * IS explosive (ENOENT = 2 = ARES_EFORMER) */
- tevent_req_error(request->req, resolv_status);
- } else {
- tevent_req_done(request->req);
- }
- }
-}
-
-int
-fo_resolve_service_recv(struct tevent_req *req, struct fo_server **server)
-{
- struct resolve_service_state *state;
-
- state = tevent_req_data(req, struct resolve_service_state);
-
- /* always return the server if asked for, otherwise the caller
- * cannot mark it as faulty in case we return an error */
- if (server)
- *server = state->server;
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-static void
-set_server_common_status(struct server_common *common,
- enum server_status status)
-{
- DEBUG(4, ("Marking server '%s' as '%s'\n", common->name,
- str_server_status(status)));
-
- common->server_status = status;
- gettimeofday(&common->last_status_change, NULL);
-}
-
-void
-fo_set_server_status(struct fo_server *server, enum server_status status)
-{
- if (server->common == NULL) {
- DEBUG(1, ("Bug: Trying to set server status of a name-less server\n"));
- return;
- }
-
- set_server_common_status(server->common, status);
-}
-
-void
-fo_set_port_status(struct fo_server *server, enum port_status status)
-{
- DEBUG(4, ("Marking port %d of server '%s' as '%s'\n", server->port,
- SERVER_NAME(server), str_port_status(status)));
-
- server->port_status = status;
- gettimeofday(&server->last_status_change, NULL);
- if (status == PORT_WORKING) {
- fo_set_server_status(server, SERVER_WORKING);
- server->service->active_server = server;
- }
-}
-
-void *
-fo_get_server_user_data(struct fo_server *server)
-{
- return server->user_data;
-}
-
-int
-fo_get_server_port(struct fo_server *server)
-{
- return server->port;
-}
-
-const char *fo_get_server_name(struct fo_server *server)
-{
- return server->common->name;
-}
-
-struct hostent *
-fo_get_server_hostent(struct fo_server *server)
-{
- if (server->common == NULL) {
- DEBUG(1, ("Bug: Trying to get hostent from a name-less server\n"));
- return NULL;
- }
- return server->common->hostent;
-}
diff --git a/server/providers/fail_over.h b/server/providers/fail_over.h
deleted file mode 100644
index e581fbaf5..000000000
--- a/server/providers/fail_over.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef __FAIL_OVER_H__
-#define __FAIL_OVER_H__
-
-#include <stdbool.h>
-#include <talloc.h>
-
-/* Some forward declarations that don't have to do anything with fail over. */
-struct hostent;
-struct resolv_ctx;
-struct tevent_context;
-struct tevent_req;
-
-enum port_status {
- PORT_NEUTRAL, /* We didn't try this port yet. */
- PORT_WORKING, /* This port was reported to work. */
- PORT_NOT_WORKING /* This port was reported to not work. */
-};
-
-enum server_status {
- SERVER_NAME_NOT_RESOLVED, /* We didn't yet resolved the host name. */
- SERVER_RESOLVING_NAME, /* Name resolving is in progress. */
- SERVER_NAME_RESOLVED, /* We resolved the host name but didn't try to connect. */
- SERVER_WORKING, /* We successfully connected to the server. */
- SERVER_NOT_WORKING /* We tried and failed to connect to the server. */
-};
-
-struct fo_ctx;
-struct fo_service;
-struct fo_server;
-
-/*
- * Create a new fail over context. The 'retry_timeout' argument specifies the
- * duration in seconds of how long a server or port will be considered
- * non-working after being marked as such.
- */
-struct fo_ctx *fo_context_init(TALLOC_CTX *mem_ctx,
- time_t retry_timeout);
-
-/*
- * Create a new service structure for 'ctx', saving it to the location pointed
- * to by '_service'. The needed memory will be allocated from 'ctx'.
- * Service name will be set to 'name'.
- */
-int fo_new_service(struct fo_ctx *ctx,
- const char *name,
- struct fo_service **_service);
-
-/*
- * Look up service named 'name' from the 'ctx' service list. Target of
- * '_service' will be set to the service if it was found.
- */
-int fo_get_service(struct fo_ctx *ctx,
- const char *name,
- struct fo_service **_service);
-
-/*
- * Adds a server 'name' to the 'service'. Port 'port' will be used for
- * connection. If 'name' is NULL, no server resolution will be done.
- */
-int fo_add_server(struct fo_service *service,
- const char *name,
- int port,
- void *user_data);
-
-/*
- * Request the first server from the service's list of servers. It is only
- * considered if it is not marked as not working (or the retry interval already
- * passed). If the server address wasn't resolved yet, it will be done.
- */
-struct tevent_req *fo_resolve_service_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct resolv_ctx *resolv,
- struct fo_service *service);
-
-int fo_resolve_service_recv(struct tevent_req *req,
- struct fo_server **server);
-
-/*
- * Set feedback about 'server'. Caller should use this to indicate a problem
- * with the server itself, not only with the service on that server. This
- * should be used, for example, when the IP address of the server can't be
- * reached. This setting can affect other services as well, since they can
- * share the same server.
- */
-void fo_set_server_status(struct fo_server *server,
- enum server_status status);
-
-/*
- * Set feedback about the port status. This function should be used when
- * the server itself is working but the service is not. When status is set
- * to PORT_WORKING, 'server' is also marked as an "active server" for its
- * service. When the next fo_resolve_service_send() function is called, this
- * server will be preferred. This will hold as long as it is not marked as
- * not-working.
- */
-void fo_set_port_status(struct fo_server *server,
- enum port_status status);
-
-
-void *fo_get_server_user_data(struct fo_server *server);
-
-int fo_get_server_port(struct fo_server *server);
-
-const char *fo_get_server_name(struct fo_server *server);
-
-struct hostent *fo_get_server_hostent(struct fo_server *server);
-
-#endif /* !__FAIL_OVER_H__ */
diff --git a/server/providers/ipa/ipa_access.c b/server/providers/ipa/ipa_access.c
deleted file mode 100644
index 7dfe1fd90..000000000
--- a/server/providers/ipa/ipa_access.c
+++ /dev/null
@@ -1,1823 +0,0 @@
-/*
- SSSD
-
- IPA Backend Module -- Access control
-
- Authors:
- Sumit Bose <sbose@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/param.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "providers/ldap/sdap_async.h"
-#include "providers/ipa/ipa_common.h"
-#include "providers/ipa/ipa_access.h"
-#include "providers/ipa/ipa_timerules.h"
-
-#define IPA_HOST_MEMBEROF "memberOf"
-#define IPA_HOST_SERVERHOSTNAME "serverHostName"
-#define IPA_HOST_FQDN "fqdn"
-#define IPA_ACCESS_RULE_TYPE "accessRuleType"
-#define IPA_MEMBER_USER "memberUser"
-#define IPA_USER_CATEGORY "userCategory"
-#define IPA_SERVICE_NAME "serviceName"
-#define IPA_SOURCE_HOST "sourceHost"
-#define IPA_SOURCE_HOST_CATEGORY "sourceHostCategory"
-#define IPA_EXTERNAL_HOST "externalHost"
-#define IPA_ACCESS_TIME "accessTime"
-#define IPA_UNIQUE_ID "ipauniqueid"
-#define IPA_ENABLED_FLAG "ipaenabledflag"
-#define IPA_MEMBER_HOST "memberHost"
-#define IPA_HOST_CATEGORY "hostCategory"
-#define IPA_CN "cn"
-
-#define IPA_HOST_BASE_TMPL "cn=computers,cn=accounts,dc=%s"
-#define IPA_HBAC_BASE_TMPL "cn=hbac,dc=%s"
-
-#define SYSDB_HBAC_BASE_TMPL "cn=hbac,"SYSDB_TMPL_CUSTOM_BASE
-
-#define HBAC_RULES_SUBDIR "hbac_rules"
-#define HBAC_HOSTS_SUBDIR "hbac_hosts"
-
-static errno_t msgs2attrs_array(TALLOC_CTX *mem_ctx, size_t count,
- struct ldb_message **msgs,
- struct sysdb_attrs ***attrs)
-{
- int i;
- struct sysdb_attrs **a;
-
- a = talloc_array(mem_ctx, struct sysdb_attrs *, count);
- if (a == NULL) {
- DEBUG(1, ("talloc_array failed.\n"));
- return ENOMEM;
- }
-
- for (i = 0; i < count; i++) {
- a[i] = talloc(a, struct sysdb_attrs);
- if (a[i] == NULL) {
- DEBUG(1, ("talloc_array failed.\n"));
- talloc_free(a);
- return ENOMEM;
- }
- a[i]->num = msgs[i]->num_elements;
- a[i]->a = talloc_steal(a[i], msgs[i]->elements);
- }
-
- *attrs = a;
-
- return EOK;
-}
-
-static void ipa_access_reply(struct be_req *be_req, int pam_status)
-{
- struct pam_data *pd;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
- pd->pam_status = pam_status;
-
- if (pam_status == PAM_SUCCESS) {
- be_req->fn(be_req, DP_ERR_OK, pam_status, NULL);
- } else {
- be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
- }
-}
-
-struct hbac_get_user_info_state {
- struct tevent_context *ev;
- struct be_ctx *be_ctx;;
- struct sysdb_handle *handle;
-
- const char *user;
- const char *user_orig_dn;
- struct ldb_dn *user_dn;
- size_t groups_count;
- const char **groups;
-};
-
-static void search_user_done(struct tevent_req *subreq);
-static void search_groups_done(struct tevent_req *subreq);
-
-struct tevent_req *hbac_get_user_info_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct be_ctx *be_ctx,
- const char *user)
-{
- struct tevent_req *req = NULL;
- struct tevent_req *subreq = NULL;
- struct hbac_get_user_info_state *state;
- int ret;
- const char **attrs;
-
- req = tevent_req_create(memctx, &state, struct hbac_get_user_info_state);
- if (req == NULL) {
- DEBUG(1, ("tevent_req_create failed.\n"));
- return NULL;
- }
-
- state->ev = ev;
- state->be_ctx = be_ctx;
- state->handle = NULL;
- state->user = user;
- state->user_orig_dn = NULL;
- state->user_dn = NULL;
- state->groups_count = 0;
- state->groups = NULL;
-
- attrs = talloc_array(state, const char *, 2);
- if (attrs == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- attrs[0] = SYSDB_ORIG_DN;
- attrs[1] = NULL;
-
- subreq = sysdb_search_user_by_name_send(state, ev, be_ctx->sysdb, NULL,
- be_ctx->domain, user, attrs);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_search_user_by_name_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, search_user_done, req);
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void search_user_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_user_info_state *state = tevent_req_data(req,
- struct hbac_get_user_info_state);
- int ret;
- const char **attrs;
- const char *dummy;
- struct ldb_message *user_msg;
-
-
- ret = sysdb_search_user_recv(subreq, state, &user_msg);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- DEBUG(9, ("Found user info for user [%s].\n", state->user));
- state->user_dn = talloc_steal(state, user_msg->dn);
- dummy = ldb_msg_find_attr_as_string(user_msg, SYSDB_ORIG_DN, NULL);
- if (dummy == NULL) {
- DEBUG(1, ("Original DN of user [%s] not available.\n", state->user));
- ret = EINVAL;
- goto failed;
- }
- state->user_orig_dn = talloc_strdup(state, dummy);
- if (state->user_dn == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- ret = ENOMEM;
- goto failed;
- }
- DEBUG(9, ("Found original DN [%s] for user [%s].\n", state->user_orig_dn,
- state->user));
-
- attrs = talloc_array(state, const char *, 2);
- if (attrs == NULL) {
- DEBUG(1, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto failed;
- }
- attrs[0] = SYSDB_ORIG_DN;
- attrs[1] = NULL;
-
- subreq = sysdb_asq_search_send(state, state->ev, state->be_ctx->sysdb, NULL,
- state->be_ctx->domain, state->user_dn, NULL,
- SYSDB_MEMBEROF, attrs);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_asq_search_send failed.\n"));
- ret = ENOMEM;
- goto failed;
- }
-
- tevent_req_set_callback(subreq, search_groups_done, req);
- return;
-
-failed:
- tevent_req_error(req, ret);
- return;
-}
-
-static void search_groups_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_user_info_state *state = tevent_req_data(req,
- struct hbac_get_user_info_state);
- int ret;
- int i;
- struct ldb_message **msg;
-
- ret = sysdb_asq_search_recv(subreq, state, &state->groups_count, &msg);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- if (state->groups_count == 0) {
- tevent_req_done(req);
- return;
- }
-
- state->groups = talloc_array(state, const char *, state->groups_count);
- if (state->groups == NULL) {
- DEBUG(1, ("talloc_groups failed.\n"));
- ret = ENOMEM;
- goto failed;
- }
-
- for(i = 0; i < state->groups_count; i++) {
- if (msg[i]->num_elements != 1) {
- DEBUG(1, ("Unexpected number of elements.\n"));
- ret = EINVAL;
- goto failed;
- }
-
- if (msg[i]->elements[0].num_values != 1) {
- DEBUG(1, ("Unexpected number of values.\n"));
- ret = EINVAL;
- goto failed;
- }
-
- state->groups[i] = talloc_strndup(state->groups,
- (const char *) msg[i]->elements[0].values[0].data,
- msg[i]->elements[0].values[0].length);
- if (state->groups[i] == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- ret = ENOMEM;
- goto failed;
- }
-
- DEBUG(9, ("Found group [%s].\n", state->groups[i]));
- }
-
- tevent_req_done(req);
- return;
-
-failed:
- talloc_free(state->groups);
- tevent_req_error(req, ret);
- return;
-}
-
-static int hbac_get_user_info_recv(struct tevent_req *req, TALLOC_CTX *memctx,
- const char **user_dn, size_t *groups_count,
- const char ***groups)
-{
- struct hbac_get_user_info_state *state = tevent_req_data(req,
- struct hbac_get_user_info_state);
- int i;
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *user_dn = talloc_steal(memctx, state->user_orig_dn);
- *groups_count = state->groups_count;
- for (i = 0; i < state->groups_count; i++) {
- talloc_steal(memctx, state->groups[i]);
- }
- *groups = talloc_steal(memctx, state->groups);
-
- return EOK;
-}
-
-
-struct hbac_get_host_info_state {
- struct tevent_context *ev;
- struct sdap_id_ctx *sdap_ctx;
- struct sysdb_ctx *sysdb;
- struct sysdb_handle *handle;
- bool offline;
-
- char *host_filter;
- char *host_search_base;
- const char **host_attrs;
-
- struct sysdb_attrs **host_reply_list;
- size_t host_reply_count;
- size_t current_item;
- struct hbac_host_info **hbac_host_info;
-};
-
-static void hbac_get_host_info_connect_done(struct tevent_req *subreq);
-static void hbac_get_host_memberof_done(struct tevent_req *subreq);
-static void hbac_get_host_info_sysdb_transaction_started(struct tevent_req *subreq);
-static void hbac_get_host_info_store_prepare(struct tevent_req *req);
-static void hbac_get_host_info_store_done(struct tevent_req *subreq);
-
-static struct tevent_req *hbac_get_host_info_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- bool offline,
- struct sdap_id_ctx *sdap_ctx,
- struct sysdb_ctx *sysdb,
- const char *ipa_domain,
- const char **hostnames)
-{
- struct tevent_req *req = NULL;
- struct tevent_req *subreq = NULL;
- struct hbac_get_host_info_state *state;
- int ret;
- int i;
-
- if (hostnames == NULL || ipa_domain == NULL) {
- DEBUG(1, ("Missing hostnames or domain.\n"));
- return NULL;
- }
-
- req = tevent_req_create(memctx, &state, struct hbac_get_host_info_state);
- if (req == NULL) {
- DEBUG(1, ("tevent_req_create failed.\n"));
- return NULL;
- }
-
- state->ev = ev;
- state->sdap_ctx = sdap_ctx;
- state->sysdb = sysdb;
- state->handle = NULL;
- state->offline = offline;
-
- state->host_reply_list = NULL;
- state->host_reply_count = 0;
- state->current_item = 0;
- state->hbac_host_info = NULL;
-
- state->host_filter = talloc_asprintf(state, "(|");
- if (state->host_filter == NULL) {
- DEBUG(1, ("Failed to create filter.\n"));
- ret = ENOMEM;
- goto fail;
- }
- for (i = 0; hostnames[i] != NULL; i++) {
- state->host_filter = talloc_asprintf_append(state->host_filter,
- "(&(objectclass=ipaHost)"
- "(|(fqdn=%s)(serverhostname=%s)))",
- hostnames[i], hostnames[i]);
- if (state->host_filter == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- }
- state->host_filter = talloc_asprintf_append(state->host_filter, ")");
- if (state->host_filter == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- state->host_search_base = talloc_asprintf(state, IPA_HOST_BASE_TMPL,
- ipa_domain);
- if (state->host_search_base == NULL) {
- DEBUG(1, ("Failed to create host search base.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- state->host_attrs = talloc_array(state, const char *, 7);
- if (state->host_attrs == NULL) {
- DEBUG(1, ("Failed to allocate host attribute list.\n"));
- ret = ENOMEM;
- goto fail;
- }
- state->host_attrs[0] = IPA_HOST_MEMBEROF;
- state->host_attrs[1] = IPA_HOST_SERVERHOSTNAME;
- state->host_attrs[2] = IPA_HOST_FQDN;
- state->host_attrs[3] = "objectClass";
- state->host_attrs[4] = SYSDB_ORIG_DN;
- state->host_attrs[5] = SYSDB_ORIG_MEMBEROF;
- state->host_attrs[6] = NULL;
-
- if (offline) {
- subreq = sysdb_search_custom_send(state, state->ev, state->sysdb, NULL,
- state->sdap_ctx->be->domain,
- state->host_filter, HBAC_HOSTS_SUBDIR,
- state->host_attrs);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_search_custom_send.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_host_memberof_done, req);
-
- return req;
- }
-
- if (sdap_ctx->gsh == NULL || ! sdap_ctx->gsh->connected) {
- if (sdap_ctx->gsh != NULL) {
- talloc_zfree(sdap_ctx->gsh);
- }
-
- subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts,
- sdap_ctx->be, sdap_ctx->service, NULL);
- if (!subreq) {
- DEBUG(1, ("sdap_cli_connect_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_host_info_connect_done, req);
-
- return req;
- }
-
- subreq = sdap_get_generic_send(state, state->ev,
- state->sdap_ctx->opts,
- state->sdap_ctx->gsh,
- state->host_search_base,
- LDAP_SCOPE_SUB,
- state->host_filter,
- state->host_attrs,
- NULL, 0);
-
- if (subreq == NULL) {
- DEBUG(1, ("sdap_get_generic_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_host_memberof_done, req);
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void hbac_get_host_info_connect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
- int ret;
-
- ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh,
- NULL);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sdap_get_generic_send(state, state->ev,
- state->sdap_ctx->opts,
- state->sdap_ctx->gsh,
- state->host_search_base,
- LDAP_SCOPE_SUB,
- state->host_filter,
- state->host_attrs,
- NULL, 0);
-
- if (subreq == NULL) {
- DEBUG(1, ("sdap_get_generic_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_host_memberof_done, req);
-
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_get_host_memberof_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
- int ret;
- int i;
- int v;
- struct ldb_message_element *el;
- struct hbac_host_info **hhi;
- struct ldb_message **msgs;
-
- if (state->offline) {
- ret = sysdb_search_custom_recv(subreq, state, &state->host_reply_count,
- &msgs);
- } else {
- ret = sdap_get_generic_recv(subreq, state, &state->host_reply_count,
- &state->host_reply_list);
- }
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- if (state->host_reply_count == 0) {
- DEBUG(1, ("No hosts not found in IPA server.\n"));
- ret = ENOENT;
- goto fail;
- }
-
- if (state->offline) {
- ret = msgs2attrs_array(state, state->host_reply_count, msgs,
- &state->host_reply_list);
- talloc_zfree(msgs);
- if (ret != EOK) {
- DEBUG(1, ("msgs2attrs_array failed.\n"));
- goto fail;
- }
- }
-
- hhi = talloc_array(state, struct hbac_host_info *, state->host_reply_count + 1);
- if (hhi == NULL) {
- DEBUG(1, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- memset(hhi, 0,
- sizeof(struct hbac_host_info *) * (state->host_reply_count + 1));
-
- for (i = 0; i < state->host_reply_count; i++) {
- hhi[i] = talloc_zero(hhi, struct hbac_host_info);
- if (hhi[i] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_get_el(state->host_reply_list[i], SYSDB_ORIG_DN, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- ret = EINVAL;
- goto fail;
- }
- DEBUG(9, ("OriginalDN: [%.*s].\n", el->values[0].length,
- (char *)el->values[0].data));
- hhi[i]->dn = talloc_strndup(hhi, (char *)el->values[0].data,
- el->values[0].length);
- if (hhi[i]->dn == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_get_el(state->host_reply_list[i],
- IPA_HOST_SERVERHOSTNAME, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- ret = EINVAL;
- goto fail;
- }
- DEBUG(9, ("ServerHostName: [%.*s].\n", el->values[0].length,
- (char *)el->values[0].data));
- hhi[i]->serverhostname = talloc_strndup(hhi, (char *)el->values[0].data,
- el->values[0].length);
- if (hhi[i]->serverhostname == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_get_el(state->host_reply_list[i],
- IPA_HOST_FQDN, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- ret = EINVAL;
- goto fail;
- }
- DEBUG(9, ("FQDN: [%.*s].\n", el->values[0].length,
- (char *)el->values[0].data));
- hhi[i]->fqdn = talloc_strndup(hhi, (char *)el->values[0].data,
- el->values[0].length);
- if (hhi[i]->fqdn == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_get_el(state->host_reply_list[i],
- state->offline ? SYSDB_ORIG_MEMBEROF :
- IPA_HOST_MEMBEROF,
- &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
-
- hhi[i]->memberof = talloc_array(hhi, const char *, el->num_values + 1);
- if (hhi[i]->memberof == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- memset(hhi[i]->memberof, 0,
- sizeof(const char *) * (el->num_values + 1));
-
- for(v = 0; v < el->num_values; v++) {
- DEBUG(9, ("%s: [%.*s].\n", IPA_HOST_MEMBEROF, el->values[v].length,
- (const char *)el->values[v].data));
- hhi[i]->memberof[v] = talloc_strndup(hhi,
- (const char *)el->values[v].data,
- el->values[v].length);
- if (hhi[i]->memberof[v] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- }
- }
-
- state->hbac_host_info = hhi;
-
- if (state->offline) {
- tevent_req_done(req);
- return;
- }
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_transaction_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, hbac_get_host_info_sysdb_transaction_started, req);
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_get_host_info_sysdb_transaction_started(
- struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
- int ret;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- state->current_item = 0;
- hbac_get_host_info_store_prepare(req);
- return;
-}
-
-static void hbac_get_host_info_store_prepare(struct tevent_req *req)
-{
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
- int ret;
- char *object_name;
- struct ldb_message_element *el;
- struct tevent_req *subreq;
-
- if (state->current_item < state->host_reply_count) {
- ret = sysdb_attrs_get_el(state->host_reply_list[state->current_item],
- IPA_HOST_FQDN, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- ret = EINVAL;
- goto fail;
- }
- object_name = talloc_strndup(state, (const char *)el->values[0].data,
- el->values[0].length);
- if (object_name == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- DEBUG(9, ("Fqdn [%s].\n", object_name));
-
-
- ret = sysdb_attrs_replace_name(
- state->host_reply_list[state->current_item],
- IPA_HOST_MEMBEROF, SYSDB_ORIG_MEMBEROF);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_replace_name failed.\n"));
- goto fail;
- }
-
- subreq = sysdb_store_custom_send(state, state->ev,
- state->handle,
- state->sdap_ctx->be->domain,
- object_name,
- HBAC_HOSTS_SUBDIR,
- state->host_reply_list[state->current_item]);
-
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_store_custom_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_host_info_store_done, req);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_transaction_commit_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
-
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_get_host_info_store_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
- int ret;
-
- ret = sysdb_store_custom_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- state->current_item++;
- hbac_get_host_info_store_prepare(req);
-}
-
-static int hbac_get_host_info_recv(struct tevent_req *req, TALLOC_CTX *memctx,
- struct hbac_host_info ***hhi)
-{
- struct hbac_get_host_info_state *state = tevent_req_data(req,
- struct hbac_get_host_info_state);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *hhi = talloc_steal(memctx, state->hbac_host_info);
- return EOK;
-}
-
-
-struct hbac_get_rules_state {
- struct tevent_context *ev;
- struct sdap_id_ctx *sdap_ctx;
- struct sysdb_ctx *sysdb;
- struct sysdb_handle *handle;
- bool offline;
-
- const char *host_dn;
- const char **memberof;
- char *hbac_filter;
- char *hbac_search_base;
- const char **hbac_attrs;
-
- struct ldb_message *old_rules;
- struct sysdb_attrs **hbac_reply_list;
- size_t hbac_reply_count;
- int current_item;
-};
-
-static void hbac_get_rules_connect_done(struct tevent_req *subreq);
-static void hbac_rule_get_done(struct tevent_req *subreq);
-static void hbac_rule_sysdb_transaction_started(struct tevent_req *subreq);
-static void hbac_rule_sysdb_delete_done(struct tevent_req *subreq);
-static void hbac_rule_store_prepare(struct tevent_req *req);
-static void hbac_rule_store_done(struct tevent_req *subreq);
-
-static struct tevent_req *hbac_get_rules_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- bool offline,
- struct sdap_id_ctx *sdap_ctx,
- struct sysdb_ctx *sysdb,
- const char *ipa_domain,
- const char *host_dn,
- const char **memberof)
-{
- struct tevent_req *req = NULL;
- struct tevent_req *subreq = NULL;
- struct hbac_get_rules_state *state;
- int ret;
- int i;
-
- if (host_dn == NULL || ipa_domain == NULL) {
- DEBUG(1, ("Missing host_dn or domain.\n"));
- return NULL;
- }
-
- req = tevent_req_create(memctx, &state, struct hbac_get_rules_state);
- if (req == NULL) {
- DEBUG(1, ("tevent_req_create failed.\n"));
- return NULL;
- }
-
- state->ev = ev;
- state->offline = offline;
- state->sdap_ctx = sdap_ctx;
- state->sysdb = sysdb;
- state->handle = NULL;
- state->host_dn = host_dn;
- state->memberof = memberof;
-
- state->old_rules = NULL;
- state->hbac_reply_list = NULL;
- state->hbac_reply_count = 0;
- state->current_item = 0;
-
- state->hbac_search_base = talloc_asprintf(state, IPA_HBAC_BASE_TMPL,
- ipa_domain);
- if (state->hbac_search_base == NULL) {
- DEBUG(1, ("Failed to create HBAC search base.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- state->hbac_attrs = talloc_array(state, const char *, 16);
- if (state->hbac_attrs == NULL) {
- DEBUG(1, ("Failed to allocate HBAC attribute list.\n"));
- ret = ENOMEM;
- goto fail;
- }
- state->hbac_attrs[0] = IPA_ACCESS_RULE_TYPE;
- state->hbac_attrs[1] = IPA_MEMBER_USER;
- state->hbac_attrs[2] = IPA_USER_CATEGORY;
- state->hbac_attrs[3] = IPA_SERVICE_NAME;
- state->hbac_attrs[4] = IPA_SOURCE_HOST;
- state->hbac_attrs[5] = IPA_SOURCE_HOST_CATEGORY;
- state->hbac_attrs[6] = IPA_EXTERNAL_HOST;
- state->hbac_attrs[7] = IPA_ACCESS_TIME;
- state->hbac_attrs[8] = IPA_UNIQUE_ID;
- state->hbac_attrs[9] = IPA_ENABLED_FLAG;
- state->hbac_attrs[10] = IPA_CN;
- state->hbac_attrs[11] = "objectclass";
- state->hbac_attrs[12] = IPA_MEMBER_HOST;
- state->hbac_attrs[13] = IPA_HOST_CATEGORY;
- state->hbac_attrs[14] = SYSDB_ORIG_DN;
- state->hbac_attrs[15] = NULL;
-
- state->hbac_filter = talloc_asprintf(state,
- "(&(objectclass=ipaHBACRule)"
- "(|(%s=%s)(%s=%s)",
- IPA_HOST_CATEGORY, "all",
- IPA_MEMBER_HOST, host_dn);
- if (state->hbac_filter == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- for (i = 0; memberof[i] != NULL; i++) {
- state->hbac_filter = talloc_asprintf_append(state->hbac_filter,
- "(%s=%s)",
- IPA_MEMBER_HOST,
- memberof[i]);
- if (state->hbac_filter == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- }
- state->hbac_filter = talloc_asprintf_append(state->hbac_filter, "))");
- if (state->hbac_filter == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- DEBUG(9, ("HBAC rule filter: [%s].\n", state->hbac_filter));
-
- if (offline) {
- subreq = sysdb_search_custom_send(state, state->ev, state->sysdb, NULL,
- state->sdap_ctx->be->domain,
- state->hbac_filter, HBAC_RULES_SUBDIR,
- state->hbac_attrs);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_search_custom_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_rule_get_done, req);
-
- return req;
- }
-
- if (sdap_ctx->gsh == NULL || ! sdap_ctx->gsh->connected) {
- if (sdap_ctx->gsh != NULL) {
- talloc_zfree(sdap_ctx->gsh);
- }
-
- subreq = sdap_cli_connect_send(state, ev, sdap_ctx->opts,
- sdap_ctx->be, sdap_ctx->service, NULL);
- if (!subreq) {
- DEBUG(1, ("sdap_cli_connect_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_get_rules_connect_done, req);
-
- return req;
- }
-
- subreq = sdap_get_generic_send(state, state->ev,
- state->sdap_ctx->opts,
- state->sdap_ctx->gsh,
- state->hbac_search_base,
- LDAP_SCOPE_SUB,
- state->hbac_filter,
- state->hbac_attrs,
- NULL, 0);
-
- if (subreq == NULL) {
- DEBUG(1, ("sdap_get_generic_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_rule_get_done, req);
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void hbac_get_rules_connect_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
-
- ret = sdap_cli_connect_recv(subreq, state->sdap_ctx, &state->sdap_ctx->gsh,
- NULL);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sdap_get_generic_send(state, state->ev,
- state->sdap_ctx->opts,
- state->sdap_ctx->gsh,
- state->hbac_search_base,
- LDAP_SCOPE_SUB,
- state->hbac_filter,
- state->hbac_attrs,
- NULL, 0);
-
- if (subreq == NULL) {
- DEBUG(1, ("sdap_get_generic_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_rule_get_done, req);
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_rule_get_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
- int i;
- struct ldb_message_element *el;
- struct ldb_message **msgs;
-
- if (state->offline) {
- ret = sysdb_search_custom_recv(subreq, state, &state->hbac_reply_count,
- &msgs);
- } else {
- ret = sdap_get_generic_recv(subreq, state, &state->hbac_reply_count,
- &state->hbac_reply_list);
- }
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- if (state->offline) {
- ret = msgs2attrs_array(state, state->hbac_reply_count, msgs,
- &state->hbac_reply_list);
- talloc_zfree(msgs);
- if (ret != EOK) {
- DEBUG(1, ("msgs2attrs_array failed.\n"));
- goto fail;
- }
- }
-
- for (i = 0; i < state->hbac_reply_count; i++) {
- ret = sysdb_attrs_get_el(state->hbac_reply_list[i], SYSDB_ORIG_DN, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- DEBUG(1, ("Missing original DN.\n"));
- ret = EINVAL;
- goto fail;
- }
- DEBUG(9, ("OriginalDN: [%s].\n", (const char *)el->values[0].data));
- }
-
- if (state->hbac_reply_count == 0 || state->offline) {
- tevent_req_done(req);
- return;
- }
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_transaction_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, hbac_rule_sysdb_transaction_started, req);
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_rule_sysdb_transaction_started(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
- struct ldb_dn *hbac_base_dn;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- hbac_base_dn = sysdb_custom_subtree_dn(state->sysdb, state,
- state->sdap_ctx->be->domain->name,
- HBAC_RULES_SUBDIR);
- if (hbac_base_dn == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- subreq = sysdb_delete_recursive_send(state, state->ev, state->handle,
- hbac_base_dn, true);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_delete_recursive_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, hbac_rule_sysdb_delete_done, req);
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_rule_sysdb_delete_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
-
- ret = sysdb_delete_recursive_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- state->current_item = 0;
- hbac_rule_store_prepare(req);
-}
-
-static void hbac_rule_store_prepare(struct tevent_req *req)
-{
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
- struct ldb_message_element *el;
- struct tevent_req *subreq;
- char *object_name;
-
- if (state->current_item < state->hbac_reply_count) {
-
- ret = sysdb_attrs_get_el(state->hbac_reply_list[state->current_item],
- IPA_UNIQUE_ID, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- goto fail;
- }
- if (el->num_values == 0) {
- ret = EINVAL;
- goto fail;
- }
- object_name = talloc_strndup(state, (const char *)el->values[0].data,
- el->values[0].length);
- if (object_name == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- DEBUG(9, ("IPAUniqueId: [%s].\n", object_name));
-
- subreq = sysdb_store_custom_send(state, state->ev,
- state->handle,
- state->sdap_ctx->be->domain,
- object_name,
- HBAC_RULES_SUBDIR,
- state->hbac_reply_list[state->current_item]);
-
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_store_custom_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- tevent_req_set_callback(subreq, hbac_rule_store_done, req);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (subreq == NULL) {
- DEBUG(1, ("sysdb_transaction_commit_send failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
-
- return;
-
-fail:
- tevent_req_error(req, ret);
- return;
-}
-
-static void hbac_rule_store_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int ret;
-
- ret = sysdb_store_custom_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- state->current_item++;
- hbac_rule_store_prepare(req);
-}
-
-static int hbac_get_rules_recv(struct tevent_req *req, TALLOC_CTX *memctx,
- size_t *hbac_rule_count,
- struct sysdb_attrs ***hbac_rule_list)
-{
- struct hbac_get_rules_state *state = tevent_req_data(req,
- struct hbac_get_rules_state);
- int i;
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *hbac_rule_count = state->hbac_reply_count;
- *hbac_rule_list = talloc_steal(memctx, state->hbac_reply_list);
- for (i = 0; i < state->hbac_reply_count; i++) {
- talloc_steal(memctx, state->hbac_reply_list[i]);
- }
- return EOK;
-}
-
-enum hbac_result {
- HBAC_ALLOW = 1,
- HBAC_DENY,
- HBAC_NOT_APPLICABLE
-};
-
-enum check_result {
- RULE_APPLICABLE = 0,
- RULE_NOT_APPLICABLE,
- RULE_ERROR
-};
-
-enum check_result check_service(struct pam_data *pd,
- struct sysdb_attrs *rule_attrs)
-{
- int ret;
- int i;
- struct ldb_message_element *el;
-
- if (pd->service == NULL) {
- DEBUG(1, ("No service in pam data, assuming error.\n"));
- return RULE_ERROR;
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_SERVICE_NAME, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- if (el->num_values == 0) {
- DEBUG(9, ("No services in rule specified, assuming rule applies.\n"));
- return RULE_APPLICABLE;
- } else {
- for (i = 0; i < el->num_values; i++) {
- if (strncasecmp(pd->service, (const char *) el->values[i].data,
- el->values[i].length) == 0) {
- DEBUG(9, ("Service [%s] found, rule applies.\n",
- pd->service));
- return RULE_APPLICABLE;
- }
- }
- DEBUG(9, ("No matching service found, rule does not apply.\n"));
- return RULE_NOT_APPLICABLE;
- }
-
- return RULE_ERROR;
-}
-
-enum check_result check_access_time(struct time_rules_ctx *tr_ctx,
- struct sysdb_attrs *rule_attrs)
-{
- int ret;
- int i;
- TALLOC_CTX *tmp_ctx = NULL;
- struct ldb_message_element *el;
- char *rule;
- time_t now;
- bool result;
-
- now = time(NULL);
- if (now == (time_t) -1) {
- DEBUG(1, ("time failed [%d][%s].\n", errno, strerror(errno)));
- return RULE_ERROR;
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_ACCESS_TIME, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- if (el->num_values == 0) {
- DEBUG(9, ("No access time specified, assuming rule applies.\n"));
- return RULE_APPLICABLE;
- } else {
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return RULE_ERROR;
- }
-
- for (i = 0; i < el->num_values; i++) {
- rule = talloc_strndup(tmp_ctx, (const char *) el->values[i].data,
- el->values[i].length);
- ret = check_time_rule(tmp_ctx, tr_ctx, rule, now, &result);
- if (ret != EOK) {
- DEBUG(1, ("check_time_rule failed.\n"));
- ret = RULE_ERROR;
- goto done;
- }
-
- if (result) {
- DEBUG(9, ("Current time [%d] matches rule [%s].\n", now, rule));
- ret = RULE_APPLICABLE;
- goto done;
- }
- }
- }
-
- ret = RULE_NOT_APPLICABLE;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-enum check_result check_user(struct hbac_ctx *hbac_ctx,
- struct sysdb_attrs *rule_attrs)
-{
- int ret;
- int i;
- int g;
- struct ldb_message_element *el;
-
- if (hbac_ctx->user_dn == NULL) {
- DEBUG(1, ("No user DN available, this should never happen.\n"));
- return RULE_ERROR;
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_USER_CATEGORY, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- if (el->num_values == 0) {
- DEBUG(9, ("USer category is not set.\n"));
- } else {
- for (i = 0; i < el->num_values; i++) {
- if (strncasecmp("all", (const char *) el->values[i].data,
- el->values[i].length) == 0) {
- DEBUG(9, ("User category is set to 'all', rule applies.\n"));
- return RULE_APPLICABLE;
- }
- DEBUG(9, ("Unsupported user category [%.*s].\n",
- el->values[i].length,
- (char *) el->values[i].data));
- }
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_USER, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- if (el->num_values == 0) {
- DEBUG(9, ("No user specified, rule does not apply.\n"));
- return RULE_APPLICABLE;
- } else {
- for (i = 0; i < el->num_values; i++) {
- DEBUG(9, ("Searching matches for [%.*s].\n", el->values[i].length,
- (const char *) el->values[i].data));
- DEBUG(9, ("Checking user [%s].\n", hbac_ctx->user_dn));
- if (strncmp(hbac_ctx->user_dn, (const char *) el->values[i].data,
- el->values[i].length) == 0) {
- DEBUG(9, ("User [%s] found, rule applies.\n",
- hbac_ctx->user_dn));
- return RULE_APPLICABLE;
- }
-
- for (g = 0; g < hbac_ctx->groups_count; g++) {
- DEBUG(9, ("Checking group [%s].\n", hbac_ctx->groups[g]));
- if (strncmp(hbac_ctx->groups[g],
- (const char *) el->values[i].data,
- el->values[i].length) == 0) {
- DEBUG(9, ("Group [%s] found, rule applies.\n",
- hbac_ctx->groups[g]));
- return RULE_APPLICABLE;
- }
- }
- }
- DEBUG(9, ("No matching user found, rule does not apply.\n"));
- return RULE_NOT_APPLICABLE;
- }
-
- return RULE_ERROR;
-}
-
-enum check_result check_remote_hosts(const char *rhost,
- struct hbac_host_info *hhi,
- struct sysdb_attrs *rule_attrs)
-{
- int ret;
- int i;
- int m;
- struct ldb_message_element *cat_el;
- struct ldb_message_element *src_el;
- struct ldb_message_element *ext_el;
-
- if (hhi == NULL && (rhost == NULL || *rhost == '\0')) {
- DEBUG(1, ("No remote host information specified, assuming error.\n"));
- return RULE_ERROR;
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST_CATEGORY, &cat_el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- if (cat_el->num_values == 0) {
- DEBUG(9, ("Source host category not set.\n"));
- } else {
- for(i = 0; i < cat_el->num_values; i++) {
- if (strncasecmp("all", (const char *) cat_el->values[i].data,
- cat_el->values[i].length) == 0) {
- DEBUG(9, ("Source host category is set to 'all', "
- "rule applies.\n"));
- return RULE_APPLICABLE;
- }
- DEBUG(9, ("Unsupported source hosts category [%.*s].\n",
- cat_el->values[i].length,
- (char *) cat_el->values[i].data));
- }
- }
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_SOURCE_HOST, &src_el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
- ret = sysdb_attrs_get_el(rule_attrs, IPA_EXTERNAL_HOST, &ext_el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return RULE_ERROR;
- }
-
- if (src_el->num_values == 0 && ext_el->num_values == 0) {
- DEBUG(9, ("No remote host specified in rule, rule does not apply.\n"));
- return RULE_NOT_APPLICABLE;
- } else {
- if (hhi != NULL) {
- for (i = 0; i < src_el->num_values; i++) {
- if (strncasecmp(hhi->dn, (const char *) src_el->values[i].data,
- src_el->values[i].length) == 0) {
- DEBUG(9, ("Source host [%s] found, rule applies.\n",
- hhi->dn));
- return RULE_APPLICABLE;
- }
- for (m = 0; hhi->memberof[m] != NULL; m++) {
- if (strncasecmp(hhi->memberof[m],
- (const char *) src_el->values[i].data,
- src_el->values[i].length) == 0) {
- DEBUG(9, ("Source host group [%s] found, rule applies.\n",
- hhi->memberof[m]));
- return RULE_APPLICABLE;
- }
- }
- }
- }
-
- if (rhost != NULL && *rhost != '\0') {
- for (i = 0; i < ext_el->num_values; i++) {
- if (strncasecmp(rhost, (const char *) ext_el->values[i].data,
- ext_el->values[i].length) == 0) {
- DEBUG(9, ("External host [%s] found, rule applies.\n",
- rhost));
- return RULE_APPLICABLE;
- }
- }
- }
- DEBUG(9, ("No matching remote host found.\n"));
- return RULE_NOT_APPLICABLE;
- }
-
- return RULE_ERROR;
-}
-
-static errno_t check_if_rule_applies(enum hbac_result *result,
- struct hbac_ctx *hbac_ctx,
- struct sysdb_attrs *rule_attrs) {
- int ret;
- struct ldb_message_element *el;
- enum hbac_result rule_type;
- char *rule_name;
- struct pam_data *pd = hbac_ctx->pd;
-
- ret = sysdb_attrs_get_el(rule_attrs, IPA_CN, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return ret;
- }
- if (el->num_values == 0) {
- DEBUG(4, ("rule has no name, assuming '(none)'.\n"));
- rule_name = talloc_strdup(rule_attrs, "(none)");
- } else {
- rule_name = talloc_strndup(rule_attrs, (const char*) el->values[0].data,
- el->values[0].length);
- }
- if (rule_name == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- return ENOMEM;
- }
- DEBUG(9, ("Processsing rule [%s].\n", rule_name));
-
- /* rule type */
- ret = sysdb_attrs_get_el(rule_attrs, IPA_ACCESS_RULE_TYPE, &el);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_get_el failed.\n"));
- return ret;
- }
- if (el->num_values == 0) {
- DEBUG(4, ("rule has no type, assuming 'deny'.\n"));
- rule_type = HBAC_DENY;
- } else if (el->num_values == 1) {
- if (strncasecmp((const char *) el->values[0].data, "allow",
- el->values[0].length) == 0) {
- rule_type = HBAC_ALLOW;
- } else {
- rule_type = HBAC_DENY;
- }
- } else {
- DEBUG(1, ("rule has an unsupported number of values [%d].\n",
- el->num_values));
- return EINVAL;
- }
-
- ret = check_service(pd, rule_attrs);
- if (ret != RULE_APPLICABLE) {
- goto not_applicable;
- }
-
- ret = check_user(hbac_ctx, rule_attrs);
- if (ret != RULE_APPLICABLE) {
- goto not_applicable;
- }
-
- ret = check_access_time(hbac_ctx->tr_ctx, rule_attrs);
- if (ret != RULE_APPLICABLE) {
- goto not_applicable;
- }
-
- ret = check_remote_hosts(pd->rhost, hbac_ctx->remote_hhi, rule_attrs);
- if (ret != RULE_APPLICABLE) {
- goto not_applicable;
- }
-
- *result = rule_type;
-
- return EOK;
-
-not_applicable:
- if (ret == RULE_NOT_APPLICABLE) {
- *result = HBAC_NOT_APPLICABLE;
- } else {
- *result = HBAC_DENY;
- }
- return EOK;
-}
-
-static int evaluate_ipa_hbac_rules(struct hbac_ctx *hbac_ctx,
- bool *access_allowed)
-{
- bool allow_matched = false;
- enum hbac_result result;
- int ret;
- int i;
-
- *access_allowed = false;
-
- for (i = 0; i < hbac_ctx->hbac_rule_count ; i++) {
-
- ret = check_if_rule_applies(&result, hbac_ctx,
- hbac_ctx->hbac_rule_list[i]);
- if (ret != EOK) {
- DEBUG(1, ("check_if_rule_applies failed.\n"));
- return ret;
- }
-
- switch (result) {
- case HBAC_DENY:
- DEBUG(3, ("Access denied by single rule.\n"));
- return EOK;
- break;
- case HBAC_ALLOW:
- allow_matched = true;
- DEBUG(9, ("Current rule allows access.\n"));
- break;
- default:
- DEBUG(9, ("Current rule does not apply.\n"));
- }
-
- }
-
- *access_allowed = allow_matched;
-
- return EOK;
-}
-
-static void hbac_get_host_info_done(struct tevent_req *req);
-static void hbac_get_rules_done(struct tevent_req *req);
-static void hbac_get_user_info_done(struct tevent_req *req);
-
-void ipa_access_handler(struct be_req *be_req)
-{
- struct tevent_req *req;
- struct pam_data *pd;
- struct hbac_ctx *hbac_ctx;
- int pam_status = PAM_SYSTEM_ERR;
- struct ipa_access_ctx *ipa_access_ctx;
- const char *hostlist[3];
-
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- hbac_ctx = talloc_zero(be_req, struct hbac_ctx);
- if (hbac_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- goto fail;
- }
- hbac_ctx->be_req = be_req;
- hbac_ctx->pd = pd;
- ipa_access_ctx = talloc_get_type(
- be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
- struct ipa_access_ctx);
- hbac_ctx->sdap_ctx = ipa_access_ctx->sdap_ctx;
- hbac_ctx->ipa_options = ipa_access_ctx->ipa_options;
- hbac_ctx->tr_ctx = ipa_access_ctx->tr_ctx;
- hbac_ctx->offline = be_is_offline(be_req->be_ctx);
-
- DEBUG(9, ("Connection status is [%s].\n", hbac_ctx->offline ? "offline" :
- "online"));
-
-
- hostlist[0] = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
- if (hostlist[0] == NULL) {
- DEBUG(1, ("ipa_hostname not available.\n"));
- goto fail;
- }
- if (pd->rhost != NULL && *pd->rhost != '\0') {
- hostlist[1] = pd->rhost;
- } else {
- hostlist[1] = NULL;
- pd->rhost = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME);
- if (pd->rhost == NULL) {
- DEBUG(1, ("ipa_hostname not available.\n"));
- goto fail;
- }
- }
- hostlist[2] = NULL;
-
- req = hbac_get_host_info_send(hbac_ctx, be_req->be_ctx->ev,
- hbac_ctx->offline,
- hbac_ctx->sdap_ctx, be_req->be_ctx->sysdb,
- dp_opt_get_string(hbac_ctx->ipa_options,
- IPA_DOMAIN),
- hostlist);
- if (req == NULL) {
- DEBUG(1, ("hbac_get_host_info_send failed.\n"));
- goto fail;
- }
-
- tevent_req_set_callback(req, hbac_get_host_info_done, hbac_ctx);
- return;
-
-fail:
- ipa_access_reply(be_req, pam_status);
-}
-
-static void hbac_get_host_info_done(struct tevent_req *req)
-{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- struct be_req *be_req = hbac_ctx->be_req;
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
- const char *ipa_hostname;
- struct hbac_host_info *local_hhi = NULL;
- int i;
-
- ret = hbac_get_host_info_recv(req, hbac_ctx, &hbac_ctx->hbac_host_info);
- talloc_zfree(req);
- if (ret != EOK) {
- goto fail;
- }
-
- ipa_hostname = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
- if (ipa_hostname == NULL) {
- DEBUG(1, ("Missing ipa_hostname, this should never happen.\n"));
- ret = EINVAL;
- goto fail;
- }
-
- for (i = 0; hbac_ctx->hbac_host_info[i] != NULL; i++) {
- if (strcmp(hbac_ctx->hbac_host_info[i]->fqdn, ipa_hostname) == 0 ||
- strcmp(hbac_ctx->hbac_host_info[i]->serverhostname,
- ipa_hostname) == 0) {
- local_hhi = hbac_ctx->hbac_host_info[i];
- }
- if (hbac_ctx->pd->rhost != NULL && *hbac_ctx->pd->rhost != '\0') {
- if (strcmp(hbac_ctx->hbac_host_info[i]->fqdn,
- hbac_ctx->pd->rhost) == 0 ||
- strcmp(hbac_ctx->hbac_host_info[i]->serverhostname,
- hbac_ctx->pd->rhost) == 0) {
- hbac_ctx->remote_hhi = hbac_ctx->hbac_host_info[i];
- }
- }
- }
- if (local_hhi == NULL) {
- DEBUG(1, ("Missing host info for [%s].\n", ipa_hostname));
- ret = EINVAL;
- goto fail;
- }
- req = hbac_get_rules_send(hbac_ctx, be_req->be_ctx->ev, hbac_ctx->offline,
- hbac_ctx->sdap_ctx, be_req->be_ctx->sysdb,
- dp_opt_get_string(hbac_ctx->ipa_options,
- IPA_DOMAIN),
- local_hhi->dn, local_hhi->memberof);
- if (req == NULL) {
- DEBUG(1, ("hbac_get_rules_send failed.\n"));
- goto fail;
- }
-
- tevent_req_set_callback(req, hbac_get_rules_done, hbac_ctx);
- return;
-
-fail:
- ipa_access_reply(be_req, pam_status);
-}
-
-static void hbac_get_rules_done(struct tevent_req *req)
-{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- struct pam_data *pd = hbac_ctx->pd;
- struct be_req *be_req = hbac_ctx->be_req;
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
-
- ret = hbac_get_rules_recv(req, hbac_ctx, &hbac_ctx->hbac_rule_count,
- &hbac_ctx->hbac_rule_list);
- talloc_zfree(req);
- if (ret != EOK) {
- goto fail;
- }
-
- req = hbac_get_user_info_send(hbac_ctx, be_req->be_ctx->ev, be_req->be_ctx,
- pd->user);
- if (req == NULL) {
- DEBUG(1, ("hbac_get_user_info_send failed.\n"));
- goto fail;
- }
-
- tevent_req_set_callback(req, hbac_get_user_info_done, hbac_ctx);
- return;
-
-fail:
- ipa_access_reply(be_req, pam_status);
-}
-
-static void hbac_get_user_info_done(struct tevent_req *req)
-{
- struct hbac_ctx *hbac_ctx = tevent_req_callback_data(req, struct hbac_ctx);
- struct be_req *be_req = hbac_ctx->be_req;
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
- bool access_allowed = false;
-
- ret = hbac_get_user_info_recv(req, hbac_ctx, &hbac_ctx->user_dn,
- &hbac_ctx->groups_count,
- &hbac_ctx->groups);
- talloc_zfree(req);
- if (ret != EOK) {
- goto failed;
- }
-
- ret = evaluate_ipa_hbac_rules(hbac_ctx, &access_allowed);
- if (ret != EOK) {
- DEBUG(1, ("evaluate_ipa_hbac_rules failed.\n"));
- goto failed;
- }
-
- if (access_allowed) {
- pam_status = PAM_SUCCESS;
- DEBUG(5, ("Access allowed.\n"));
- } else {
- pam_status = PAM_PERM_DENIED;
- DEBUG(3, ("Access denied.\n"));
- }
-
-failed:
- ipa_access_reply(be_req, pam_status);
-}
diff --git a/server/providers/ipa/ipa_access.h b/server/providers/ipa/ipa_access.h
deleted file mode 100644
index bd221c574..000000000
--- a/server/providers/ipa/ipa_access.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- SSSD
-
- IPA Backend Module -- Access control
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef _IPA_ACCESS_H_
-#define _IPA_ACCESS_H_
-
-#include "providers/ldap/ldap_common.h"
-
-enum ipa_access_mode {
- IPA_ACCESS_DENY = 0,
- IPA_ACCESS_ALLOW
-};
-
-struct hbac_host_info {
- const char *fqdn;
- const char *serverhostname;
- const char *dn;
- const char **memberof;
-};
-
-struct ipa_access_ctx {
- struct sdap_id_ctx *sdap_ctx;
- struct dp_option *ipa_options;
- struct time_rules_ctx *tr_ctx;
-};
-
-struct hbac_ctx {
- struct sdap_id_ctx *sdap_ctx;
- struct dp_option *ipa_options;
- struct time_rules_ctx *tr_ctx;
- struct be_req *be_req;
- struct pam_data *pd;
- struct hbac_host_info **hbac_host_info;
- struct hbac_host_info *remote_hhi;
- struct sysdb_attrs **hbac_rule_list;
- size_t hbac_rule_count;
- const char *user_dn;
- size_t groups_count;
- const char **groups;
- bool offline;
-};
-
-void ipa_access_handler(struct be_req *be_req);
-
-#endif /* _IPA_ACCESS_H_ */
diff --git a/server/providers/ipa/ipa_auth.c b/server/providers/ipa/ipa_auth.c
deleted file mode 100644
index 86b72e495..000000000
--- a/server/providers/ipa/ipa_auth.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- SSSD
-
- IPA Backend Module -- Authentication
-
- Authors:
- Sumit Bose <sbose@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/param.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "providers/ldap/ldap_common.h"
-#include "providers/ldap/sdap_async.h"
-#include "providers/krb5/krb5_auth.h"
-#include "providers/ipa/ipa_common.h"
-
-struct ipa_auth_ctx {
- struct sdap_auth_ctx *sdap_auth_ctx;
- struct krb5_ctx *krb5_ctx;
- struct be_req *be_req;
- be_async_callback_t callback;
- void *pvt;
- bool password_migration;
-
- int dp_err_type;
- int errnum;
- char *errstr;
-};
-
-static void ipa_auth_reply(struct ipa_auth_ctx *ipa_auth_ctx)
-{
- struct pam_data *pd;
- struct be_req *be_req = ipa_auth_ctx->be_req;
- be_req->fn = ipa_auth_ctx->callback;
- be_req->pvt = ipa_auth_ctx->pvt;
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data = ipa_auth_ctx->krb5_ctx;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
- int dp_err_type = ipa_auth_ctx->dp_err_type;
- char *errstr = ipa_auth_ctx->errstr;
-
- talloc_zfree(ipa_auth_ctx);
- DEBUG(9, ("sending [%d] [%d] [%s].\n", dp_err_type, pd->pam_status,
- errstr));
-
- be_req->fn(be_req, dp_err_type, pd->pam_status, errstr);
-}
-
-struct ipa_auth_handler_state {
- struct tevent_context *ev;
-
- int dp_err_type;
- int errnum;
- char *errstr;
-};
-
-static void ipa_auth_handler_callback(struct be_req *be_req,
- int dp_err_type,
- int errnum,
- const char *errstr);
-
-static struct tevent_req *ipa_auth_handler_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct be_req *be_req,
- be_req_fn_t auth_handler)
-{
- struct ipa_auth_handler_state *state;
- struct tevent_req *req;
-
- req = tevent_req_create(memctx, &state, struct ipa_auth_handler_state);
- if (req == NULL) {
- DEBUG(1, ("tevent_req_create failed.\n"));
- return NULL;
- }
-
- state->ev = ev;
-
- be_req->fn = ipa_auth_handler_callback;
- be_req->pvt = req;
-
- auth_handler(be_req);
-
- return req;
-}
-
-static void ipa_auth_handler_callback(struct be_req *be_req,
- int dp_err_type,
- int errnum,
- const char *errstr)
-{
- struct tevent_req *req = talloc_get_type(be_req->pvt, struct tevent_req);
- struct ipa_auth_handler_state *state = tevent_req_data(req,
- struct ipa_auth_handler_state);
-
- DEBUG(9, ("received from handler [%d] [%d] [%s].\n", dp_err_type, errnum,
- errstr));
- state->dp_err_type = dp_err_type;
- state->errnum = errnum;
- state->errstr = talloc_strdup(state, errstr);
-
- tevent_req_post(req, state->ev);
- tevent_req_done(req);
- return;
-}
-
-static int ipa_auth_handler_recv(struct tevent_req *req, TALLOC_CTX *memctx,
- int *dp_err_type, int *errnum,
- char **errstr)
-{
- struct ipa_auth_handler_state *state = tevent_req_data(req,
- struct ipa_auth_handler_state);
- enum tevent_req_state tstate;
- uint64_t err;
-
- if (tevent_req_is_error(req, &tstate, &err)) {
- if (err) return err;
- return EIO;
- }
-
- *dp_err_type = state->dp_err_type;
- *errnum = state->errnum;
- *errstr = talloc_steal(memctx, state->errstr);
-
- return EOK;
-}
-
-
-static void ipa_auth_handler_done(struct tevent_req *req);
-static void ipa_auth_ldap_done(struct tevent_req *req);
-static void ipa_auth_handler_retry_done(struct tevent_req *req);
-
-void ipa_auth(struct be_req *be_req)
-{
- struct tevent_req *req;
- struct ipa_auth_ctx *ipa_auth_ctx;
- struct sdap_id_ctx *sdap_id_ctx;
-
- ipa_auth_ctx = talloc_zero(be_req, struct ipa_auth_ctx);
- if (ipa_auth_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
- }
-
- ipa_auth_ctx->callback = be_req->fn;
- ipa_auth_ctx->pvt = be_req->pvt;
-
- ipa_auth_ctx->be_req = be_req;
-
- ipa_auth_ctx->sdap_auth_ctx = talloc_zero(ipa_auth_ctx,
- struct sdap_auth_ctx);
- if (ipa_auth_ctx->sdap_auth_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- goto fail;
- }
-
- sdap_id_ctx = talloc_get_type(
- be_req->be_ctx->bet_info[BET_ID].pvt_bet_data,
- struct sdap_id_ctx);
- ipa_auth_ctx->sdap_auth_ctx->be = sdap_id_ctx->be;
- ipa_auth_ctx->sdap_auth_ctx->opts = sdap_id_ctx->opts;
-
- ipa_auth_ctx->krb5_ctx = talloc_get_type(
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
- struct krb5_ctx);
-
-/* TODO: test and activate when server side support is available */
- ipa_auth_ctx->password_migration = false;
-
- ipa_auth_ctx->dp_err_type = DP_ERR_FATAL;
- ipa_auth_ctx->errnum = EIO;
- ipa_auth_ctx->errstr = NULL;
-
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- krb5_pam_handler);
- if (req == NULL) {
- DEBUG(1, ("ipa_auth_handler_send failed.\n"));
- goto fail;
- }
-
- tevent_req_set_callback(req, ipa_auth_handler_done, ipa_auth_ctx);
- return;
-
-fail:
- ipa_auth_reply(ipa_auth_ctx);
-}
-
-static void ipa_auth_handler_done(struct tevent_req *req)
-{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
- int ret;
-
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
- goto done;
- }
-
- if (ipa_auth_ctx->password_migration && pd->pam_status == PAM_CRED_ERR) {
- DEBUG(1, ("Assuming Kerberos password is missing, "
- "starting password migration.\n"));
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data =
- ipa_auth_ctx->sdap_auth_ctx;
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- sdap_pam_auth_handler);
- if (req == NULL) {
- DEBUG(1, ("ipa_auth_ldap_send failed.\n"));
- goto done;
- }
-
- tevent_req_set_callback(req, ipa_auth_ldap_done, ipa_auth_ctx);
- return;
- }
-
-done:
- ipa_auth_reply(ipa_auth_ctx);
-}
-
-static void ipa_auth_ldap_done(struct tevent_req *req)
-{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
- int ret;
-
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
- goto done;
- }
-
- if (pd->pam_status == PAM_SUCCESS) {
- DEBUG(1, ("LDAP authentication succeded, "
- "trying Kerberos authentication again.\n"));
- be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data = ipa_auth_ctx->krb5_ctx;
- req = ipa_auth_handler_send(ipa_auth_ctx, be_req->be_ctx->ev, be_req,
- krb5_pam_handler);
- if (req == NULL) {
- DEBUG(1, ("ipa_auth_ldap_send failed.\n"));
- goto done;
- }
-
- tevent_req_set_callback(req, ipa_auth_handler_retry_done, ipa_auth_ctx);
- return;
- }
-
-done:
- ipa_auth_reply(ipa_auth_ctx);
-}
-
-static void ipa_auth_handler_retry_done(struct tevent_req *req)
-{
- struct ipa_auth_ctx *ipa_auth_ctx = tevent_req_callback_data(req,
- struct ipa_auth_ctx);
- struct pam_data *pd;
- struct be_req *be_req;
- int ret;
-
- be_req = ipa_auth_ctx->be_req;
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- ret = ipa_auth_handler_recv(req, ipa_auth_ctx, &ipa_auth_ctx->dp_err_type,
- &ipa_auth_ctx->errnum, &ipa_auth_ctx->errstr);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("ipa_auth_handler request failed.\n"));
- pd->pam_status = PAM_SYSTEM_ERR;
- }
- if (ipa_auth_ctx->dp_err_type != DP_ERR_OK) {
- pd->pam_status = ipa_auth_ctx->errnum;
- }
-
- ipa_auth_reply(ipa_auth_ctx);
-}
diff --git a/server/providers/ipa/ipa_auth.h b/server/providers/ipa/ipa_auth.h
deleted file mode 100644
index 3079bbd1b..000000000
--- a/server/providers/ipa/ipa_auth.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- SSSD
-
- IPA Backend Module -- Authentication
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef _IPA_AUTH_H_
-#define _IPA_AUTH_H_
-
-#include "providers/dp_backend.h"
-
-void ipa_auth(struct be_req *be_req);
-
-#endif /* _IPA_AUTH_H_ */
diff --git a/server/providers/ipa/ipa_common.c b/server/providers/ipa/ipa_common.c
deleted file mode 100644
index 7686227a5..000000000
--- a/server/providers/ipa/ipa_common.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- SSSD
-
- IPA Provider Common 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 <netdb.h>
-#include <ctype.h>
-#include "providers/ipa/ipa_common.h"
-
-struct dp_option ipa_basic_opts[] = {
- { "ipa_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "ipa_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "ipa_hostname", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-};
-
-struct dp_option ipa_def_ldap_opts[] = {
- { "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "ldap_search_base", DP_OPT_STRING, NULL_STRING, 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, { "ipa_v1" }, NULL_STRING },
- { "ldap_offline_timeout", DP_OPT_NUMBER, { .number = 60 }, NULL_NUMBER },
- { "ldap_force_upper_case_realm", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
- { "ldap_enumeration_refresh_timeout", DP_OPT_NUMBER, { .number = 300 }, NULL_NUMBER },
- { "ldap_purge_cache_timeout", DP_OPT_NUMBER, { .number = 3600 }, NULL_NUMBER },
- { "entry_cache_timeout", 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, { "GSSAPI" } , 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 ipa_attr_map[] = {
- { "ldap_entry_usn", "entryUSN", SYSDB_USN, NULL },
- { "ldap_rootdse_last_usn", "lastUSN", SYSDB_HIGH_USN, NULL }
-};
-
-struct sdap_attr_map ipa_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 },
- { "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 ipa_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 },
- { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL },
- { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }
-};
-
-struct dp_option ipa_def_krb5_opts[] = {
- { "krb5_kdcip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_ccachedir", DP_OPT_STRING, { "/tmp" }, NULL_STRING },
- { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
- { "krb5_changepw_principal", DP_OPT_STRING, { "kadmin/changepw" }, NULL_STRING },
- { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
- { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
- { "krb5_validate", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }
-};
-
-int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn)
-{
- const char *s;
- char *dn;
- char *p;
- int l;
-
- s = domain;
- dn = talloc_strdup(memctx, "dc=");
-
- while ((p = strchr(s, '.'))) {
- l = p - s;
- dn = talloc_asprintf_append_buffer(dn, "%.*s,dc=", l, s);
- if (!dn) {
- return ENOMEM;
- }
- s = p + 1;
- }
- dn = talloc_strdup_append_buffer(dn, s);
- if (!dn) {
- return ENOMEM;
- }
-
- *basedn = dn;
- return EOK;
-}
-
-int ipa_get_options(TALLOC_CTX *memctx,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct sss_domain_info *dom,
- struct ipa_options **_opts)
-{
- struct ipa_options *opts;
- char *domain;
- char *server;
- char *ipa_hostname;
- int ret;
- char hostname[HOST_NAME_MAX + 1];
-
- opts = talloc_zero(memctx, struct ipa_options);
- if (!opts) return ENOMEM;
-
- ret = dp_get_options(opts, cdb, conf_path,
- ipa_basic_opts,
- IPA_OPTS_BASIC,
- &opts->basic);
- if (ret != EOK) {
- goto done;
- }
-
- domain = dp_opt_get_string(opts->basic, IPA_DOMAIN);
- if (!domain) {
- ret = dp_opt_set_string(opts->basic, IPA_DOMAIN, dom->name);
- if (ret != EOK) {
- goto done;
- }
- }
-
- /* FIXME: Make non-fatal once we have discovery */
- server = dp_opt_get_string(opts->basic, IPA_SERVER);
- if (!server) {
- DEBUG(0, ("Can't find ipa server, missing option!\n"));
- ret = EINVAL;
- goto done;
- }
-
- ipa_hostname = dp_opt_get_string(opts->basic, IPA_HOSTNAME);
- if (ipa_hostname == NULL) {
- ret = gethostname(hostname, HOST_NAME_MAX);
- if (ret != EOK) {
- DEBUG(1, ("gethostname failed [%d][%s].\n", errno,
- strerror(errno)));
- ret = errno;
- goto done;
- }
- hostname[HOST_NAME_MAX] = '\0';
- DEBUG(9, ("Setting ipa_hostname to [%s].\n", hostname));
- ret = dp_opt_set_string(opts->basic, IPA_HOSTNAME, hostname);
- if (ret != EOK) {
- goto done;
- }
- }
-
-
- ret = EOK;
- *_opts = opts;
-
-done:
- if (ret != EOK) {
- talloc_zfree(opts);
- }
- return ret;
-}
-
-int ipa_get_id_options(struct ipa_options *ipa_opts,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct sdap_options **_opts)
-{
- TALLOC_CTX *tmpctx;
- char *hostname;
- char *basedn;
- char *realm;
- char *value;
- int ret;
- int i;
-
- /* self check test, this should never fail, unless someone forgot
- * to properly update the code after new ldap options have been added */
- if (SDAP_OPTS_BASIC != IPA_OPTS_BASIC_TEST) {
- DEBUG(0, ("Option numbers do not match (%d != %d)\n",
- SDAP_OPTS_BASIC, IPA_OPTS_BASIC_TEST));
- abort();
- }
-
- tmpctx = talloc_new(ipa_opts);
- if (!tmpctx) {
- return ENOMEM;
- }
-
- ipa_opts->id = talloc_zero(ipa_opts, struct sdap_options);
- if (!ipa_opts->id) {
- ret = ENOMEM;
- goto done;
- }
-
- /* get sdap options */
- ret = dp_get_options(ipa_opts->id, cdb, conf_path,
- ipa_def_ldap_opts,
- SDAP_OPTS_BASIC,
- &ipa_opts->id->basic);
- if (ret != EOK) {
- goto done;
- }
-
- if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_SEARCH_BASE)) {
- ret = domain_to_basedn(tmpctx,
- dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN),
- &basedn);
- if (ret != EOK) {
- goto done;
- }
-
- /* FIXME: get values by querying IPA */
- /* set search base */
- value = talloc_asprintf(tmpctx, "cn=accounts,%s", basedn);
- if (!value) {
- ret = ENOMEM;
- goto done;
- }
- ret = dp_opt_set_string(ipa_opts->id->basic,
- SDAP_SEARCH_BASE, value);
- if (ret != EOK) {
- goto done;
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->id->basic[SDAP_SEARCH_BASE].opt_name,
- dp_opt_get_string(ipa_opts->id->basic, SDAP_SEARCH_BASE)));
- }
-
- /* set the ldap_sasl_authid if the ipa_hostname override was specified */
- if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_SASL_AUTHID)) {
- hostname = dp_opt_get_string(ipa_opts->basic, IPA_HOSTNAME);
- if (hostname) {
- value = talloc_asprintf(tmpctx, "host/%s", hostname);
- if (!value) {
- ret = ENOMEM;
- goto done;
- }
- ret = dp_opt_set_string(ipa_opts->id->basic,
- SDAP_SASL_AUTHID, value);
- if (ret != EOK) {
- goto done;
- }
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->id->basic[SDAP_SASL_AUTHID].opt_name,
- dp_opt_get_string(ipa_opts->id->basic, SDAP_SASL_AUTHID)));
- }
-
- /* set krb realm */
- if (NULL == dp_opt_get_string(ipa_opts->id->basic, SDAP_KRB5_REALM)) {
- realm = dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN);
- for (i = 0; realm[i]; i++) {
- realm[i] = toupper(realm[i]);
- }
- ret = dp_opt_set_string(ipa_opts->id->basic,
- SDAP_KRB5_REALM, realm);
- if (ret != EOK) {
- goto done;
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->id->basic[SDAP_KRB5_REALM].opt_name,
- dp_opt_get_string(ipa_opts->id->basic, SDAP_KRB5_REALM)));
- }
-
- /* fix schema to IPAv1 for now */
- ipa_opts->id->schema_type = SDAP_SCHEMA_IPA_V1;
-
- /* set user/group search bases if they are not specified */
- if (NULL == dp_opt_get_string(ipa_opts->id->basic,
- SDAP_USER_SEARCH_BASE)) {
- ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_USER_SEARCH_BASE,
- dp_opt_get_string(ipa_opts->id->basic,
- SDAP_SEARCH_BASE));
- if (ret != EOK) {
- goto done;
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->id->basic[SDAP_USER_SEARCH_BASE].opt_name,
- dp_opt_get_string(ipa_opts->id->basic,
- SDAP_USER_SEARCH_BASE)));
- }
-
- if (NULL == dp_opt_get_string(ipa_opts->id->basic,
- SDAP_GROUP_SEARCH_BASE)) {
- ret = dp_opt_set_string(ipa_opts->id->basic, SDAP_GROUP_SEARCH_BASE,
- dp_opt_get_string(ipa_opts->id->basic,
- SDAP_SEARCH_BASE));
- if (ret != EOK) {
- goto done;
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->id->basic[SDAP_GROUP_SEARCH_BASE].opt_name,
- dp_opt_get_string(ipa_opts->id->basic,
- SDAP_GROUP_SEARCH_BASE)));
- }
-
- ret = sdap_get_map(ipa_opts->id, cdb, conf_path,
- ipa_attr_map,
- SDAP_AT_GENERAL,
- &ipa_opts->id->gen_map);
- if (ret != EOK) {
- goto done;
- }
-
- ret = sdap_get_map(ipa_opts->id,
- cdb, conf_path,
- ipa_user_map,
- SDAP_OPTS_USER,
- &ipa_opts->id->user_map);
- if (ret != EOK) {
- goto done;
- }
-
- ret = sdap_get_map(ipa_opts->id,
- cdb, conf_path,
- ipa_group_map,
- SDAP_OPTS_GROUP,
- &ipa_opts->id->group_map);
- if (ret != EOK) {
- goto done;
- }
-
- ret = EOK;
- *_opts = ipa_opts->id;
-
-done:
- talloc_zfree(tmpctx);
- if (ret != EOK) {
- talloc_zfree(ipa_opts->id);
- }
- return ret;
-}
-
-/* the following define is used to keep track of * the options in the krb5
- * module, so that if they change and ipa is not updated correspondingly
- * this will trigger a runtime abort error */
-#define IPA_KRB5_OPTS_TEST 8
-
-int ipa_get_auth_options(struct ipa_options *ipa_opts,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct dp_option **_opts)
-{
- char *value;
- int ret;
- int i;
-
- /* self check test, this should never fail, unless someone forgot
- * to properly update the code after new ldap options have been added */
- if (KRB5_OPTS != IPA_KRB5_OPTS_TEST) {
- DEBUG(0, ("Option numbers do not match (%d != %d)\n",
- KRB5_OPTS, IPA_KRB5_OPTS_TEST));
- abort();
- }
-
- ipa_opts->auth = talloc_zero(ipa_opts, struct dp_option);
- if (ipa_opts->auth == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- /* get krb5 options */
- ret = dp_get_options(ipa_opts, cdb, conf_path,
- ipa_def_krb5_opts,
- KRB5_OPTS, &ipa_opts->auth);
- if (ret != EOK) {
- goto done;
- }
-
- /* set krb realm */
- if (NULL == dp_opt_get_string(ipa_opts->auth, KRB5_REALM)) {
- value = dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN);
- if (!value) {
- ret = ENOMEM;
- goto done;
- }
- for (i = 0; value[i]; i++) {
- value[i] = toupper(value[i]);
- }
- ret = dp_opt_set_string(ipa_opts->auth, KRB5_REALM, value);
- if (ret != EOK) {
- goto done;
- }
- DEBUG(6, ("Option %s set to %s\n",
- ipa_opts->auth[KRB5_REALM].opt_name,
- dp_opt_get_string(ipa_opts->auth, KRB5_REALM)));
- }
-
- *_opts = ipa_opts->auth;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_zfree(ipa_opts->auth);
- }
- return ret;
-}
-
-static void ipa_resolve_callback(void *private_data, struct fo_server *server)
-{
- struct ipa_service *service;
- struct hostent *srvaddr;
- char *address;
- char *new_uri;
- int ret;
-
- service = talloc_get_type(private_data, struct ipa_service);
- if (!service) {
- DEBUG(1, ("FATAL: Bad private_data\n"));
- return;
- }
-
- srvaddr = fo_get_server_hostent(server);
- if (!srvaddr) {
- DEBUG(1, ("FATAL: No hostent available for server (%s)\n",
- fo_get_server_name(server)));
- return;
- }
-
- address = talloc_asprintf(service, "%s", srvaddr->h_name);
- if (!address) {
- DEBUG(1, ("Failed to copy address ...\n"));
- return;
- }
-
- new_uri = talloc_asprintf(service, "ldap://%s", address);
- if (!new_uri) {
- DEBUG(2, ("Failed to copy URI ...\n"));
- talloc_free(address);
- return;
- }
-
- /* free old one and replace with new one */
- talloc_zfree(service->sdap->uri);
- service->sdap->uri = new_uri;
- talloc_zfree(service->krb5_service->address);
- service->krb5_service->address = address;
-
- ret = write_kdcinfo_file(service->krb5_service->realm, address);
- if (ret != EOK) {
- DEBUG(2, ("write_kdcinfo_file failed, authentication might fail.\n"));
- }
-
-}
-
-int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
- const char *servers, const char *domain,
- struct ipa_service **_service)
-{
- TALLOC_CTX *tmp_ctx;
- struct ipa_service *service;
- char **list = NULL;
- char *realm;
- int ret;
- int i;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- service = talloc_zero(tmp_ctx, struct ipa_service);
- if (!service) {
- ret = ENOMEM;
- goto done;
- }
- service->sdap = talloc_zero(service, struct sdap_service);
- if (!service->sdap) {
- ret = ENOMEM;
- goto done;
- }
- service->krb5_service = talloc_zero(service, struct krb5_service);
- if (!service->krb5_service) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = be_fo_add_service(ctx, "IPA");
- if (ret != EOK) {
- DEBUG(1, ("Failed to create failover service!\n"));
- goto done;
- }
-
- service->sdap->name = talloc_strdup(service, "IPA");
- if (!service->sdap->name) {
- ret = ENOMEM;
- goto done;
- }
-
- service->krb5_service->name = talloc_strdup(service, "IPA");
- if (!service->krb5_service->name) {
- ret = ENOMEM;
- goto done;
- }
-
- realm = talloc_strdup(service, domain);
- if (!realm) {
- ret = ENOMEM;
- goto done;
- }
- for (i = 0; realm[i]; i++) {
- realm[i] = toupper(realm[i]);
- }
- service->krb5_service->realm = realm;
-
- /* split server parm into a list */
- ret = split_on_separator(tmp_ctx, servers, ',', true, &list, NULL);
- if (ret != EOK) {
- DEBUG(1, ("Failed to parse server list!\n"));
- goto done;
- }
-
- /* now for each one add a new server to the failover service */
- for (i = 0; list[i]; i++) {
-
- talloc_steal(service, list[i]);
-
- ret = be_fo_add_server(ctx, "IPA", list[i], 0, NULL);
- if (ret && ret != EEXIST) {
- DEBUG(0, ("Failed to add server\n"));
- goto done;
- }
-
- DEBUG(6, ("Added Server %s\n", list[i]));
- }
-
- ret = be_fo_service_add_callback(memctx, ctx, "IPA",
- ipa_resolve_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/ipa/ipa_common.h b/server/providers/ipa/ipa_common.h
deleted file mode 100644
index 60c7313f0..000000000
--- a/server/providers/ipa/ipa_common.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- SSSD
-
- IPA 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 _IPA_COMMON_H_
-#define _IPA_COMMON_H_
-
-#include "util/util.h"
-#include "confdb/confdb.h"
-#include "providers/ldap/ldap_common.h"
-#include "providers/krb5/krb5_common.h"
-
-struct ipa_service {
- struct sdap_service *sdap;
- struct krb5_service *krb5_service;
-};
-
-/* the following define is used to keep track of the options in the ldap
- * module, so that if they change and ipa is not updated correspondingly
- * this will trigger a runtime abort error */
-#define IPA_OPTS_BASIC_TEST 31
-
-enum ipa_basic_opt {
- IPA_DOMAIN = 0,
- IPA_SERVER,
- IPA_HOSTNAME,
-
- IPA_OPTS_BASIC /* opts counter */
-};
-
-struct ipa_options {
- struct dp_option *basic;
-
- struct ipa_service *service;
-
- /* id provider */
- struct sdap_options *id;
- struct sdap_id_ctx *id_ctx;
-
- /* auth and chpass provider */
- struct dp_option *auth;
- struct krb5_ctx *auth_ctx;
-};
-
-/* options parsers */
-int ipa_get_options(TALLOC_CTX *memctx,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct sss_domain_info *dom,
- struct ipa_options **_opts);
-
-int ipa_get_id_options(struct ipa_options *ipa_opts,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct sdap_options **_opts);
-
-int ipa_get_auth_options(struct ipa_options *ipa_opts,
- struct confdb_ctx *cdb,
- const char *conf_path,
- struct dp_option **_opts);
-
-int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
- const char *servers, const char *domain,
- struct ipa_service **_service);
-
-#endif /* _IPA_COMMON_H_ */
diff --git a/server/providers/ipa/ipa_init.c b/server/providers/ipa/ipa_init.c
deleted file mode 100644
index 10b9257a2..000000000
--- a/server/providers/ipa/ipa_init.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- SSSD
-
- IPA 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 <sys/types.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "providers/child_common.h"
-#include "providers/ipa/ipa_common.h"
-#include "providers/krb5/krb5_auth.h"
-#include "providers/ipa/ipa_auth.h"
-#include "providers/ipa/ipa_access.h"
-#include "providers/ipa/ipa_timerules.h"
-
-struct ipa_options *ipa_options = NULL;
-
-/* Id Handler */
-struct bet_ops ipa_id_ops = {
- .handler = sdap_account_info_handler,
- .finalize = NULL
-};
-
-struct bet_ops ipa_auth_ops = {
- .handler = ipa_auth,
- .finalize = NULL,
-};
-
-struct bet_ops ipa_chpass_ops = {
- .handler = krb5_pam_handler,
- .finalize = NULL,
-};
-
-struct bet_ops ipa_access_ops = {
- .handler = ipa_access_handler,
- .finalize = NULL
-};
-
-int common_ipa_init(struct be_ctx *bectx)
-{
- const char *ipa_servers;
- const char *ipa_domain;
- int ret;
-
- ret = ipa_get_options(bectx, bectx->cdb,
- bectx->conf_path,
- bectx->domain, &ipa_options);
- if (ret != EOK) {
- return ret;
- }
-
- ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER);
- if (!ipa_servers) {
- DEBUG(0, ("Missing ipa_server option!\n"));
- return EINVAL;
- }
-
- ipa_domain = dp_opt_get_string(ipa_options->basic, IPA_DOMAIN);
- if (!ipa_domain) {
- DEBUG(0, ("Missing ipa_domain option!\n"));
- return EINVAL;
- }
-
- ret = ipa_service_init(ipa_options, bectx, ipa_servers, ipa_domain,
- &ipa_options->service);
- if (ret != EOK) {
- DEBUG(0, ("Failed to init IPA failover service!\n"));
- return ret;
- }
-
- return EOK;
-}
-
-int sssm_ipa_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- struct sdap_id_ctx *ctx;
- int ret;
-
- if (!ipa_options) {
- ret = common_ipa_init(bectx);
- if (ret != EOK) {
- return ret;
- }
- }
-
- if (ipa_options->id_ctx) {
- /* already initialized */
- *ops = &ipa_id_ops;
- *pvt_data = ipa_options->id_ctx;
- return EOK;
- }
-
- ctx = talloc_zero(ipa_options, struct sdap_id_ctx);
- if (!ctx) {
- return ENOMEM;
- }
- ctx->be = bectx;
- ctx->service = ipa_options->service->sdap;
- ipa_options->id_ctx = ctx;
-
- ret = ipa_get_id_options(ipa_options, bectx->cdb,
- bectx->conf_path,
- &ctx->opts);
- if (ret != EOK) {
- 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 = &ipa_id_ops;
- *pvt_data = ctx;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_zfree(ipa_options->id_ctx);
- }
- return ret;
-}
-
-int sssm_ipa_auth_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- struct krb5_ctx *ctx;
- struct tevent_signal *sige;
- FILE *debug_filep;
- unsigned v;
- int ret;
-
- if (!ipa_options) {
- ret = common_ipa_init(bectx);
- if (ret != EOK) {
- return ret;
- }
- }
-
- if (ipa_options->auth_ctx) {
- /* already initialized */
- *ops = &ipa_auth_ops;
- *pvt_data = ipa_options->auth_ctx;
- return EOK;
- }
-
- ctx = talloc_zero(bectx, struct krb5_ctx);
- if (!ctx) {
- return ENOMEM;
- }
- ctx->service = ipa_options->service->krb5_service;
- ipa_options->auth_ctx = ctx;
-
- ret = ipa_get_auth_options(ipa_options, bectx->cdb,
- bectx->conf_path,
- &ctx->opts);
- if (ret != EOK) {
- goto done;
- }
-
- ret = check_and_export_options(ctx->opts, bectx->domain);
- if (ret != EOK) {
- DEBUG(1, ("check_and_export_opts failed.\n"));
- goto done;
- }
-
- sige = tevent_add_signal(bectx->ev, ctx, SIGCHLD, SA_SIGINFO,
- child_sig_handler, NULL);
- if (sige == NULL) {
- DEBUG(1, ("tevent_add_signal failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- if (debug_to_file != 0) {
- ret = open_debug_file_ex("krb5_child", &debug_filep);
- if (ret != EOK) {
- DEBUG(0, ("Error setting up logging (%d) [%s]\n",
- ret, strerror(ret)));
- goto done;
- }
-
- ctx->child_debug_fd = fileno(debug_filep);
- if (ctx->child_debug_fd == -1) {
- DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno)));
- ret = errno;
- goto done;
- }
-
- v = fcntl(ctx->child_debug_fd, F_GETFD, 0);
- fcntl(ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC);
- }
-
- *ops = &ipa_auth_ops;
- *pvt_data = ctx;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_zfree(ipa_options->auth_ctx);
- }
- return ret;
-}
-
-int sssm_ipa_chpass_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- int ret;
- ret = sssm_ipa_auth_init(bectx, ops, pvt_data);
- *ops = &ipa_chpass_ops;
- return ret;
-}
-
-int sssm_ipa_access_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_data)
-{
- int ret;
- struct ipa_access_ctx *ipa_access_ctx;
-
- ipa_access_ctx = talloc_zero(bectx, struct ipa_access_ctx);
- if (ipa_access_ctx == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- return ENOMEM;
- }
-
- ret = sssm_ipa_init(bectx, ops, (void **) &ipa_access_ctx->sdap_ctx);
- if (ret != EOK) {
- DEBUG(1, ("sssm_ipa_init failed.\n"));
- goto done;
- }
-
- ret = dp_copy_options(ipa_access_ctx, ipa_options->basic,
- IPA_OPTS_BASIC, &ipa_access_ctx->ipa_options);
- if (ret != EOK) {
- DEBUG(1, ("dp_copy_options failed.\n"));
- goto done;
- }
-
- ret = init_time_rules_parser(ipa_access_ctx, &ipa_access_ctx->tr_ctx);
- if (ret != EOK) {
- DEBUG(1, ("init_time_rules_parser failed.\n"));
- goto done;
- }
-
- *ops = &ipa_access_ops;
- *pvt_data = ipa_access_ctx;
-
-done:
- if (ret != EOK) {
- talloc_free(ipa_access_ctx);
- }
- return ret;
-}
diff --git a/server/providers/ipa/ipa_timerules.c b/server/providers/ipa/ipa_timerules.c
deleted file mode 100644
index 1a52eef12..000000000
--- a/server/providers/ipa/ipa_timerules.c
+++ /dev/null
@@ -1,1186 +0,0 @@
-/*
- SSSD
-
- IPA Provider Time Rules Parsing
-
- Authors:
- Jakub Hrozek <jhrozek@redhat.com>
-
- Copyright (C) Red Hat, Inc 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/>.
-*/
-
-#define _XOPEN_SOURCE /* strptime() needs this */
-
-#include <pcre.h>
-#include <talloc.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-#include <stdbool.h>
-#include <limits.h>
-
-#include "providers/ipa/ipa_timerules.h"
-#include "util/util.h"
-
-#define JMP_NEOK(variable) do { \
- if (variable != EOK) goto done; \
-} while (0)
-
-#define JMP_NEOK_LABEL(variable, label) do { \
- if (variable != EOK) goto label; \
-} while (0)
-
-#define CHECK_PTR(ptr) do { \
- if (ptr == NULL) { \
- return ENOMEM; \
- } \
-} while (0)
-
-#define CHECK_PTR_JMP(ptr) do { \
- if (ptr == NULL) { \
- ret = ENOMEM; \
- goto done; \
- } \
-} while (0)
-
-#define BUFFER_OR_JUMP(ctx, ptr, count) do { \
- ptr = talloc_array(ctx, unsigned char, count); \
- if (ptr == NULL) { \
- return ENOMEM; \
- } \
- memset(ptr, 0, sizeof(unsigned char)*count); \
-} while (0)
-
-#define TEST_BIT_RANGE(bitfield, index, resptr) do { \
- if (bitfield) { \
- if (test_bit(&bitfield, index) == 0) { \
- *resptr = false; \
- return EOK; \
- } \
- } \
-} while (0)
-
-#define TEST_BIT_RANGE_PTR(bitfield, index, resptr) do { \
- if (bitfield) { \
- if (test_bit(bitfield, index) == 0) { \
- *resptr = false; \
- return EOK; \
- } \
- } \
-} while (0)
-
-/* number of match offsets when matching pcre regexes */
-#define OVEC_SIZE 30
-
-/* regular expressions describing syntax of our HBAC grammar */
-#define RGX_WEEKLY "day (?P<day_of_week>(0|1|2|3|4|5|6|7|Mon|Tue|Wed|Thu|Fri|Sat|Sun|,|-)+)"
-
-#define RGX_MDAY "(?P<mperspec_day>day) (?P<interval_day>[0-9,-]+) "
-#define RGX_MWEEK "(?P<mperspec_week>week) (?P<interval_week>[0-9,-]+) "RGX_WEEKLY
-#define RGX_MONTHLY RGX_MDAY"|"RGX_MWEEK
-
-#define RGX_YDAY "(?P<yperspec_day>day) (?P<day_of_year>[0-9,-]+) "
-#define RGX_YWEEK "(?P<yperspec_week>week) (?P<week_of_year>[0-9,-]+) "RGX_WEEKLY
-#define RGX_YMONTH "(?P<yperspec_month>month) (?P<month_number>[0-9,-]+) (?P<m_period>.*?)$"
-#define RGX_YEARLY RGX_YMONTH"|"RGX_YWEEK"|"RGX_YDAY
-
-#define RGX_TIMESPEC "(?P<timeFrom>[0-9]{4}) ~ (?P<timeTo>[0-9]{4})"
-
-#define RGX_GENERALIZED "(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})(?P<hour>[0-9]{2})?(?P<minute>[0-9]{2})?(?P<second>[0-9]{2})?"
-
-#define RGX_PERIODIC "^periodic (?P<perspec>daily|weekly|monthly|yearly) (?P<period>.*?)"RGX_TIMESPEC"$"
-#define RGX_ABSOLUTE "^absolute (?P<from>\\S+) ~ (?P<to>\\S+)$"
-
-/* limits on various parameters */
-#define DAY_OF_WEEK_MAX 7
-#define DAY_OF_MONTH_MAX 31
-#define WEEK_OF_MONTH_MAX 5
-#define WEEK_OF_YEAR_MAX 54
-#define DAY_OF_YEAR_MAX 366
-#define MONTH_MAX 12
-#define HOUR_MAX 23
-#define MINUTE_MAX 59
-
-/* limits on sizes of buffers for bit arrays */
-#define DAY_OF_MONTH_BUFSIZE 8
-#define DAY_OF_YEAR_BUFSIZE 44
-#define WEEK_OF_YEAR_BUFSIZE 13
-#define MONTH_BUFSIZE 2
-#define HOUR_BUFSIZE 4
-#define MINUTE_BUFSIZE 8
-
-/* Lookup tables for translating names of days and months */
-static const char *names_day_of_week[] =
- { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", NULL };
-static const char *names_months[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Nov", "Dec", NULL };
-
-/*
- * Timelib knows two types of ranges - periodic and absolute
- */
-enum rangetypes {
- TYPE_ABSOLUTE,
- TYPE_PERIODIC
-};
-
-struct absolute_range {
- time_t time_from;
- time_t time_to;
-};
-
-struct periodic_range {
- unsigned char day_of_week;
- unsigned char *day_of_month;
- unsigned char *day_of_year;
- unsigned char week_of_month;
- unsigned char *week_of_year;
- unsigned char *month;
- unsigned char *hour;
- unsigned char *minute;
-};
-
-/*
- * Context of one time rule being analyzed
- */
-struct range_ctx {
- /* main context with precompiled patterns */
- struct time_rules_ctx *trctx;
- /* enum rangetypes */
- enum rangetypes type;
-
- struct absolute_range *abs;
- struct periodic_range *per;
-};
-
-
-/*
- * The context of one regular expression
- */
-struct parse_ctx {
- /* the regular expression used for one parsing */
- pcre *re;
- /* number of matches */
- int matches;
- /* vector of matches */
- int *ovec;
-};
-
-/* indexes to the array of precompiled regexes */
-enum timelib_rgx {
- LP_RGX_GENERALIZED,
- LP_RGX_MDAY,
- LP_RGX_MWEEK,
- LP_RGX_YEARLY,
- LP_RGX_WEEKLY,
- LP_RGX_ABSOLUTE,
- LP_RGX_PERIODIC,
- LP_RGX_MAX,
-};
-
-/* matches the indexes */
-static const char *lookup_table[] = {
- RGX_GENERALIZED,
- RGX_MDAY,
- RGX_MWEEK,
- RGX_YEARLY,
- RGX_WEEKLY,
- RGX_ABSOLUTE,
- RGX_PERIODIC,
- NULL,
-};
-
-/*
- * Main struct passed outside
- * holds precompiled regular expressions
- */
-struct time_rules_ctx {
- pcre *re[LP_RGX_MAX];
-};
-
-/*******************************************************************
- * helper function - bit arrays *
- *******************************************************************/
-
-/* set a single bit in a bitmap */
-static void set_bit(unsigned char *bitmap, unsigned int bit)
-{
- bitmap[bit/CHAR_BIT] |= 1 << (bit%CHAR_BIT);
-}
-
-/*
- * This function is based on bit_nset macro written originally by Paul Vixie,
- * copyrighted by The Regents of the University of California, as found
- * in tarball of fcron, file bitstring.h
- */
-static void set_bit_range(unsigned char *bitmap, unsigned int start,
- unsigned int stop)
-{
- int startbyte = start/CHAR_BIT;
- int stopbyte = stop/CHAR_BIT;
-
- if (startbyte == stopbyte) {
- bitmap[startbyte] |= ((0xff << (start & 0x7)) &
- (0xff >> (CHAR_BIT- 1 - (stop & 0x7))));
- } else {
- bitmap[startbyte] |= 0xff << (start & 0x7);
- while (++startbyte < stopbyte) {
- bitmap[startbyte] |= 0xff;
- }
- bitmap[stopbyte] |= 0xff >> (CHAR_BIT- 1 - (stop & 0x7));
- }
-}
-
-static int test_bit(unsigned char *bitmap, unsigned int bit)
-{
- return (int)(bitmap[bit/CHAR_BIT] >> (bit%CHAR_BIT)) & 1;
-}
-
-/*******************************************************************
- * parsing intervals *
- *******************************************************************/
-
-/*
- * Some ranges allow symbolic names, like Mon..Sun for names of day.
- * This routine takes a list of symbolic names as NAME_ARRAY and the
- * one we're looking for as KEY and returns its index or -1 when not
- * found. The last member of NAME_ARRAY must be NULL.
- */
-static int name_index(const char **name_array, const char *key, int min)
-{
- int index = 0;
- const char *one;
-
- if (name_array == NULL) {
- return -1;
- }
-
- while ((one = name_array[index]) != NULL) {
- if (strcmp(key,one) == 0) {
- return index+min;
- }
- index++;
- }
-
- return -1;
-}
-
-/*
- * Sets appropriate bits given by an interval in STR (in form of 1,5-7,10) to
- * a bitfield given in OUT. Does no boundary checking. STR can also contain
- * symbolic names, these would be given in TRANSLATE.
- */
-static int interval2bitfield(TALLOC_CTX *mem_ctx,
- unsigned char *out,
- const char *str,
- int min, int max,
- const char **translate)
-{
- char *copy;
- char *next, *token;
- int tokval, tokmax;
- char *end_ptr;
- int ret;
- char *dash;
-
- DEBUG(9, ("Converting '%s' to interval\n", str));
-
- copy = talloc_strdup(mem_ctx, str);
- CHECK_PTR(copy);
-
- next = copy;
- while (next) {
- token = next;
- next = strchr(next, ',');
- if (next) {
- *next = '\0';
- next++;
- }
-
- errno = 0;
- tokval = strtol(token, &end_ptr, 10);
- if (*end_ptr == '\0' && errno == 0) {
- if (tokval <= max && tokval >= 0) {
- set_bit(out, tokval);
- continue;
- } else {
- ret = ERANGE;
- goto done;
- }
- } else if ((dash = strchr(token, '-')) != NULL){
- *dash = '\0';
- ++dash;
-
- errno = 0;
- tokval = strtol(token, &end_ptr, 10);
- if (*end_ptr != '\0' || errno != 0) {
- tokval = name_index(translate, token, min);
- if (tokval == -1) {
- ret = ERANGE;
- goto done;
- }
- }
- errno = 0;
- tokmax = strtol(dash, &end_ptr, 10);
- if (*end_ptr != '\0' || errno != 0) {
- tokmax = name_index(translate, dash, min);
- if (tokmax == -1) {
- ret = ERANGE;
- goto done;
- }
- }
-
- if (tokval <= max && tokmax <= max &&
- tokval >= min && tokmax >= min) {
- if (tokmax > tokval) {
- DEBUG(7, ("Setting interval %d-%d\n", tokval, tokmax));
- DEBUG(9, ("interval: %p\n", out));
- set_bit_range(out, tokval, tokmax);
- } else {
- /* Interval wraps around - i.e. from 18.00 to 06.00 */
- DEBUG(7, ("Setting inverted interval %d-%d\n", tokval, tokmax));
- DEBUG(9, ("interval: %p\n", out));
- set_bit_range(out, min, tokmax);
- set_bit_range(out, tokval, max);
- }
- continue;
- } else {
- /* tokval or tokmax are not between <min, max> */
- ret = ERANGE;
- goto done;
- }
- } else if ((tokval = name_index(translate, token, min)) != -1) {
- /* Try to translate one token by name */
- if (tokval <= max) {
- set_bit(out, tokval);
- continue;
- } else {
- ret = ERANGE;
- goto done;
- }
- } else {
- ret = EINVAL;
- goto done;
- }
- }
-
- ret = EOK;
-done:
- talloc_free(copy);
- return ret;
-}
-
-/*******************************************************************
- * wrappers around regexp handling *
- *******************************************************************/
-
-/*
- * Copies a named substring SUBSTR_NAME from string STR using the parsing
- * information from PCTX. The context PCTX is also used as a talloc context.
- *
- * The resulting string is stored in OUT.
- * Return value is EOK on no error or ENOENT on error capturing the substring
- */
-static int copy_substring(struct parse_ctx *pctx,
- const char *str,
- const char *substr_name,
- char **out)
-{
- const char *result = NULL;
- int ret;
- char *o = NULL;
-
- result = NULL;
-
- ret = pcre_get_named_substring(pctx->re, str, pctx->ovec,
- pctx->matches, substr_name, &result);
- if (ret < 0 || result == NULL) {
- DEBUG(5, ("named substring '%s' does not exist in '%s'\n",
- substr_name, str));
- return ENOENT;
- }
-
- o = talloc_strdup(pctx, result);
- pcre_free_substring(result);
- if (o == NULL) {
- return ENOMEM;
- }
-
- DEBUG(9, ("Copied substring named '%s' value '%s'\n", substr_name, o));
-
- *out = o;
- return EOK;
-}
-
-/*
- * Copies a named substring SUBSTR_NAME from string STR using the parsing
- * information from PCTX and converts it to an integer.
- * The context PCTX is also used as a talloc context.
- *
- * The resulting string is stored in OUT.
- * Return value is EOK on no error or ENOENT on error capturing the substring
- */
-static int substring_strtol(struct parse_ctx *pctx,
- const char *str,
- const char *substr_name,
- int *out)
-{
- char *substr = NULL;
- int ret;
- int val;
- char *err_ptr;
-
- ret = copy_substring(pctx, str, substr_name, &substr);
- if (ret != EOK) {
- DEBUG(5, ("substring '%s' does not exist\n", substr_name));
- return ret;
- }
-
- errno = 0;
- val = strtol(substr, &err_ptr, 10);
- if (substr == '\0' || *err_ptr != '\0' || errno != 0) {
- DEBUG(5, ("substring '%s' does not contain an integerexist\n",
- substr));
- talloc_free(substr);
- return EINVAL;
- }
-
- *out = val;
- talloc_free(substr);
- return EOK;
-}
-
-/*
- * Compiles a regular expression REGEXP and tries to match it against the
- * string STR. Fills in structure _PCTX with info about matching.
- *
- * Returns EOK on no error, EFAULT on bad regexp, EINVAL when it cannot
- * match the regexp.
- */
-static int matches_regexp(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- enum timelib_rgx regex,
- struct parse_ctx **_pctx)
-{
- int ret;
- struct parse_ctx *pctx = NULL;
-
- pctx = talloc_zero(ctx, struct parse_ctx);
- CHECK_PTR(pctx);
- pctx->ovec = talloc_array(pctx, int, OVEC_SIZE);
- CHECK_PTR_JMP(pctx->ovec);
- pctx->re = trctx->re[regex];
-
- ret = pcre_exec(pctx->re, NULL, str, strlen(str), 0, PCRE_NOTEMPTY, pctx->ovec, OVEC_SIZE);
- if (ret <= 0) {
- DEBUG(8, ("string '%s' did *NOT* match regexp '%s'\n", str, lookup_table[regex]));
- ret = EINVAL;
- goto done;
- }
- DEBUG(8, ("string '%s' matched regexp '%s'\n", str, lookup_table[regex]));
-
- pctx->matches = ret;
- *_pctx = pctx;
- return EOK;
-
-done:
- talloc_free(pctx);
- return ret;
-}
-
-/*******************************************************************
- * date/time helper functions *
- *******************************************************************/
-
-/*
- * Returns week number as an integer
- * This may seem ugly, but I think it's actually less error prone
- * than writing my own routine
- */
-static int weeknum(const struct tm *t)
-{
- char buf[3];
-
- if (!strftime(buf, 3, "%U", t)) {
- return -1;
- }
-
- /* %U returns 0-53, we want 1-54 */
- return atoi(buf)+1;
-}
-
-/*
- * Return the week of the month
- * Range is 1 to 5
- */
-static int get_week_of_month(const struct tm *t)
-{
- int fs; /* first sunday */
-
- fs = (t->tm_mday % 7) - t->tm_wday;
- if (fs <= 0) {
- fs += 7;
- }
-
- return (t->tm_mday <= fs) ? 1 : (2 + (t->tm_mday - fs - 1) / 7);
-}
-
-/*
- * Normalize differencies between our HBAC definition and semantics of
- * struct tm
- */
-static void abs2tm(struct tm *t)
-{
- /* tm defines tm_year as num of yrs since 1900, we have absolute number */
- t->tm_year %= 1900;
- /* struct tm defines tm_mon as number of month since January */
- t->tm_mon--;
-}
-
-/*
- * Normalize differencies between our HBAC definition and semantics of
- * struct tm
- */
-static void tm2abs(struct tm *t)
-{
- /* tm defines tm_year as num of yrs since 1900, we have absolute number */
- t->tm_year += 1900;
- /* struct tm defines tm_mon as number of month since January */
- t->tm_mon++;
-}
-
-/*******************************************************************
- * parsing of HBAC rules themselves *
- *******************************************************************/
-
-/*
- * Parses generalized time string given in STR and fills the
- * information into OUT.
- */
-static int parse_generalized_time(struct parse_ctx *pctx,
- struct time_rules_ctx *trctx,
- const char *str,
- time_t *out)
-{
- int ret;
- struct parse_ctx *gctx = NULL;
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_isdst = -1;
-
- ret = matches_regexp(pctx, trctx, str, LP_RGX_GENERALIZED, &gctx);
- JMP_NEOK(ret);
-
- /* compulsory */
- ret = substring_strtol(gctx, str, "year", &tm.tm_year);
- JMP_NEOK(ret);
- ret = substring_strtol(gctx, str, "month", &tm.tm_mon);
- JMP_NEOK(ret);
- ret = substring_strtol(gctx, str, "day", &tm.tm_mday);
- JMP_NEOK(ret);
- /* optional */
- ret = substring_strtol(gctx, str, "hour", &tm.tm_hour);
- JMP_NEOK_LABEL(ret, enoent);
- ret = substring_strtol(gctx, str, "minute", &tm.tm_min);
- JMP_NEOK_LABEL(ret, enoent);
- ret = substring_strtol(gctx, str, "second", &tm.tm_sec);
- JMP_NEOK_LABEL(ret, enoent);
-
-enoent:
- if (ret == ENOENT) {
- ret = EOK;
- }
-
- abs2tm(&tm);
-
- *out = mktime(&tm);
- DEBUG(3, ("converted to time: '%s'\n", ctime(out)));
- if (*out == -1) {
- ret = EINVAL;
- }
-done:
- talloc_free(gctx);
- return ret;
-}
-
-/*
- * Parses absolute timerange string given in STR and fills the
- * information into ABS.
- */
-static int parse_absolute(struct absolute_range *absr,
- struct time_rules_ctx *trctx,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *from = NULL, *to = NULL;
- int ret;
-
- ret = copy_substring(pctx, str, "from", &from);
- if (ret != EOK) {
- DEBUG(1, ("Missing required part 'from' in absolute timespec\n"));
- ret = EINVAL;
- goto done;
- }
- ret = copy_substring(pctx, str, "to", &to);
- if (ret != EOK) {
- DEBUG(1, ("Missing required part 'to' in absolute timespec\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = parse_generalized_time(pctx, trctx, from, &absr->time_from);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse generalized time - first part\n"));
- goto done;
- }
-
- ret = parse_generalized_time(pctx, trctx, to, &absr->time_to);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse generalized time - second part\n"));
- goto done;
- }
-
- if (difftime(absr->time_to, absr->time_from) < 0) {
- DEBUG(1, ("Not a valid interval\n"));
- ret = EINVAL;
- }
-
- ret = EOK;
-done:
- talloc_free(from);
- talloc_free(to);
- return ret;
-}
-
-static int parse_hhmm(const char *str, int *hour, int *min)
-{
- struct tm t;
- char *err;
-
- err = strptime(str, "%H%M", &t);
- if (*err != '\0') {
- return EINVAL;
- }
-
- *hour = t.tm_hour;
- *min = t.tm_min;
-
- return EOK;
-}
-
-/*
- * Parses monthly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_monthly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *mpctx = NULL;
- char *match = NULL;
- char *mperspec = NULL;
-
- /* This code would be much less ugly if RHEL5 PCRE knew about PCRE_DUPNAMES */
- ret = matches_regexp(ctx, trctx, str, LP_RGX_MDAY, &mpctx);
- if (ret == EOK) {
- ret = copy_substring(mpctx, str, "mperspec_day", &mperspec);
- JMP_NEOK(ret);
- ret = copy_substring(mpctx, str, "interval_day", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(ctx, per->day_of_month, DAY_OF_MONTH_BUFSIZE);
- ret = interval2bitfield(mpctx, per->day_of_month, match,
- 1, DAY_OF_MONTH_MAX, NULL);
- JMP_NEOK(ret);
- } else {
- ret = matches_regexp(ctx, trctx, str, LP_RGX_MWEEK, &mpctx);
- JMP_NEOK(ret);
- ret = copy_substring(mpctx, str, "mperspec_week", &mperspec);
- JMP_NEOK(ret);
-
- ret = copy_substring(mpctx, str, "interval_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(mpctx, &per->week_of_month, match,
- 1, WEEK_OF_MONTH_MAX, NULL);
- JMP_NEOK(ret);
-
- ret = copy_substring(mpctx, str, "day_of_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(mpctx, &per->day_of_week, match,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
- JMP_NEOK(ret);
- }
-
-done:
- talloc_free(mpctx);
- return ret;
-}
-
-/*
- * Parses yearly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_yearly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *ypctx = NULL;
- char *match = NULL;
- char *yperspec = NULL;
-
- ret = matches_regexp(ctx, trctx, str, LP_RGX_YEARLY, &ypctx);
- JMP_NEOK(ret);
- ret = copy_substring(ypctx, str, "yperspec_day", &yperspec);
- if (ret == EOK) {
- ret = copy_substring(ypctx, str, "day_of_year", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(ypctx, per->day_of_year, DAY_OF_YEAR_BUFSIZE);
- ret = interval2bitfield(ypctx, per->day_of_year, match,
- 1, DAY_OF_YEAR_MAX, NULL);
- JMP_NEOK(ret);
- }
-
- if (ret != ENOENT) goto done;
-
- ret = copy_substring(ypctx, str, "yperspec_week", &yperspec);
- if (ret == EOK) {
- ret = copy_substring(ypctx, str, "week_of_year", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(ypctx, per->week_of_year, WEEK_OF_YEAR_BUFSIZE);
- ret = interval2bitfield(ypctx, per->week_of_year, match,
- 1, WEEK_OF_YEAR_MAX, NULL);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "day_of_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(ypctx, &per->day_of_week, match,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
- JMP_NEOK(ret);
- }
-
- if (ret != ENOENT) goto done;
-
- ret = copy_substring(ypctx, str, "yperspec_month", &yperspec);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "month_number", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(ypctx, per->month, MONTH_BUFSIZE);
- ret = interval2bitfield(ypctx, per->month, match,
- 1, MONTH_MAX, names_months);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "m_period", &match);
- JMP_NEOK(ret);
- DEBUG(7, ("Monthly year period - calling parse_periodic_monthly()\n"));
- ret = parse_periodic_monthly(ypctx, trctx, per, match);
- JMP_NEOK(ret);
-
-done:
- talloc_free(ypctx);
- return ret;
-}
-
-/*
- * Parses weekly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_weekly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *wpctx = NULL;
- char *dow = NULL;
-
- ret = matches_regexp(ctx, trctx, str, LP_RGX_WEEKLY, &wpctx);
- JMP_NEOK(ret);
-
- ret = copy_substring(wpctx, str, "day_of_week", &dow);
- JMP_NEOK(ret);
- DEBUG(8, ("day_of_week = '%s'\n", dow));
-
- ret = interval2bitfield(wpctx, &per->day_of_week, dow,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
-
-done:
- talloc_free(wpctx);
- return ret;
-}
-
-static int parse_periodic_time(struct periodic_range *per,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *substr = NULL;
- int ret;
-
- int hour_from;
- int hour_to;
- int min_from;
- int min_to;
-
- /* parse out the time */
- ret = copy_substring(pctx, str, "timeFrom", &substr);
- JMP_NEOK(ret);
- parse_hhmm(substr, &hour_from, &min_from);
- DEBUG(7, ("Parsed timeFrom: %d:%d\n", hour_from, min_from));
- JMP_NEOK(ret);
-
- talloc_free(substr);
- ret = copy_substring(pctx, str, "timeTo", &substr);
- JMP_NEOK(ret);
- parse_hhmm(substr, &hour_to, &min_to);
- DEBUG(7, ("Parsed timeTo: %d:%d\n", hour_to, min_to));
- JMP_NEOK(ret);
-
- /* set the interval */
- if (hour_from > hour_to ) {
- set_bit_range(per->hour, 0, hour_to);
- set_bit_range(per->hour, hour_from, HOUR_MAX);
- } else {
- set_bit_range(per->hour, hour_from, hour_to);
- }
-
- if (min_from > min_to) {
- set_bit_range(per->minute, 0, min_to);
- set_bit_range(per->minute, min_from, MINUTE_MAX);
- } else {
- set_bit_range(per->minute, min_from, min_to);
- }
-
-
- ret = EOK;
-done:
- talloc_free(substr);
- return ret;
-}
-
-/*
- * Parses periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic(struct periodic_range *per,
- struct time_rules_ctx *trctx,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *substr = NULL;
- char *period = NULL;
- int ret;
-
- /* These are mandatory */
- BUFFER_OR_JUMP(per, per->hour, HOUR_BUFSIZE);
- BUFFER_OR_JUMP(per, per->minute, MINUTE_BUFSIZE);
-
- ret = copy_substring(pctx, str, "perspec", &substr);
- JMP_NEOK(ret);
- ret = copy_substring(pctx, str, "period", &period);
- JMP_NEOK(ret);
-
- if (strcmp(substr, "yearly") == 0) {
- DEBUG(5, ("periodic yearly\n"));
- ret = parse_periodic_yearly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "monthly") == 0) {
- DEBUG(5, ("periodic monthly\n"));
- ret = parse_periodic_monthly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "weekly") == 0) {
- DEBUG(5, ("periodic weekly\n"));
- ret = parse_periodic_weekly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "daily") == 0) {
- DEBUG(5, ("periodic daily\n"));
- } else {
- DEBUG(1, ("Cannot determine periodic rule type"
- "(perspec = '%s', period = '%s')\n", substr, period));
- ret = EINVAL;
- goto done;
- }
-
- talloc_free(period);
-
- ret = parse_periodic_time(per, pctx, str);
- JMP_NEOK(ret);
-
- ret = EOK;
-done:
- talloc_free(substr);
- return ret;
-}
-
-/*
- * Parses time specification given in string RULE into range_ctx
- * context CTX.
- */
-static int parse_timespec(struct range_ctx *ctx, const char *rule)
-{
- int ret;
- struct parse_ctx *pctx = NULL;
-
- if (matches_regexp(ctx, ctx->trctx, rule, LP_RGX_ABSOLUTE, &pctx) == EOK) {
- DEBUG(5, ("Matched absolute range\n"));
- ctx->type = TYPE_ABSOLUTE;
- ctx->abs = talloc_zero(ctx, struct absolute_range);
- CHECK_PTR_JMP(ctx->abs);
-
- ret = parse_absolute(ctx->abs, ctx->trctx, pctx, rule);
- JMP_NEOK(ret);
- } else if (matches_regexp(ctx, ctx->trctx, rule, LP_RGX_PERIODIC, &pctx) == EOK) {
- DEBUG(5, ("Matched periodic range\n"));
- ctx->type = TYPE_PERIODIC;
- ctx->per = talloc_zero(ctx, struct periodic_range);
- CHECK_PTR_JMP(ctx->per);
-
- ret = parse_periodic(ctx->per, ctx->trctx, pctx, rule);
- JMP_NEOK(ret);
- } else {
- DEBUG(1, ("Cannot determine rule type\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = EOK;
-done:
- talloc_free(pctx);
- return ret;
-}
-
-/*******************************************************************
- * validation of rules against time_t *
- *******************************************************************/
-
-static int absolute_timerange_valid(struct absolute_range *absr,
- const time_t now,
- bool *result)
-{
- if (difftime(absr->time_from, now) > 0) {
- DEBUG(3, ("Absolute timerange invalid (before interval)\n"));
- *result = false;
- return EOK;
- }
-
- if (difftime(absr->time_to, now) < 0) {
- DEBUG(3, ("Absolute timerange invalid (after interval)\n"));
- *result = false;
- return EOK;
- }
-
- DEBUG(3, ("Absolute timerange valid\n"));
- *result = true;
- return EOK;
-}
-
-static int periodic_timerange_valid(struct periodic_range *per,
- const time_t now,
- bool *result)
-{
- struct tm tm_now;
- int wnum;
- int wom;
-
- memset(&tm_now, 0, sizeof(struct tm));
- if (localtime_r(&now, &tm_now) == NULL) {
- DEBUG(0, ("Cannot convert time_t to struct tm\n"));
- return EFAULT;
- }
- DEBUG(9, ("Got struct tm value %s", asctime(&tm_now)));
- tm2abs(&tm_now);
-
- wnum = weeknum(&tm_now);
- if (wnum == -1) {
- DEBUG(7, ("Cannot get week number"));
- return EINVAL;
- }
- DEBUG(9, ("Week number is %d\n", wnum));
-
- wom = get_week_of_month(&tm_now);
- if (wnum == -1) {
- DEBUG(7, ("Cannot get week of number"));
- return EINVAL;
- }
- DEBUG(9, ("Week of month number is %d\n", wom));
-
- /* The validation itself */
- TEST_BIT_RANGE(per->day_of_week, tm_now.tm_wday, result);
- DEBUG(9, ("day of week OK\n"));
- TEST_BIT_RANGE_PTR(per->day_of_month, tm_now.tm_mday, result);
- DEBUG(9, ("day of month OK\n"));
- TEST_BIT_RANGE(per->week_of_month, wom, result);
- DEBUG(9, ("week of month OK\n"));
- TEST_BIT_RANGE_PTR(per->week_of_year, wnum, result);
- DEBUG(9, ("week of year OK\n"));
- TEST_BIT_RANGE_PTR(per->month, tm_now.tm_mon, result);
- DEBUG(9, ("month OK\n"));
- TEST_BIT_RANGE_PTR(per->day_of_year, tm_now.tm_yday, result);
- DEBUG(9, ("day of year OK\n"));
- TEST_BIT_RANGE_PTR(per->hour, tm_now.tm_hour, result);
- DEBUG(9, ("hour OK\n"));
- TEST_BIT_RANGE_PTR(per->minute, tm_now.tm_min, result);
- DEBUG(9, ("minute OK\n"));
-
- DEBUG(3, ("Periodic timerange valid\n"));
- *result = true;
- return EOK;
-}
-
-/*
- * Returns EOK if the timerange in range_ctx context is valid compared against a
- * given time_t value in NOW, returns ERANGE if the time value is outside the
- * specified range.
- */
-static int timerange_valid(struct range_ctx *ctx,
- const time_t now,
- bool *result)
-{
- int ret;
-
- switch(ctx->type) {
- case TYPE_ABSOLUTE:
- DEBUG(7, ("Checking absolute range\n"));
- ret = absolute_timerange_valid(ctx->abs, now, result);
- break;
-
- case TYPE_PERIODIC:
- DEBUG(7, ("Checking periodic range\n"));
- ret = periodic_timerange_valid(ctx->per, now, result);
- break;
-
- default:
- DEBUG(1, ("Unknown range type (%d)\n", ctx->type));
- ret = EINVAL;
- break;
- }
-
- return ret;
-}
-
-/*******************************************************************
- * public interface *
- *******************************************************************/
-
-/*
- * This is actually the meat of the library. The function takes a string
- * representation of a time rule in STR and time to check against (usually that
- * would be current time) in NOW.
- *
- * It returns EOK if the rule is valid in the current time, ERANGE if not and
- * EINVAL if the rule cannot be parsed
- */
-int check_time_rule(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- const time_t now,
- bool *result)
-{
- int ret;
- struct range_ctx *ctx;
-
- ctx = talloc_zero(mem_ctx, struct range_ctx);
- CHECK_PTR_JMP(ctx);
- ctx->trctx = trctx;
-
- DEBUG(9, ("Got time_t value %s", ctime(&now)));
-
- ret = parse_timespec(ctx, str);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse the time specification (%d)\n", ret));
- goto done;
- }
-
- ret = timerange_valid(ctx, now, result);
- if (ret != EOK) {
- DEBUG(1, ("Cannot check the time range (%d)\n", ret));
- goto done;
- }
-
- ret = EOK;
-done:
- talloc_free(ctx);
- return EOK;
-}
-
-/*
- * Frees the resources taken by the precompiled rules
- */
-static int time_rules_parser_destructor(struct time_rules_ctx *ctx)
-{
- int i;
-
- for (i = 0; i< LP_RGX_MAX; ++i) {
- pcre_free(ctx->re[i]);
- ctx->re[i] = NULL;
- }
-
- return 0;
-}
-
-/*
- * Initializes the parser by precompiling the regular expressions
- * for later use
- */
-int init_time_rules_parser(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx **_out)
-{
- const char *errstr;
- int errval;
- int errpos;
- int ret;
- int i;
- struct time_rules_ctx *ctx = NULL;
-
- ctx = talloc_zero(mem_ctx, struct time_rules_ctx);
- CHECK_PTR(ctx);
- talloc_set_destructor(ctx, time_rules_parser_destructor);
-
- /* Precompile regular expressions */
- for (i = LP_RGX_GENERALIZED; i< LP_RGX_MAX; ++i) {
- ctx->re[i] = pcre_compile2(lookup_table[i],
- 0,
- &errval,
- &errstr,
- &errpos,
- NULL);
-
- if (ctx->re[i] == NULL) {
- DEBUG(0, ("Invalid Regular Expression pattern '%s' at position %d"
- " (Error: %d [%s])\n", lookup_table[i],
- errpos, errval, errstr));
- ret = EFAULT;
- goto done;
- }
-
- }
-
- *_out = ctx;
- return EOK;
-done:
- talloc_free(ctx);
- return ret;
-}
-
diff --git a/server/providers/ipa/ipa_timerules.h b/server/providers/ipa/ipa_timerules.h
deleted file mode 100644
index e1beaa22e..000000000
--- a/server/providers/ipa/ipa_timerules.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- SSSD
-
- IPA Provider Time Rules Parsing
-
- Authors:
- Jakub Hrozek <jhrozek@redhat.com>
-
- Copyright (C) Red Hat, Inc 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 __IPA_TIMERULES_H_
-#define __IPA_TIMERULES_H_
-
-#include <stdbool.h>
-#include <talloc.h>
-
-/* Opaque structure given after init */
-struct time_rules_ctx;
-
-/*
- * Init the parser. Destroy the allocated resources by simply
- * talloc_free()-ing the time_rules_ctx
- */
-int init_time_rules_parser(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx **_out);
-
-/*
- * This is actually the meat of the library. The function takes a string
- * representation of a time rule in STR and time to check against (usually that
- * would be current time) in NOW.
- *
- * It returns EOK if the rule can be parsed, error code if not. If the time
- * given in the NOW parameter would be accepted by the rule, it stores true in
- * RESULT, false otherwise.
- */
-int check_time_rule(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- const time_t now,
- bool *result);
-
-#endif /* __IPA_TIMERULES_H_ */
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
deleted file mode 100644
index a2dadc808..000000000
--- a/server/providers/krb5/krb5_auth.c
+++ /dev/null
@@ -1,1193 +0,0 @@
-/*
- SSSD
-
- Kerberos 5 Backend Module
-
- Authors:
- Sumit Bose <sbose@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 <sys/time.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <pwd.h>
-#include <sys/stat.h>
-
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "util/find_uid.h"
-#include "db/sysdb.h"
-#include "providers/child_common.h"
-#include "providers/krb5/krb5_auth.h"
-#include "providers/krb5/krb5_utils.h"
-
-#ifndef SSSD_LIBEXEC_PATH
-#error "SSSD_LIBEXEC_PATH not defined"
-#else
-#define KRB5_CHILD SSSD_LIBEXEC_PATH"/krb5_child"
-#endif
-
-static errno_t add_krb5_env(struct dp_option *opts, const char *ccname,
- struct pam_data *pd)
-{
- int ret;
- const char *dummy;
- char *env;
- TALLOC_CTX *tmp_ctx = NULL;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- if (ccname != NULL) {
- env = talloc_asprintf(tmp_ctx, "%s=%s",CCACHE_ENV_NAME, ccname);
- if (env == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(env)+1,
- (uint8_t *) env);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- goto done;
- }
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_REALM);
- if (dummy != NULL) {
- env = talloc_asprintf(tmp_ctx, "%s=%s", SSSD_KRB5_REALM, dummy);
- if (env == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(env)+1,
- (uint8_t *) env);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- goto done;
- }
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_KDC);
- if (dummy != NULL) {
- env = talloc_asprintf(tmp_ctx, "%s=%s", SSSD_KRB5_KDC, dummy);
- if (env == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(env)+1,
- (uint8_t *) env);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- goto done;
- }
- }
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static errno_t check_if_ccache_file_is_used(uid_t uid, const char *ccname,
- bool *result)
-{
- int ret;
- size_t offset = 0;
- struct stat stat_buf;
- const char *filename;
- bool active;
-
- *result = false;
-
- if (ccname == NULL || *ccname == '\0') {
- return EINVAL;
- }
-
- if (strncmp(ccname, "FILE:", 5) == 0) {
- offset = 5;
- }
-
- filename = ccname + offset;
-
- if (filename[0] != '/') {
- DEBUG(1, ("Only absolute path names are allowed"));
- return EINVAL;
- }
-
- ret = lstat(filename, &stat_buf);
-
- if (ret == -1 && errno != ENOENT) {
- DEBUG(1, ("stat failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- } else if (ret == EOK) {
- if (stat_buf.st_uid != uid) {
- DEBUG(1, ("Cache file [%s] exists, but is owned by [%d] instead of "
- "[%d].\n", filename, stat_buf.st_uid, uid));
- return EINVAL;
- }
-
- if (!S_ISREG(stat_buf.st_mode)) {
- DEBUG(1, ("Cache file [%s] exists, but is not a regular file.\n",
- filename));
- return EINVAL;
- }
- }
-
- ret = check_if_uid_is_active(uid, &active);
- if (ret != EOK) {
- DEBUG(1, ("check_if_uid_is_active failed.\n"));
- return ret;
- }
-
- if (!active) {
- DEBUG(5, ("User [%d] is not active\n", uid));
- } else {
- DEBUG(9, ("User [%d] is still active, reusing ccache file [%s].\n",
- uid, filename));
- *result = true;
- }
- return EOK;
-}
-
-struct krb5_save_ccname_state {
- struct tevent_context *ev;
- struct sysdb_ctx *sysdb;
- struct sysdb_handle *handle;
- struct sss_domain_info *domain;
- const char *name;
- struct sysdb_attrs *attrs;
-};
-
-static void krb5_save_ccname_trans(struct tevent_req *subreq);
-static void krb5_set_user_attr_done(struct tevent_req *subreq);
-
-static struct tevent_req *krb5_save_ccname_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- const char *name,
- const char *ccname)
-{
- struct tevent_req *req;
- struct tevent_req *subreq;
- struct krb5_save_ccname_state *state;
- int ret;
-
- if (name == NULL || ccname == NULL) {
- DEBUG(1, ("Missing user or ccache name.\n"));
- return NULL;
- }
-
- req = tevent_req_create(mem_ctx, &state, struct krb5_save_ccname_state);
- if (req == NULL) {
- DEBUG(1, ("tevent_req_create failed.\n"));
- return NULL;
- }
-
- state->ev = ev;
- state->sysdb = sysdb;
- state->handle = NULL;
- state->domain = domain;
- state->name = name;
-
- state->attrs = sysdb_new_attrs(state);
- ret = sysdb_attrs_add_string(state->attrs, SYSDB_CCACHE_FILE, ccname);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_add_string failed.\n"));
- goto failed;
- }
-
- subreq = sysdb_transaction_send(state, ev, sysdb);
- if (subreq == NULL) {
- goto failed;
- }
- tevent_req_set_callback(subreq, krb5_save_ccname_trans, req);
-
- return req;
-
-failed:
- talloc_free(req);
- return NULL;
-}
-
-static void krb5_save_ccname_trans(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct krb5_save_ccname_state *state = tevent_req_data(req,
- struct krb5_save_ccname_state);
- int ret;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
- state->domain, state->name,
- state->attrs, SYSDB_MOD_REP);
- if (subreq == NULL) {
- DEBUG(6, ("Error: Out of memory\n"));
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, krb5_set_user_attr_done, req);
-}
-
-static void krb5_set_user_attr_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct krb5_save_ccname_state *state = tevent_req_data(req,
- struct krb5_save_ccname_state);
- int ret;
-
- ret = sysdb_set_user_attr_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (subreq == NULL) {
- DEBUG(6, ("Error: Out of memory\n"));
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
- return;
-}
-
-int krb5_save_ccname_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
-{
- struct io_buffer *buf;
- size_t rp;
- const char *keytab;
- uint32_t validate;
-
- keytab = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_KEYTAB);
- if (keytab == NULL) {
- DEBUG(1, ("Missing keytab option.\n"));
- return EINVAL;
- }
-
- validate = dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) ? 1 : 0;
-
- buf = talloc(kr, struct io_buffer);
- if (buf == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- return ENOMEM;
- }
-
- buf->size = 9*sizeof(uint32_t) + strlen(kr->pd->upn) + strlen(kr->ccname) +
- strlen(keytab) +
- kr->pd->authtok_size;
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
- buf->size += sizeof(uint32_t) + kr->pd->newauthtok_size;
- }
-
- buf->data = talloc_size(kr, buf->size);
- if (buf->data == NULL) {
- DEBUG(1, ("talloc_size failed.\n"));
- talloc_free(buf);
- return ENOMEM;
- }
-
- rp = 0;
- COPY_UINT32(&buf->data[rp], &kr->pd->cmd, rp);
- COPY_UINT32(&buf->data[rp], &kr->pd->pw_uid, rp);
- COPY_UINT32(&buf->data[rp], &kr->pd->gr_gid, rp);
- COPY_UINT32(&buf->data[rp], &validate, rp);
- COPY_UINT32(&buf->data[rp], &kr->is_offline, rp);
-
- COPY_UINT32_VALUE(&buf->data[rp], strlen(kr->pd->upn), rp);
- COPY_MEM(&buf->data[rp], kr->pd->upn, rp, strlen(kr->pd->upn));
-
- COPY_UINT32_VALUE(&buf->data[rp], strlen(kr->ccname), rp);
- COPY_MEM(&buf->data[rp], kr->ccname, rp, strlen(kr->ccname));
-
- COPY_UINT32_VALUE(&buf->data[rp], strlen(keytab), rp);
- COPY_MEM(&buf->data[rp], keytab, rp, strlen(keytab));
-
- COPY_UINT32(&buf->data[rp], &kr->pd->authtok_size, rp);
- COPY_MEM(&buf->data[rp], kr->pd->authtok, rp, kr->pd->authtok_size);
-
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
- COPY_UINT32(&buf->data[rp], &kr->pd->newauthtok_size, rp);
- COPY_MEM(&buf->data[rp], kr->pd->newauthtok,
- rp, kr->pd->newauthtok_size);
- }
-
- *io_buf = buf;
-
- return EOK;
-}
-
-static struct krb5_ctx *get_krb5_ctx(struct be_req *be_req)
-{
- struct pam_data *pd;
-
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- return talloc_get_type(be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
- struct krb5_ctx);
- break;
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- return talloc_get_type(be_req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
- struct krb5_ctx);
- break;
- default:
- DEBUG(1, ("Unsupported PAM task.\n"));
- return NULL;
- }
-}
-
-static void krb_reply(struct be_req *req, int dp_err, int result);
-
-static void krb5_child_timeout(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- struct krb5child_req *kr = talloc_get_type(pvt, struct krb5child_req);
- struct be_req *be_req = kr->req;
- struct pam_data *pd = kr->pd;
- int ret;
-
- if (kr->timeout_handler == NULL) {
- return;
- }
-
- DEBUG(9, ("timeout for child [%d] reached.\n", kr->child_pid));
-
- ret = kill(kr->child_pid, SIGKILL);
- if (ret == -1) {
- DEBUG(1, ("kill failed [%d][%s].\n", errno, strerror(errno)));
- }
-
- talloc_zfree(kr);
-
- pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- be_mark_offline(be_req->be_ctx);
-
- krb_reply(be_req, DP_ERR_OFFLINE, pd->pam_status);
-}
-
-static errno_t activate_child_timeout_handler(struct krb5child_req *kr)
-{
- struct timeval tv;
-
- tv = tevent_timeval_current();
- tv = tevent_timeval_add(&tv,
- dp_opt_get_int(kr->krb5_ctx->opts,
- KRB5_AUTH_TIMEOUT),
- 0);
- kr->timeout_handler = tevent_add_timer(kr->req->be_ctx->ev, kr, tv,
- krb5_child_timeout, kr);
- if (kr->timeout_handler == NULL) {
- DEBUG(1, ("tevent_add_timer failed.\n"));
- return ENOMEM;
- }
-
- return EOK;
-}
-
-static int krb5_cleanup(void *ptr)
-{
- struct krb5child_req *kr = talloc_get_type(ptr, struct krb5child_req);
-
- if (kr == NULL) return EOK;
-
- child_cleanup(kr->read_from_child_fd, kr->write_to_child_fd);
- memset(kr, 0, sizeof(struct krb5child_req));
-
- return EOK;
-}
-
-static errno_t krb5_setup(struct be_req *req, struct krb5child_req **krb5_req)
-{
- struct krb5child_req *kr = NULL;
- struct krb5_ctx *krb5_ctx;
- struct pam_data *pd;
- errno_t err;
-
- pd = talloc_get_type(req->req_data, struct pam_data);
-
- krb5_ctx = get_krb5_ctx(req);
- if (krb5_ctx == NULL) {
- DEBUG(1, ("Kerberos context not available.\n"));
- err = EINVAL;
- goto failed;
- }
-
- kr = talloc_zero(req, struct krb5child_req);
- if (kr == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- err = ENOMEM;
- goto failed;
- }
- kr->read_from_child_fd = -1;
- kr->write_to_child_fd = -1;
- kr->is_offline = false;
- kr->active_ccache_present = true;
- talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
-
- kr->pd = pd;
- kr->req = req;
- kr->krb5_ctx = krb5_ctx;
-
- *krb5_req = kr;
-
- return EOK;
-
-failed:
- talloc_zfree(kr);
-
- return err;
-}
-
-static errno_t fork_child(struct krb5child_req *kr)
-{
- 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", errno, strerror(errno)));
- return err;
- }
- ret = pipe(pipefd_to_child);
- if (ret == -1) {
- err = errno;
- DEBUG(1, ("pipe failed [%d][%s].\n", errno, strerror(errno)));
- return err;
- }
-
- pid = fork();
-
- if (pid == 0) { /* child */
- /* We need to keep the root privileges to read the keytab file if
- * validation is enabled, otherwise we can drop them here and run
- * krb5_child with user privileges.
- * If authtok_size is zero we are offline and want to create an empty
- * ccache file. In this case we can drop the privileges, too. */
- if (!dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) ||
- kr->pd->authtok_size == 0) {
- ret = become_user(kr->pd->pw_uid, kr->pd->gr_gid);
- if (ret != EOK) {
- DEBUG(1, ("become_user failed.\n"));
- return ret;
- }
- }
-
- err = exec_child(kr,
- pipefd_to_child, pipefd_from_child,
- KRB5_CHILD, kr->krb5_ctx->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 */
- kr->child_pid = pid;
- kr->read_from_child_fd = pipefd_from_child[0];
- close(pipefd_from_child[1]);
- kr->write_to_child_fd = pipefd_to_child[1];
- close(pipefd_to_child[0]);
- fd_nonblocking(kr->read_from_child_fd);
- fd_nonblocking(kr->write_to_child_fd);
-
- err = activate_child_timeout_handler(kr);
- if (err != EOK) {
- DEBUG(1, ("activate_child_timeout_handler failed.\n"));
- }
-
- } else { /* error */
- err = errno;
- DEBUG(1, ("fork failed [%d][%s].\n", errno, strerror(errno)));
- return err;
- }
-
- return EOK;
-}
-
-struct handle_child_state {
- struct tevent_context *ev;
- struct krb5child_req *kr;
- uint8_t *buf;
- ssize_t len;
-};
-
-static void handle_child_step(struct tevent_req *subreq);
-static void handle_child_done(struct tevent_req *subreq);
-
-static struct tevent_req *handle_child_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct krb5child_req *kr)
-{
- struct tevent_req *req, *subreq;
- struct handle_child_state *state;
- struct io_buffer *buf;
- int ret;
-
- req = tevent_req_create(mem_ctx, &state, struct handle_child_state);
- if (req == NULL) {
- return NULL;
- }
-
- state->ev = ev;
- state->kr = kr;
- state->buf = NULL;
- state->len = 0;
-
- ret = create_send_buffer(kr, &buf);
- if (ret != EOK) {
- DEBUG(1, ("create_send_buffer failed.\n"));
- goto fail;
- }
-
- ret = fork_child(kr);
- if (ret != EOK) {
- DEBUG(1, ("fork_child failed.\n"));
- goto fail;
- }
-
- subreq = write_pipe_send(state, ev, buf->data, buf->size,
- kr->write_to_child_fd);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, handle_child_step, req);
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void handle_child_step(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct handle_child_state *state = tevent_req_data(req,
- struct handle_child_state);
- int ret;
-
- ret = write_pipe_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- close(state->kr->write_to_child_fd);
- state->kr->write_to_child_fd = -1;
-
- subreq = read_pipe_send(state, state->ev, state->kr->read_from_child_fd);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, handle_child_done, req);
-}
-
-static void handle_child_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct handle_child_state *state = tevent_req_data(req,
- struct handle_child_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;
- }
-
- close(state->kr->read_from_child_fd);
- state->kr->read_from_child_fd = -1;
-
- tevent_req_done(req);
- return;
-}
-
-static int handle_child_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- uint8_t **buf, ssize_t *len)
-{
- struct handle_child_state *state = tevent_req_data(req,
- struct handle_child_state);
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- *buf = talloc_move(mem_ctx, &state->buf);
- *len = state->len;
-
- return EOK;
-}
-
-static void get_user_attr_done(void *pvt, int err, struct ldb_result *res);
-static void krb5_resolve_done(struct tevent_req *req);
-static void krb5_save_ccname_done(struct tevent_req *req);
-static void krb5_child_done(struct tevent_req *req);
-static void krb5_pam_handler_cache_done(struct tevent_req *treq);
-
-void krb5_pam_handler(struct be_req *be_req)
-{
- struct pam_data *pd;
- const char **attrs;
- int pam_status = PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_FATAL;
- int ret;
-
- pd = talloc_get_type(be_req->req_data, struct pam_data);
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- break;
- case SSS_PAM_ACCT_MGMT:
- case SSS_PAM_SETCRED:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
- goto done;
- break;
- default:
- DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd));
- pam_status = PAM_MODULE_UNKNOWN;
- dp_err = DP_ERR_OK;
- goto done;
- }
-
- if (be_is_offline(be_req->be_ctx) &&
- (pd->cmd == SSS_PAM_CHAUTHTOK || pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM)) {
- DEBUG(9, ("Password changes are not possible while offline.\n"));
- pam_status = PAM_AUTHINFO_UNAVAIL;
- dp_err = DP_ERR_OFFLINE;
- goto done;
- }
-
- attrs = talloc_array(be_req, const char *, 4);
- if (attrs == NULL) {
- goto done;
- }
-
- attrs[0] = SYSDB_UPN;
- attrs[1] = SYSDB_HOMEDIR;
- attrs[2] = SYSDB_CCACHE_FILE;
- attrs[3] = NULL;
-
- ret = sysdb_get_user_attr(be_req, be_req->be_ctx->sysdb,
- be_req->be_ctx->domain, pd->user, attrs,
- get_user_attr_done, be_req);
-
- if (ret) {
- goto done;
- }
-
- return;
-
-done:
- pd->pam_status = pam_status;
-
- krb_reply(be_req, dp_err, pd->pam_status);
-}
-
-static void get_user_attr_done(void *pvt, int err, struct ldb_result *res)
-{
- struct be_req *be_req = talloc_get_type(pvt, struct be_req);
- struct krb5_ctx *krb5_ctx;
- struct krb5child_req *kr = NULL;
- struct tevent_req *req;
- krb5_error_code kerr;
- int ret;
- struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data);
- int pam_status=PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_FATAL;
- const char *ccache_file = NULL;
- const char *realm;
-
- ret = krb5_setup(be_req, &kr);
- if (ret != EOK) {
- DEBUG(1, ("krb5_setup failed.\n"));
- goto failed;
- }
-
- krb5_ctx = kr->krb5_ctx;
-
- if (err != LDB_SUCCESS) {
- DEBUG(5, ("sysdb search for upn of user [%s] failed.\n", pd->user));
- goto failed;
- }
-
- realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
- if (realm == NULL) {
- DEBUG(1, ("Missing Kerberos realm.\n"));
- goto failed;
- }
-
- switch (res->count) {
- case 0:
- DEBUG(5, ("No attributes for user [%s] found.\n", pd->user));
- goto failed;
- break;
-
- case 1:
- pd->upn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_UPN, NULL);
- if (pd->upn == NULL) {
- /* NOTE: this is a hack, works only in some environments */
- pd->upn = talloc_asprintf(be_req, "%s@%s", pd->user, realm);
- if (pd->upn == NULL) {
- DEBUG(1, ("failed to build simple upn.\n"));
- goto failed;
- }
- DEBUG(9, ("Using simple UPN [%s].\n", pd->upn));
- }
-
- kr->homedir = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_HOMEDIR,
- NULL);
- if (kr->homedir == NULL) {
- DEBUG(4, ("Home directory for user [%s] not known.\n", pd->user));
- }
-
- ccache_file = ldb_msg_find_attr_as_string(res->msgs[0],
- SYSDB_CCACHE_FILE,
- NULL);
- if (ccache_file != NULL) {
- ret = check_if_ccache_file_is_used(pd->pw_uid, ccache_file,
- &kr->active_ccache_present);
- if (ret != EOK) {
- DEBUG(1, ("check_if_ccache_file_is_used failed.\n"));
- goto failed;
- }
-
- kerr = check_for_valid_tgt(ccache_file, realm, pd->upn,
- &kr->valid_tgt_present);
- if (kerr != 0) {
- DEBUG(1, ("check_for_valid_tgt failed.\n"));
- goto failed;
- }
- } else {
- kr->active_ccache_present = false;
- kr->valid_tgt_present = false;
- DEBUG(4, ("No ccache file for user [%s] found.\n", pd->user));
- }
- DEBUG(9, ("Ccache_file is [%s] and is %s active and TGT is %s valid.\n",
- ccache_file ? ccache_file : "not set",
- kr->active_ccache_present ? "" : "not",
- kr->valid_tgt_present ? "" : "not"));
- kr->ccname = ccache_file;
- break;
-
- default:
- DEBUG(1, ("A user search by name (%s) returned > 1 results!\n",
- pd->user));
- goto failed;
- break;
- }
-
- req = be_resolve_server_send(kr, be_req->be_ctx->ev, be_req->be_ctx,
- krb5_ctx->service->name);
- if (req == NULL) {
- DEBUG(1, ("handle_child_send failed.\n"));
- goto failed;
- }
-
- tevent_req_set_callback(req, krb5_resolve_done, kr);
-
- return;
-
-failed:
- talloc_free(kr);
-
- pd->pam_status = pam_status;
- krb_reply(be_req, dp_err, pd->pam_status);
-}
-
-static void krb5_resolve_done(struct tevent_req *req)
-{
- struct krb5child_req *kr = tevent_req_callback_data(req,
- struct krb5child_req);
- int ret;
- int pam_status = PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_FATAL;
- struct pam_data *pd = kr->pd;
- struct be_req *be_req = kr->req;
- char *msg;
- size_t offset = 0;
-
- ret = be_resolve_server_recv(req, &kr->srv);
- talloc_zfree(req);
- if (ret) {
- /* all servers have been tried and none
- * was found good, setting offline,
- * but we still have to call the child to setup
- * the ccache file. */
- be_mark_offline(be_req->be_ctx);
- kr->is_offline = true;
- }
-
- if (kr->ccname == NULL ||
- (be_is_offline(be_req->be_ctx) && !kr->active_ccache_present &&
- !kr->valid_tgt_present) ||
- (!be_is_offline(be_req->be_ctx) && !kr->active_ccache_present)) {
- DEBUG(9, ("Recreating ccache file.\n"));
- if (kr->ccname != NULL) {
- if (strncmp(kr->ccname, "FILE:", 5) == 0) {
- offset = 5;
- }
- if (kr->ccname[offset] != '/') {
- DEBUG(1, ("Ccache file name [%s] is not an absolute path.\n",
- kr->ccname + offset));
- goto done;
- }
- ret = unlink(kr->ccname + offset);
- if (ret == -1 && errno != ENOENT) {
- DEBUG(1, ("unlink [%s] failed [%d][%s].\n", kr->ccname,
- errno, strerror(errno)));
- goto done;
- }
- }
- kr->ccname = expand_ccname_template(kr, kr,
- dp_opt_get_cstring(kr->krb5_ctx->opts,
- KRB5_CCNAME_TMPL)
- );
- if (kr->ccname == NULL) {
- DEBUG(1, ("expand_ccname_template failed.\n"));
- goto done;
- }
- }
-
- if (be_is_offline(be_req->be_ctx)) {
- DEBUG(9, ("Preparing for offline operation.\n"));
- kr->is_offline = true;
-
- if (kr->valid_tgt_present) {
- DEBUG(9, ("Valid TGT available, nothing to do.\n"));
- msg = talloc_asprintf(pd, "%s=%s", CCACHE_ENV_NAME, kr->ccname);
- if (msg == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- goto done;
- }
-
- ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(msg) + 1,
- (uint8_t *) msg);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
-
- pam_status = PAM_AUTHINFO_UNAVAIL;
- dp_err = DP_ERR_OFFLINE;
- goto done;
- }
- memset(pd->authtok, 0, pd->authtok_size);
- pd->authtok_size = 0;
-
- if (kr->active_ccache_present) {
- req = krb5_save_ccname_send(kr, be_req->be_ctx->ev,
- be_req->be_ctx->sysdb,
- be_req->be_ctx->domain, pd->user,
- kr->ccname);
- if (req == NULL) {
- DEBUG(1, ("krb5_save_ccname_send failed.\n"));
- goto done;
- }
-
- tevent_req_set_callback(req, krb5_save_ccname_done, kr);
- return;
- }
- }
-
- req = handle_child_send(kr, be_req->be_ctx->ev, kr);
- if (req == NULL) {
- DEBUG(1, ("handle_child_send failed.\n"));
- goto done;
- }
-
- tevent_req_set_callback(req, krb5_child_done, kr);
- return;
-
-done:
- talloc_free(kr);
- pd->pam_status = pam_status;
- krb_reply(be_req, dp_err, pd->pam_status);
-}
-
-static void krb5_child_done(struct tevent_req *req)
-{
- struct krb5child_req *kr = tevent_req_callback_data(req,
- struct krb5child_req);
- struct pam_data *pd = kr->pd;
- struct be_req *be_req = kr->req;
- int ret;
- uint8_t *buf = NULL;
- ssize_t len = -1;
- ssize_t pref_len;
- int p;
- int32_t *msg_status;
- int32_t *msg_type;
- int32_t *msg_len;
- int pam_status = PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_FATAL;
-
- ret = handle_child_recv(req, pd, &buf, &len);
- talloc_zfree(kr->timeout_handler);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("child failed (%d [%s])\n", ret, strerror(ret)));
- goto done;
- }
-
- if ((size_t) len < 3*sizeof(int32_t)) {
- DEBUG(1, ("message too short.\n"));
- goto done;
- }
-
- p=0;
- msg_status = ((int32_t *)(buf+p));
- p += sizeof(int32_t);
-
- msg_type = ((int32_t *)(buf+p));
- p += sizeof(int32_t);
-
- msg_len = ((int32_t *)(buf+p));
- p += sizeof(int32_t);
-
- DEBUG(4, ("child response [%d][%d][%d].\n", *msg_status, *msg_type,
- *msg_len));
-
- if ((p + *msg_len) != len) {
- DEBUG(1, ("message format error.\n"));
- goto done;
- }
-
- if (*msg_status != PAM_SUCCESS && *msg_status != PAM_AUTHINFO_UNAVAIL) {
- pam_status = *msg_status;
- dp_err = DP_ERR_OK;
-
- ret = pam_add_response(pd, *msg_type, *msg_len, &buf[p]);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
-
- goto done;
- } else {
- pd->pam_status = *msg_status;
- }
-
- if (*msg_status == PAM_SUCCESS && pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
- goto done;
- }
-
- pref_len = strlen(CCACHE_ENV_NAME)+1;
- if (*msg_len > pref_len &&
- strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0) {
- kr->ccname = talloc_strndup(kr, (char *) &buf[p+pref_len],
- *msg_len-pref_len);
- if (kr->ccname == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- goto done;
- }
- } else {
- DEBUG(1, ("Missing ccache name in child response [%.*s].\n", *msg_len,
- &buf[p]));
- goto done;
- }
-
- if (*msg_status == PAM_AUTHINFO_UNAVAIL) {
- if (kr->srv != NULL) {
- fo_set_port_status(kr->srv, PORT_NOT_WORKING);
- }
- be_mark_offline(be_req->be_ctx);
- kr->is_offline = true;
- } else if (kr->srv != NULL) {
- fo_set_port_status(kr->srv, PORT_WORKING);
- }
-
- struct sysdb_attrs *attrs;
- attrs = sysdb_new_attrs(kr);
- ret = sysdb_attrs_add_string(attrs, SYSDB_CCACHE_FILE, kr->ccname);
- if (ret != EOK) {
- DEBUG(1, ("sysdb_attrs_add_string failed.\n"));
- goto done;
- }
-
- req = krb5_save_ccname_send(kr, be_req->be_ctx->ev, be_req->be_ctx->sysdb,
- be_req->be_ctx->domain, pd->user, kr->ccname);
- if (req == NULL) {
- DEBUG(1, ("krb5_save_ccname_send failed.\n"));
- goto done;
- }
-
- tevent_req_set_callback(req, krb5_save_ccname_done, kr);
- return;
-done:
- talloc_free(kr);
- pd->pam_status = pam_status;
- krb_reply(be_req, dp_err, pd->pam_status);
-}
-
-static void krb5_save_ccname_done(struct tevent_req *req)
-{
- struct krb5child_req *kr = tevent_req_callback_data(req,
- struct krb5child_req);
- struct pam_data *pd = kr->pd;
- struct be_req *be_req = kr->req;
- struct krb5_ctx *krb5_ctx = kr->krb5_ctx;
- int pam_status = PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_FATAL;
- int ret;
- char *password = NULL;
-
- if (pd->cmd == SSS_PAM_AUTHENTICATE) {
- ret = add_krb5_env(krb5_ctx->opts, kr->ccname, pd);
- if (ret != EOK) {
- DEBUG(1, ("add_krb5_env failed.\n"));
- goto failed;
- }
- }
-
- ret = sysdb_set_user_attr_recv(req);
- talloc_zfree(req);
- if (ret != EOK) {
- DEBUG(1, ("Saving ccache name failed.\n"));
- goto failed;
- }
-
- if (kr->is_offline) {
- DEBUG(4, ("Backend is marked offline, retry later!\n"));
- pam_status = PAM_AUTHINFO_UNAVAIL;
- dp_err = DP_ERR_OFFLINE;
- goto failed;
- }
-
- if (be_req->be_ctx->domain->cache_credentials == TRUE) {
-
- /* password caching failures are not fatal errors */
- pd->pam_status = PAM_SUCCESS;
-
- switch(pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- password = talloc_size(be_req, pd->authtok_size + 1);
- if (password != NULL) {
- memcpy(password, pd->authtok, pd->authtok_size);
- password[pd->authtok_size] = '\0';
- }
- break;
- case SSS_PAM_CHAUTHTOK:
- password = talloc_size(be_req, pd->newauthtok_size + 1);
- if (password != NULL) {
- memcpy(password, pd->newauthtok, pd->newauthtok_size);
- password[pd->newauthtok_size] = '\0';
- }
- break;
- default:
- DEBUG(0, ("unsupported PAM command [%d].\n", pd->cmd));
- }
-
- if (password == NULL) {
- DEBUG(0, ("password not available, offline auth may not work.\n"));
- goto failed;
- }
-
- talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
-
- req = sysdb_cache_password_send(be_req, be_req->be_ctx->ev,
- be_req->be_ctx->sysdb, NULL,
- be_req->be_ctx->domain, pd->user,
- password);
- if (req == NULL) {
- DEBUG(2, ("cache_password_send failed, offline auth may not work.\n"));
- goto failed;
- }
- tevent_req_set_callback(req, krb5_pam_handler_cache_done, be_req);
- return;
- }
-
- pam_status = PAM_SUCCESS;
- dp_err = DP_ERR_OK;
-
-failed:
- talloc_free(kr);
-
- pd->pam_status = pam_status;
- krb_reply(be_req, dp_err, pd->pam_status);
-}
-
-static void krb5_pam_handler_cache_done(struct tevent_req *subreq)
-{
- struct be_req *be_req = tevent_req_callback_data(subreq, struct be_req);
- int ret;
-
- /* password caching failures are not fatal errors */
- ret = sysdb_cache_password_recv(subreq);
- talloc_zfree(subreq);
-
- /* so we just log it any return */
- if (ret) {
- DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
- ret, strerror(ret)));
- }
-
- krb_reply(be_req, DP_ERR_OK, PAM_SUCCESS);
-}
-
-static void krb_reply(struct be_req *req, int dp_err, int result)
-{
- req->fn(req, dp_err, result, NULL);
-}
-
diff --git a/server/providers/krb5/krb5_auth.h b/server/providers/krb5/krb5_auth.h
deleted file mode 100644
index a011af890..000000000
--- a/server/providers/krb5/krb5_auth.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- SSSD
-
- Kerberos Backend, private header file
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef __KRB5_AUTH_H__
-#define __KRB5_AUTH_H__
-
-#include "util/sss_krb5.h"
-#include "providers/dp_backend.h"
-#include "providers/krb5/krb5_common.h"
-
-#define CCACHE_ENV_NAME "KRB5CCNAME"
-#define SSSD_KRB5_CHANGEPW_PRINCIPLE "SSSD_KRB5_CHANGEPW_PRINCIPLE"
-
-typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
-
-struct krb5child_req {
- pid_t child_pid;
- int read_from_child_fd;
- int write_to_child_fd;
-
- struct be_req *req;
- struct pam_data *pd;
- struct krb5_ctx *krb5_ctx;
-
- struct tevent_timer *timeout_handler;
-
- const char *ccname;
- const char *homedir;
- bool is_offline;
- struct fo_server *srv;
- bool active_ccache_present;
- bool valid_tgt_present;
-};
-
-struct fo_service;
-
-struct krb5_ctx {
- /* opts taken from kinit */
- /* in seconds */
- krb5_deltat starttime;
- krb5_deltat lifetime;
- krb5_deltat rlife;
-
- int forwardable;
- int proxiable;
- int addresses;
-
- int not_forwardable;
- int not_proxiable;
- int no_addresses;
-
- int verbose;
-
- char* principal_name;
- char* service_name;
- char* keytab_name;
- char* k5_cache_name;
- char* k4_cache_name;
-
- action_type action;
-
- struct dp_option *opts;
- struct krb5_service *service;
- int child_debug_fd;
-};
-
-void krb5_pam_handler(struct be_req *be_req);
-
-#endif /* __KRB5_AUTH_H__ */
diff --git a/server/providers/krb5/krb5_become_user.c b/server/providers/krb5/krb5_become_user.c
deleted file mode 100644
index 351f539a3..000000000
--- a/server/providers/krb5/krb5_become_user.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- SSSD
-
- Kerberos 5 Backend Module -- Utilities
-
- Authors:
- Sumit Bose <sbose@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 "util/util.h"
-
-errno_t become_user(uid_t uid, gid_t gid)
-{
- int ret;
-
- DEBUG(9, ("Trying to become user [%d][%d].\n", uid, gid));
- ret = setgid(gid);
- if (ret == -1) {
- DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- }
-
- ret = setuid(uid);
- if (ret == -1) {
- DEBUG(1, ("setuid failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- }
-
- ret = setegid(gid);
- if (ret == -1) {
- DEBUG(1, ("setegid failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- }
-
- ret = seteuid(uid);
- if (ret == -1) {
- DEBUG(1, ("seteuid failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- }
-
- return EOK;
-}
-
diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
deleted file mode 100644
index 5e185940e..000000000
--- a/server/providers/krb5/krb5_child.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- SSSD
-
- Kerberos 5 Backend Module -- tgt_req and changepw child
-
- Authors:
- Sumit Bose <sbose@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/user_info_msg.h"
-#include "providers/child_common.h"
-#include "providers/dp_backend.h"
-#include "providers/krb5/krb5_auth.h"
-#include "providers/krb5/krb5_utils.h"
-
-struct krb5_child_ctx {
- /* opts taken from kinit */
- /* in seconds */
- krb5_deltat starttime;
- krb5_deltat lifetime;
- krb5_deltat rlife;
-
- int forwardable;
- int proxiable;
- int addresses;
-
- int not_forwardable;
- int not_proxiable;
- int no_addresses;
-
- int verbose;
-
- char* principal_name;
- char* service_name;
- char* keytab_name;
- char* k5_cache_name;
- char* k4_cache_name;
-
- action_type action;
-
- char *kdcip;
- char *realm;
- char *changepw_principle;
- char *ccache_dir;
- char *ccname_template;
- int auth_timeout;
-
- int child_debug_fd;
-};
-
-struct krb5_req {
- krb5_context ctx;
- krb5_principal princ;
- char* name;
- krb5_creds *creds;
- krb5_get_init_creds_opt *options;
- pid_t child_pid;
- int read_from_child_fd;
- int write_to_child_fd;
-
- struct be_req *req;
- struct pam_data *pd;
- struct krb5_child_ctx *krb5_ctx;
- errno_t (*child_req)(int fd, struct krb5_req *kr);
-
- char *ccname;
- char *keytab;
- bool validate;
-};
-
-static krb5_context krb5_error_ctx;
-static const char *__krb5_error_msg;
-#define KRB5_DEBUG(level, krb5_error) do { \
- __krb5_error_msg = sss_krb5_get_error_message(krb5_error_ctx, krb5_error); \
- DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
- sss_krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
-} while(0);
-
-static krb5_error_code create_empty_cred(struct krb5_req *kr, krb5_creds **_cred)
-{
- krb5_error_code kerr;
- krb5_creds *cred = NULL;
- krb5_data *krb5_realm;
-
- cred = calloc(sizeof(krb5_creds), 1);
- if (cred == NULL) {
- DEBUG(1, ("calloc failed.\n"));
- return ENOMEM;
- }
-
- kerr = krb5_copy_principal(kr->ctx, kr->princ, &cred->client);
- if (kerr != 0) {
- DEBUG(1, ("krb5_copy_principal failed.\n"));
- goto done;
- }
-
- krb5_realm = krb5_princ_realm(kr->ctx, kr->princ);
-
- kerr = krb5_build_principal_ext(kr->ctx, &cred->server,
- krb5_realm->length, krb5_realm->data,
- KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
- krb5_realm->length, krb5_realm->data, 0);
- if (kerr != 0) {
- DEBUG(1, ("krb5_build_principal_ext failed.\n"));
- goto done;
- }
-
-done:
- if (kerr != 0) {
- if (cred != NULL && cred->client != NULL) {
- krb5_free_principal(kr->ctx, cred->client);
- }
-
- free(cred);
- } else {
- *_cred = cred;
- }
-
- return kerr;
-}
-
-static krb5_error_code create_ccache_file(struct krb5_req *kr, krb5_creds *creds)
-{
- krb5_error_code kerr;
- krb5_ccache tmp_cc = NULL;
- char *cc_file_name;
- int fd = -1;
- size_t ccname_len;
- char *dummy;
- char *tmp_ccname;
- krb5_creds *l_cred;
-
- if (strncmp(kr->ccname, "FILE:", 5) == 0) {
- cc_file_name = kr->ccname + 5;
- } else {
- cc_file_name = kr->ccname;
- }
-
- if (cc_file_name[0] != '/') {
- DEBUG(1, ("Ccache filename is not an absolute path.\n"));
- return EINVAL;
- }
-
- dummy = strrchr(cc_file_name, '/');
- tmp_ccname = talloc_strndup(kr, cc_file_name, (size_t) (dummy-cc_file_name));
- if (tmp_ccname == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- return ENOMEM;
- }
- tmp_ccname = talloc_asprintf_append(tmp_ccname, "/.krb5cc_dummy_XXXXXX");
-
- fd = mkstemp(tmp_ccname);
- if (fd == -1) {
- DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
- return errno;
- }
-
- kerr = krb5_cc_resolve(kr->ctx, tmp_ccname, &tmp_cc);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
-
- kerr = krb5_cc_initialize(kr->ctx, tmp_cc, kr->princ);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
- if (fd != -1) {
- close(fd);
- fd = -1;
- }
-
- if (creds == NULL) {
- kerr = create_empty_cred(kr, &l_cred);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
- } else {
- l_cred = creds;
- }
-
- kerr = krb5_cc_store_cred(kr->ctx, tmp_cc, l_cred);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
-
- kerr = krb5_cc_close(kr->ctx, tmp_cc);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
- tmp_cc = NULL;
-
- ccname_len = strlen(cc_file_name);
- if (ccname_len >= 6 && strcmp(cc_file_name + (ccname_len-6), "XXXXXX")==0 ) {
- fd = mkstemp(cc_file_name);
- if (fd == -1) {
- DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
- kerr = errno;
- goto done;
- }
- }
-
- kerr = rename(tmp_ccname, cc_file_name);
- if (kerr == -1) {
- DEBUG(1, ("rename failed [%d][%s].\n", errno, strerror(errno)));
- }
-
-done:
- if (fd != -1) {
- close(fd);
- fd = -1;
- }
- if (kerr != 0 && tmp_cc != NULL) {
- krb5_cc_destroy(kr->ctx, tmp_cc);
- }
- return kerr;
-}
-
-static struct response *init_response(TALLOC_CTX *mem_ctx) {
- struct response *r;
- r = talloc(mem_ctx, struct response);
- r->buf = talloc_size(mem_ctx, MAX_CHILD_MSG_SIZE);
- if (r->buf == NULL) {
- DEBUG(1, ("talloc_size failed.\n"));
- return NULL;
- }
- r->max_size = MAX_CHILD_MSG_SIZE;
- r->size = 0;
-
- return r;
-}
-
-static errno_t pack_response_packet(struct response *resp, int status, int type,
- size_t len, const uint8_t *data)
-{
- int p=0;
-
- if ((3*sizeof(int32_t) + len +1) > resp->max_size) {
- DEBUG(1, ("response message too big.\n"));
- return ENOMEM;
- }
-
- COPY_INT32_VALUE(&resp->buf[p], status, p);
- COPY_INT32_VALUE(&resp->buf[p], type, p);
- COPY_INT32_VALUE(&resp->buf[p], len, p);
- COPY_MEM(&resp->buf[p], data, p, len);
-
- resp->size = p;
-
- return EOK;
-}
-
-static struct response *prepare_response_message(struct krb5_req *kr,
- krb5_error_code kerr,
- char *user_error_message,
- int pam_status)
-{
- char *msg = NULL;
- const char *krb5_msg = NULL;
- int ret;
- struct response *resp;
- size_t user_resp_len;
- uint8_t *user_resp;
-
- resp = init_response(kr);
- if (resp == NULL) {
- DEBUG(1, ("init_response failed.\n"));
- return NULL;
- }
-
- if (kerr == 0) {
- if(kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- ret = pack_response_packet(resp, PAM_SUCCESS, SSS_PAM_SYSTEM_INFO,
- strlen("success") + 1,
- (const uint8_t *) "success");
- } else {
- if (kr->ccname == NULL) {
- DEBUG(1, ("Error obtaining ccname.\n"));
- return NULL;
- }
-
- msg = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, kr->ccname);
- if (msg == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- return NULL;
- }
-
- ret = pack_response_packet(resp, PAM_SUCCESS, SSS_PAM_ENV_ITEM,
- strlen(msg) + 1, (uint8_t *) msg);
- talloc_zfree(msg);
- }
- } else {
-
- if (user_error_message != NULL) {
- ret = pack_user_info_chpass_error(kr, user_error_message,
- &user_resp_len, &user_resp);
- if (ret != EOK) {
- DEBUG(1, ("pack_user_info_chpass_error failed.\n"));
- talloc_zfree(user_error_message);
- } else {
- ret = pack_response_packet(resp, pam_status, SSS_PAM_USER_INFO,
- user_resp_len, user_resp);
- if (ret != EOK) {
- DEBUG(1, ("pack_response_packet failed.\n"));
- talloc_zfree(user_error_message);
- }
- }
- }
-
- if (user_error_message == NULL) {
- 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 NULL;
- }
-
- ret = pack_response_packet(resp, pam_status, SSS_PAM_SYSTEM_INFO,
- strlen(krb5_msg) + 1,
- (const uint8_t *) krb5_msg);
- sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
- } else {
-
- }
-
- }
-
- if (ret != EOK) {
- DEBUG(1, ("pack_response_packet failed.\n"));
- return NULL;
- }
-
- return resp;
-}
-
-static errno_t sendresponse(int fd, krb5_error_code kerr,
- char *user_error_message, int pam_status,
- struct krb5_req *kr)
-{
- struct response *resp;
- size_t written;
- int ret;
-
- resp = prepare_response_message(kr, kerr, user_error_message, pam_status);
- if (resp == NULL) {
- DEBUG(1, ("prepare_response_message failed.\n"));
- return ENOMEM;
- }
-
- written = 0;
- while (written < resp->size) {
- ret = write(fd, 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;
- }
-
- return EOK;
-}
-
-static krb5_error_code validate_tgt(struct krb5_req *kr)
-{
- krb5_error_code kerr;
- krb5_error_code kt_err;
- char *principal;
- krb5_keytab keytab;
- krb5_kt_cursor cursor;
- krb5_keytab_entry entry;
- krb5_verify_init_creds_opt opt;
-
- memset(&keytab, 0, sizeof(keytab));
- kerr = krb5_kt_resolve(kr->ctx, kr->keytab, &keytab);
- if (kerr != 0) {
- DEBUG(1, ("error resolving keytab [%s], not verifying TGT.\n",
- kr->keytab));
- return kerr;
- }
-
- memset(&cursor, 0, sizeof(cursor));
- kerr = krb5_kt_start_seq_get(kr->ctx, keytab, &cursor);
- if (kerr != 0) {
- DEBUG(1, ("error reading keytab [%s], not verifying TGT.\n",
- kr->keytab));
- return kerr;
- }
-
- /* We look for the first entry from our realm or take the last one */
- memset(&entry, 0, sizeof(entry));
- while ((kt_err = krb5_kt_next_entry(kr->ctx, keytab, &entry, &cursor)) == 0) {
- if (krb5_realm_compare(kr->ctx, entry.principal, kr->princ)) {
- DEBUG(9, ("Found keytab entry with the realm of the credential.\n"));
- break;
- }
-
- kerr = krb5_free_keytab_entry_contents(kr->ctx, &entry);
- if (kerr != 0) {
- DEBUG(1, ("Failed to free keytab entry.\n"));
- }
- memset(&entry, 0, sizeof(entry));
- }
-
- /* Close the keytab here. Even though we're using cursors, the file
- * handle is stored in the krb5_keytab structure, and it gets
- * overwritten when the verify_init_creds() call below creates its own
- * cursor, creating a leak. */
- kerr = krb5_kt_end_seq_get(kr->ctx, keytab, &cursor);
- if (kerr != 0) {
- DEBUG(1, ("krb5_kt_end_seq_get failed, not verifying TGT.\n"));
- goto done;
- }
-
- /* check if we got any errors from krb5_kt_next_entry */
- if (kt_err != 0 && kt_err != KRB5_KT_END) {
- DEBUG(1, ("error reading keytab [%s], not verifying TGT.\n",
- kr->keytab));
- goto done;
- }
-
- /* Get the principal to which the key belongs, for logging purposes. */
- principal = NULL;
- kerr = krb5_unparse_name(kr->ctx, entry.principal, &principal);
- if (kerr != 0) {
- DEBUG(1, ("internal error parsing principal name, "
- "not verifying TGT.\n"));
- goto done;
- }
-
-
- krb5_verify_init_creds_opt_init(&opt);
- kerr = krb5_verify_init_creds(kr->ctx, kr->creds, entry.principal, keytab,
- NULL, &opt);
-
- if (kerr == 0) {
- DEBUG(5, ("TGT verified using key for [%s].\n", principal));
- } else {
- DEBUG(1 ,("TGT failed verification using key for [%s].\n", principal));
- }
-
-done:
- if (krb5_kt_close(kr->ctx, keytab) != 0) {
- DEBUG(1, ("krb5_kt_close failed"));
- }
- if (krb5_free_keytab_entry_contents(kr->ctx, &entry) != 0) {
- DEBUG(1, ("Failed to free keytab entry.\n"));
- }
- if (principal != NULL) {
- sss_krb5_free_unparsed_name(kr->ctx, principal);
- }
-
- return kerr;
-
-}
-
-static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
- char *password)
-{
- krb5_error_code kerr = 0;
- int ret;
-
- kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- password, NULL, NULL, 0, NULL,
- kr->options);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- return kerr;
- }
-
- if (kr->validate) {
- kerr = validate_tgt(kr);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- return kerr;
- }
-
- /* We drop root privileges which were needed to read the keytab file
- * for the validation validation of the credentials here to run the
- * ccache I/O operations with user privileges. */
- ret = become_user(kr->pd->pw_uid, kr->pd->gr_gid);
- if (ret != EOK) {
- DEBUG(1, ("become_user failed.\n"));
- return ret;
- }
- } else {
- DEBUG(9, ("TGT validation is disabled.\n"));
- }
-
- kerr = create_ccache_file(kr, kr->creds);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto done;
- }
-
- kerr = 0;
-
-done:
- krb5_free_cred_contents(kr->ctx, kr->creds);
-
- return kerr;
-
-}
-
-static errno_t changepw_child(int fd, struct krb5_req *kr)
-{
- int ret;
- krb5_error_code kerr = 0;
- char *pass_str = NULL;
- char *newpass_str = NULL;
- int pam_status = PAM_SYSTEM_ERR;
- int result_code = -1;
- krb5_data result_code_string;
- krb5_data result_string;
- char *user_error_message = NULL;
-
- pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
- kr->pd->authtok_size);
- if (pass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
- kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- pass_str, NULL, NULL, 0,
- kr->krb5_ctx->changepw_principle,
- kr->options);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- if (kerr == KRB5_KDC_UNREACH) {
- pam_status = PAM_AUTHINFO_UNAVAIL;
- }
- goto sendresponse;
- }
-
- memset(pass_str, 0, kr->pd->authtok_size);
- talloc_zfree(pass_str);
- memset(kr->pd->authtok, 0, kr->pd->authtok_size);
-
- if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
- DEBUG(9, ("Initial authentication for change password operation "
- "successfull.\n"));
- krb5_free_cred_contents(kr->ctx, kr->creds);
- pam_status = PAM_SUCCESS;
- goto sendresponse;
- }
-
- newpass_str = talloc_strndup(kr, (const char *) kr->pd->newauthtok,
- kr->pd->newauthtok_size);
- if (newpass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
- kerr = krb5_change_password(kr->ctx, kr->creds, newpass_str, &result_code,
- &result_code_string, &result_string);
-
- if (kerr != 0 || result_code != 0) {
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- } else {
- kerr = KRB5KRB_ERR_GENERIC;
- }
-
- if (result_code_string.length > 0) {
- DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
- result_code_string.length, result_code_string.data));
- user_error_message = talloc_strndup(kr->pd, result_code_string.data,
- result_code_string.length);
- if (user_error_message == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- }
- }
-
- if (result_string.length > 0) {
- DEBUG(1, ("krb5_change_password failed [%d][%.*s].\n", result_code,
- result_string.length, result_string.data));
- talloc_free(user_error_message);
- user_error_message = talloc_strndup(kr->pd, result_string.data,
- result_string.length);
- if (user_error_message == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- }
- }
-
- pam_status = PAM_AUTHTOK_ERR;
- goto sendresponse;
- }
-
- krb5_free_cred_contents(kr->ctx, kr->creds);
-
- kerr = get_and_save_tgt(kr, newpass_str);
- memset(newpass_str, 0, kr->pd->newauthtok_size);
- talloc_zfree(newpass_str);
- memset(kr->pd->newauthtok, 0, kr->pd->newauthtok_size);
-
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- if (kerr == KRB5_KDC_UNREACH) {
- pam_status = PAM_AUTHINFO_UNAVAIL;
- }
- }
-
-sendresponse:
- ret = sendresponse(fd, kerr, user_error_message, pam_status, kr);
- if (ret != EOK) {
- DEBUG(1, ("sendresponse failed.\n"));
- }
-
- return ret;
-}
-
-static errno_t tgt_req_child(int fd, struct krb5_req *kr)
-{
- int ret;
- krb5_error_code kerr = 0;
- char *pass_str = NULL;
- int pam_status = PAM_SYSTEM_ERR;
-
- pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
- kr->pd->authtok_size);
- if (pass_str == NULL) {
- DEBUG(1, ("talloc_strndup failed.\n"));
- kerr = KRB5KRB_ERR_GENERIC;
- goto sendresponse;
- }
-
- kerr = get_and_save_tgt(kr, pass_str);
-
- /* If the password is expired the KDC will always return
- KRB5KDC_ERR_KEY_EXP regardless if the supplied password is correct or
- not. In general the password can still be used to get a changepw ticket.
- So we validate the password by trying to get a changepw ticket. */
- if (kerr == KRB5KDC_ERR_KEY_EXP) {
- kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
- pass_str, NULL, NULL, 0,
- kr->krb5_ctx->changepw_principle,
- kr->options);
- krb5_free_cred_contents(kr->ctx, kr->creds);
- if (kerr == 0) {
- kerr = KRB5KDC_ERR_KEY_EXP;
- }
- }
-
- memset(pass_str, 0, kr->pd->authtok_size);
- talloc_zfree(pass_str);
- memset(kr->pd->authtok, 0, kr->pd->authtok_size);
-
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- switch (kerr) {
- case KRB5_KDC_UNREACH:
- pam_status = PAM_AUTHINFO_UNAVAIL;
- break;
- case KRB5KDC_ERR_KEY_EXP:
- pam_status = PAM_AUTHTOK_EXPIRED;
- break;
- case KRB5KDC_ERR_PREAUTH_FAILED:
- pam_status = PAM_CRED_ERR;
- break;
- default:
- pam_status = PAM_SYSTEM_ERR;
- }
- }
-
-sendresponse:
- ret = sendresponse(fd, kerr, NULL, pam_status, kr);
- if (ret != EOK) {
- DEBUG(1, ("sendresponse failed.\n"));
- }
-
- return ret;
-}
-
-static errno_t create_empty_ccache(int fd, struct krb5_req *kr)
-{
- int ret;
- int pam_status = PAM_SUCCESS;
-
- ret = create_ccache_file(kr, NULL);
- if (ret != 0) {
- KRB5_DEBUG(1, ret);
- pam_status = PAM_SYSTEM_ERR;
- }
-
- ret = sendresponse(fd, ret, NULL, pam_status, kr);
- if (ret != EOK) {
- DEBUG(1, ("sendresponse failed.\n"));
- }
-
- return ret;
-}
-
-static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
- char **ccname, char **keytab, uint32_t *validate,
- uint32_t *offline)
-{
- size_t p = 0;
- uint32_t len;
-
- COPY_UINT32_CHECK(&pd->cmd, buf + p, p, size);
- COPY_UINT32_CHECK(&pd->pw_uid, buf + p, p, size);
- COPY_UINT32_CHECK(&pd->gr_gid, buf + p, p, size);
- COPY_UINT32_CHECK(validate, buf + p, p, size);
- COPY_UINT32_CHECK(offline, buf + p, p, size);
-
- COPY_UINT32_CHECK(&len, buf + p, p, size);
- if ((p + len ) > size) return EINVAL;
- pd->upn = talloc_strndup(pd, (char *)(buf + p), len);
- if (pd->upn == NULL) return ENOMEM;
- p += len;
-
- COPY_UINT32_CHECK(&len, buf + p, p, size);
- if ((p + len ) > size) return EINVAL;
- *ccname = talloc_strndup(pd, (char *)(buf + p), len);
- if (*ccname == NULL) return ENOMEM;
- p += len;
-
- COPY_UINT32_CHECK(&len, buf + p, p, size);
- if ((p + len ) > size) return EINVAL;
- *keytab = talloc_strndup(pd, (char *)(buf + p), len);
- if (*keytab == NULL) return ENOMEM;
- p += len;
-
- COPY_UINT32_CHECK(&len, buf + p, p, size);
- if ((p + len) > size) return EINVAL;
- pd->authtok = (uint8_t *)talloc_strndup(pd, (char *)(buf + p), len);
- if (pd->authtok == NULL) return ENOMEM;
- pd->authtok_size = len + 1;
- p += len;
-
- if (pd->cmd == SSS_PAM_CHAUTHTOK) {
- COPY_UINT32_CHECK(&len, buf + p, p, size);
-
- if ((p + len) > size) return EINVAL;
- pd->newauthtok = (uint8_t *)talloc_strndup(pd, (char *)(buf + p), len);
- if (pd->newauthtok == NULL) return ENOMEM;
- pd->newauthtok_size = len + 1;
- p += len;
- } else {
- pd->newauthtok = NULL;
- pd->newauthtok_size = 0;
- }
-
- return EOK;
-}
-
-static int krb5_cleanup(void *ptr)
-{
- struct krb5_req *kr = talloc_get_type(ptr, struct krb5_req);
- if (kr == NULL) return EOK;
-
- if (kr->options != NULL) {
- sss_krb5_get_init_creds_opt_free(kr->ctx, kr->options);
- }
-
- if (kr->creds != NULL) {
- krb5_free_cred_contents(kr->ctx, kr->creds);
- krb5_free_creds(kr->ctx, kr->creds);
- }
- if (kr->name != NULL)
- sss_krb5_free_unparsed_name(kr->ctx, kr->name);
- if (kr->princ != NULL)
- krb5_free_principal(kr->ctx, kr->princ);
- if (kr->ctx != NULL)
- krb5_free_context(kr->ctx);
-
- if (kr->krb5_ctx != NULL) {
- memset(kr->krb5_ctx, 0, sizeof(struct krb5_child_ctx));
- }
- memset(kr, 0, sizeof(struct krb5_req));
-
- return EOK;
-}
-
-static int krb5_setup(struct pam_data *pd, const char *user_princ_str,
- uint32_t offline, struct krb5_req **krb5_req)
-{
- struct krb5_req *kr = NULL;
- krb5_error_code kerr = 0;
-
- kr = talloc_zero(pd, struct krb5_req);
- if (kr == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- kerr = ENOMEM;
- goto failed;
- }
- talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
-
- kr->krb5_ctx = talloc_zero(kr, struct krb5_child_ctx);
- if (kr->krb5_ctx == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- kerr = ENOMEM;
- goto failed;
- }
-
- kr->krb5_ctx->changepw_principle = getenv(SSSD_KRB5_CHANGEPW_PRINCIPLE);
- if (kr->krb5_ctx->changepw_principle == NULL) {
- DEBUG(1, ("Cannot read [%s] from environment.\n",
- SSSD_KRB5_CHANGEPW_PRINCIPLE));
- if (pd->cmd == SSS_PAM_CHAUTHTOK) {
- goto failed;
- }
- }
-
- kr->krb5_ctx->realm = getenv(SSSD_KRB5_REALM);
- if (kr->krb5_ctx->realm == NULL) {
- DEBUG(2, ("Cannot read [%s] from environment.\n", SSSD_KRB5_REALM));
- }
-
- kr->pd = pd;
-
- switch(pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- /* If we are offline, we need to create an empty ccache file */
- if (offline) {
- kr->child_req = create_empty_ccache;
- } else {
- kr->child_req = tgt_req_child;
- }
- break;
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- kr->child_req = changepw_child;
- break;
- default:
- DEBUG(1, ("PAM command [%d] not supported.\n", pd->cmd));
- kerr = EINVAL;
- goto failed;
- }
-
- kerr = krb5_init_context(&kr->ctx);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto failed;
- }
-
- kerr = krb5_parse_name(kr->ctx, user_princ_str, &kr->princ);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto failed;
- }
-
- kerr = krb5_unparse_name(kr->ctx, kr->princ, &kr->name);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto failed;
- }
-
- kr->creds = calloc(1, sizeof(krb5_creds));
- if (kr->creds == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- kerr = ENOMEM;
- goto failed;
- }
-
- kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
- if (kerr != 0) {
- KRB5_DEBUG(1, kerr);
- goto failed;
- }
-
-/* TODO: set options, e.g.
- * krb5_get_init_creds_opt_set_tkt_life
- * krb5_get_init_creds_opt_set_renew_life
- * krb5_get_init_creds_opt_set_forwardable
- * krb5_get_init_creds_opt_set_proxiable
- * krb5_get_init_creds_opt_set_etype_list
- * krb5_get_init_creds_opt_set_address_list
- * krb5_get_init_creds_opt_set_preauth_list
- * krb5_get_init_creds_opt_set_salt
- * krb5_get_init_creds_opt_set_change_password_prompt
- * krb5_get_init_creds_opt_set_pa
- */
-
- *krb5_req = kr;
- return EOK;
-
-failed:
- talloc_free(kr);
-
- return kerr;
-}
-
-int main(int argc, const char *argv[])
-{
- uint8_t *buf = NULL;
- int ret;
- ssize_t len = 0;
- struct pam_data *pd = NULL;
- struct krb5_req *kr = NULL;
- char *ccname;
- char *keytab;
- uint32_t validate;
- uint32_t offline;
- int opt;
- poptContext pc;
- int debug_fd = -1;
-
- 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, ("krb5_child started.\n"));
-
- pd = talloc(NULL, struct pam_data);
- if (pd == NULL) {
- DEBUG(1, ("malloc failed.\n"));
- _exit(-1);
- }
-
- debug_prg_name = talloc_asprintf(pd, "[sssd[krb5_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(pd, sizeof(uint8_t)*IN_BUF_SIZE);
- if (buf == NULL) {
- DEBUG(1, ("malloc failed.\n"));
- _exit(-1);
- }
-
- 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, pd, &ccname, &keytab, &validate, &offline);
- if (ret != EOK) {
- DEBUG(1, ("unpack_buffer failed.\n"));
- goto fail;
- }
-
- ret = krb5_setup(pd, pd->upn, offline, &kr);
- if (ret != EOK) {
- DEBUG(1, ("krb5_setup failed.\n"));
- goto fail;
- }
- kr->ccname = ccname;
- kr->keytab = keytab;
- kr->validate = (validate == 0) ? false : true;
-
- ret = kr->child_req(STDOUT_FILENO, kr);
- if (ret != EOK) {
- DEBUG(1, ("Child request failed.\n"));
- goto fail;
- }
-
- close(STDOUT_FILENO);
- talloc_free(pd);
-
- return 0;
-
-fail:
- close(STDOUT_FILENO);
- talloc_free(pd);
- exit(-1);
-}
diff --git a/server/providers/krb5/krb5_common.c b/server/providers/krb5/krb5_common.c
deleted file mode 100644
index 86676f44c..000000000
--- a/server/providers/krb5/krb5_common.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- SSSD
-
- Kerberos Provider Common Functions
-
- Authors:
- Sumit Bose <sbose@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 <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <netdb.h>
-
-#include "providers/dp_backend.h"
-#include "providers/krb5/krb5_common.h"
-
-struct dp_option default_krb5_opts[] = {
- { "krb5_kdcip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
- { "krb5_ccachedir", DP_OPT_STRING, { "/tmp" }, NULL_STRING },
- { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
- { "krb5_changepw_principal", DP_OPT_STRING, { "kadmin/changepw" }, NULL_STRING },
- { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
- { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
- { "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }
-};
-
-errno_t check_and_export_options(struct dp_option *opts,
- struct sss_domain_info *dom)
-{
- int ret;
- char *value;
- const char *realm;
- const char *dummy;
- struct stat stat_buf;
- char **list;
-
- realm = dp_opt_get_cstring(opts, KRB5_REALM);
- if (realm == NULL) {
- ret = dp_opt_set_string(opts, KRB5_REALM, dom->name);
- if (ret != EOK) {
- DEBUG(1, ("dp_opt_set_string failed.\n"));
- return ret;
- }
- realm = dom->name;
- }
-
- ret = setenv(SSSD_KRB5_REALM, realm, 1);
- if (ret != EOK) {
- DEBUG(2, ("setenv %s failed, authentication might fail.\n",
- SSSD_KRB5_REALM));
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_KDC);
- if (dummy == NULL) {
- DEBUG(1, ("No KDC expicitly configured, using defaults"));
- } else {
- ret = split_on_separator(opts, dummy, ',', true, &list, NULL);
- if (ret != EOK) {
- DEBUG(1, ("Failed to parse server list!\n"));
- return ret;
- }
- ret = write_kdcinfo_file(realm, list[0]);
- if (ret != EOK) {
- DEBUG(1, ("write_kdcinfo_file failed, "
- "using kerberos defaults from /etc/krb5.conf"));
- }
- talloc_free(list);
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_CCACHEDIR);
- ret = lstat(dummy, &stat_buf);
- if (ret != EOK) {
- DEBUG(1, ("lstat for [%s] failed: [%d][%s].\n", dummy, errno,
- strerror(errno)));
- return ret;
- }
- if ( !S_ISDIR(stat_buf.st_mode) ) {
- DEBUG(1, ("Value of krb5ccache_dir [%s] is not a directory.\n", dummy));
- return EINVAL;
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_CCNAME_TMPL);
- if (dummy == NULL) {
- DEBUG(1, ("Missing credential cache name template.\n"));
- return EINVAL;
- }
- if (dummy[0] != '/' && strncmp(dummy, "FILE:", 5) != 0) {
- DEBUG(1, ("Currently only file based credential caches are supported "
- "and krb5ccname_template must start with '/' or 'FILE:'\n"));
- return EINVAL;
- }
-
- dummy = dp_opt_get_cstring(opts, KRB5_CHANGEPW_PRINC);
- if (dummy == NULL) {
- DEBUG(1, ("Missing change password principle.\n"));
- return EINVAL;
- }
- if (strchr(dummy, '@') == NULL) {
- value = talloc_asprintf(opts, "%s@%s", dummy, realm);
- if (value == NULL) {
- DEBUG(7, ("talloc_asprintf failed.\n"));
- return ENOMEM;
- }
- ret = dp_opt_set_string(opts, KRB5_CHANGEPW_PRINC, value);
- if (ret != EOK) {
- DEBUG(1, ("dp_opt_set_string failed.\n"));
- return ret;
- }
- dummy = value;
- }
-
- ret = setenv(SSSD_KRB5_CHANGEPW_PRINCIPLE, dummy, 1);
- if (ret != EOK) {
- DEBUG(2, ("setenv %s failed, password change might fail.\n",
- SSSD_KRB5_CHANGEPW_PRINCIPLE));
- }
-
- return EOK;
-}
-
-errno_t krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
- const char *conf_path, struct dp_option **_opts)
-{
- int ret;
- struct dp_option *opts;
-
- opts = talloc_zero(memctx, struct dp_option);
- if (opts == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- return ENOMEM;
- }
-
- ret = dp_get_options(opts, cdb, conf_path, default_krb5_opts,
- KRB5_OPTS, &opts);
- if (ret != EOK) {
- DEBUG(1, ("dp_get_options failed.\n"));
- goto done;
- }
-
- *_opts = opts;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_zfree(opts);
- }
-
- return ret;
-}
-
-errno_t write_kdcinfo_file(const char *realm, const char *kdc)
-{
- int ret;
- int fd = -1;
- char *tmp_name = NULL;
- char *kdcinfo_name = NULL;
- TALLOC_CTX *tmp_ctx = NULL;
- int kdc_len;
-
- if (realm == NULL || *realm == '\0' || kdc == NULL || *kdc == '\0') {
- DEBUG(1, ("Missing or empty realm or kdc.\n"));
- return EINVAL;
- }
-
- kdc_len = strlen(kdc);
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(1, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- tmp_name = talloc_asprintf(tmp_ctx, PUBCONF_PATH"/.kdcinfo_dummy_XXXXXX");
- if (tmp_name == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- kdcinfo_name = talloc_asprintf(tmp_ctx, KDCINFO_TMPL, realm);
- if (kdcinfo_name == NULL) {
- DEBUG(1, ("talloc_asprintf failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- fd = mkstemp(tmp_name);
- if (fd == -1) {
- DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
- ret = errno;
- goto done;
- }
-
- ret = write(fd, kdc, kdc_len);
- if (ret == -1) {
- DEBUG(1, ("write failed [%d][%s].\n", errno, strerror(errno)));
- goto done;
- }
- if (ret != kdc_len) {
- DEBUG(1, ("Partial write occured, this should never happen.\n"));
- ret = EINTR;
- goto done;
- }
-
- ret = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (ret == -1) {
- DEBUG(1, ("fchmod failed [%d][%s].\n", errno, strerror(errno)));
- goto done;
- }
-
- ret = close(fd);
- if (ret == -1) {
- DEBUG(1, ("close failed [%d][%s].\n", errno, strerror(errno)));
- goto done;
- }
-
- ret = rename(tmp_name, kdcinfo_name);
- if (ret == -1) {
- DEBUG(1, ("rename failed [%d][%s].\n", errno, strerror(errno)));
- goto done;
- }
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static void krb5_resolve_callback(void *private_data, struct fo_server *server)
-{
- struct krb5_service *krb5_service;
- struct hostent *srvaddr;
- char *address;
- int ret;
-
- krb5_service = talloc_get_type(private_data, struct krb5_service);
- if (!krb5_service) {
- DEBUG(1, ("FATAL: Bad private_data\n"));
- return;
- }
-
- srvaddr = fo_get_server_hostent(server);
- if (!srvaddr) {
- DEBUG(1, ("FATAL: No hostent available for server (%s)\n",
- fo_get_server_name(server)));
- return;
- }
-
- address = talloc_asprintf(krb5_service, "%s", srvaddr->h_name);
- if (!address) {
- DEBUG(1, ("Failed to copy address ...\n"));
- return;
- }
-
- talloc_zfree(krb5_service->address);
- krb5_service->address = address;
-
- ret = write_kdcinfo_file(krb5_service->realm, address);
- if (ret != EOK) {
- DEBUG(2, ("write_kdcinfo_file failed, authentication might fail.\n"));
- }
-
- return;
-}
-
-
-int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
- const char *service_name, const char *servers,
- const char *realm, struct krb5_service **_service)
-{
- TALLOC_CTX *tmp_ctx;
- struct krb5_service *service;
- char **list = NULL;
- int ret;
- int i;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- service = talloc_zero(tmp_ctx, struct krb5_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;
- }
-
- service->realm = talloc_strdup(service, realm);
- if (!service->realm) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = split_on_separator(tmp_ctx, servers, ',', true, &list, NULL);
- if (ret != EOK) {
- DEBUG(1, ("Failed to parse server list!\n"));
- goto done;
- }
-
- for (i = 0; list[i]; i++) {
-
- talloc_steal(service, list[i]);
-
- ret = be_fo_add_server(ctx, service_name, list[i], 0, NULL);
- if (ret && ret != EEXIST) {
- DEBUG(0, ("Failed to add server\n"));
- goto done;
- }
-
- DEBUG(6, ("Added Server %s\n", list[i]));
- }
-
- ret = be_fo_service_add_callback(memctx, ctx, service_name,
- krb5_resolve_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/krb5/krb5_common.h b/server/providers/krb5/krb5_common.h
deleted file mode 100644
index 832ffcdd5..000000000
--- a/server/providers/krb5/krb5_common.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- SSSD
-
- Kerberos Backend, common header file
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef __KRB5_COMMON_H__
-#define __KRB5_COMMON_H__
-
-#include "config.h"
-#include <stdbool.h>
-
-#include "providers/dp_backend.h"
-#include "util/util.h"
-#include "util/sss_krb5.h"
-
-#define SSSD_KRB5_KDC "SSSD_KRB5_KDC"
-#define SSSD_KRB5_REALM "SSSD_KRB5_REALM"
-#define SSSD_KRB5_CHANGEPW_PRINCIPLE "SSSD_KRB5_CHANGEPW_PRINCIPLE"
-
-#define KDCINFO_TMPL PUBCONF_PATH"/kdcinfo.%s"
-
-enum krb5_opts {
- KRB5_KDC = 0,
- KRB5_REALM,
- KRB5_CCACHEDIR,
- KRB5_CCNAME_TMPL,
- KRB5_CHANGEPW_PRINC,
- KRB5_AUTH_TIMEOUT,
- KRB5_KEYTAB,
- KRB5_VALIDATE,
-
- KRB5_OPTS
-};
-
-struct krb5_service {
- char *name;
- char *address;
- char *realm;
-};
-
-errno_t check_and_export_options(struct dp_option *opts,
- struct sss_domain_info *dom);
-
-errno_t krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
- const char *conf_path, struct dp_option **_opts);
-
-errno_t write_kdcinfo_file(const char *realm, const char *kdc);
-
-int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
- const char *service_name, const char *servers,
- const char *realm, struct krb5_service **_service);
-#endif /* __KRB5_COMMON_H__ */
diff --git a/server/providers/krb5/krb5_init.c b/server/providers/krb5/krb5_init.c
deleted file mode 100644
index 43cbc1bc7..000000000
--- a/server/providers/krb5/krb5_init.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- SSSD
-
- Kerberos 5 Backend Module
-
- Authors:
- Sumit Bose <sbose@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 <fcntl.h>
-#include <sys/stat.h>
-#include "providers/child_common.h"
-#include "providers/krb5/krb5_auth.h"
-#include "providers/krb5/krb5_common.h"
-
-struct krb5_options {
- struct dp_option *opts;
- struct krb5_ctx *auth_ctx;
-};
-
-struct krb5_options *krb5_options = NULL;
-
-struct bet_ops krb5_auth_ops = {
- .handler = krb5_pam_handler,
- .finalize = NULL,
-};
-
-int sssm_krb5_auth_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_auth_data)
-{
- struct krb5_ctx *ctx = NULL;
- int ret;
- struct tevent_signal *sige;
- unsigned v;
- FILE *debug_filep;
- const char *krb5_servers;
- const char *krb5_realm;
-
- if (krb5_options == NULL) {
- krb5_options = talloc_zero(bectx, struct krb5_options);
- if (krb5_options == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- return ENOMEM;
- }
- ret = krb5_get_options(krb5_options, bectx->cdb, bectx->conf_path,
- &krb5_options->opts);
- if (ret != EOK) {
- DEBUG(1, ("krb5_get_options failed.\n"));
- return ret;
- }
- }
-
- if (krb5_options->auth_ctx != NULL) {
- *ops = &krb5_auth_ops;
- *pvt_auth_data = krb5_options->auth_ctx;
- return EOK;
- }
-
- ctx = talloc_zero(bectx, struct krb5_ctx);
- if (!ctx) {
- DEBUG(1, ("talloc failed.\n"));
- return ENOMEM;
- }
-
- ctx->action = INIT_PW;
- ctx->opts = krb5_options->opts;
-
- krb5_servers = dp_opt_get_string(ctx->opts, KRB5_KDC);
- if (krb5_servers == NULL) {
- DEBUG(0, ("Missing krb5_kdcip option!\n"));
- return EINVAL;
- }
-
- krb5_realm = dp_opt_get_string(ctx->opts, KRB5_REALM);
- if (krb5_realm == NULL) {
- DEBUG(0, ("Missing krb5_realm option!\n"));
- return EINVAL;
- }
-
- ret = krb5_service_init(ctx, bectx, "KRB5", krb5_servers, krb5_realm,
- &ctx->service);
- if (ret != EOK) {
- DEBUG(0, ("Failed to init IPA failover service!\n"));
- return ret;
- }
-
- ret = check_and_export_options(ctx->opts, bectx->domain);
- if (ret != EOK) {
- DEBUG(1, ("check_and_export_options failed.\n"));
- goto fail;
- }
-
- sige = tevent_add_signal(bectx->ev, ctx, SIGCHLD, SA_SIGINFO,
- child_sig_handler, NULL);
- if (sige == NULL) {
- DEBUG(1, ("tevent_add_signal failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- if (debug_to_file != 0) {
- ret = open_debug_file_ex("krb5_child", &debug_filep);
- if (ret != EOK) {
- DEBUG(0, ("Error setting up logging (%d) [%s]\n",
- ret, strerror(ret)));
- goto fail;
- }
-
- ctx->child_debug_fd = fileno(debug_filep);
- if (ctx->child_debug_fd == -1) {
- DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno)));
- ret = errno;
- goto fail;
- }
-
- v = fcntl(ctx->child_debug_fd, F_GETFD, 0);
- fcntl(ctx->child_debug_fd, F_SETFD, v & ~FD_CLOEXEC);
- }
-
- *ops = &krb5_auth_ops;
- *pvt_auth_data = ctx;
- return EOK;
-
-fail:
- talloc_free(ctx);
- return ret;
-}
-
-int sssm_krb5_chpass_init(struct be_ctx *bectx,
- struct bet_ops **ops,
- void **pvt_auth_data)
-{
- return sssm_krb5_auth_init(bectx, ops, pvt_auth_data);
-}
diff --git a/server/providers/krb5/krb5_utils.c b/server/providers/krb5/krb5_utils.c
deleted file mode 100644
index 489030af8..000000000
--- a/server/providers/krb5/krb5_utils.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- SSSD
-
- Kerberos 5 Backend Module -- Utilities
-
- Authors:
- Sumit Bose <sbose@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 <string.h>
-#include <stdlib.h>
-
-#include "providers/krb5/krb5_utils.h"
-#include "providers/krb5/krb5_auth.h"
-#include "util/util.h"
-
-char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
- const char *template)
-{
- char *copy;
- char *p;
- char *n;
- char *result = NULL;
- const char *dummy;
-
- if (template == NULL) {
- DEBUG(1, ("Missing template.\n"));
- return NULL;
- }
-
- copy = talloc_strdup(mem_ctx, template);
- if (copy == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- return NULL;
- }
-
- result = talloc_strdup(mem_ctx, "");
- if (result == NULL) {
- DEBUG(1, ("talloc_strdup failed.\n"));
- return NULL;
- }
-
- p = copy;
- while ( (n = strchr(p, '%')) != NULL) {
- *n = '\0';
- n++;
- if ( *n == '\0' ) {
- DEBUG(1, ("format error, single %% at the end of the template.\n"));
- return NULL;
- }
-
- switch( *n ) {
- case 'u':
- if (kr->pd->user == NULL) {
- DEBUG(1, ("Cannot expand user name template "
- "because user name is empty.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%s", p,
- kr->pd->user);
- break;
- case 'U':
- if (kr->pd->pw_uid <= 0) {
- DEBUG(1, ("Cannot expand uid template "
- "because uid is invalid.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%d", p,
- kr->pd->pw_uid);
- break;
- case 'p':
- if (kr->pd->upn == NULL) {
- DEBUG(1, ("Cannot expand user principle name template "
- "because upn is empty.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%s", p, kr->pd->upn);
- break;
- case '%':
- result = talloc_asprintf_append(result, "%s%%", p);
- break;
- case 'r':
- dummy = dp_opt_get_string(kr->krb5_ctx->opts, KRB5_REALM);
- if (dummy == NULL) {
- DEBUG(1, ("Missing kerberos realm.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%s", p, dummy);
- break;
- case 'h':
- if (kr->homedir == NULL) {
- DEBUG(1, ("Cannot expand home directory template "
- "because the path is not available.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%s", p, kr->homedir);
- break;
- case 'd':
- dummy = dp_opt_get_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR);
- if (dummy == NULL) {
- DEBUG(1, ("Missing credential cache directory.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%s", p, dummy);
- break;
- case 'P':
- if (kr->pd->cli_pid == 0) {
- DEBUG(1, ("Cannot expand PID template "
- "because PID is not available.\n"));
- return NULL;
- }
- result = talloc_asprintf_append(result, "%s%d", p,
- kr->pd->cli_pid);
- break;
- default:
- DEBUG(1, ("format error, unknown template [%%%c].\n", *n));
- return NULL;
- }
-
- if (result == NULL) {
- DEBUG(1, ("talloc_asprintf_append failed.\n"));
- return NULL;
- }
-
- p = n + 1;
- }
-
- result = talloc_asprintf_append(result, "%s", p);
-
- return result;
-}
diff --git a/server/providers/krb5/krb5_utils.h b/server/providers/krb5/krb5_utils.h
deleted file mode 100644
index 7637041a6..000000000
--- a/server/providers/krb5/krb5_utils.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- SSSD
-
- Kerberos Backend, header file for utilities
-
- Authors:
- Sumit Bose <sbose@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/>.
-*/
-
-#ifndef __KRB5_UTILS_H__
-#define __KRB5_UTILS_H__
-
-#include <talloc.h>
-
-#include "providers/krb5/krb5_auth.h"
-#include "providers/data_provider.h"
-
-char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
- const char *template);
-
-errno_t become_user(uid_t uid, gid_t gid);
-
-#endif /* __KRB5_UTILS_H__ */
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
deleted file mode 100644
index cfe8adb97..000000000
--- 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 0d34be2ca..000000000
--- 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 bd4294f83..000000000
--- 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 ff1ffb725..000000000
--- 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 4bbc07a68..000000000
--- 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 f3fb4443c..000000000
--- 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 bc06e8bdc..000000000
--- 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, &timestamp);
- 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, &timestamp);
- 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 b1f053fbc..000000000
--- 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 39c67cc92..000000000
--- 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 16dbb7843..000000000
--- 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 959c08a65..000000000
--- 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 3c52d236b..000000000
--- 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 abebe2883..000000000
--- 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, &timestamp);
- 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, &timestamp);
- 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 18e47d3b7..000000000
--- 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 55f76ed70..000000000
--- 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 0a95c8a0d..000000000
--- 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;
-}
diff --git a/server/providers/providers.h b/server/providers/providers.h
deleted file mode 100644
index 44e7028ab..000000000
--- a/server/providers/providers.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- SSSD
-
- Data Provider, public header file
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
-
- 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/>.
-*/
-
-int dp_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb);
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
deleted file mode 100644
index 12bb25ec7..000000000
--- a/server/providers/proxy.c
+++ /dev/null
@@ -1,2521 +0,0 @@
-/*
- SSSD
-
- Proxy Module
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008-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 <nss.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <dlfcn.h>
-
-#include <security/pam_appl.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "providers/dp_backend.h"
-#include "db/sysdb.h"
-
-struct proxy_nss_ops {
- enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*setpwent)(void);
- enum nss_status (*getpwent_r)(struct passwd *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*endpwent)(void);
-
- enum nss_status (*getgrnam_r)(const char *name, struct group *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*setgrent)(void);
- enum nss_status (*getgrent_r)(struct group *result,
- char *buffer, size_t buflen, int *errnop);
- enum nss_status (*endgrent)(void);
- enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
- long int *start, long int *size,
- gid_t **groups, long int limit,
- int *errnop);
-};
-
-struct proxy_ctx {
- struct be_ctx *be;
- int entry_cache_timeout;
- struct proxy_nss_ops ops;
-};
-
-struct proxy_auth_ctx {
- struct be_ctx *be;
- char *pam_target;
-};
-
-struct authtok_conv {
- uint32_t authtok_size;
- uint8_t *authtok;
-};
-
-static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
- struct pam_response **response,
- void *appdata_ptr) {
- int i;
- struct pam_response *reply;
- struct authtok_conv *auth_data;
-
- auth_data = talloc_get_type(appdata_ptr, struct authtok_conv);
-
- if (num_msg <= 0) return PAM_CONV_ERR;
-
- reply = (struct pam_response *) calloc(num_msg,
- sizeof(struct pam_response));
- if (reply == NULL) return PAM_CONV_ERR;
-
- for (i=0; i < num_msg; i++) {
- switch( msgm[i]->msg_style ) {
- case PAM_PROMPT_ECHO_OFF:
- DEBUG(4, ("Conversation message: [%s]\n", msgm[i]->msg));
- reply[i].resp_retcode = 0;
- reply[i].resp = calloc(auth_data->authtok_size + 1,
- sizeof(char));
- if (reply[i].resp == NULL) goto failed;
- memcpy(reply[i].resp, auth_data->authtok, auth_data->authtok_size);
-
- break;
- default:
- DEBUG(1, ("Conversation style %d not supported.\n",
- msgm[i]->msg_style));
- goto failed;
- }
- }
-
- *response = reply;
- reply = NULL;
-
- return PAM_SUCCESS;
-
-failed:
- free(reply);
- return PAM_CONV_ERR;
-}
-
-static void proxy_pam_handler_cache_done(struct tevent_req *treq);
-static void proxy_reply(struct be_req *req, int dp_err,
- int error, const char *errstr);
-
-static void proxy_pam_handler(struct be_req *req) {
- int ret;
- int pam_status;
- pam_handle_t *pamh=NULL;
- struct authtok_conv *auth_data;
- struct pam_conv conv;
- struct pam_data *pd;
- struct proxy_auth_ctx *ctx;;
- bool cache_auth_data = false;
-
- pd = talloc_get_type(req->req_data, struct pam_data);
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- ctx = talloc_get_type(req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
- struct proxy_auth_ctx);
- break;
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- ctx = talloc_get_type(req->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
- struct proxy_auth_ctx);
- break;
- case SSS_PAM_ACCT_MGMT:
- ctx = talloc_get_type(req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
- struct proxy_auth_ctx);
- break;
- case SSS_PAM_SETCRED:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- pd->pam_status = PAM_SUCCESS;
- proxy_reply(req, DP_ERR_OK, EOK, NULL);
- return;
- default:
- DEBUG(1, ("Unsupported PAM task.\n"));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- proxy_reply(req, DP_ERR_OK, EINVAL, "Unsupported PAM task");
- return;
- }
-
- conv.conv=proxy_internal_conv;
- auth_data = talloc_zero(req, struct authtok_conv);
- conv.appdata_ptr=auth_data;
-
- ret = pam_start(ctx->pam_target, pd->user, &conv, &pamh);
- if (ret == PAM_SUCCESS) {
- DEBUG(1, ("Pam transaction started.\n"));
- ret = pam_set_item(pamh, PAM_TTY, pd->tty);
- if (ret != PAM_SUCCESS) {
- DEBUG(1, ("Setting PAM_TTY failed: %s.\n", pam_strerror(pamh, ret)));
- }
- ret = pam_set_item(pamh, PAM_RUSER, pd->ruser);
- if (ret != PAM_SUCCESS) {
- DEBUG(1, ("Setting PAM_RUSER failed: %s.\n", pam_strerror(pamh, ret)));
- }
- ret = pam_set_item(pamh, PAM_RHOST, pd->rhost);
- if (ret != PAM_SUCCESS) {
- DEBUG(1, ("Setting PAM_RHOST failed: %s.\n", pam_strerror(pamh, ret)));
- }
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
- pam_status = pam_authenticate(pamh, 0);
- if ((pam_status == PAM_SUCCESS) &&
- (req->be_ctx->domain->cache_credentials)) {
- cache_auth_data = true;
- }
- break;
- case SSS_PAM_SETCRED:
- pam_status=pam_setcred(pamh, 0);
- break;
- case SSS_PAM_ACCT_MGMT:
- pam_status=pam_acct_mgmt(pamh, 0);
- break;
- case SSS_PAM_OPEN_SESSION:
- pam_status=pam_open_session(pamh, 0);
- break;
- case SSS_PAM_CLOSE_SESSION:
- pam_status=pam_close_session(pamh, 0);
- break;
- case SSS_PAM_CHAUTHTOK:
- if (pd->priv != 1) {
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
- pam_status = pam_authenticate(pamh, 0);
- if (pam_status != PAM_SUCCESS) break;
- }
- auth_data->authtok_size = pd->newauthtok_size;
- auth_data->authtok = pd->newauthtok;
- pam_status = pam_chauthtok(pamh, 0);
- if ((pam_status == PAM_SUCCESS) &&
- (req->be_ctx->domain->cache_credentials)) {
- cache_auth_data = true;
- }
- break;
- case SSS_PAM_CHAUTHTOK_PRELIM:
- if (pd->priv != 1) {
- auth_data->authtok_size = pd->authtok_size;
- auth_data->authtok = pd->authtok;
- pam_status = pam_authenticate(pamh, 0);
- } else {
- pam_status = PAM_SUCCESS;
- }
- break;
- default:
- DEBUG(1, ("unknown PAM call"));
- pam_status=PAM_ABORT;
- }
-
- DEBUG(4, ("Pam result: [%d][%s]\n", pam_status,
- pam_strerror(pamh, pam_status)));
-
- if (pam_status == PAM_AUTHINFO_UNAVAIL) {
- be_mark_offline(req->be_ctx);
- }
-
- ret = pam_end(pamh, pam_status);
- if (ret != PAM_SUCCESS) {
- pamh=NULL;
- DEBUG(1, ("Cannot terminate pam transaction.\n"));
- }
-
- } else {
- DEBUG(1, ("Failed to initialize pam transaction.\n"));
- pam_status = PAM_SYSTEM_ERR;
- }
-
- pd->pam_status = pam_status;
-
- if (cache_auth_data) {
- struct tevent_req *subreq;
- char *password;
-
- password = talloc_size(req, auth_data->authtok_size + 1);
- if (!password) {
- /* password caching failures are not fatal errors */
- return proxy_reply(req, DP_ERR_OK, EOK, NULL);
- }
- memcpy(password, auth_data->authtok, auth_data->authtok_size);
- password[auth_data->authtok_size] = '\0';
- talloc_set_destructor((TALLOC_CTX *)password, password_destructor);
-
- subreq = sysdb_cache_password_send(req, req->be_ctx->ev,
- req->be_ctx->sysdb, NULL,
- req->be_ctx->domain,
- pd->user, password);
- if (!subreq) {
- /* password caching failures are not fatal errors */
- return proxy_reply(req, DP_ERR_OK, EOK, NULL);
- }
- tevent_req_set_callback(subreq, proxy_pam_handler_cache_done, req);
- }
-
- proxy_reply(req, DP_ERR_OK, EOK, NULL);
-}
-
-static void proxy_pam_handler_cache_done(struct tevent_req *subreq)
-{
- struct be_req *req = tevent_req_callback_data(subreq, struct be_req);
- int ret;
-
- /* password caching failures are not fatal errors */
- ret = sysdb_cache_password_recv(subreq);
- talloc_zfree(subreq);
-
- /* so we just log it any return */
- if (ret) {
- DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
- ret, strerror(ret)));
- }
-
- return proxy_reply(req, DP_ERR_OK, EOK, NULL);
-}
-
-static void proxy_reply(struct be_req *req, int dp_err,
- int error, const char *errstr)
-{
- return req->fn(req, dp_err, error, errstr);
-}
-
-/* =Common-proxy-tevent_req-utils=========================================*/
-
-#define DEFAULT_BUFSIZE 4096
-#define MAX_BUF_SIZE 1024*1024 /* max 1MiB */
-
-struct proxy_state {
- struct tevent_context *ev;
- struct proxy_ctx *ctx;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *domain;
- const char *name;
-
- struct sysdb_handle *handle;
- struct passwd *pwd;
- struct group *grp;
- uid_t uid;
- gid_t gid;
-};
-
-static void proxy_default_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- int ret;
-
- ret = sysdb_transaction_commit_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static int proxy_default_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-
-/* =Getpwnam-wrapper======================================================*/
-
-static void get_pw_name_process(struct tevent_req *subreq);
-static void get_pw_name_remove_done(struct tevent_req *subreq);
-static void get_pw_name_add_done(struct tevent_req *subreq);
-
-static struct tevent_req *get_pw_name_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- const char *name)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->name = name;
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_pw_name_process, req);
-
- return req;
-}
-
-static void get_pw_name_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- size_t buflen;
- bool delete_user = false;
- int ret;
-
- DEBUG(7, ("Searching user by name (%s)\n", state->name));
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->pwd = talloc(state, struct passwd);
- if (!state->pwd) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- /* FIXME: should we move this call outside the transaction to keep the
- * transaction as short as possible ? */
- status = ctx->ops.getpwnam_r(state->name, state->pwd,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_NOTFOUND:
-
- DEBUG(7, ("User %s not found.\n", state->name));
- delete_user = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("User %s found: (%s, %d, %d)\n",
- state->name, state->pwd->pw_name,
- state->pwd->pw_uid, state->pwd->pw_gid));
-
- /* uid=0 or gid=0 are invalid values */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) ||
- OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
- state->name));
- delete_user = true;
- break;
- }
-
- subreq = sysdb_store_user_send(state, state->ev, state->handle,
- state->domain,
- state->pwd->pw_name,
- state->pwd->pw_passwd,
- state->pwd->pw_uid,
- state->pwd->pw_gid,
- state->pwd->pw_gecos,
- state->pwd->pw_dir,
- state->pwd->pw_shell,
- NULL, ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_pw_name_add_done, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- tevent_req_error(req, ENXIO);
- return;
-
- default:
- DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
- state->name, status));
- tevent_req_error(req, EIO);
- return;
- }
-
- if (delete_user) {
- struct ldb_dn *dn;
-
- DEBUG(7, ("User %s does not exist (or is invalid) on remote server,"
- " deleting!\n", state->name));
-
- dn = sysdb_user_dn(state->sysdb, state,
- state->domain->name, state->name);
- if (!dn) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- subreq = sysdb_delete_entry_send(state, state->ev, state->handle, dn, true);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_pw_name_remove_done, req);
- }
-}
-
-static void get_pw_name_add_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_store_user_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-static void get_pw_name_remove_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_delete_entry_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-/* =Getpwuid-wrapper======================================================*/
-
-static void get_pw_uid_process(struct tevent_req *subreq);
-static void get_pw_uid_remove_done(struct tevent_req *subreq);
-
-static struct tevent_req *get_pw_uid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- uid_t uid)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->uid = uid;
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_pw_uid_process, req);
-
- return req;
-}
-
-static void get_pw_uid_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- size_t buflen;
- bool delete_user = false;
- int ret;
-
- DEBUG(7, ("Searching user by uid (%d)\n", state->uid));
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->pwd = talloc(state, struct passwd);
- if (!state->pwd) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- /* always zero out the pwd structure */
- memset(state->pwd, 0, sizeof(struct passwd));
-
- status = ctx->ops.getpwuid_r(state->uid, state->pwd,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_NOTFOUND:
-
- DEBUG(7, ("User %d not found.\n", state->uid));
- delete_user = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("User %d found (%s, %d, %d)\n",
- state->uid, state->pwd->pw_name,
- state->pwd->pw_uid, state->pwd->pw_gid));
-
- /* uid=0 or gid=0 are invalid values */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) ||
- OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
- state->name));
- delete_user = true;
- break;
- }
-
- subreq = sysdb_store_user_send(state, state->ev, state->handle,
- state->domain,
- state->pwd->pw_name,
- state->pwd->pw_passwd,
- state->pwd->pw_uid,
- state->pwd->pw_gid,
- state->pwd->pw_gecos,
- state->pwd->pw_dir,
- state->pwd->pw_shell,
- NULL, ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_pw_name_add_done, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- tevent_req_error(req, ENXIO);
- return;
-
- default:
- DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
- state->name, status));
- tevent_req_error(req, EIO);
- return;
- }
-
- if (delete_user) {
- DEBUG(7, ("User %d does not exist (or is invalid) on remote server,"
- " deleting!\n", state->uid));
-
- subreq = sysdb_delete_user_send(state, state->ev,
- NULL, state->handle,
- state->domain,
- NULL, state->uid);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_pw_uid_remove_done, req);
- }
-}
-
-static void get_pw_uid_remove_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_delete_user_recv(subreq);
- talloc_zfree(subreq);
- if (ret && ret != ENOENT) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-/* =Getpwent-wrapper======================================================*/
-
-struct enum_users_state {
- struct tevent_context *ev;
- struct proxy_ctx *ctx;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *domain;
- struct sysdb_handle *handle;
-
- struct passwd *pwd;
-
- size_t buflen;
- char *buffer;
-
- bool in_transaction;
-};
-
-static void enum_users_process(struct tevent_req *subreq);
-
-static struct tevent_req *enum_users_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain)
-{
- struct tevent_req *req, *subreq;
- struct enum_users_state *state;
- enum nss_status status;
-
- DEBUG(7, ("Enumerating users\n"));
-
- req = tevent_req_create(mem_ctx, &state, struct enum_users_state);
- if (!req) return NULL;
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->handle = NULL;
-
- state->pwd = talloc(state, struct passwd);
- if (!state->pwd) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
-
- state->buflen = DEFAULT_BUFSIZE;
- state->buffer = talloc_size(state, state->buflen);
- if (!state->buffer) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
-
- state->in_transaction = false;
-
- status = ctx->ops.setpwent();
- if (status != NSS_STATUS_SUCCESS) {
- tevent_req_error(req, EIO);
- goto fail;
- }
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
- tevent_req_set_callback(subreq, enum_users_process, req);
-
- return req;
-
-fail:
- tevent_req_post(req, ev);
- return req;
-}
-
-static void enum_users_process(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);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *newbuf;
- int ret;
-
- if (!state->in_transaction) {
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- goto fail;
- }
- talloc_zfree(subreq);
-
- state->in_transaction = true;
- } else {
- ret = sysdb_store_user_recv(subreq);
- if (ret) {
- /* Do not fail completely on errors.
- * Just report the failure to save and go on */
- DEBUG(2, ("Failed to store user. Ignoring.\n"));
- }
- talloc_zfree(subreq);
- }
-
-again:
- /* always zero out the pwd structure */
- memset(state->pwd, 0, sizeof(struct passwd));
-
- /* get entry */
- status = ctx->ops.getpwent_r(state->pwd,
- state->buffer, state->buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (state->buflen < MAX_BUF_SIZE) {
- state->buflen *= 2;
- }
- if (state->buflen > MAX_BUF_SIZE) {
- state->buflen = MAX_BUF_SIZE;
- }
- newbuf = talloc_realloc_size(state, state->buffer, state->buflen);
- if (!newbuf) {
- ret = ENOMEM;
- goto fail;
- }
- state->buffer = newbuf;
- goto again;
-
- case NSS_STATUS_NOTFOUND:
-
- /* we are done here */
- DEBUG(7, ("Enumeration completed.\n"));
-
- ctx->ops.endpwent();
- subreq = sysdb_transaction_commit_send(state, state->ev,
- state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
- return;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("User found (%s, %d, %d)\n", state->pwd->pw_name,
- state->pwd->pw_uid, state->pwd->pw_gid));
-
- /* uid=0 or gid=0 are invalid values */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) ||
- OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
- state->pwd->pw_name));
-
- goto again; /* skip */
- }
-
- subreq = sysdb_store_user_send(state, state->ev, state->handle,
- state->domain,
- state->pwd->pw_name,
- state->pwd->pw_passwd,
- state->pwd->pw_uid,
- state->pwd->pw_gid,
- state->pwd->pw_gecos,
- state->pwd->pw_dir,
- state->pwd->pw_shell,
- NULL, ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, enum_users_process, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- ret = ENXIO;
- goto fail;
-
- default:
- DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n",
- ret, strerror(ret)));
- goto fail;
- }
-
-fail:
- ctx->ops.endpwent();
- tevent_req_error(req, ret);
-}
-
-/* =Getgrnam-wrapper======================================================*/
-
-#define DEBUG_GR_MEM(level, state) \
- do { \
- if (debug_level >= level) { \
- if (!state->grp->gr_mem || !state->grp->gr_mem[0]) { \
- DEBUG(level, ("Group %s has no members!\n", \
- state->grp->gr_name)); \
- } else { \
- int i = 0; \
- while (state->grp->gr_mem[i]) { \
- /* count */ \
- i++; \
- } \
- DEBUG(level, ("Group %s has %d members!\n", \
- state->grp->gr_name, i)); \
- } \
- } \
- } while(0)
-
-static void get_gr_name_process(struct tevent_req *subreq);
-static void get_gr_name_remove_done(struct tevent_req *subreq);
-static void get_gr_name_add_done(struct tevent_req *subreq);
-
-static struct tevent_req *get_gr_name_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- const char *name)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->name = name;
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_gr_name_process, req);
-
- return req;
-}
-
-static void get_gr_name_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- char *newbuf;
- size_t buflen;
- bool delete_group = false;
- struct sysdb_attrs *members;
- int ret;
-
- DEBUG(7, ("Searching group by name (%s)\n", state->name));
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->grp = talloc(state, struct group);
- if (!state->grp) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- /* FIXME: should we move this call outside the transaction to keep the
- * transaction as short as possible ? */
-again:
- /* always zero out the grp structure */
- memset(state->grp, 0, sizeof(struct group));
-
- status = ctx->ops.getgrnam_r(state->name, state->grp,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (buflen < MAX_BUF_SIZE) {
- buflen *= 2;
- }
- if (buflen > MAX_BUF_SIZE) {
- buflen = MAX_BUF_SIZE;
- }
- newbuf = talloc_realloc_size(state, buffer, buflen);
- if (!newbuf) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- buffer = newbuf;
- goto again;
-
- case NSS_STATUS_NOTFOUND:
-
- DEBUG(7, ("Group %s not found.\n", state->name));
- delete_group = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("Group %s found: (%s, %d)\n", state->name,
- state->grp->gr_name, state->grp->gr_gid));
-
- /* gid=0 is an invalid value */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->grp->gr_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
- state->name));
- delete_group = true;
- break;
- }
-
- DEBUG_GR_MEM(7, state);
-
- if (state->grp->gr_mem && state->grp->gr_mem[0]) {
- members = sysdb_new_attrs(state);
- if (!members) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER,
- state->domain->name,
- (const char **)state->grp->gr_mem);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- } else {
- members = NULL;
- }
-
- subreq = sysdb_store_group_send(state, state->ev, state->handle,
- state->domain,
- state->grp->gr_name,
- state->grp->gr_gid,
- members,
- ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_gr_name_add_done, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- tevent_req_error(req, ENXIO);
- return;
-
- default:
- DEBUG(2, ("proxy -> getgrnam_r failed for '%s' <%d>\n",
- state->name, status));
- tevent_req_error(req, EIO);
- return;
- }
-
- if (delete_group) {
- struct ldb_dn *dn;
-
- DEBUG(7, ("Group %s does not exist (or is invalid) on remote server,"
- " deleting!\n", state->name));
-
- dn = sysdb_group_dn(state->sysdb, state,
- state->domain->name, state->name);
- if (!dn) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- subreq = sysdb_delete_entry_send(state, state->ev, state->handle, dn, true);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_gr_name_remove_done, req);
- }
-}
-
-static void get_gr_name_add_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_store_group_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-static void get_gr_name_remove_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_delete_entry_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-/* =Getgrgid-wrapper======================================================*/
-
-static void get_gr_gid_process(struct tevent_req *subreq);
-static void get_gr_gid_remove_done(struct tevent_req *subreq);
-
-static struct tevent_req *get_gr_gid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- gid_t gid)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->gid = gid;
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_gr_gid_process, req);
-
- return req;
-}
-
-static void get_gr_gid_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- char *newbuf;
- size_t buflen;
- bool delete_group = false;
- struct sysdb_attrs *members;
- int ret;
-
- DEBUG(7, ("Searching group by gid (%d)\n", state->gid));
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->grp = talloc(state, struct group);
- if (!state->grp) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
-again:
- /* always zero out the group structure */
- memset(state->grp, 0, sizeof(struct group));
-
- status = ctx->ops.getgrgid_r(state->gid, state->grp,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (buflen < MAX_BUF_SIZE) {
- buflen *= 2;
- }
- if (buflen > MAX_BUF_SIZE) {
- buflen = MAX_BUF_SIZE;
- }
- newbuf = talloc_realloc_size(state, buffer, buflen);
- if (!newbuf) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- buffer = newbuf;
- goto again;
-
- case NSS_STATUS_NOTFOUND:
-
- DEBUG(7, ("Group %d not found.\n", state->gid));
- delete_group = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("Group %d found (%s, %d)\n", state->gid,
- state->grp->gr_name, state->grp->gr_gid));
-
- /* gid=0 is an invalid value */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->grp->gr_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
- state->grp->gr_name));
- delete_group = true;
- break;
- }
-
- DEBUG_GR_MEM(7, state);
-
- if (state->grp->gr_mem && state->grp->gr_mem[0]) {
- members = sysdb_new_attrs(state);
- if (!members) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER,
- state->domain->name,
- (const char **)state->grp->gr_mem);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- } else {
- members = NULL;
- }
-
- subreq = sysdb_store_group_send(state, state->ev, state->handle,
- state->domain,
- state->grp->gr_name,
- state->grp->gr_gid,
- members,
- ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_gr_name_add_done, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- tevent_req_error(req, ENXIO);
- return;
-
- default:
- DEBUG(2, ("proxy -> getgrgid_r failed for '%d' <%d>\n",
- state->gid, status));
- tevent_req_error(req, EIO);
- return;
- }
-
- if (delete_group) {
-
- DEBUG(7, ("Group %d does not exist (or is invalid) on remote server,"
- " deleting!\n", state->gid));
-
- subreq = sysdb_delete_group_send(state, state->ev,
- NULL, state->handle,
- state->domain,
- NULL, state->gid);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_gr_gid_remove_done, req);
- }
-}
-
-static void get_gr_gid_remove_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = sysdb_delete_group_recv(subreq);
- talloc_zfree(subreq);
- if (ret && ret != ENOENT) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-/* =Getgrent-wrapper======================================================*/
-
-struct enum_groups_state {
- struct tevent_context *ev;
- struct proxy_ctx *ctx;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *domain;
- struct sysdb_handle *handle;
-
- struct group *grp;
-
- size_t buflen;
- char *buffer;
-
- bool in_transaction;
-};
-
-static void enum_groups_process(struct tevent_req *subreq);
-
-static struct tevent_req *enum_groups_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain)
-{
- struct tevent_req *req, *subreq;
- struct enum_groups_state *state;
- enum nss_status status;
-
- DEBUG(7, ("Enumerating groups\n"));
-
- req = tevent_req_create(mem_ctx, &state, struct enum_groups_state);
- if (!req) return NULL;
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->handle = NULL;
-
- state->grp = talloc(state, struct group);
- if (!state->grp) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
-
- state->buflen = DEFAULT_BUFSIZE;
- state->buffer = talloc_size(state, state->buflen);
- if (!state->buffer) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
-
- state->in_transaction = false;
-
- status = ctx->ops.setgrent();
- if (status != NSS_STATUS_SUCCESS) {
- tevent_req_error(req, EIO);
- goto fail;
- }
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- goto fail;
- }
- tevent_req_set_callback(subreq, enum_groups_process, req);
-
- return req;
-
-fail:
- tevent_req_post(req, ev);
- return req;
-}
-
-static void enum_groups_process(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);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- struct sysdb_attrs *members;
- char *newbuf;
- int ret;
-
- if (!state->in_transaction) {
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->in_transaction = true;
- } else {
- ret = sysdb_store_group_recv(subreq);
- if (ret) {
- /* Do not fail completely on errors.
- * Just report the failure to save and go on */
- DEBUG(2, ("Failed to store group. Ignoring.\n"));
- }
- talloc_zfree(subreq);
- }
-
-again:
- /* always zero out the grp structure */
- memset(state->grp, 0, sizeof(struct group));
-
- /* get entry */
- status = ctx->ops.getgrent_r(state->grp,
- state->buffer, state->buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (state->buflen < MAX_BUF_SIZE) {
- state->buflen *= 2;
- }
- if (state->buflen > MAX_BUF_SIZE) {
- state->buflen = MAX_BUF_SIZE;
- }
- newbuf = talloc_realloc_size(state, state->buffer, state->buflen);
- if (!newbuf) {
- ret = ENOMEM;
- goto fail;
- }
- state->buffer = newbuf;
- goto again;
-
- case NSS_STATUS_NOTFOUND:
-
- /* we are done here */
- DEBUG(7, ("Enumeration completed.\n"));
-
- ctx->ops.endgrent();
- subreq = sysdb_transaction_commit_send(state, state->ev,
- state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
- return;
-
- case NSS_STATUS_SUCCESS:
-
- DEBUG(7, ("Group found (%s, %d)\n",
- state->grp->gr_name, state->grp->gr_gid));
-
- /* gid=0 is an invalid value */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->grp->gr_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
- state->grp->gr_name));
-
- goto again; /* skip */
- }
-
- DEBUG_GR_MEM(7, state);
-
- if (state->grp->gr_mem && state->grp->gr_mem[0]) {
- members = sysdb_new_attrs(state);
- if (!members) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER,
- state->domain->name,
- (const char **)state->grp->gr_mem);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- } else {
- members = NULL;
- }
-
- subreq = sysdb_store_group_send(state, state->ev, state->handle,
- state->domain,
- state->grp->gr_name,
- state->grp->gr_gid,
- members,
- ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, enum_groups_process, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- ret = ENXIO;
- goto fail;
-
- default:
- DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n",
- ret, strerror(ret)));
- goto fail;
- }
-
-fail:
- ctx->ops.endgrent();
- tevent_req_error(req, ret);
-}
-
-
-/* =Initgroups-wrapper====================================================*/
-
-static void get_initgr_process(struct tevent_req *subreq);
-static void get_initgr_groups_process(struct tevent_req *subreq);
-static void get_initgr_groups_done(struct tevent_req *subreq);
-static struct tevent_req *get_groups_by_gid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sysdb_handle *handle,
- struct proxy_ctx *ctx,
- struct sss_domain_info *domain,
- gid_t *gids, int num_gids);
-static int get_groups_by_gid_recv(struct tevent_req *req);
-static void get_groups_by_gid_process(struct tevent_req *subreq);
-static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sysdb_handle *handle,
- struct proxy_ctx *ctx,
- struct sss_domain_info *domain,
- gid_t gid);
-static int get_group_from_gid_recv(struct tevent_req *req);
-static void get_group_from_gid_send_del_done(struct tevent_req *subreq);
-static void get_group_from_gid_send_add_done(struct tevent_req *subreq);
-
-
-static struct tevent_req *get_initgr_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct proxy_ctx *ctx,
- struct sysdb_ctx *sysdb,
- struct sss_domain_info *domain,
- const char *name)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->ctx = ctx;
- state->sysdb = sysdb;
- state->domain = domain;
- state->name = name;
-
- subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_initgr_process, req);
-
- return req;
-}
-
-static void get_initgr_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- size_t buflen;
- bool delete_user = false;
- int ret;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- state->pwd = talloc(state, struct passwd);
- if (!state->pwd) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- /* FIXME: should we move this call outside the transaction to keep the
- * transaction as short as possible ? */
- status = ctx->ops.getpwnam_r(state->name, state->pwd,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_NOTFOUND:
-
- delete_user = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- /* uid=0 or gid=0 are invalid values */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->pwd->pw_uid, dom->id_min, dom->id_max) ||
- OUT_OF_ID_RANGE(state->pwd->pw_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
- state->name));
- delete_user = true;
- break;
- }
-
- subreq = sysdb_store_user_send(state, state->ev, state->handle,
- state->domain,
- state->pwd->pw_name,
- state->pwd->pw_passwd,
- state->pwd->pw_uid,
- state->pwd->pw_gid,
- state->pwd->pw_gecos,
- state->pwd->pw_dir,
- state->pwd->pw_shell,
- NULL, ctx->entry_cache_timeout);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_initgr_groups_process, req);
- return;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- tevent_req_error(req, ENXIO);
- return;
-
- default:
- DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
- state->name, status));
- tevent_req_error(req, EIO);
- return;
- }
-
- if (delete_user) {
- struct ldb_dn *dn;
-
- dn = sysdb_user_dn(state->sysdb, state,
- state->domain->name, state->name);
- if (!dn) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- subreq = sysdb_delete_entry_send(state, state->ev, state->handle, dn, true);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_pw_name_remove_done, req);
- }
-}
-
-static void get_initgr_groups_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- struct proxy_ctx *ctx = state->ctx;
- enum nss_status status;
- long int limit;
- long int size;
- long int num;
- long int num_gids;
- gid_t *gids;
- int ret;
-
- ret = sysdb_store_user_recv(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
- talloc_zfree(subreq);
-
- num_gids = 0;
- limit = 4096;
- num = 4096;
- size = num*sizeof(gid_t);
- gids = talloc_size(state, size);
- if (!gids) {
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- state->gid = state->pwd->pw_gid;
-
-again:
- /* FIXME: should we move this call outside the transaction to keep the
- * transaction as short as possible ? */
- status = ctx->ops.initgroups_dyn(state->name, state->gid, &num_gids,
- &num, &gids, limit, &ret);
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (size < MAX_BUF_SIZE) {
- num *= 2;
- size = num*sizeof(gid_t);
- }
- if (size > MAX_BUF_SIZE) {
- size = MAX_BUF_SIZE;
- num = size/sizeof(gid_t);
- }
- limit = num;
- gids = talloc_realloc_size(state, gids, size);
- if (!gids) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- goto again; /* retry with more memory */
-
- case NSS_STATUS_SUCCESS:
- DEBUG(4, ("User [%s] appears to be member of %lu groups\n",
- state->name, num_gids));
-
- subreq = get_groups_by_gid_send(state, state->ev, state->handle,
- state->ctx, state->domain,
- gids, num_gids);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_initgr_groups_done, req);
- break;
-
- default:
- DEBUG(2, ("proxy -> initgroups_dyn failed (%d)[%s]\n",
- ret, strerror(ret)));
- tevent_req_error(req, EIO);
- return;
- }
-}
-
-static void get_initgr_groups_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct proxy_state *state = tevent_req_data(req,
- struct proxy_state);
- int ret;
-
- ret = get_groups_by_gid_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, proxy_default_done, req);
-}
-
-struct get_groups_state {
- struct tevent_context *ev;
- struct sysdb_handle *handle;
- struct proxy_ctx *ctx;
- struct sss_domain_info *domain;
-
- gid_t *gids;
- int num_gids;
- int cur_gid;
-};
-
-static struct tevent_req *get_groups_by_gid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sysdb_handle *handle,
- struct proxy_ctx *ctx,
- struct sss_domain_info *domain,
- gid_t *gids, int num_gids)
-{
- struct tevent_req *req, *subreq;
- struct get_groups_state *state;
-
- req = tevent_req_create(mem_ctx, &state, struct get_groups_state);
- if (!req) return NULL;
-
- state->ev = ev;
- state->handle = handle;
- state->ctx = ctx;
- state->domain = domain;
- state->gids = gids;
- state->num_gids = num_gids;
- state->cur_gid = 0;
-
- subreq = get_group_from_gid_send(state, ev, handle, ctx, domain, gids[0]);
- if (!subreq) {
- talloc_zfree(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, get_groups_by_gid_process, req);
-
- return req;
-}
-
-static void get_groups_by_gid_process(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct get_groups_state *state = tevent_req_data(req,
- struct get_groups_state);
- int ret;
-
- ret = get_group_from_gid_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- state->cur_gid++;
- if (state->cur_gid >= state->num_gids) {
- tevent_req_done(req);
- return;
- }
-
- subreq = get_group_from_gid_send(state,
- state->ev, state->handle,
- state->ctx, state->domain,
- state->gids[state->cur_gid]);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, get_groups_by_gid_process, req);
-}
-
-static int get_groups_by_gid_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-static struct tevent_req *get_group_from_gid_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct sysdb_handle *handle,
- struct proxy_ctx *ctx,
- struct sss_domain_info *domain,
- gid_t gid)
-{
- struct tevent_req *req, *subreq;
- struct proxy_state *state;
- struct sss_domain_info *dom = ctx->be->domain;
- enum nss_status status;
- char *buffer;
- char *newbuf;
- size_t buflen;
- bool delete_group = false;
- struct sysdb_attrs *members;
- int ret;
-
- req = tevent_req_create(mem_ctx, &state, struct proxy_state);
- if (!req) return NULL;
-
- memset(state, 0, sizeof(struct proxy_state));
-
- state->ev = ev;
- state->handle = handle;
- state->ctx = ctx;
- state->domain = domain;
- state->gid = gid;
-
- state->grp = talloc(state, struct group);
- if (!state->grp) {
- ret = ENOMEM;
- goto fail;
- }
-
- buflen = DEFAULT_BUFSIZE;
- buffer = talloc_size(state, buflen);
- if (!buffer) {
- ret = ENOMEM;
- goto fail;
- }
-
-again:
- /* always zero out the grp structure */
- memset(state->grp, 0, sizeof(struct group));
-
- status = ctx->ops.getgrgid_r(state->gid, state->grp,
- buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (buflen < MAX_BUF_SIZE) {
- buflen *= 2;
- }
- if (buflen > MAX_BUF_SIZE) {
- buflen = MAX_BUF_SIZE;
- }
- newbuf = talloc_realloc_size(state, buffer, buflen);
- if (!newbuf) {
- ret = ENOMEM;
- goto fail;
- }
- buffer = newbuf;
- goto again;
-
- case NSS_STATUS_NOTFOUND:
-
- delete_group = true;
- break;
-
- case NSS_STATUS_SUCCESS:
-
- /* gid=0 is an invalid value */
- /* also check that the id is in the valid range for this domain */
- if (OUT_OF_ID_RANGE(state->grp->gr_gid, dom->id_min, dom->id_max)) {
-
- DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
- state->grp->gr_name));
- delete_group = true;
- break;
- }
-
- if (state->grp->gr_mem && state->grp->gr_mem[0]) {
- members = sysdb_new_attrs(state);
- if (!members) {
- ret = ENOMEM;
- goto fail;
- }
- ret = sysdb_attrs_users_from_str_list(members, SYSDB_MEMBER,
- state->domain->name,
- (const char **)state->grp->gr_mem);
- if (ret) {
- goto fail;
- }
- } else {
- members = NULL;
- }
-
- subreq = sysdb_store_group_send(state, state->ev, state->handle,
- state->domain,
- state->grp->gr_name,
- state->grp->gr_gid,
- members,
- ctx->entry_cache_timeout);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, get_group_from_gid_send_add_done, req);
- break;
-
- case NSS_STATUS_UNAVAIL:
- /* "remote" backend unavailable. Enter offline mode */
- ret = ENXIO;
- goto fail;
-
- default:
- DEBUG(2, ("proxy -> getgrgid_r failed for '%d' <%d>\n",
- state->gid, status));
- ret = EIO;
- goto fail;
- }
-
- if (delete_group) {
- subreq = sysdb_delete_group_send(state, state->ev,
- NULL, state->handle,
- state->domain,
- NULL, state->gid);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, get_group_from_gid_send_del_done, req);
- }
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void get_group_from_gid_send_add_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- int ret;
-
- ret = sysdb_store_group_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static void get_group_from_gid_send_del_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- int ret;
-
- ret = sysdb_delete_entry_recv(subreq);
- talloc_zfree(subreq);
- if (ret && ret != ENOENT) {
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static int get_group_from_gid_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-
-/* =Proxy_Id-Functions====================================================*/
-
-static void proxy_get_account_info_done(struct tevent_req *subreq);
-
-/* TODO: See if we can use async_req code */
-static void proxy_get_account_info(struct be_req *breq)
-{
- struct tevent_req *subreq;
- struct be_acct_req *ar;
- struct proxy_ctx *ctx;
- struct tevent_context *ev;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *domain;
- uid_t uid;
- gid_t gid;
-
- ar = talloc_get_type(breq->req_data, struct be_acct_req);
- ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, struct proxy_ctx);
- ev = breq->be_ctx->ev;
- sysdb = breq->be_ctx->sysdb;
- domain = breq->be_ctx->domain;
-
- if (be_is_offline(breq->be_ctx)) {
- return proxy_reply(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
- }
-
- /* for now we support only core attrs */
- if (ar->attr_type != BE_ATTR_CORE) {
- return proxy_reply(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type");
- }
-
- switch (ar->entry_type & 0xFFF) {
- case BE_REQ_USER: /* user */
- switch (ar->filter_type) {
- case BE_FILTER_NAME:
- if (strchr(ar->filter_value, '*')) {
- subreq = enum_users_send(breq, ev, ctx,
- sysdb, domain);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- } else {
- subreq = get_pw_name_send(breq, ev, ctx,
- sysdb, domain,
- ar->filter_value);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- }
- break;
-
- case BE_FILTER_IDNUM:
- if (strchr(ar->filter_value, '*')) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid attr type");
- } else {
- char *endptr;
- errno = 0;
- uid = (uid_t)strtol(ar->filter_value, &endptr, 0);
- if (errno || *endptr || (ar->filter_value == endptr)) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid attr type");
- }
- subreq = get_pw_uid_send(breq, ev, ctx,
- sysdb, domain, uid);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- }
- break;
- default:
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid filter type");
- }
- break;
-
- case BE_REQ_GROUP: /* group */
- switch (ar->filter_type) {
- case BE_FILTER_NAME:
- if (strchr(ar->filter_value, '*')) {
- subreq = enum_groups_send(breq, ev, ctx,
- sysdb, domain);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- } else {
- subreq = get_gr_name_send(breq, ev, ctx,
- sysdb, domain,
- ar->filter_value);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- }
- break;
- case BE_FILTER_IDNUM:
- if (strchr(ar->filter_value, '*')) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid attr type");
- } else {
- char *endptr;
- errno = 0;
- gid = (gid_t)strtol(ar->filter_value, &endptr, 0);
- if (errno || *endptr || (ar->filter_value == endptr)) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid attr type");
- }
- subreq = get_gr_gid_send(breq, ev, ctx,
- sysdb, domain, gid);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
- }
- break;
- default:
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid filter type");
- }
- break;
-
- case BE_REQ_INITGROUPS: /* init groups for user */
- if (ar->filter_type != BE_FILTER_NAME) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid filter type");
- }
- if (strchr(ar->filter_value, '*')) {
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid filter value");
- }
- if (ctx->ops.initgroups_dyn == NULL) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENODEV, "Initgroups call not supported");
- }
- subreq = get_initgr_send(breq, ev, ctx, sysdb,
- domain, ar->filter_value);
- if (!subreq) {
- return proxy_reply(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
- }
- tevent_req_set_callback(subreq,
- proxy_get_account_info_done, breq);
- return;
-
- default: /*fail*/
- break;
- }
-
- return proxy_reply(breq, DP_ERR_FATAL,
- EINVAL, "Invalid request type");
-}
-
-static void proxy_get_account_info_done(struct tevent_req *subreq)
-{
- struct be_req *breq = tevent_req_callback_data(subreq,
- struct be_req);
- int ret;
- ret = proxy_default_recv(subreq);
- talloc_zfree(subreq);
- if (ret) {
- if (ret == ENXIO) {
- DEBUG(2, ("proxy returned UNAVAIL error, going offline!\n"));
- be_mark_offline(breq->be_ctx);
- }
- proxy_reply(breq, DP_ERR_FATAL, ret, NULL);
- return;
- }
- proxy_reply(breq, DP_ERR_OK, EOK, NULL);
-}
-
-static void proxy_shutdown(struct be_req *req)
-{
- /* TODO: Clean up any internal data */
- req->fn(req, DP_ERR_OK, EOK, NULL);
-}
-
-static void proxy_auth_shutdown(struct be_req *req)
-{
- talloc_free(req->be_ctx->bet_info[BET_AUTH].pvt_bet_data);
- req->fn(req, DP_ERR_OK, EOK, NULL);
-}
-
-struct bet_ops proxy_id_ops = {
- .handler = proxy_get_account_info,
- .finalize = proxy_shutdown
-};
-
-struct bet_ops proxy_auth_ops = {
- .handler = proxy_pam_handler,
- .finalize = proxy_auth_shutdown
-};
-
-struct bet_ops proxy_access_ops = {
- .handler = proxy_pam_handler,
- .finalize = proxy_auth_shutdown
-};
-
-struct bet_ops proxy_chpass_ops = {
- .handler = proxy_pam_handler,
- .finalize = proxy_auth_shutdown
-};
-
-static void *proxy_dlsym(void *handle, const char *functemp, char *libname)
-{
- char *funcname;
- void *funcptr;
-
- funcname = talloc_asprintf(NULL, functemp, libname);
- if (funcname == NULL) return NULL;
-
- funcptr = dlsym(handle, funcname);
- talloc_free(funcname);
-
- return funcptr;
-}
-
-int sssm_proxy_init(struct be_ctx *bectx,
- struct bet_ops **ops, void **pvt_data)
-{
- struct proxy_ctx *ctx;
- char *libname;
- char *libpath;
- void *handle;
- int ret;
-
- ctx = talloc_zero(bectx, struct proxy_ctx);
- if (!ctx) {
- return ENOMEM;
- }
- ctx->be = bectx;
-
- ret = confdb_get_int(bectx->cdb, ctx, bectx->conf_path,
- CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT, 600,
- &ctx->entry_cache_timeout);
- if (ret != EOK) goto done;
-
- ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
- CONFDB_PROXY_LIBNAME, NULL, &libname);
- if (ret != EOK) goto done;
- if (libname == NULL) {
- ret = ENOENT;
- goto done;
- }
-
- libpath = talloc_asprintf(ctx, "libnss_%s.so.2", libname);
- if (!libpath) {
- ret = ENOMEM;
- goto done;
- }
-
- handle = dlopen(libpath, RTLD_NOW);
- if (!handle) {
- DEBUG(0, ("Unable to load %s module with path, error: %s\n",
- libpath, dlerror()));
- ret = ELIBACC;
- goto done;
- }
-
- ctx->ops.getpwnam_r = proxy_dlsym(handle, "_nss_%s_getpwnam_r", libname);
- if (!ctx->ops.getpwnam_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.getpwuid_r = proxy_dlsym(handle, "_nss_%s_getpwuid_r", libname);
- if (!ctx->ops.getpwuid_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.setpwent = proxy_dlsym(handle, "_nss_%s_setpwent", libname);
- if (!ctx->ops.setpwent) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.getpwent_r = proxy_dlsym(handle, "_nss_%s_getpwent_r", libname);
- if (!ctx->ops.getpwent_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.endpwent = proxy_dlsym(handle, "_nss_%s_endpwent", libname);
- if (!ctx->ops.endpwent) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.getgrnam_r = proxy_dlsym(handle, "_nss_%s_getgrnam_r", libname);
- if (!ctx->ops.getgrnam_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.getgrgid_r = proxy_dlsym(handle, "_nss_%s_getgrgid_r", libname);
- if (!ctx->ops.getgrgid_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.setgrent = proxy_dlsym(handle, "_nss_%s_setgrent", libname);
- if (!ctx->ops.setgrent) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.getgrent_r = proxy_dlsym(handle, "_nss_%s_getgrent_r", libname);
- if (!ctx->ops.getgrent_r) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.endgrent = proxy_dlsym(handle, "_nss_%s_endgrent", libname);
- if (!ctx->ops.endgrent) {
- DEBUG(0, ("Failed to load NSS fns, error: %s\n", dlerror()));
- ret = ELIBBAD;
- goto done;
- }
-
- ctx->ops.initgroups_dyn = proxy_dlsym(handle, "_nss_%s_initgroups_dyn",
- libname);
- if (!ctx->ops.initgroups_dyn) {
- DEBUG(1, ("The '%s' library does not provides the "
- "_nss_XXX_initgroups_dyn function!\n"
- "initgroups will be slow as it will require "
- "full groups enumeration!\n", libname));
- }
-
- *ops = &proxy_id_ops;
- *pvt_data = ctx;
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_free(ctx);
- }
- return ret;
-}
-
-int sssm_proxy_auth_init(struct be_ctx *bectx,
- struct bet_ops **ops, void **pvt_data)
-{
- struct proxy_auth_ctx *ctx;
- int ret;
-
- ctx = talloc(bectx, struct proxy_auth_ctx);
- if (!ctx) {
- return ENOMEM;
- }
- ctx->be = bectx;
-
- ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
- CONFDB_PROXY_PAM_TARGET, NULL,
- &ctx->pam_target);
- if (ret != EOK) goto done;
- if (!ctx->pam_target) {
- DEBUG(1, ("Missing option proxy_pam_target.\n"));
- ret = EINVAL;
- goto done;
- }
-
- *ops = &proxy_auth_ops;
- *pvt_data = ctx;
-
-done:
- if (ret != EOK) {
- talloc_free(ctx);
- }
- return ret;
-}
-
-int sssm_proxy_access_init(struct be_ctx *bectx,
- struct bet_ops **ops, void **pvt_data)
-{
- int ret;
- ret = sssm_proxy_auth_init(bectx, ops, pvt_data);
- *ops = &proxy_access_ops;
- return ret;
-}
-
-int sssm_proxy_chpass_init(struct be_ctx *bectx,
- struct bet_ops **ops, void **pvt_data)
-{
- int ret;
- ret = sssm_proxy_auth_init(bectx, ops, pvt_data);
- *ops = &proxy_chpass_ops;
- return ret;
-}
diff --git a/server/providers/sssd_be.exports b/server/providers/sssd_be.exports
deleted file mode 100644
index 9afa106be..000000000
--- a/server/providers/sssd_be.exports
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- global:
- *;
-};