summaryrefslogtreecommitdiffstats
path: root/server/responder
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/responder
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/responder')
-rw-r--r--server/responder/common/responder.h152
-rw-r--r--server/responder/common/responder_cmd.c103
-rw-r--r--server/responder/common/responder_common.c589
-rw-r--r--server/responder/common/responder_dp.c590
-rw-r--r--server/responder/common/responder_packet.c253
-rw-r--r--server/responder/common/responder_packet.h43
-rw-r--r--server/responder/nss/nsssrv.c367
-rw-r--r--server/responder/nss/nsssrv.h70
-rw-r--r--server/responder/nss/nsssrv_cmd.c3182
-rw-r--r--server/responder/nss/nsssrv_nc.c321
-rw-r--r--server/responder/nss/nsssrv_nc.h51
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c476
-rw-r--r--server/responder/pam/pamsrv.c224
-rw-r--r--server/responder/pam/pamsrv.h57
-rw-r--r--server/responder/pam/pamsrv_cmd.c1181
-rw-r--r--server/responder/pam/pamsrv_dp.c142
16 files changed, 0 insertions, 7801 deletions
diff --git a/server/responder/common/responder.h b/server/responder/common/responder.h
deleted file mode 100644
index ea6ba5831..000000000
--- a/server/responder/common/responder.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- SSSD
-
- SSS Client Responder, 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 __SSS_RESPONDER_H__
-#define __SSS_RESPONDER_H__
-
-#include <stdint.h>
-#include <sys/un.h>
-#include <pcre.h>
-#include "config.h"
-#include "talloc.h"
-#include "tevent.h"
-#include "ldb.h"
-#include "dhash.h"
-#include "sbus/sssd_dbus.h"
-#include "sss_client/sss_cli.h"
-
-extern hash_table_t *dp_requests;
-
-/* if there is a provider other than the special local */
-#define NEED_CHECK_PROVIDER(provider) \
- (provider != NULL && strcmp(provider, "local") != 0)
-
-/* needed until nsssrv.h is updated */
-struct cli_request {
-
- /* original request from the wire */
- struct sss_packet *in;
-
- /* reply data */
- struct sss_packet *out;
-};
-
-struct cli_protocol_version {
- uint32_t version;
- const char *date;
- const char *description;
-};
-
-struct be_conn {
- struct be_conn *next;
- struct be_conn *prev;
-
- const char *cli_name;
- struct sss_domain_info *domain;
-
- char *sbus_address;
- struct sbus_interface *intf;
- struct sbus_connection *conn;
-};
-
-struct resp_ctx {
- struct tevent_context *ev;
- struct tevent_fd *lfde;
- int lfd;
- struct tevent_fd *priv_lfde;
- int priv_lfd;
- struct confdb_ctx *cdb;
- const char *sock_name;
- const char *priv_sock_name;
-
- struct sbus_connection *mon_conn;
- struct be_conn *be_conns;
-
- struct sss_domain_info *domains;
- struct sysdb_ctx_list *db_list;
-
- struct sss_cmd_table *sss_cmds;
- const char *sss_pipe_name;
- const char *confdb_service_path;
-
- struct sss_names_ctx *names;
-
- void *pvt_ctx;
-};
-
-struct cli_ctx {
- struct tevent_context *ev;
- struct resp_ctx *rctx;
- int cfd;
- struct tevent_fd *cfde;
- struct sockaddr_un addr;
- struct cli_request *creq;
- struct cli_protocol_version *cli_protocol_version;
- int priv;
-};
-
-struct sss_cmd_table {
- enum sss_cli_command cmd;
- int (*fn)(struct cli_ctx *cctx);
-};
-
-/* responder_common.c */
-int sss_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb,
- struct sss_cmd_table sss_cmds[],
- const char *sss_pipe_name,
- const char *sss_priv_pipe_name,
- const char *confdb_service_path,
- const char *svc_name,
- uint16_t svc_version,
- struct sbus_interface *monitor_intf,
- const char *cli_name,
- struct sbus_interface *dp_intf,
- struct resp_ctx **responder_ctx);
-
-int sss_parse_name(TALLOC_CTX *memctx,
- struct sss_names_ctx *snctx,
- const char *orig, char **domain, char **name);
-
-int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
- struct be_conn **_conn);
-
-/* responder_cmd.c */
-int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds);
-void sss_cmd_done(struct cli_ctx *cctx, void *freectx);
-int sss_cmd_get_version(struct cli_ctx *cctx);
-struct cli_protocol_version *register_cli_protocol_version(void);
-
-#define SSS_DP_USER 1
-#define SSS_DP_GROUP 2
-#define SSS_DP_INITGROUPS 3
-
-typedef void (*sss_dp_callback_t)(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-int sss_dp_send_acct_req(struct resp_ctx *rctx, TALLOC_CTX *callback_memctx,
- sss_dp_callback_t callback, void *callback_ctx,
- int timeout, const char *domain,
- bool fast_reply, int type,
- const char *opt_name, uint32_t opt_id);
-
-#endif /* __SSS_RESPONDER_H__ */
diff --git a/server/responder/common/responder_cmd.c b/server/responder/common/responder_cmd.c
deleted file mode 100644
index cd9890305..000000000
--- a/server/responder/common/responder_cmd.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- SSSD
-
- SSS Client Responder, command parser
-
- 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 <errno.h>
-#include "util/util.h"
-#include "responder/common/responder.h"
-#include "responder/common/responder_packet.h"
-
-
-void sss_cmd_done(struct cli_ctx *cctx, void *freectx)
-{
- /* now that the packet is in place, unlock queue
- * making the event writable */
- TEVENT_FD_WRITEABLE(cctx->cfde);
-
- /* free all request related data through the talloc hierarchy */
- talloc_free(freectx);
-}
-
-int sss_cmd_get_version(struct cli_ctx *cctx)
-{
- uint8_t *req_body;
- size_t req_blen;
- uint8_t *body;
- size_t blen;
- int ret;
- uint32_t client_version;
- int i;
- static struct cli_protocol_version *cli_protocol_version = NULL;
-
- cctx->cli_protocol_version = NULL;
-
- if (cli_protocol_version == NULL) {
- cli_protocol_version = register_cli_protocol_version();
- }
-
- if (cli_protocol_version != NULL) {
- cctx->cli_protocol_version = &cli_protocol_version[0];
-
- sss_packet_get_body(cctx->creq->in, &req_body, &req_blen);
- if (req_blen == sizeof(uint32_t)) {
- memcpy(&client_version, req_body, sizeof(uint32_t));
- DEBUG(5, ("Received client version [%d].\n", client_version));
-
- i=0;
- while(cli_protocol_version[i].version>0) {
- if (cli_protocol_version[i].version == client_version) {
- cctx->cli_protocol_version = &cli_protocol_version[i];
- break;
- }
- i++;
- }
- }
- }
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = cctx->cli_protocol_version!=NULL ?
- cctx->cli_protocol_version->version : 0;
- DEBUG(5, ("Offered version [%d].\n", ((uint32_t *)body)[0]));
-
- sss_cmd_done(cctx, NULL);
- return EOK;
-}
-
-int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
-{
- enum sss_cli_command cmd;
- int i;
-
- cmd = sss_packet_get_cmd(cctx->creq->in);
-
- for (i = 0; sss_cmds[i].cmd != SSS_CLI_NULL; i++) {
- if (cmd == sss_cmds[i].cmd) {
- return sss_cmds[i].fn(cctx);
- }
- }
-
- return EINVAL;
-}
diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c
deleted file mode 100644
index 37bbcb30f..000000000
--- a/server/responder/common/responder_common.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- SSSD
-
- Common Responder methods
-
- 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 "popt.h"
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "monitor/monitor_interfaces.h"
-#include "sbus/sbus_client.h"
-
-static void set_nonblocking(int fd)
-{
- unsigned v;
- v = fcntl(fd, F_GETFL, 0);
- fcntl(fd, F_SETFL, v | O_NONBLOCK);
-}
-
-static void set_close_on_exec(int fd)
-{
- unsigned v;
- v = fcntl(fd, F_GETFD, 0);
- fcntl(fd, F_SETFD, v | FD_CLOEXEC);
-}
-
-static int client_destructor(struct cli_ctx *ctx)
-{
- if (ctx->cfd > 0) close(ctx->cfd);
- return 0;
-}
-
-static void client_send(struct tevent_context *ev, struct cli_ctx *cctx)
-{
- int ret;
-
- ret = sss_packet_send(cctx->creq->out, cctx->cfd);
- if (ret == EAGAIN) {
- /* not all data was sent, loop again */
- return;
- }
- if (ret != EOK) {
- DEBUG(0, ("Failed to read request, aborting client!\n"));
- talloc_free(cctx);
- return;
- }
-
- /* ok all sent */
- TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
- TEVENT_FD_READABLE(cctx->cfde);
- talloc_free(cctx->creq);
- cctx->creq = NULL;
- return;
-}
-
-static void client_recv(struct tevent_context *ev, struct cli_ctx *cctx)
-{
- int ret;
-
- if (!cctx->creq) {
- cctx->creq = talloc_zero(cctx, struct cli_request);
- if (!cctx->creq) {
- DEBUG(0, ("Failed to alloc request, aborting client!\n"));
- talloc_free(cctx);
- return;
- }
- }
-
- if (!cctx->creq->in) {
- ret = sss_packet_new(cctx->creq, SSS_PACKET_MAX_RECV_SIZE,
- 0, &cctx->creq->in);
- if (ret != EOK) {
- DEBUG(0, ("Failed to alloc request, aborting client!\n"));
- talloc_free(cctx);
- return;
- }
- }
-
- ret = sss_packet_recv(cctx->creq->in, cctx->cfd);
- switch (ret) {
- case EOK:
- /* do not read anymore */
- TEVENT_FD_NOT_READABLE(cctx->cfde);
- /* execute command */
- ret = sss_cmd_execute(cctx, cctx->rctx->sss_cmds);
- if (ret != EOK) {
- DEBUG(0, ("Failed to execute request, aborting client!\n"));
- talloc_free(cctx);
- }
- /* past this point cctx can be freed at any time by callbacks
- * in case of error, do not use it */
- return;
-
- case EAGAIN:
- /* need to read still some data, loop again */
- break;
-
- case EINVAL:
- DEBUG(6, ("Invalid data from client, closing connection!\n"));
- talloc_free(cctx);
- break;
-
- case ENODATA:
- DEBUG(5, ("Client disconnected!\n"));
- talloc_free(cctx);
- break;
-
- default:
- DEBUG(6, ("Failed to read request, aborting client!\n"));
- talloc_free(cctx);
- }
-
- return;
-}
-
-static void client_fd_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *ptr)
-{
- struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
-
- if (flags & TEVENT_FD_READ) {
- client_recv(ev, cctx);
- return;
- }
- if (flags & TEVENT_FD_WRITE) {
- client_send(ev, cctx);
- return;
- }
-}
-
-/* TODO: this is a copy of accept_fd_handler, maybe both can be put into on
- * handler. */
-static void accept_priv_fd_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *ptr)
-{
- /* accept and attach new event handler */
- struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
- struct cli_ctx *cctx;
- socklen_t len;
- struct stat stat_buf;
- int ret;
-
- ret = stat(rctx->priv_sock_name, &stat_buf);
- if (ret == -1) {
- DEBUG(1, ("stat on privileged pipe failed: [%d][%s].\n", errno,
- strerror(errno)));
- return;
- }
-
- if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
- (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
- DEBUG(1, ("privileged pipe has an illegal status.\n"));
-/* TODO: what is the best response to this condition? Terminate? */
- return;
- }
-
-
- cctx = talloc_zero(rctx, struct cli_ctx);
- if (!cctx) {
- struct sockaddr_un addr;
- int fd;
- DEBUG(0, ("Out of memory trying to setup client context on privileged pipe!\n"));
- /* accept and close to signal the client we have a problem */
- memset(&addr, 0, sizeof(addr));
- len = sizeof(addr);
- fd = accept(rctx->priv_lfd, (struct sockaddr *)&addr, &len);
- if (fd == -1) {
- return;
- }
- close(fd);
- return;
- }
-
- len = sizeof(cctx->addr);
- cctx->cfd = accept(rctx->priv_lfd, (struct sockaddr *)&cctx->addr, &len);
- if (cctx->cfd == -1) {
- DEBUG(1, ("Accept failed [%s]", strerror(errno)));
- talloc_free(cctx);
- return;
- }
-
- cctx->priv = 1;
-
- cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
- TEVENT_FD_READ, client_fd_handler, cctx);
- if (!cctx->cfde) {
- close(cctx->cfd);
- talloc_free(cctx);
- DEBUG(2, ("Failed to queue client handler on privileged pipe\n"));
- }
-
- cctx->ev = ev;
- cctx->rctx = rctx;
-
- talloc_set_destructor(cctx, client_destructor);
-
- DEBUG(4, ("Client connected to privileged pipe!\n"));
-
- return;
-}
-
-static void accept_fd_handler(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *ptr)
-{
- /* accept and attach new event handler */
- struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
- struct cli_ctx *cctx;
- socklen_t len;
-
- cctx = talloc_zero(rctx, struct cli_ctx);
- if (!cctx) {
- struct sockaddr_un addr;
- int fd;
- DEBUG(0, ("Out of memory trying to setup client context!\n"));
- /* accept and close to signal the client we have a problem */
- memset(&addr, 0, sizeof(addr));
- len = sizeof(addr);
- fd = accept(rctx->lfd, (struct sockaddr *)&addr, &len);
- if (fd == -1) {
- return;
- }
- close(fd);
- return;
- }
-
- len = sizeof(cctx->addr);
- cctx->cfd = accept(rctx->lfd, (struct sockaddr *)&cctx->addr, &len);
- if (cctx->cfd == -1) {
- DEBUG(1, ("Accept failed [%s]", strerror(errno)));
- talloc_free(cctx);
- return;
- }
-
- cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
- TEVENT_FD_READ, client_fd_handler, cctx);
- if (!cctx->cfde) {
- close(cctx->cfd);
- talloc_free(cctx);
- DEBUG(2, ("Failed to queue client handler\n"));
- }
-
- cctx->ev = ev;
- cctx->rctx = rctx;
-
- talloc_set_destructor(cctx, client_destructor);
-
- DEBUG(4, ("Client connected!\n"));
-
- return;
-}
-
-static int sss_monitor_init(struct resp_ctx *rctx,
- struct sbus_interface *intf,
- const char *svc_name,
- uint16_t svc_version)
-{
- char *sbus_address;
- int ret;
-
- /* Set up SBUS connection to the monitor */
- ret = monitor_get_sbus_address(rctx, &sbus_address);
- if (ret != EOK) {
- DEBUG(0, ("Could not locate monitor address.\n"));
- return ret;
- }
-
- ret = sbus_client_init(rctx, rctx->ev, sbus_address,
- intf, &rctx->mon_conn,
- NULL, NULL);
- if (ret != EOK) {
- DEBUG(0, ("Failed to connect to monitor services.\n"));
- return ret;
- }
-
- /* Identify ourselves to the monitor */
- ret = monitor_common_send_id(rctx->mon_conn, svc_name, svc_version);
- if (ret != EOK) {
- DEBUG(0, ("Failed to identify to the monitor!\n"));
- return ret;
- }
-
- return EOK;
-}
-
-static int sss_dp_init(struct resp_ctx *rctx,
- struct sbus_interface *intf,
- const char *cli_name,
- struct sss_domain_info *domain)
-{
- struct be_conn *be_conn;
- int ret;
-
- be_conn = talloc_zero(rctx, struct be_conn);
- if (!be_conn) return ENOMEM;
-
- be_conn->cli_name = cli_name;
- be_conn->domain = domain;
- be_conn->intf = intf;
-
- /* Set up SBUS connection to the monitor */
- ret = dp_get_sbus_address(be_conn, &be_conn->sbus_address, domain->name);
- if (ret != EOK) {
- DEBUG(0, ("Could not locate DP address.\n"));
- return ret;
- }
- ret = sbus_client_init(rctx, rctx->ev,
- be_conn->sbus_address,
- intf, &be_conn->conn,
- NULL, NULL);
- if (ret != EOK) {
- DEBUG(0, ("Failed to connect to monitor services.\n"));
- return ret;
- }
-
- DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
-
- /* Identify ourselves to the DP */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- cli_name, domain->name);
- if (ret != EOK) {
- DEBUG(0, ("Failed to identify to the DP!\n"));
- return ret;
- }
-
- return EOK;
-}
-
-/* create a unix socket and listen to it */
-static int set_unix_socket(struct resp_ctx *rctx)
-{
- struct sockaddr_un addr;
-
-/* for future use */
-#if 0
- char *default_pipe;
- int ret;
-
- default_pipe = talloc_asprintf(rctx, "%s/%s", PIPE_PATH,
- rctx->sss_pipe_name);
- if (!default_pipe) {
- return ENOMEM;
- }
-
- ret = confdb_get_string(rctx->cdb, rctx,
- rctx->confdb_socket_path, "unixSocket",
- default_pipe, &rctx->sock_name);
- if (ret != EOK) {
- talloc_free(default_pipe);
- return ret;
- }
- talloc_free(default_pipe);
-
- default_pipe = talloc_asprintf(rctx, "%s/private/%s", PIPE_PATH,
- rctx->sss_pipe_name);
- if (!default_pipe) {
- return ENOMEM;
- }
-
- ret = confdb_get_string(rctx->cdb, rctx,
- rctx->confdb_socket_path, "privUnixSocket",
- default_pipe, &rctx->priv_sock_name);
- if (ret != EOK) {
- talloc_free(default_pipe);
- return ret;
- }
- talloc_free(default_pipe);
-#endif
-
- if (rctx->sock_name != NULL ) {
- rctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (rctx->lfd == -1) {
- return EIO;
- }
-
- /* Set the umask so that permissions are set right on the socket.
- * It must be readable and writable by anybody on the system. */
- umask(0111);
-
- set_nonblocking(rctx->lfd);
- set_close_on_exec(rctx->lfd);
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, rctx->sock_name, sizeof(addr.sun_path));
-
- /* make sure we have no old sockets around */
- unlink(rctx->sock_name);
-
- if (bind(rctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- DEBUG(0,("Unable to bind on socket '%s'\n", rctx->sock_name));
- goto failed;
- }
- if (listen(rctx->lfd, 10) != 0) {
- DEBUG(0,("Unable to listen on socket '%s'\n", rctx->sock_name));
- goto failed;
- }
-
- rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
- TEVENT_FD_READ, accept_fd_handler, rctx);
- if (!rctx->lfde) {
- DEBUG(0, ("Failed to queue handler on pipe\n"));
- goto failed;
- }
- }
-
- if (rctx->priv_sock_name != NULL ) {
- /* create privileged pipe */
- rctx->priv_lfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (rctx->priv_lfd == -1) {
- close(rctx->lfd);
- return EIO;
- }
-
- umask(0177);
-
- set_nonblocking(rctx->priv_lfd);
- set_close_on_exec(rctx->priv_lfd);
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, rctx->priv_sock_name, sizeof(addr.sun_path));
-
- unlink(rctx->priv_sock_name);
-
- if (bind(rctx->priv_lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- DEBUG(0,("Unable to bind on socket '%s'\n", rctx->priv_sock_name));
- goto failed;
- }
- if (listen(rctx->priv_lfd, 10) != 0) {
- DEBUG(0,("Unable to listen on socket '%s'\n", rctx->priv_sock_name));
- goto failed;
- }
-
- rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
- TEVENT_FD_READ, accept_priv_fd_handler, rctx);
- if (!rctx->priv_lfde) {
- DEBUG(0, ("Failed to queue handler on privileged pipe\n"));
- goto failed;
- }
- }
-
- /* we want default permissions on created files to be very strict,
- so set our umask to 0177 */
- umask(0177);
- return EOK;
-
-failed:
- /* we want default permissions on created files to be very strict,
- so set our umask to 0177 */
- umask(0177);
- close(rctx->lfd);
- close(rctx->priv_lfd);
- return EIO;
-}
-
-int sss_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb,
- struct sss_cmd_table sss_cmds[],
- const char *sss_pipe_name,
- const char *sss_priv_pipe_name,
- const char *confdb_service_path,
- const char *svc_name,
- uint16_t svc_version,
- struct sbus_interface *monitor_intf,
- const char *cli_name,
- struct sbus_interface *dp_intf,
- struct resp_ctx **responder_ctx)
-{
- struct resp_ctx *rctx;
- struct sss_domain_info *dom;
- int ret;
-
- rctx = talloc_zero(mem_ctx, struct resp_ctx);
- if (!rctx) {
- DEBUG(0, ("fatal error initializing resp_ctx\n"));
- return ENOMEM;
- }
- rctx->ev = ev;
- rctx->cdb = cdb;
- rctx->sss_cmds = sss_cmds;
- rctx->sock_name = sss_pipe_name;
- rctx->priv_sock_name = sss_priv_pipe_name;
- rctx->confdb_service_path = confdb_service_path;
-
- ret = confdb_get_domains(rctx->cdb, &rctx->domains);
- if (ret != EOK) {
- DEBUG(0, ("fatal error setting up domain map\n"));
- return ret;
- }
-
- ret = sss_monitor_init(rctx, monitor_intf, svc_name, svc_version);
- if (ret != EOK) {
- DEBUG(0, ("fatal error setting up message bus\n"));
- return ret;
- }
-
- for (dom = rctx->domains; dom; dom = dom->next) {
-
- /* skip local domain, it doesn't have a backend */
- if (strcasecmp(dom->provider, "local") == 0) {
- continue;
- }
-
- ret = sss_dp_init(rctx, dp_intf, cli_name, dom);
- if (ret != EOK) {
- DEBUG(0, ("fatal error setting up backend connector\n"));
- return ret;
- }
- }
-
- ret = sysdb_init(rctx, ev, cdb, NULL, false, &rctx->db_list);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing resp_ctx\n"));
- return ret;
- }
-
- ret = sss_names_init(rctx, rctx->cdb, &rctx->names);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing regex data\n"));
- return ret;
- }
-
- /* after all initializations we are ready to listen on our socket */
- ret = set_unix_socket(rctx);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing socket\n"));
- return ret;
- }
-
- DEBUG(1, ("Responder Initialization complete\n"));
-
- *responder_ctx = rctx;
- return EOK;
-}
-
-int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
- struct be_conn **_conn)
-{
- struct be_conn *iter;
-
- if (!rctx->be_conns) return ENOENT;
-
- for (iter = rctx->be_conns; iter; iter = iter->next) {
- if (strcasecmp(domain, iter->domain->name) == 0) break;
- }
-
- if (!iter) return ENOENT;
-
- *_conn = iter;
-
- return EOK;
-}
-
diff --git a/server/responder/common/responder_dp.c b/server/responder/common/responder_dp.c
deleted file mode 100644
index 782befb17..000000000
--- a/server/responder/common/responder_dp.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- Authors:
- Simo Sorce <ssorce@redhat.com>
- Stephen Gallagher <sgallagh@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/time.h>
-#include <time.h>
-#include "util/util.h"
-#include "responder/common/responder_packet.h"
-#include "responder/common/responder.h"
-#include "providers/data_provider.h"
-#include "sbus/sbus_client.h"
-
-hash_table_t *dp_requests = NULL;
-
-struct sss_dp_req;
-
-struct sss_dp_callback {
- struct sss_dp_callback *prev;
- struct sss_dp_callback *next;
-
- struct sss_dp_req *sdp_req;
-
- sss_dp_callback_t callback;
- void *callback_ctx;
-};
-
-struct sss_dp_req {
- struct tevent_context *ev;
- DBusPendingCall *pending_reply;
-
- char *key;
-
- struct tevent_timer *tev;
- struct sss_dp_callback *cb_list;
-
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
- char *err_msg;
-};
-
-static int sss_dp_callback_destructor(void *ptr)
-{
- struct sss_dp_callback *cb = talloc_get_type(ptr, struct sss_dp_callback);
-
- DLIST_REMOVE(cb->sdp_req->cb_list, cb);
-
- return EOK;
-}
-
-static int sss_dp_req_destructor(void *ptr)
-{
- struct sss_dp_req *sdp_req = talloc_get_type(ptr, struct sss_dp_req);
- struct sss_dp_callback *cb, *next;
- hash_key_t key;
-
- /* Cancel Dbus pending reply if still pending */
- if (sdp_req->pending_reply) {
- dbus_pending_call_cancel(sdp_req->pending_reply);
- sdp_req->pending_reply = NULL;
- }
-
- /* Destroy the hash entry */
- key.type = HASH_KEY_STRING;
- key.str = sdp_req->key;
- int hret = hash_delete(dp_requests, &key);
- if (hret != HASH_SUCCESS) {
- /* This should never happen */
- DEBUG(0, ("Could not clear entry from request queue\n"));
- }
-
- /* Free any remaining callback */
- if (sdp_req->err_maj == DP_ERR_OK) {
- sdp_req->err_maj = DP_ERR_FATAL;
- sdp_req->err_min = EIO;
- sdp_req->err_msg = discard_const_p(char, "Internal Error");
- }
-
- cb = sdp_req->cb_list;
- while (cb) {
- cb->callback(sdp_req->err_maj,
- sdp_req->err_min,
- sdp_req->err_msg,
- cb->callback_ctx);
- next = cb->next;
- talloc_free(cb);
- cb = next;
- }
-
- return 0;
-}
-
-static void sdp_req_timeout(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval t, void *ptr)
-{
- struct sss_dp_req *sdp_req = talloc_get_type(ptr, struct sss_dp_req);
-
- sdp_req->err_maj = DP_ERR_FATAL;
- sdp_req->err_min = ETIMEDOUT;
- sdp_req->err_msg = discard_const_p(char, "Timed out");
-
- /* steal te on NULL because it will be freed as soon as the handler
- * returns. Causing a double free if we don't, as te is allocated on
- * sdp_req and we are just going to free it */
- talloc_steal(NULL, te);
-
- talloc_free(sdp_req);
-}
-
-static int sss_dp_get_reply(DBusPendingCall *pending,
- dbus_uint16_t *err_maj,
- dbus_uint32_t *err_min,
- char **err_msg);
-
-static void sss_dp_invoke_callback(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval t, void *ptr)
-{
- struct sss_dp_req *sdp_req = talloc_get_type(ptr, struct sss_dp_req);
- struct sss_dp_callback *cb;
- struct timeval tv;
- struct tevent_timer *tev;
-
- cb = sdp_req->cb_list;
- /* Remove the callback from the list, the caller may free it, within the
- * callback. */
- talloc_set_destructor((TALLOC_CTX *)cb, NULL);
- DLIST_REMOVE(sdp_req->cb_list, cb);
-
- cb->callback(sdp_req->err_maj,
- sdp_req->err_min,
- sdp_req->err_msg,
- cb->callback_ctx);
-
- /* Call the next callback if needed */
- if (sdp_req->cb_list != NULL) {
- tv = tevent_timeval_current();
- tev = tevent_add_timer(sdp_req->ev, sdp_req, tv,
- sss_dp_invoke_callback, sdp_req);
- if (!te) {
- /* Out of memory or other serious error */
- goto done;
- }
-
- return;
- }
-
- /* No more callbacks to invoke. Destroy the request */
-done:
- /* steal te on NULL because it will be freed as soon as the handler
- * returns. Causing a double free if we don't, as te is allocated on
- * sdp_req and we are just going to free it */
- talloc_steal(NULL, te);
-
- talloc_zfree(sdp_req);
-}
-
-static void sss_dp_send_acct_callback(DBusPendingCall *pending, void *ptr)
-{
- int ret;
- struct sss_dp_req *sdp_req;
- struct sss_dp_callback *cb;
- struct timeval tv;
- struct tevent_timer *te;
-
- sdp_req = talloc_get_type(ptr, struct sss_dp_req);
-
- /* prevent trying to cancel a reply that we already received */
- sdp_req->pending_reply = NULL;
-
- ret = sss_dp_get_reply(pending,
- &sdp_req->err_maj,
- &sdp_req->err_min,
- &sdp_req->err_msg);
- if (ret != EOK) {
- if (ret == ETIME) {
- sdp_req->err_maj = DP_ERR_TIMEOUT;
- sdp_req->err_min = ret;
- sdp_req->err_msg = talloc_strdup(sdp_req, "Request timed out");
- }
- else {
- sdp_req->err_maj = DP_ERR_FATAL;
- sdp_req->err_min = ret;
- sdp_req->err_msg =
- talloc_strdup(sdp_req,
- "Failed to get reply from Data Provider");
- }
- }
-
- /* Check whether we need to issue any callbacks */
- cb = sdp_req->cb_list;
- if (sdp_req->cb_list == NULL) {
- if (cb == NULL) {
- /* No callbacks to invoke. Destroy the hash entry */
- talloc_zfree(sdp_req);
- return;
- }
- }
-
- /* Queue up all callbacks */
- tv = tevent_timeval_current();
- te = tevent_add_timer(sdp_req->ev, sdp_req, tv,
- sss_dp_invoke_callback, sdp_req);
- if (!te) {
- /* Out of memory or other serious error */
- goto error;
- }
-
- return;
-
-error:
- talloc_zfree(sdp_req);
-}
-
-static int sss_dp_send_acct_req_create(struct resp_ctx *rctx,
- TALLOC_CTX *callback_memctx,
- const char *domain,
- uint32_t be_type,
- char *filter,
- int timeout,
- sss_dp_callback_t callback,
- void *callback_ctx,
- struct sss_dp_req **ndp);
-
-int sss_dp_send_acct_req(struct resp_ctx *rctx, TALLOC_CTX *callback_memctx,
- sss_dp_callback_t callback, void *callback_ctx,
- int timeout, const char *domain,
- bool fast_reply, int type,
- const char *opt_name, uint32_t opt_id)
-{
- int ret, hret;
- uint32_t be_type;
- char *filter;
- hash_key_t key;
- hash_value_t value;
- TALLOC_CTX *tmp_ctx;
- struct timeval tv;
- struct sss_dp_req *sdp_req = NULL;
- struct sss_dp_callback *cb;
-
- /* either, or, not both */
- if (opt_name && opt_id) {
- return EINVAL;
- }
-
- if (!domain) {
- return EINVAL;
- }
-
- switch (type) {
- case SSS_DP_USER:
- be_type = BE_REQ_USER;
- break;
- case SSS_DP_GROUP:
- be_type = BE_REQ_GROUP;
- break;
- case SSS_DP_INITGROUPS:
- be_type = BE_REQ_INITGROUPS;
- break;
- default:
- return EINVAL;
- }
-
- if (fast_reply) {
- be_type |= BE_REQ_FAST;
- }
-
- if (dp_requests == NULL) {
- /* Create a hash table to handle queued update requests */
- ret = hash_create(10, &dp_requests, NULL, NULL);
- if (ret != HASH_SUCCESS) {
- fprintf(stderr, "cannot create hash table (%s)\n", hash_error_string(ret));
- return EIO;
- }
- }
-
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- key.type = HASH_KEY_STRING;
- key.str = NULL;
-
- if (opt_name) {
- filter = talloc_asprintf(tmp_ctx, "name=%s", opt_name);
- key.str = talloc_asprintf(tmp_ctx, "%d%s@%s", type, opt_name, domain);
- } else if (opt_id) {
- filter = talloc_asprintf(tmp_ctx, "idnumber=%u", opt_id);
- key.str = talloc_asprintf(tmp_ctx, "%d%d@%s", type, opt_id, domain);
- } else {
- filter = talloc_strdup(tmp_ctx, "name=*");
- key.str = talloc_asprintf(tmp_ctx, "%d*@%s", type, domain);
- }
- if (!filter || !key.str) {
- talloc_zfree(tmp_ctx);
- return ENOMEM;
- }
-
- /* Check whether there's already a request in progress */
- hret = hash_lookup(dp_requests, &key, &value);
- switch (hret) {
- case HASH_SUCCESS:
- /* Request already in progress
- * Add an additional callback if needed and return
- */
- DEBUG(2, ("Identical request in progress\n"));
-
- if (callback) {
- /* We have a new request asking for a callback */
- sdp_req = talloc_get_type(value.ptr, struct sss_dp_req);
- if (!sdp_req) {
- DEBUG(0, ("Could not retrieve DP request context\n"));
- ret = EIO;
- goto done;
- }
-
- cb = talloc_zero(callback_memctx, struct sss_dp_callback);
- if (!cb) {
- ret = ENOMEM;
- goto done;
- }
-
- cb->callback = callback;
- cb->callback_ctx = callback_ctx;
- cb->sdp_req = sdp_req;
-
- DLIST_ADD_END(sdp_req->cb_list, cb, struct sss_dp_callback *);
- talloc_set_destructor((TALLOC_CTX *)cb, sss_dp_callback_destructor);
- }
-
- ret = EOK;
- break;
-
- case HASH_ERROR_KEY_NOT_FOUND:
- /* No such request in progress
- * Create a new request
- */
- ret = sss_dp_send_acct_req_create(rctx, callback_memctx, domain,
- be_type, filter, timeout,
- callback, callback_ctx,
- &sdp_req);
- if (ret != EOK) {
- goto done;
- }
-
- value.type = HASH_VALUE_PTR;
- value.ptr = sdp_req;
- hret = hash_enter(dp_requests, &key, &value);
- if (hret != HASH_SUCCESS) {
- DEBUG(0, ("Could not store request query (%s)",
- hash_error_string(hret)));
- talloc_zfree(sdp_req);
- ret = EIO;
- goto done;
- }
-
- sdp_req->key = talloc_strdup(sdp_req, key.str);
-
- tv = tevent_timeval_current_ofs(timeout, 0);
- sdp_req->tev = tevent_add_timer(sdp_req->ev, sdp_req, tv,
- sdp_req_timeout, sdp_req);
- if (!sdp_req->tev) {
- DEBUG(0, ("Out of Memory!?"));
- talloc_zfree(sdp_req);
- ret = ENOMEM;
- goto done;
- }
-
- talloc_set_destructor((TALLOC_CTX *)sdp_req, sss_dp_req_destructor);
-
- ret = EOK;
- break;
-
- default:
- DEBUG(0,("Could not query request list (%s)\n",
- hash_error_string(hret)));
- talloc_zfree(sdp_req);
- ret = EIO;
- }
-
-done:
- talloc_zfree(tmp_ctx);
- return ret;
-}
-
-static int sss_dp_send_acct_req_create(struct resp_ctx *rctx,
- TALLOC_CTX *callback_memctx,
- const char *domain,
- uint32_t be_type,
- char *filter,
- int timeout,
- sss_dp_callback_t callback,
- void *callback_ctx,
- struct sss_dp_req **ndp)
-{
- DBusConnection *dbus_conn;
- DBusMessage *msg;
- DBusPendingCall *pending_reply;
- dbus_bool_t dbret;
- struct sss_dp_callback *cb;
- struct sss_dp_req *sdp_req;
- uint32_t attrs = BE_ATTR_CORE;
- struct be_conn *be_conn;
- int ret;
-
- /* double check dp_ctx has actually been initialized.
- * in some pathological cases it may happen that nss starts up before
- * dp connection code is actually able to establish a connection.
- */
- ret = sss_dp_get_domain_conn(rctx, domain, &be_conn);
- if (ret != EOK) {
- DEBUG(1, ("The Data Provider connection for %s is not available!"
- " This maybe a bug, it shouldn't happen!\n", domain));
- return EIO;
- }
- dbus_conn = sbus_get_connection(be_conn->conn);
-
- /* create the message */
- msg = dbus_message_new_method_call(NULL,
- DP_PATH,
- DP_INTERFACE,
- DP_METHOD_GETACCTINFO);
- if (msg == NULL) {
- DEBUG(0,("Out of memory?!\n"));
- return ENOMEM;
- }
-
- DEBUG(4, ("Sending request for [%s][%u][%d][%s]\n",
- domain, be_type, attrs, filter));
-
- dbret = dbus_message_append_args(msg,
- DBUS_TYPE_UINT32, &be_type,
- DBUS_TYPE_UINT32, &attrs,
- DBUS_TYPE_STRING, &filter,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(1,("Failed to build message\n"));
- return EIO;
- }
-
- dbret = dbus_connection_send_with_reply(dbus_conn, msg,
- &pending_reply, timeout);
- if (!dbret || pending_reply == NULL) {
- /*
- * 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;
- }
-
- sdp_req = talloc_zero(rctx, struct sss_dp_req);
- if (!sdp_req) {
- dbus_message_unref(msg);
- return ENOMEM;
- }
- sdp_req->ev = rctx->ev;
- sdp_req->pending_reply = pending_reply;
-
- if (callback) {
- cb = talloc_zero(callback_memctx, struct sss_dp_callback);
- if (!cb) {
- dbus_message_unref(msg);
- talloc_zfree(sdp_req);
- return ENOMEM;
- }
- cb->callback = callback;
- cb->callback_ctx = callback_ctx;
- cb->sdp_req = sdp_req;
-
- DLIST_ADD(sdp_req->cb_list, cb);
- talloc_set_destructor((TALLOC_CTX *)cb, sss_dp_callback_destructor);
- }
-
- /* Set up the reply handler */
- dbret = dbus_pending_call_set_notify(pending_reply,
- sss_dp_send_acct_callback,
- sdp_req, NULL);
- if (!dbret) {
- DEBUG(0, ("Could not queue up pending request!"));
- talloc_zfree(sdp_req);
- dbus_pending_call_cancel(pending_reply);
- dbus_message_unref(msg);
- return EIO;
- }
-
- dbus_message_unref(msg);
-
- *ndp = sdp_req;
-
- return EOK;
-}
-
-static int sss_dp_get_reply(DBusPendingCall *pending,
- dbus_uint16_t *err_maj,
- dbus_uint32_t *err_min,
- char **err_msg)
-{
- DBusMessage *reply;
- DBusError dbus_error;
- dbus_bool_t ret;
- int type;
- int err = EOK;
-
- 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 ? */
- err = EIO;
- 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, err_maj,
- DBUS_TYPE_UINT32, err_min,
- DBUS_TYPE_STRING, err_msg,
- DBUS_TYPE_INVALID);
- if (!ret) {
- DEBUG(1,("Failed to parse message\n"));
- /* FIXME: Destroy this connection ? */
- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
- err = EIO;
- goto done;
- }
-
- DEBUG(4, ("Got reply (%u, %u, %s) from Data Provider\n",
- (unsigned int)*err_maj, (unsigned int)*err_min, *err_msg));
-
- break;
-
- case DBUS_MESSAGE_TYPE_ERROR:
- if (strcmp(dbus_message_get_error_name(reply),
- DBUS_ERROR_NO_REPLY) == 0) {
- err = ETIME;
- goto done;
- }
- DEBUG(0,("The Data Provider 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 ? */
- err = EIO;
- }
-
-done:
- dbus_pending_call_unref(pending);
- dbus_message_unref(reply);
-
- return err;
-}
-
diff --git a/server/responder/common/responder_packet.c b/server/responder/common/responder_packet.c
deleted file mode 100644
index 6e581a3c9..000000000
--- a/server/responder/common/responder_packet.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- SSSD
-
- SSS Client Responder, command parser
-
- 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 <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <errno.h>
-#include "talloc.h"
-#include "util/util.h"
-#include "responder/common/responder_packet.h"
-
-#define SSSSRV_PACKET_MEM_SIZE 512
-
-struct sss_packet {
- size_t memsize;
- uint8_t *buffer;
-
- /* header */
- uint32_t *len;
- uint32_t *cmd;
- uint32_t *status;
- uint32_t *reserved;
-
- uint8_t *body;
-
- /* io pointer */
- size_t iop;
-};
-
-/*
- * Allocate a new packet structure
- *
- * - if size is defined use it otherwise the default packet will be
- * SSSSRV_PACKET_MEM_SIZE bytes.
- */
-int sss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
- enum sss_cli_command cmd,
- struct sss_packet **rpacket)
-{
- struct sss_packet *packet;
-
- packet = talloc(mem_ctx, struct sss_packet);
- if (!packet) return ENOMEM;
-
- if (size) {
- int n = (size + SSS_NSS_HEADER_SIZE) % SSSSRV_PACKET_MEM_SIZE;
- packet->memsize = (n + 1) * SSSSRV_PACKET_MEM_SIZE;
- } else {
- packet->memsize = SSSSRV_PACKET_MEM_SIZE;
- }
-
- packet->buffer = talloc_size(packet, packet->memsize);
- if (!packet->buffer) {
- talloc_free(packet);
- return ENOMEM;
- }
- memset(packet->buffer, 0, SSS_NSS_HEADER_SIZE);
-
- packet->len = &((uint32_t *)packet->buffer)[0];
- packet->cmd = &((uint32_t *)packet->buffer)[1];
- packet->status = &((uint32_t *)packet->buffer)[2];
- packet->reserved = &((uint32_t *)packet->buffer)[3];
- packet->body = (uint8_t *)&((uint32_t *)packet->buffer)[4];
-
- *(packet->len) = size + SSS_NSS_HEADER_SIZE;
- *(packet->cmd) = cmd;
-
- packet->iop = 0;
-
- *rpacket = packet;
-
- return EOK;
-}
-
-/* grows a packet size only in SSSSRV_PACKET_MEM_SIZE chunks */
-int sss_packet_grow(struct sss_packet *packet, size_t size)
-{
- size_t totlen, len;
- uint8_t *newmem;
-
- if (size == 0) {
- return EOK;
- }
-
- totlen = packet->memsize;
- len = *packet->len + size;
-
- /* make sure we do not overflow */
- if (totlen < len) {
- int n = len % SSSSRV_PACKET_MEM_SIZE + 1;
- totlen += n * SSSSRV_PACKET_MEM_SIZE;
- if (totlen < len) {
- return EINVAL;
- }
- }
-
- if (totlen > packet->memsize) {
- newmem = talloc_realloc_size(packet, packet->buffer, totlen);
- if (!newmem) {
- return ENOMEM;
- }
-
- packet->memsize = totlen;
-
- /* re-set pointers if realloc had to move memory */
- if (newmem != packet->buffer) {
- packet->buffer = newmem;
- packet->len = &((uint32_t *)packet->buffer)[0];
- packet->cmd = &((uint32_t *)packet->buffer)[1];
- packet->status = &((uint32_t *)packet->buffer)[2];
- packet->reserved = &((uint32_t *)packet->buffer)[3];
- packet->body = (uint8_t *)&((uint32_t *)packet->buffer)[4];
- }
- }
-
- *(packet->len) += size;
-
- return 0;
-}
-
-/* reclaim backet previously resrved space in the packet
- * usually done in functione recovering from not fatal erros */
-int sss_packet_shrink(struct sss_packet *packet, size_t size)
-{
- size_t newlen;
-
- if (size > *(packet->len)) return EINVAL;
-
- newlen = *(packet->len) - size;
- if (newlen < SSS_NSS_HEADER_SIZE) return EINVAL;
-
- *(packet->len) = newlen;
- return 0;
-}
-
-int sss_packet_set_size(struct sss_packet *packet, size_t size)
-{
- size_t newlen;
-
- newlen = SSS_NSS_HEADER_SIZE + size;
-
- /* make sure we do not overflow */
- if (packet->memsize < newlen) return EINVAL;
-
- *(packet->len) = newlen;
-
- return 0;
-}
-
-int sss_packet_recv(struct sss_packet *packet, int fd)
-{
- size_t rb;
- size_t len;
- void *buf;
-
- buf = packet->buffer + packet->iop;
- if (packet->iop > 4) len = *packet->len - packet->iop;
- else len = packet->memsize - packet->iop;
-
- /* check for wrapping */
- if (len > packet->memsize) {
- return EINVAL;
- }
-
- errno = 0;
- rb = recv(fd, buf, len, 0);
-
- if (rb == -1 && errno == EAGAIN) {
- return EAGAIN;
- }
-
- if (rb == 0) {
- return ENODATA;
- }
-
- if (*packet->len > packet->memsize) {
- return EINVAL;
- }
-
- packet->iop += rb;
- if (packet->iop < 4) {
- return EAGAIN;
- }
-
- if (packet->iop < *packet->len) {
- return EAGAIN;
- }
-
- return EOK;
-}
-
-int sss_packet_send(struct sss_packet *packet, int fd)
-{
- size_t rb;
- size_t len;
- void *buf;
-
- buf = packet->buffer + packet->iop;
- len = *packet->len - packet->iop;
-
- errno = 0;
- rb = send(fd, buf, len, 0);
-
- if (rb == -1 && errno == EAGAIN) {
- return EAGAIN;
- }
-
- if (rb == 0) {
- return EIO;
- }
-
- packet->iop += rb;
-
- if (packet->iop < *packet->len) {
- return EAGAIN;
- }
-
- return EOK;
-}
-
-enum sss_cli_command sss_packet_get_cmd(struct sss_packet *packet)
-{
- return (enum sss_cli_command)(*packet->cmd);
-}
-
-void sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen)
-{
- *body = packet->body;
- *blen = *packet->len - SSS_NSS_HEADER_SIZE;
-}
-
-void sss_packet_set_error(struct sss_packet *packet, int error)
-{
- *(packet->status) = error;
-}
diff --git a/server/responder/common/responder_packet.h b/server/responder/common/responder_packet.h
deleted file mode 100644
index 2bfdc8a32..000000000
--- a/server/responder/common/responder_packet.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- SSSD
-
- SSS Client Responder, 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 __SSSSRV_PACKET_H__
-#define __SSSSRV_PACKET_H__
-
-#include "sss_client/sss_cli.h"
-
-#define SSS_PACKET_MAX_RECV_SIZE 1024
-
-struct sss_packet;
-
-int sss_packet_new(TALLOC_CTX *mem_ctx, size_t size,
- enum sss_cli_command cmd,
- struct sss_packet **rpacket);
-int sss_packet_grow(struct sss_packet *packet, size_t size);
-int sss_packet_shrink(struct sss_packet *packet, size_t size);
-int sss_packet_set_size(struct sss_packet *packet, size_t size);
-int sss_packet_recv(struct sss_packet *packet, int fd);
-int sss_packet_send(struct sss_packet *packet, int fd);
-enum sss_cli_command sss_packet_get_cmd(struct sss_packet *packet);
-void sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen);
-void sss_packet_set_error(struct sss_packet *packet, int error);
-
-#endif /* __SSSSRV_PACKET_H__ */
diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c
deleted file mode 100644
index 7de346f0c..000000000
--- a/server/responder/nss/nsssrv.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- SSSD
-
- NSS Responder
-
- 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 "popt.h"
-#include "util/util.h"
-#include "responder/nss/nsssrv.h"
-#include "responder/nss/nsssrv_nc.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "monitor/monitor_interfaces.h"
-#include "sbus/sbus_client.h"
-
-#define SSS_NSS_PIPE_NAME "nss"
-
-#define DEFAULT_PWFIELD "*"
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn);
-
-struct sbus_method monitor_nss_methods[] = {
- { MON_CLI_METHOD_PING, monitor_common_pong },
- { MON_CLI_METHOD_RELOAD, service_reload },
- { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
- { NULL, NULL }
-};
-
-struct sbus_interface monitor_nss_interface = {
- MONITOR_INTERFACE,
- MONITOR_PATH,
- SBUS_DEFAULT_VTABLE,
- monitor_nss_methods,
- NULL
-};
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn)
-{
- /* Monitor calls this function when we need to reload
- * our configuration information. Perform whatever steps
- * are needed to update the configuration objects.
- */
-
- /* Send an empty reply to acknowledge receipt */
- return monitor_common_pong(message, conn);
-}
-
-static int nss_get_config(struct nss_ctx *nctx,
- struct resp_ctx *rctx,
- struct confdb_ctx *cdb)
-{
- TALLOC_CTX *tmpctx;
- struct sss_domain_info *dom;
- char *domain, *name;
- char **filter_list;
- int ret, i;
-
- tmpctx = talloc_new(nctx);
- if (!tmpctx) return ENOMEM;
-
- ret = confdb_get_int(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_ENUM_CACHE_TIMEOUT, 120,
- &nctx->enum_cache_timeout);
- if (ret != EOK) goto done;
-
- ret = confdb_get_int(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_ENTRY_NEG_TIMEOUT, 15,
- &nctx->neg_timeout);
- if (ret != EOK) goto done;
-
- ret = confdb_get_bool(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_FILTER_USERS_IN_GROUPS, true,
- &nctx->filter_users_in_groups);
- if (ret != EOK) goto done;
-
-
- ret = confdb_get_int(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_ENTRY_CACHE_NOWAIT_PERCENTAGE, 0,
- &nctx->cache_refresh_percent);
- if (ret != EOK) goto done;
- if (nctx->cache_refresh_percent < 0 ||
- nctx->cache_refresh_percent > 99) {
- DEBUG(0,("Configuration error: entry_cache_nowait_percentage is"
- "invalid. Disabling feature.\n"));
- nctx->cache_refresh_percent = 0;
- }
-
- ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_FILTER_USERS, &filter_list);
- if (ret == ENOENT) {
- filter_list = talloc_array(tmpctx, char *, 2);
- filter_list[0] = talloc_strdup(tmpctx, "root");
- filter_list[1] = NULL;
- if (!filter_list || !filter_list[0]) {
- ret = ENOMEM;
- goto done;
- }
- ret = EOK;
- }
- else if (ret != EOK) goto done;
-
- for (i = 0; (filter_list && filter_list[i]); i++) {
- ret = sss_parse_name(tmpctx, nctx->rctx->names,
- filter_list[i], &domain, &name);
- if (ret != EOK) {
- DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n",
- filter_list[i], ret));
- continue;
- }
- if (domain) {
- ret = nss_ncache_set_user(nctx->ncache, true, domain, name);
- if (ret != EOK) {
- DEBUG(1, ("Failed to store permanent user filter for [%s]"
- " (%d [%s])\n", filter_list[i],
- ret, strerror(ret)));
- continue;
- }
- } else {
- for (dom = rctx->domains; dom; dom = dom->next) {
- ret = nss_ncache_set_user(nctx->ncache, true, dom->name, name);
- if (ret != EOK) {
- DEBUG(1, ("Failed to store permanent user filter for"
- " [%s:%s] (%d [%s])\n",
- dom->name, filter_list[i],
- ret, strerror(ret)));
- continue;
- }
- }
- }
- }
-
- ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_FILTER_GROUPS, &filter_list);
- if (ret == ENOENT) {
- filter_list = talloc_array(tmpctx, char *, 2);
- filter_list[0] = talloc_strdup(tmpctx, "root");
- filter_list[1] = NULL;
- if (!filter_list || !filter_list[0]) {
- ret = ENOMEM;
- goto done;
- }
- ret = EOK;
- }
- else if (ret != EOK) goto done;
-
- for (i = 0; (filter_list && filter_list[i]); i++) {
- ret = sss_parse_name(tmpctx, nctx->rctx->names,
- filter_list[i], &domain, &name);
- if (ret != EOK) {
- DEBUG(1, ("Invalid name in filterGroups list: [%s] (%d)\n",
- filter_list[i], ret));
- continue;
- }
- if (domain) {
- ret = nss_ncache_set_group(nctx->ncache, true, domain, name);
- if (ret != EOK) {
- DEBUG(1, ("Failed to store permanent group filter for"
- " [%s] (%d [%s])\n", filter_list[i],
- ret, strerror(ret)));
- continue;
- }
- } else {
- for (dom = rctx->domains; dom; dom = dom->next) {
- ret = nss_ncache_set_group(nctx->ncache, true, dom->name, name);
- if (ret != EOK) {
- DEBUG(1, ("Failed to store permanent group filter for"
- " [%s:%s] (%d [%s])\n",
- dom->name, filter_list[i],
- ret, strerror(ret)));
- continue;
- }
- }
- }
- }
-
- ret = confdb_get_string(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
- CONFDB_NSS_PWFIELD, DEFAULT_PWFIELD,
- &nctx->pwfield);
- if (ret != EOK) goto done;
-
- ret = 0;
-done:
- talloc_free(tmpctx);
- return ret;
-}
-
-static struct sbus_method nss_dp_methods[] = {
- { NULL, NULL }
-};
-
-struct sbus_interface nss_dp_interface = {
- DP_INTERFACE,
- DP_PATH,
- SBUS_DEFAULT_VTABLE,
- nss_dp_methods,
- NULL
-};
-
-
-static void nss_dp_reconnect_init(struct sbus_connection *conn,
- int status, void *pvt)
-{
- struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
- int ret;
-
- /* Did we reconnect successfully? */
- if (status == SBUS_RECONNECT_SUCCESS) {
- DEBUG(1, ("Reconnected to the Data Provider.\n"));
-
- /* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "NSS", be_conn->domain->name);
- /* all fine */
- if (ret == EOK) return;
- }
-
- /* Failed to reconnect */
- DEBUG(0, ("Could not reconnect to %s provider.\n",
- be_conn->domain->name));
-
- /* FIXME: kill the frontend and let the monitor restart it ? */
- /* nss_shutdown(rctx); */
-}
-
-int nss_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb)
-{
- struct sss_cmd_table *nss_cmds;
- struct be_conn *iter;
- struct nss_ctx *nctx;
- int ret, max_retries;
-
- nctx = talloc_zero(mem_ctx, struct nss_ctx);
- if (!nctx) {
- DEBUG(0, ("fatal error initializing nss_ctx\n"));
- return ENOMEM;
- }
-
- ret = nss_ncache_init(nctx, &nctx->ncache);
- if (ret != EOK) {
- DEBUG(0, ("fatal error initializing negative cache\n"));
- return ret;
- }
-
- nss_cmds = get_nss_cmds();
-
- ret = sss_process_init(nctx, ev, cdb,
- nss_cmds,
- SSS_NSS_SOCKET_NAME, NULL,
- CONFDB_NSS_CONF_ENTRY,
- NSS_SBUS_SERVICE_NAME,
- NSS_SBUS_SERVICE_VERSION,
- &monitor_nss_interface,
- "NSS", &nss_dp_interface,
- &nctx->rctx);
- if (ret != EOK) {
- return ret;
- }
- nctx->rctx->pvt_ctx = nctx;
-
- ret = nss_get_config(nctx, nctx->rctx, cdb);
- if (ret != EOK) {
- DEBUG(0, ("fatal error getting nss config\n"));
- return ret;
- }
-
- /* Enable automatic reconnection to the Data Provider */
- ret = confdb_get_int(nctx->rctx->cdb, nctx->rctx,
- CONFDB_NSS_CONF_ENTRY,
- CONFDB_SERVICE_RECON_RETRIES,
- 3, &max_retries);
- if (ret != EOK) {
- DEBUG(0, ("Failed to set up automatic reconnection\n"));
- return ret;
- }
-
- for (iter = nctx->rctx->be_conns; iter; iter = iter->next) {
- sbus_reconnect_init(iter->conn, max_retries,
- nss_dp_reconnect_init, iter);
- }
-
- DEBUG(1, ("NSS Initialization complete\n"));
-
- return EOK;
-}
-
-int main(int argc, const char *argv[])
-{
- int opt;
- poptContext pc;
- struct main_context *main_ctx;
- int ret;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- SSSD_MAIN_OPTS
- { NULL }
- };
-
- 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;
- }
- }
-
- poptFreeContext(pc);
-
- /* set up things like debug, signals, daemonization, etc... */
- debug_log_file = "sssd_nss";
-
- ret = server_setup("sssd[nss]", 0, CONFDB_NSS_CONF_ENTRY, &main_ctx);
- if (ret != EOK) 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 = nss_process_init(main_ctx,
- main_ctx->event_ctx,
- main_ctx->confdb_ctx);
- if (ret != EOK) return 3;
-
- /* loop on main */
- server_loop(main_ctx);
-
- return 0;
-}
-
diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h
deleted file mode 100644
index a6c661835..000000000
--- a/server/responder/nss/nsssrv.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- SSSD
-
- NSS Responder, 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 __NSSSRV_H__
-#define __NSSSRV_H__
-
-#include <stdint.h>
-#include <sys/un.h>
-#include "config.h"
-#include "talloc.h"
-#include "tevent.h"
-#include "ldb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder_packet.h"
-#include "responder/common/responder.h"
-#include "responder/nss/nsssrv_nc.h"
-
-#define NSS_SBUS_SERVICE_VERSION 0x0001
-#define NSS_SBUS_SERVICE_NAME "nss"
-
-#define NSS_PACKET_MAX_RECV_SIZE 1024
-
-struct getent_ctx;
-
-struct nss_ctx {
- struct resp_ctx *rctx;
-
- int neg_timeout;
- struct nss_nc_ctx *ncache;
-
- int cache_refresh_percent;
-
- int enum_cache_timeout;
- time_t last_user_enum;
- time_t last_group_enum;
-
- struct getent_ctx *pctx;
- struct getent_ctx *gctx;
-
- bool filter_users_in_groups;
-
- char *pwfield;
-};
-
-struct nss_packet;
-
-int nss_cmd_execute(struct cli_ctx *cctx);
-
-struct sss_cmd_table *get_nss_cmds(void);
-
-#endif /* __NSSSRV_H__ */
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
deleted file mode 100644
index 46d4a2361..000000000
--- a/server/responder/nss/nsssrv_cmd.c
+++ /dev/null
@@ -1,3182 +0,0 @@
-/*
- SSSD
-
- NSS Responder
-
- 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 "util/util.h"
-#include "responder/nss/nsssrv.h"
-#include "confdb/confdb.h"
-#include "db/sysdb.h"
-#include <time.h>
-
-struct nss_cmd_ctx {
- struct cli_ctx *cctx;
- char *name;
- uint32_t id;
-
- bool immediate;
- bool check_next;
- bool enum_cached;
-};
-
-struct dom_ctx {
- struct sss_domain_info *domain;
- struct ldb_result *res;
- int cur;
-};
-
-struct getent_ctx {
- struct dom_ctx *doms;
- int num;
- int cur;
-};
-
-struct nss_dom_ctx {
- struct nss_cmd_ctx *cmdctx;
- struct sss_domain_info *domain;
-
- bool check_provider;
-
- /* cache results */
- struct ldb_result *res;
-};
-
-static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
-{
- struct cli_ctx *cctx = cmdctx->cctx;
- int ret;
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
-
- sss_packet_set_error(cctx->creq->out, err);
- return EOK;
-}
-
-#define NSS_CMD_FATAL_ERROR(cctx) do { \
- DEBUG(1,("Fatal error, killing connection!")); \
- talloc_free(cctx); \
- return; \
-} while(0)
-
-#define NSS_CMD_FATAL_ERROR_CODE(cctx, ret) do { \
- DEBUG(1,("Fatal error, killing connection!")); \
- talloc_free(cctx); \
- return ret; \
-} while(0)
-
-static struct sss_domain_info *nss_get_dom(struct sss_domain_info *doms,
- const char *domain)
-{
- struct sss_domain_info *dom;
-
- for (dom = doms; dom; dom = dom->next) {
- if (strcasecmp(dom->name, domain) == 0) break;
- }
- if (!dom) DEBUG(2, ("Unknown domain [%s]!\n", domain));
-
- return dom;
-}
-
-static int fill_empty(struct sss_packet *packet)
-{
- uint8_t *body;
- size_t blen;
- int ret;
-
- ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
- if (ret != EOK) return ret;
-
- sss_packet_get_body(packet, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* num results */
- ((uint32_t *)body)[1] = 0; /* reserved */
-
- return EOK;
-}
-
-/****************************************************************************
- * PASSWD db related functions
- ***************************************************************************/
-
-static int fill_pwent(struct sss_packet *packet,
- struct sss_domain_info *dom,
- struct nss_ctx *nctx,
- bool filter_users,
- struct ldb_message **msgs,
- int count)
-{
- struct ldb_message *msg;
- uint8_t *body;
- const char *name;
- const char *gecos;
- const char *homedir;
- const char *shell;
- uint32_t uid;
- uint32_t gid;
- size_t rsize, rp, blen;
- size_t s1, s2, s3, s4, s5;
- size_t dom_len = 0;
- int delim = 1;
- int i, ret, num, t;
- bool add_domain = dom->fqnames;
- const char *domain = dom->name;
- const char *namefmt = nctx->rctx->names->fq_fmt;
- bool packet_initialized = false;
- int ncret;
-
- if (add_domain) dom_len = strlen(domain);
-
- rp = 2*sizeof(uint32_t);
-
- num = 0;
- for (i = 0; i < count; i++) {
- msg = msgs[i];
-
- name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
- gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
-
- if (!name || !uid || !gid) {
- DEBUG(1, ("Incomplete user object for %s[%llu]! Skipping\n",
- name?name:"<NULL>", (unsigned long long int)uid));
- continue;
- }
-
- if (filter_users) {
- ncret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- domain, name);
- if (ncret == EEXIST) {
- DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n",
- name, domain));
- continue;
- }
- }
-
- if (!packet_initialized) {
- /* first 2 fields (len and reserved), filled up later */
- ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
- if (ret != EOK) return ret;
- packet_initialized = true;
- }
-
- gecos = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
- homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
- shell = ldb_msg_find_attr_as_string(msg, SYSDB_SHELL, NULL);
-
- if (!gecos) gecos = "";
- if (!homedir) homedir = "/";
- if (!shell) shell = "";
-
- s1 = strlen(name) + 1;
- s2 = strlen(gecos) + 1;
- s3 = strlen(homedir) + 1;
- s4 = strlen(shell) + 1;
- s5 = strlen(nctx->pwfield) + 1;
- if (add_domain) s1 += delim + dom_len;
-
- rsize = 2*sizeof(uint32_t) +s1 + s2 + s3 + s4 + s5;
-
- ret = sss_packet_grow(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
-
- ((uint32_t *)(&body[rp]))[0] = uid;
- ((uint32_t *)(&body[rp]))[1] = gid;
- rp += 2*sizeof(uint32_t);
-
- if (add_domain) {
- ret = snprintf((char *)&body[rp], s1, namefmt, name, domain);
- if (ret >= s1) {
- /* need more space, got creative with the print format ? */
- t = ret - s1 + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- delim += t;
- s1 += t;
- sss_packet_get_body(packet, &body, &blen);
-
- /* retry */
- ret = snprintf((char *)&body[rp], s1, namefmt, name, domain);
- }
-
- if (ret != s1-1) {
- DEBUG(1, ("Failed to generate a fully qualified name for user "
- "[%s] in [%s]! Skipping user.\n", name, domain));
- continue;
- }
- } else {
- memcpy(&body[rp], name, s1);
- }
- rp += s1;
-
- memcpy(&body[rp], nctx->pwfield, s5);
- rp += s5;
- memcpy(&body[rp], gecos, s2);
- rp += s2;
- memcpy(&body[rp], homedir, s3);
- rp += s3;
- memcpy(&body[rp], shell, s4);
- rp += s4;
-
- num++;
- }
-
-done:
- /* if there are no results just return ENOENT,
- * let the caller decide if this is the last packet or not */
- if (!packet_initialized) return ENOENT;
-
- sss_packet_get_body(packet, &body, &blen);
- ((uint32_t *)body)[0] = num; /* num results */
- ((uint32_t *)body)[1] = 0; /* reserved */
-
- return EOK;
-}
-
-static errno_t check_cache(struct nss_dom_ctx *dctx,
- struct nss_ctx *nctx,
- struct ldb_result *res,
- int req_type,
- const char *opt_name,
- uint32_t opt_id,
- sss_dp_callback_t callback)
-{
- errno_t ret;
- int timeout;
- time_t now;
- uint64_t lastUpdate;
- uint64_t cacheExpire = 0;
- uint64_t midpoint_refresh;
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- bool off_band_update = false;
-
- /* when searching for a user, more than one reply is a db error */
- if ((req_type == SSS_DP_USER) && (res->count > 1)) {
- DEBUG(1, ("getpwXXX call returned more than one result!"
- " DB Corrupted?\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR_CODE(cctx, ENOENT);
- }
- sss_cmd_done(cctx, cmdctx);
- return ENOENT;
- }
-
- /* if we have any reply let's check cache validity */
- if (res->count > 0) {
-
- now = time(NULL);
-
- lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_LAST_UPDATE, 0);
- if (req_type == SSS_DP_INITGROUPS) {
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_INITGR_EXPIRE, 1);
- }
- if (cacheExpire == 0) {
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
- }
-
- midpoint_refresh = 0;
- if(nctx->cache_refresh_percent) {
- midpoint_refresh = lastUpdate +
- (cacheExpire - lastUpdate)*nctx->cache_refresh_percent/100;
- if (midpoint_refresh - lastUpdate < 10) {
- /* If the percentage results in an expiration
- * less than ten seconds after the lastUpdate time,
- * that's too often we will simply set it to 10s
- */
- midpoint_refresh = lastUpdate+10;
- }
- }
-
- if (cacheExpire > now) {
- /* cache still valid */
-
- if (midpoint_refresh && midpoint_refresh < now) {
- /* We're past the the cache refresh timeout
- * We'll return the value from the cache, but we'll also
- * queue the cache entry for update out-of-band.
- */
- DEBUG(6, ("Performing midpoint cache update on [%s]\n",
- opt_name));
- off_band_update = true;
- }
- else {
-
- /* Cache is still valid. Just return it. */
- return EOK;
- }
- }
- }
-
- if (off_band_update) {
-
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- /* No callback required
- * This was an out-of-band update. We'll return EOK
- * so the calling function can return the cached entry
- * immediately.
- */
- ret = sss_dp_send_acct_req(cctx->rctx, NULL, NULL, NULL,
- timeout, dctx->domain->name,
- true, req_type,
- opt_name, opt_id);
- if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- } else {
-
- DEBUG(3, ("Updating cache out-of-band\n"));
- }
-
- } else {
- /* This is a cache miss. Or the cache is expired.
- * We need to get the updated user information before returning it.
- */
-
- /* dont loop forever :-) */
- dctx->check_provider = false;
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- /* keep around current data in case backend is offline */
- if (res->count) {
- dctx->res = talloc_steal(dctx, res);
- }
-
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- callback, dctx, timeout,
- dctx->domain->name,
- true, req_type,
- opt_name, opt_id);
- if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR_CODE(cctx, EIO);
- }
- sss_cmd_done(cctx, cmdctx);
- return EIO;
- }
-
- return EAGAIN;
- }
-
- return EOK;
-}
-
-static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_getpwnam_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- struct sss_domain_info *dom;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- bool neghit = false;
- int ncret;
- int ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, status);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_USER, cmdctx->name, 0,
- nss_cmd_getpwnam_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
- }
- }
-
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
-
- ret = EOK;
-
- /* skip domains that require FQnames or have negative caches */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- ncret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
- cmdctx->name));
- ret = ENOENT;
- }
- if (dom == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n",
- cmdctx->name));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- if (dctx->res) talloc_free(res);
- dctx->res = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getpwnam_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
-
- DEBUG(2, ("No results for getpwnam call\n"));
-
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_user(nctx->ncache, false,
- dctx->domain->name, cmdctx->name);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- case 1:
- DEBUG(6, ("Returning info for user [%s]\n", cmdctx->name));
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = fill_pwent(cctx->creq->out,
- dctx->domain,
- nctx, false,
- res->msgs, res->count);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
- }
- sss_packet_set_error(cctx->creq->out, ret);
-
- break;
-
- default:
- DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (!dctx->res) {
- /* return 0 results */
- dctx->res = talloc_zero(dctx, struct ldb_result);
- if (!dctx->res) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
- return;
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getpwnam_callback, dctx);
-
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
- ret, strerror(ret)));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_getpwnam(struct cli_ctx *cctx)
-{
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- const char *rawname;
- char *domname;
- uint8_t *body;
- size_t blen;
- int ret;
- int ncret;
- bool neghit = false;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* get user name to query */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
-
- /* if not terminated fail */
- if (body[blen -1] != '\0') {
- ret = EINVAL;
- goto done;
- }
- rawname = (const char *)body;
-
- domname = NULL;
- ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
- &domname, &cmdctx->name);
- if (ret != EOK) {
- DEBUG(2, ("Invalid name received [%s]\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, domname?domname:"<ALL>"));
-
- if (domname) {
- dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
- if (!dctx->domain) {
- ret = ENOENT;
- goto done;
- }
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dctx->domain->name, cmdctx->name);
- if (ncret == EEXIST) {
- neghit = true;
- }
- }
- else {
- /* skip domains that require FQnames or have negative caches */
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- dctx->domain = dom;
- }
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n", rawname));
- ret = ENOENT;
- goto done;
- }
- if (dctx->domain == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-
- if (!domname) {
- /* this is a multidomain search */
- cmdctx->check_next = true;
- }
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_getpwnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getpwnam_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_getpwuid_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- bool neghit = false;
- int ret;
- int ncret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, status);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_USER, NULL, cmdctx->id,
- nss_cmd_getpwuid_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
- }
- }
-
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
-
- ret = EOK;
-
- dom = dctx->domain->next;
- ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Uid [%lu] does not exist! (negative cache)\n",
- (unsigned long)cmdctx->id));
- ret = ENOENT;
- }
- if (dom == NULL) {
- DEBUG(0, ("No matching domain found for [%lu], fail!\n",
- (unsigned long)cmdctx->id));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- if (dctx->res) talloc_free(res);
- dctx->res = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
-
- DEBUG(2, ("No results for getpwuid call\n"));
-
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_uid(nctx->ncache, false, cmdctx->id);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- case 1:
- DEBUG(6, ("Returning info for user [%u]\n", (unsigned)cmdctx->id));
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
-
- ret = fill_pwent(cctx->creq->out,
- dctx->domain,
- nctx, true,
- res->msgs, res->count);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
- }
- sss_packet_set_error(cctx->creq->out, ret);
-
- break;
-
- default:
- DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (!dctx->res) {
- /* return 0 results */
- dctx->res = talloc_zero(dctx, struct ldb_result);
- if (!dctx->res) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- nss_cmd_getpwuid_callback(dctx, LDB_SUCCESS, dctx->res);
- return;
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_callback, dctx);
-
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_getpwuid(struct cli_ctx *cctx)
-{
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- int ret;
- int ncret;
-
- ret = ENOENT;
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* get uid to query */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
-
- if (blen != sizeof(uint32_t)) {
- ret = EINVAL;
- goto done;
- }
- cmdctx->id = *((uint32_t *)body);
-
- /* this is a multidomain search */
- cmdctx->check_next = true;
-
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Uid [%lu] does not exist! (negative cache)\n",
- (unsigned long)cmdctx->id));
- continue;
- }
-
- /* check that the uid is valid for this domain */
- if ((dom->id_min && (cmdctx->id < dom->id_min)) ||
- (dom->id_max && (cmdctx->id > dom->id_max))) {
- DEBUG(4, ("Uid [%lu] does not exist in domain [%s]! "
- "(id out of range)\n",
- (unsigned long)cmdctx->id, dom->name));
- continue;
- }
-
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-
- DEBUG(4, ("Requesting info for [%lu@%s]\n",
- cmdctx->id, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_getpwuid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getpwuid_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
-
- break;
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-/* to keep it simple at this stage we are retrieving the
- * full enumeration again for each request for each process
- * and we also block on setpwent() for the full time needed
- * to retrieve the data. And endpwent() frees all the data.
- * Next steps are:
- * - use an nsssrv wide cache with data already structured
- * so that it can be immediately returned (see nscd way)
- * - use mutexes so that setpwent() can return immediately
- * even if the data is still being fetched
- * - make getpwent() wait on the mutex
- */
-static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx);
-
-static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_setpwent_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct getent_ctx *pctx;
- struct nss_ctx *nctx;
- int timeout;
- int ret;
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- pctx = nctx->pctx;
- if (pctx == NULL) {
- pctx = talloc_zero(nctx, struct getent_ctx);
- if (!pctx) {
- ret = nss_cmd_send_error(cmdctx, ENOMEM);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
- nctx->pctx = pctx;
- }
-
- pctx->doms = talloc_realloc(pctx, pctx->doms, struct dom_ctx, pctx->num +1);
- if (!pctx->doms) {
- talloc_free(pctx);
- nctx->pctx = NULL;
- NSS_CMD_FATAL_ERROR(cctx);
- }
-
- pctx->doms[pctx->num].domain = dctx->domain;
- pctx->doms[pctx->num].res = talloc_steal(pctx->doms, res);
- pctx->doms[pctx->num].cur = 0;
-
- pctx->num++;
-
- /* do not reply until all domain searches are done */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
- if (dom->enumerate != 0) break;
- }
- dctx->domain = dom;
-
- if (dctx->domain != NULL) {
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- }
-
- if (dctx->check_provider) {
- timeout = SSS_CLI_SOCKET_TIMEOUT;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setpw_dp_callback, dctx,
- timeout, dom->name, true,
- SSS_DP_USER, NULL, 0);
- } else {
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_enumpwent(dctx, sysdb,
- dctx->domain, NULL,
- nss_cmd_setpwent_callback, dctx);
- }
- if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
- dom->name));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
- return;
- }
-
- /* set cache mark */
- nctx->last_user_enum = time(NULL);
-
- if (cmdctx->immediate) {
- /* this was a getpwent call w/o setpwent,
- * return immediately one result */
- ret = nss_cmd_getpwent_immediate(cmdctx);
- if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
- return;
- }
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_enumpwent(cmdctx, sysdb,
- dctx->domain, NULL,
- nss_cmd_setpwent_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
-{
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct nss_ctx *nctx;
- time_t now = time(NULL);
- int timeout;
- uint8_t *body;
- size_t blen;
- int ret;
-
- DEBUG(4, ("Requesting info for all users\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- talloc_free(nctx->pctx);
- nctx->pctx = NULL;
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
- cmdctx->immediate = immediate;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* do not query backends if we have a recent enumeration */
- if (nctx->enum_cache_timeout) {
- if (nctx->last_user_enum +
- nctx->enum_cache_timeout > now) {
- cmdctx->enum_cached = true;
- }
- }
-
- /* check if enumeration is enabled in any domain */
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- if (dom->enumerate != 0) break;
- }
- dctx->domain = dom;
-
- if (dctx->domain == NULL) {
- DEBUG(2, ("Enumeration disabled on all domains!\n"));
- ret = ENOENT;
- goto done;
- }
-
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- }
-
- if (dctx->check_provider) {
- timeout = SSS_CLI_SOCKET_TIMEOUT;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setpw_dp_callback, dctx,
- timeout, dom->name, true,
- SSS_DP_USER, NULL, 0);
- } else {
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_enumpwent(dctx, sysdb,
- dctx->domain, NULL,
- nss_cmd_setpwent_callback, dctx);
- }
- if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
- dom->name));
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- if (cmdctx->immediate) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- else {
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-static int nss_cmd_setpwent(struct cli_ctx *cctx)
-{
- return nss_cmd_setpwent_ext(cctx, false);
-}
-
-
-static int nss_cmd_retpwent(struct cli_ctx *cctx, int num)
-{
- struct nss_ctx *nctx;
- struct getent_ctx *pctx;
- struct ldb_message **msgs = NULL;
- struct dom_ctx *pdom = NULL;
- int n = 0;
- int ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- pctx = nctx->pctx;
-
-retry:
- if (pctx->cur >= pctx->num) goto none;
-
- pdom = &pctx->doms[pctx->cur];
-
- n = pdom->res->count - pdom->cur;
- if (n == 0 && (pctx->cur+1 < pctx->num)) {
- pctx->cur++;
- pdom = &pctx->doms[pctx->cur];
- n = pdom->res->count - pdom->cur;
- }
-
- if (!n) goto none;
-
- if (n > num) n = num;
-
- msgs = &(pdom->res->msgs[pdom->cur]);
- pdom->cur += n;
-
- ret = fill_pwent(cctx->creq->out, pdom->domain, nctx, true, msgs, n);
- if (ret == ENOENT) goto retry;
- return ret;
-
-none:
- return fill_empty(cctx->creq->out);
-}
-
-/* used only if a process calls getpwent() without first calling setpwent()
- */
-static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx)
-{
- struct cli_ctx *cctx = cmdctx->cctx;
- uint8_t *body;
- size_t blen;
- uint32_t num;
- int ret;
-
- /* get max num of entries to return in one call */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen != sizeof(uint32_t)) {
- return EINVAL;
- }
- num = *((uint32_t *)body);
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
-
- ret = nss_cmd_retpwent(cctx, num);
-
- sss_packet_set_error(cctx->creq->out, ret);
- sss_cmd_done(cctx, cmdctx);
-
- return EOK;
-}
-
-static int nss_cmd_getpwent(struct cli_ctx *cctx)
-{
- struct nss_ctx *nctx;
- struct nss_cmd_ctx *cmdctx;
-
- DEBUG(4, ("Requesting info for all accounts\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- /* see if we need to trigger an implicit setpwent() */
- if (nctx->pctx == NULL) {
- nctx->pctx = talloc_zero(nctx, struct getent_ctx);
- if (!nctx->pctx) return ENOMEM;
-
- return nss_cmd_setpwent_ext(cctx, true);
- }
-
- cmdctx = talloc(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- return nss_cmd_getpwent_immediate(cmdctx);
-}
-
-static int nss_cmd_endpwent(struct cli_ctx *cctx)
-{
- struct nss_ctx *nctx;
- int ret;
-
- DEBUG(4, ("Terminating request info for all accounts\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
-
- if (nctx->pctx == NULL) goto done;
-
- /* free results and reset */
- talloc_free(nctx->pctx);
- nctx->pctx = NULL;
-
-done:
- sss_cmd_done(cctx, NULL);
- return EOK;
-}
-
-/****************************************************************************
- * GROUP db related functions
- ***************************************************************************/
-
-#define GID_ROFFSET 0
-#define MNUM_ROFFSET sizeof(uint32_t)
-#define STRS_ROFFSET 2*sizeof(uint32_t)
-
-static int fill_grent(struct sss_packet *packet,
- struct sss_domain_info *dom,
- struct nss_ctx *nctx,
- bool filter_groups,
- struct ldb_message **msgs,
- int max, int *count)
-{
- struct ldb_message *msg;
- struct ldb_message_element *el;
- uint8_t *body;
- size_t blen;
- uint32_t gid;
- const char *name;
- size_t nsize;
- size_t delim;
- size_t dom_len;
- size_t pwlen;
- int i = 0;
- int j = 0;
- int ret, num, memnum;
- size_t rzero, rsize;
- bool add_domain = dom->fqnames;
- const char *domain = dom->name;
- const char *namefmt = nctx->rctx->names->fq_fmt;
-
- if (add_domain) {
- delim = 1;
- dom_len = strlen(domain);
- } else {
- delim = 0;
- dom_len = 0;
- }
-
- num = 0;
- pwlen = strlen(nctx->pwfield) + 1;
-
- /* first 2 fields (len and reserved), filled up later */
- ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
- if (ret != EOK) {
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- rzero = 2*sizeof(uint32_t);
- rsize = 0;
-
- for (i = 0; i < *count; i++) {
- msg = msgs[i];
-
- /* new group */
- if (!ldb_msg_check_string_attribute(msg, "objectClass",
- SYSDB_GROUP_CLASS)) {
- DEBUG(1, ("Wrong object (%s) found on stack!\n",
- ldb_dn_get_linearized(msg->dn)));
- continue;
- }
-
- /* if we reached the max allowed entries, simply return */
- if (num >= max) {
- goto done;
- }
-
- /* new result starts at end of previous result */
- rzero += rsize;
- rsize = 0;
-
- /* find group name/gid */
- name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
- gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
- if (!name || !gid) {
- DEBUG(1, ("Incomplete group object for %s[%llu]! Skipping\n",
- name?name:"<NULL>", (unsigned long long int)gid));
- continue;
- }
-
- if (filter_groups) {
- ret = nss_ncache_check_group(nctx->ncache,
- nctx->neg_timeout, domain, name);
- if (ret == EEXIST) {
- DEBUG(4, ("Group [%s@%s] filtered out! (negative cache)\n",
- name, domain));
- continue;
- }
- }
-
- nsize = strlen(name) + 1; /* includes terminating \0 */
- if (add_domain) nsize += delim + dom_len;
-
- /* fill in gid and name and set pointer for number of members */
- rsize = STRS_ROFFSET + nsize + pwlen; /* name\0x\0 */
-
- ret = sss_packet_grow(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
-
- /* 0-3: 32bit number gid */
- ((uint32_t *)(&body[rzero+GID_ROFFSET]))[0] = gid;
-
- /* 4-7: 32bit unsigned number of members */
- ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = 0;
-
- /* 8-X: sequence of strings (name, passwd, mem..) */
- if (add_domain) {
- ret = snprintf((char *)&body[rzero+STRS_ROFFSET],
- nsize, namefmt, name, domain);
- if (ret >= nsize) {
- /* need more space, got creative with the print format ? */
- int t = ret - nsize + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- rsize += t;
- delim += t;
- nsize += t;
-
- /* retry */
- ret = snprintf((char *)&body[rzero+STRS_ROFFSET],
- nsize, namefmt, name, domain);
- }
-
- if (ret != nsize-1) {
- DEBUG(1, ("Failed to generate a fully qualified name for"
- " group [%s] in [%s]! Skipping\n", name, domain));
- /* reclaim space */
- ret = sss_packet_shrink(packet, rsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- rsize = 0;
- continue;
- }
- } else {
- memcpy(&body[rzero+STRS_ROFFSET], name, nsize);
- }
-
- /* group passwd field */
- memcpy(&body[rzero + rsize -pwlen], nctx->pwfield, pwlen);
-
- el = ldb_msg_find_element(msg, SYSDB_MEMBERUID);
- if (el) {
- memnum = 0;
-
- for (j = 0; j < el->num_values; j++) {
- name = (const char *)el->values[j].data;
-
- if (nctx->filter_users_in_groups) {
- ret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- domain, name);
- if (ret == EEXIST) {
- DEBUG(6, ("Group [%s] member [%s@%s] filtered out!"
- " (negative cache)\n",
- (char *)&body[rzero+STRS_ROFFSET],
- name, domain));
- continue;
- }
- }
-
- nsize = strlen(name) + 1; /* includes terminating \0 */
- if (add_domain) nsize += delim + dom_len;
-
- ret = sss_packet_grow(packet, nsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
-
- if (add_domain) {
- ret = snprintf((char *)&body[rzero + rsize],
- nsize, namefmt, name, domain);
- if (ret >= nsize) {
- /* need more space,
- * got creative with the print format ? */
- int t = ret - nsize + 1;
- ret = sss_packet_grow(packet, t);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- sss_packet_get_body(packet, &body, &blen);
- delim += t;
- nsize += t;
-
- /* retry */
- ret = snprintf((char *)&body[rzero + rsize],
- nsize, namefmt, name, domain);
- }
-
- if (ret != nsize-1) {
- DEBUG(1, ("Failed to generate a fully qualified name"
- " for member [%s@%s] of group [%s]!"
- " Skipping\n", name, domain,
- (char *)&body[rzero+STRS_ROFFSET]));
- /* reclaim space */
- ret = sss_packet_shrink(packet, nsize);
- if (ret != EOK) {
- num = 0;
- goto done;
- }
- continue;
- }
-
- } else {
- memcpy(&body[rzero + rsize], name, nsize);
- }
-
- rsize += nsize;
-
- memnum++;
- }
-
- if (memnum) {
- /* set num of members */
- ((uint32_t *)(&body[rzero+MNUM_ROFFSET]))[0] = memnum;
- }
- }
-
- num++;
- continue;
- }
-
-done:
- *count = i;
-
- if (num == 0) {
- /* if num is 0 most probably something went wrong,
- * reset packet and return ENOENT */
- ret = sss_packet_set_size(packet, 0);
- if (ret != EOK) return ret;
- return ENOENT;
- }
-
- ((uint32_t *)body)[0] = num; /* num results */
- ((uint32_t *)body)[1] = 0; /* reserved */
-
- return EOK;
-}
-
-static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_getgrnam_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- bool neghit = false;
- int ncret;
- int i, ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, status);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_GROUP, cmdctx->name, 0,
- nss_cmd_getgrnam_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
- }
- }
-
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
-
- ret = EOK;
-
- /* skip domains that require FQnames or have negative caches */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- ncret = nss_ncache_check_group(nctx->ncache,
- nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- if (neghit) {
- DEBUG(2, ("Group [%s] does not exist! (negative cache)\n",
- cmdctx->name));
- ret = ENOENT;
- }
- if (dom == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n",
- cmdctx->name));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- if (dctx->res) talloc_free(res);
- dctx->res = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getgrnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getgrnam_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
-
-
- DEBUG(2, ("No results for getgrnam call\n"));
-
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_group(nctx->ncache, false,
- dctx->domain->name, cmdctx->name);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- default:
-
- DEBUG(6, ("Returning info for group [%s]\n", cmdctx->name));
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- i = res->count;
- ret = fill_grent(cctx->creq->out,
- dctx->domain,
- nctx, false,
- res->msgs, 1, &i);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
- }
- sss_packet_set_error(cctx->creq->out, ret);
- }
-
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (!dctx->res) {
- /* return 0 results */
- dctx->res = talloc_zero(dctx, struct ldb_result);
- if (!dctx->res) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- nss_cmd_getgrnam_callback(dctx, LDB_SUCCESS, dctx->res);
- return;
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getgrnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getgrnam_callback, dctx);
-
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
- ret, strerror(ret)));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_getgrnam(struct cli_ctx *cctx)
-{
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- const char *rawname;
- char *domname;
- uint8_t *body;
- size_t blen;
- int ret;
- int ncret;
- bool neghit = false;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* get user name to query */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
-
- /* if not terminated fail */
- if (body[blen -1] != '\0') {
- ret = EINVAL;
- goto done;
- }
- rawname = (const char *)body;
-
- domname = NULL;
- ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
- &domname, &cmdctx->name);
- if (ret != EOK) {
- DEBUG(2, ("Invalid name received [%s]\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, domname?domname:"<ALL>"));
-
- if (domname) {
- dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
- if (!dctx->domain) {
- ret = ENOENT;
- goto done;
- }
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout,
- dctx->domain->name, cmdctx->name);
- if (ncret == EEXIST) {
- neghit = true;
- }
- }
- else {
- /* skip domains that require FQnames or have negative caches */
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- dctx->domain = dom;
- }
- if (neghit) {
- DEBUG(2, ("Group [%s] does not exist! (negative cache)\n", rawname));
- ret = ENOENT;
- goto done;
- }
- if (dctx->domain == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-
- if (!domname) {
- /* this is a multidomain search */
- cmdctx->check_next = true;
- }
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_getgrnam(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getgrnam_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_getgrgid_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- bool neghit = false;
- int i, ret;
- int ncret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, status);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_GROUP, NULL, cmdctx->id,
- nss_cmd_getgrgid_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
- }
- }
-
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
-
- ret = EOK;
-
- dom = dctx->domain->next;
-
- ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n",
- (unsigned long)cmdctx->id));
- ret = ENOENT;
- }
- if (dom == NULL) {
- DEBUG(0, ("No matching domain found for [%lu], fail!\n",
- (unsigned long)cmdctx->id));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- if (dctx->res) talloc_free(res);
- dctx->res = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getgrgid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getgrgid_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
-
- DEBUG(2, ("No results for getgrgid call\n"));
-
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_gid(nctx->ncache, false, cmdctx->id);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- default:
-
- DEBUG(6, ("Returning info for group [%u]\n", (unsigned)cmdctx->id));
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- i = res->count;
- ret = fill_grent(cctx->creq->out,
- dctx->domain,
- nctx, true,
- res->msgs, 1, &i);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
- }
- sss_packet_set_error(cctx->creq->out, ret);
- }
-
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (!dctx->res) {
- /* return 0 results */
- dctx->res = talloc_zero(dctx, struct ldb_result);
- if (!dctx->res) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- nss_cmd_getgrgid_callback(dctx, LDB_SUCCESS, dctx->res);
- return;
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_getgrgid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getgrgid_callback, dctx);
-
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_getgrgid(struct cli_ctx *cctx)
-{
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- int ret;
- int ncret;
-
- ret = ENOENT;
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* get uid to query */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
-
- if (blen != sizeof(uint32_t)) {
- ret = EINVAL;
- goto done;
- }
- cmdctx->id = *((uint32_t *)body);
-
- /* this is a multidomain search */
- cmdctx->check_next = true;
-
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout,
- cmdctx->id);
- if (ncret == EEXIST) {
- DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n",
- (unsigned long)cmdctx->id));
- continue;
- }
-
- /* check that the uid is valid for this domain */
- if ((dom->id_min && (cmdctx->id < dom->id_min)) ||
- (dom->id_max && (cmdctx->id > dom->id_max))) {
- DEBUG(4, ("Gid [%lu] does not exist in domain [%s]! "
- "(id out of range)\n",
- (unsigned long)cmdctx->id, dom->name));
- continue;
- }
-
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-
- DEBUG(4, ("Requesting info for [%lu@%s]\n",
- cmdctx->id, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_getgrgid(cmdctx, sysdb,
- dctx->domain, cmdctx->id,
- nss_cmd_getgrgid_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
-
- break;
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-/* to keep it simple at this stage we are retrieving the
- * full enumeration again for each request for each process
- * and we also block on setgrent() for the full time needed
- * to retrieve the data. And endgrent() frees all the data.
- * Next steps are:
- * - use and nsssrv wide cache with data already structured
- * so that it can be immediately returned (see nscd way)
- * - use mutexes so that setgrent() can return immediately
- * even if the data is still being fetched
- * - make getgrent() wait on the mutex
- */
-static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx);
-
-static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_setgrent_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct getent_ctx *gctx;
- struct nss_ctx *nctx;
- int timeout;
- int ret;
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, ENOENT);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- gctx = nctx->gctx;
- if (gctx == NULL) {
- gctx = talloc_zero(nctx, struct getent_ctx);
- if (!gctx) {
- ret = nss_cmd_send_error(cmdctx, ENOMEM);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
- nctx->gctx = gctx;
- }
-
- gctx->doms = talloc_realloc(gctx, gctx->doms, struct dom_ctx, gctx->num +1);
- if (!gctx->doms) NSS_CMD_FATAL_ERROR(cctx);
-
- gctx->doms[gctx->num].domain = dctx->domain;
- gctx->doms[gctx->num].res = talloc_steal(gctx->doms, res);
- gctx->doms[gctx->num].cur = 0;
-
- gctx->num++;
-
- /* do not reply until all domain searches are done */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
- if (dom->enumerate != 0) break;
- }
- dctx->domain = dom;
-
- if (dctx->domain != NULL) {
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- }
-
- if (dctx->check_provider) {
- timeout = SSS_CLI_SOCKET_TIMEOUT;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setgr_dp_callback, dctx,
- timeout, dom->name, true,
- SSS_DP_GROUP, NULL, 0);
- } else {
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
- }
- if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
- dom->name));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
- return;
- }
-
- /* set cache mark */
- nctx->last_group_enum = time(NULL);
-
- if (cmdctx->immediate) {
- /* this was a getgrent call w/o setgrent,
- * return immediately one result */
- ret = nss_cmd_getgrent_immediate(cmdctx);
- if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
- return;
- }
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
-{
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct nss_ctx *nctx;
- time_t now = time(NULL);
- int timeout;
- uint8_t *body;
- size_t blen;
- int ret;
-
- DEBUG(4, ("Requesting info for all groups\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- talloc_free(nctx->gctx);
- nctx->gctx = NULL;
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
- cmdctx->immediate = immediate;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* do not query backends if we have a recent enumeration */
- if (nctx->enum_cache_timeout) {
- if (nctx->last_group_enum +
- nctx->enum_cache_timeout > now) {
- cmdctx->enum_cached = true;
- }
- }
-
- /* check if enumeration is enabled in any domain */
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- if (dom->enumerate != 0) break;
- }
- dctx->domain = dom;
-
- if (dctx->domain == NULL) {
- DEBUG(2, ("Enumeration disabled on all domains!\n"));
- ret = ENOENT;
- goto done;
- }
-
- if (cmdctx->enum_cached) {
- dctx->check_provider = false;
- } else {
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- }
-
- if (dctx->check_provider) {
- timeout = SSS_CLI_SOCKET_TIMEOUT;
- ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
- nss_cmd_setgr_dp_callback, dctx,
- timeout, dom->name, true,
- SSS_DP_GROUP, NULL, 0);
- } else {
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_enumgrent(dctx, sysdb,
- dctx->domain,
- nss_cmd_setgrent_callback, dctx);
- }
- if (ret != EOK) {
- /* FIXME: shutdown ? */
- DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
- dom->name));
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- if (cmdctx->immediate) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- else {
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-static int nss_cmd_setgrent(struct cli_ctx *cctx)
-{
- return nss_cmd_setgrent_ext(cctx, false);
-}
-
-static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
-{
- struct nss_ctx *nctx;
- struct getent_ctx *gctx;
- struct ldb_message **msgs = NULL;
- struct dom_ctx *gdom = NULL;
- int n = 0;
- int ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
- gctx = nctx->gctx;
-
- do {
- if (gctx->cur >= gctx->num) goto none;
-
- gdom = &gctx->doms[gctx->cur];
-
- n = gdom->res->count - gdom->cur;
- if (n == 0 && (gctx->cur+1 < gctx->num)) {
- gctx->cur++;
- gdom = &gctx->doms[gctx->cur];
- n = gdom->res->count - gdom->cur;
- }
-
- if (!n) goto none;
-
- msgs = &(gdom->res->msgs[gdom->cur]);
-
- ret = fill_grent(cctx->creq->out, gdom->domain, nctx, true, msgs, num, &n);
-
- gdom->cur += n;
-
- } while(ret == ENOENT);
-
- return ret;
-
-none:
- return fill_empty(cctx->creq->out);
-}
-
-/* used only if a process calls getpwent() without first calling setpwent()
- */
-static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx)
-{
- struct cli_ctx *cctx = cmdctx->cctx;
- uint8_t *body;
- size_t blen;
- uint32_t num;
- int ret;
-
- /* get max num of entries to return in one call */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen != sizeof(uint32_t)) {
- return EINVAL;
- }
- num = *((uint32_t *)body);
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
-
- ret = nss_cmd_retgrent(cctx, num);
-
- sss_packet_set_error(cctx->creq->out, ret);
- sss_cmd_done(cctx, cmdctx);
-
- return EOK;
-}
-
-static int nss_cmd_getgrent(struct cli_ctx *cctx)
-{
- struct nss_ctx *nctx;
- struct nss_cmd_ctx *cmdctx;
-
- DEBUG(4, ("Requesting info for all groups\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- /* see if we need to trigger an implicit setpwent() */
- if (nctx->gctx == NULL) {
- nctx->gctx = talloc_zero(nctx, struct getent_ctx);
- if (!nctx->gctx) return ENOMEM;
-
- return nss_cmd_setgrent_ext(cctx, true);
- }
-
- cmdctx = talloc(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- return nss_cmd_getgrent_immediate(cmdctx);
-}
-
-static int nss_cmd_endgrent(struct cli_ctx *cctx)
-{
- struct nss_ctx *nctx;
- int ret;
-
- DEBUG(4, ("Terminating request info for all groups\n"));
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- /* create response packet */
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
-
- if (nctx->gctx == NULL) goto done;
-
- /* free results and reset */
- talloc_free(nctx->gctx);
- nctx->gctx = NULL;
-
-done:
- sss_cmd_done(cctx, NULL);
- return EOK;
-}
-
-static int fill_initgr(struct sss_packet *packet, struct ldb_result *res)
-{
- uint8_t *body;
- size_t blen;
- gid_t gid;
- int ret, i, num;
-
- if (res->count == 0) {
- return ENOENT;
- }
-
- /* one less, the first one is the user entry */
- num = res->count -1;
-
- ret = sss_packet_grow(packet, (2 + res->count) * sizeof(uint32_t));
- if (ret != EOK) {
- return ret;
- }
- sss_packet_get_body(packet, &body, &blen);
-
- /* skip first entry, it's the user entry */
- for (i = 0; i < num; i++) {
- gid = ldb_msg_find_attr_as_uint64(res->msgs[i + 1], SYSDB_GIDNUM, 0);
- if (!gid) {
- DEBUG(1, ("Incomplete group object for initgroups! Aborting\n"));
- return EFAULT;
- }
- ((uint32_t *)body)[2 + i] = gid;
- }
-
- ((uint32_t *)body)[0] = num; /* num results */
- ((uint32_t *)body)[1] = 0; /* reserved */
-
- return EOK;
-}
-
-static void nss_cmd_getinitgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-
-static void nss_cmd_getinitgr_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- uint8_t *body;
- size_t blen;
- bool neghit = false;
- int ncret;
- int ret;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- if (status != LDB_SUCCESS) {
- ret = nss_cmd_send_error(cmdctx, status);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- return;
- }
-
- if (dctx->check_provider) {
- ret = check_cache(dctx, nctx, res,
- SSS_DP_INITGROUPS, cmdctx->name, 0,
- nss_cmd_getinitgr_dp_callback);
- if (ret != EOK) {
- /* Anything but EOK means we should reenter the mainloop
- * because we may be refreshing the cache
- */
- return;
- }
- }
-
- switch (res->count) {
- case 0:
- if (cmdctx->check_next) {
-
- ret = EOK;
-
- /* skip domains that require FQnames or have negative caches */
- for (dom = dctx->domain->next; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- ncret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
- cmdctx->name));
- ret = ENOENT;
- }
- if (dom == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n",
- cmdctx->name));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- dctx->domain = dom;
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
- if (dctx->res) talloc_free(res);
- dctx->res = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_initgroups(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinitgr_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
-
- DEBUG(2, ("No results for initgroups call\n"));
-
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_user(nctx->ncache, false,
- dctx->domain->name, cmdctx->name);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- break;
-
- default:
-
- DEBUG(6, ("Returning initgr for user [%s]\n", cmdctx->name));
-
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = fill_initgr(cctx->creq->out, res);
- if (ret == ENOENT) {
- ret = fill_empty(cctx->creq->out);
- }
- sss_packet_set_error(cctx->creq->out, ret);
- }
-
- sss_cmd_done(cctx, cmdctx);
-}
-
-static void nss_cmd_getinitgr_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
- struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
- struct cli_ctx *cctx = cmdctx->cctx;
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n"
- "Will try to return what we have in cache\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
-
- if (!dctx->res) {
- /* return 0 results */
- dctx->res = talloc_zero(dctx, struct ldb_result);
- if (!dctx->res) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- nss_cmd_getinitgr_callback(dctx, LDB_SUCCESS, dctx->res);
- return;
- }
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- NSS_CMD_FATAL_ERROR(cctx);
- }
- ret = sysdb_initgroups(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinitgr_callback, dctx);
-
-done:
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
-
- ret = nss_cmd_send_error(cmdctx, ret);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- sss_cmd_done(cctx, cmdctx);
- }
-}
-
-/* for now, if we are online, try to always query the backend */
-static int nss_cmd_initgroups(struct cli_ctx *cctx)
-{
- struct nss_cmd_ctx *cmdctx;
- struct nss_dom_ctx *dctx;
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct nss_ctx *nctx;
- const char *rawname;
- char *domname;
- uint8_t *body;
- size_t blen;
- int ret;
- int ncret;
- bool neghit = false;
-
- nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
-
- cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
- if (!cmdctx) {
- return ENOMEM;
- }
- cmdctx->cctx = cctx;
-
- dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
- if (!dctx) {
- ret = ENOMEM;
- goto done;
- }
- dctx->cmdctx = cmdctx;
-
- /* get user name to query */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
-
- /* if not terminated fail */
- if (body[blen -1] != '\0') {
- ret = EINVAL;
- goto done;
- }
- rawname = (const char *)body;
-
- domname = NULL;
- ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
- &domname, &cmdctx->name);
- if (ret != EOK) {
- DEBUG(2, ("Invalid name received [%s]\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- DEBUG(4, ("Requesting info for [%s] from [%s]\n",
- cmdctx->name, domname ? : "<ALL>"));
-
- if (domname) {
- dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
- if (!dctx->domain) {
- ret = ENOENT;
- goto done;
- }
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- domname, cmdctx->name);
- if (ncret == EEXIST) {
- neghit = true;
- }
- }
- else {
- /* skip domains that require FQnames or have negative caches */
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
- /* verify this user has not yet been negatively cached,
- * or has been permanently filtered */
- ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
- }
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- dctx->domain = dom;
- }
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n", rawname));
- ret = ENOENT;
- goto done;
- }
- if (dctx->domain == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
- ret = ENOENT;
- goto done;
- }
-
- dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
-
- if (!domname) {
- /* this is a multidomain search */
- cmdctx->check_next = true;
- }
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- cmdctx->name, dctx->domain->name));
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- dctx->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- ret = EFAULT;
- goto done;
- }
- ret = sysdb_initgroups(cmdctx, sysdb,
- dctx->domain, cmdctx->name,
- nss_cmd_getinitgr_callback, dctx);
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
-
-done:
- if (ret != EOK) {
- if (ret == ENOENT) {
- /* we do not have any entry to return */
- ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret == EOK) {
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- ((uint32_t *)body)[0] = 0; /* 0 results */
- ((uint32_t *)body)[1] = 0; /* reserved */
- }
- }
- if (ret != EOK) {
- ret = nss_cmd_send_error(cmdctx, ret);
- }
- if (ret == EOK) {
- sss_cmd_done(cctx, cmdctx);
- }
- return ret;
- }
-
- return EOK;
-}
-
-struct cli_protocol_version *register_cli_protocol_version(void)
-{
- static struct cli_protocol_version nss_cli_protocol_version[] = {
- {1, "2008-09-05", "initial version, \\0 terminated strings"},
- {0, NULL, NULL}
- };
-
- return nss_cli_protocol_version;
-}
-
-static struct sss_cmd_table nss_cmds[] = {
- {SSS_GET_VERSION, sss_cmd_get_version},
- {SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
- {SSS_NSS_GETPWUID, nss_cmd_getpwuid},
- {SSS_NSS_SETPWENT, nss_cmd_setpwent},
- {SSS_NSS_GETPWENT, nss_cmd_getpwent},
- {SSS_NSS_ENDPWENT, nss_cmd_endpwent},
- {SSS_NSS_GETGRNAM, nss_cmd_getgrnam},
- {SSS_NSS_GETGRGID, nss_cmd_getgrgid},
- {SSS_NSS_SETGRENT, nss_cmd_setgrent},
- {SSS_NSS_GETGRENT, nss_cmd_getgrent},
- {SSS_NSS_ENDGRENT, nss_cmd_endgrent},
- {SSS_NSS_INITGR, nss_cmd_initgroups},
- {SSS_CLI_NULL, NULL}
-};
-
-struct sss_cmd_table *get_nss_cmds(void) {
- return nss_cmds;
-}
-
-int nss_cmd_execute(struct cli_ctx *cctx)
-{
- enum sss_cli_command cmd;
- int i;
-
- cmd = sss_packet_get_cmd(cctx->creq->in);
-
- for (i = 0; nss_cmds[i].cmd != SSS_CLI_NULL; i++) {
- if (cmd == nss_cmds[i].cmd) {
- return nss_cmds[i].fn(cctx);
- }
- }
-
- return EINVAL;
-}
-
diff --git a/server/responder/nss/nsssrv_nc.c b/server/responder/nss/nsssrv_nc.c
deleted file mode 100644
index 1fa7d612f..000000000
--- a/server/responder/nss/nsssrv_nc.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- SSSD
-
- NSS Responder
-
- 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 "util/util.h"
-#include <fcntl.h>
-#include <time.h>
-#include "tdb.h"
-
-#define NC_ENTRY_PREFIX "NCE/"
-#define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
-#define NC_GROUP_PREFIX NC_ENTRY_PREFIX"GROUP"
-#define NC_UID_PREFIX NC_ENTRY_PREFIX"UID"
-#define NC_GID_PREFIX NC_ENTRY_PREFIX"GID"
-
-struct nss_nc_ctx {
- struct tdb_context *tdb;
-};
-
-static int string_to_tdb_data(char *str, TDB_DATA *ret)
-{
- if (!str || !ret) return EINVAL;
-
- ret->dptr = (uint8_t *)str;
- ret->dsize = strlen(str)+1;
-
- return EOK;
-}
-
-int nss_ncache_init(TALLOC_CTX *memctx, struct nss_nc_ctx **_ctx)
-{
- struct nss_nc_ctx *ctx;
-
- ctx = talloc_zero(memctx, struct nss_nc_ctx);
- if (!ctx) return ENOMEM;
-
- errno = 0;
- /* open a memory only tdb with default hash size */
- ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
- if (!ctx->tdb) return errno;
-
- *_ctx = ctx;
- return EOK;
-};
-
-static int nss_ncache_check_str(struct nss_nc_ctx *ctx, char *str, int ttl)
-{
- TDB_DATA key;
- TDB_DATA data;
- unsigned long long int timestamp;
- bool expired = false;
- char *ep;
- int ret;
-
- ret = string_to_tdb_data(str, &key);
- if (ret != EOK) goto done;
-
- data = tdb_fetch(ctx->tdb, key);
-
- if (!data.dptr) {
- ret = ENOENT;
- goto done;
- }
-
- if (ttl == -1) {
- /* a negative ttl means: never expires */
- ret = EEXIST;
- goto done;
- }
-
- errno = 0;
- timestamp = strtoull((const char *)data.dptr, &ep, 0);
- if (errno != 0 || *ep != '\0') {
- /* Malformed entry, remove it and return no entry */
- expired = true;
- goto done;
- }
-
- if (timestamp == 0) {
- /* a 0 timestamp means this is a permanent entry */
- ret = EEXIST;
- goto done;
- }
-
- if (timestamp + ttl > time(NULL)) {
- /* still valid */
- ret = EEXIST;
- goto done;
- }
-
- expired = true;
-
-done:
- if (expired) {
- /* expired, remove and return no entry */
- tdb_delete(ctx->tdb, key);
- ret = ENOENT;
- }
-
- return ret;
-}
-
-static int nss_ncache_set_str(struct nss_nc_ctx *ctx,
- char *str, bool permanent)
-{
- TDB_DATA key;
- TDB_DATA data;
- char *timest;
- int ret;
-
- ret = string_to_tdb_data(str, &key);
- if (ret != EOK) return ret;
-
- if (permanent) {
- timest = talloc_strdup(ctx, "0");
- } else {
- timest = talloc_asprintf(ctx, "%llu",
- (unsigned long long int)time(NULL));
- }
- if (!timest) return ENOMEM;
-
- ret = string_to_tdb_data(timest, &data);
- if (ret != EOK) goto done;
-
- ret = tdb_store(ctx->tdb, key, data, TDB_REPLACE);
- if (ret != 0) {
- DEBUG(1, ("Negative cache failed to set entry: [%s]",
- tdb_errorstr(ctx->tdb)));
- ret = EFAULT;
- }
-
-done:
- talloc_free(timest);
- return ret;
-}
-
-int nss_ncache_check_user(struct nss_nc_ctx *ctx, int ttl,
- const char *domain, const char *name)
-{
- char *str;
- int ret;
-
- if (!name || !*name) return EINVAL;
-
- str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_check_str(ctx, str, ttl);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_check_group(struct nss_nc_ctx *ctx, int ttl,
- const char *domain, const char *name)
-{
- char *str;
- int ret;
-
- if (!name || !*name) return EINVAL;
-
- str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_check_str(ctx, str, ttl);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_check_uid(struct nss_nc_ctx *ctx, int ttl, uid_t uid)
-{
- char *str;
- int ret;
-
- str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_check_str(ctx, str, ttl);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_check_gid(struct nss_nc_ctx *ctx, int ttl, gid_t gid)
-{
- char *str;
- int ret;
-
- str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_check_str(ctx, str, ttl);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_set_user(struct nss_nc_ctx *ctx, bool permanent,
- const char *domain, const char *name)
-{
- char *str;
- int ret;
-
- if (!name || !*name) return EINVAL;
-
- str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_set_str(ctx, str, permanent);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_set_group(struct nss_nc_ctx *ctx, bool permanent,
- const char *domain, const char *name)
-{
- char *str;
- int ret;
-
- if (!name || !*name) return EINVAL;
-
- str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_set_str(ctx, str, permanent);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_set_uid(struct nss_nc_ctx *ctx, bool permanent, uid_t uid)
-{
- char *str;
- int ret;
-
- str = talloc_asprintf(ctx, "%s/%u", NC_UID_PREFIX, uid);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_set_str(ctx, str, permanent);
-
- talloc_free(str);
- return ret;
-}
-
-int nss_ncache_set_gid(struct nss_nc_ctx *ctx, bool permanent, gid_t gid)
-{
- char *str;
- int ret;
-
- str = talloc_asprintf(ctx, "%s/%u", NC_GID_PREFIX, gid);
- if (!str) return ENOMEM;
-
- ret = nss_ncache_set_str(ctx, str, permanent);
-
- talloc_free(str);
- return ret;
-}
-
-static int delete_permanent(struct tdb_context *tdb,
- TDB_DATA key, TDB_DATA data, void *state)
-{
- unsigned long long int timestamp;
- bool remove_key = false;
- char *ep;
-
- if (strncmp((char *)key.dptr,
- NC_ENTRY_PREFIX, sizeof(NC_ENTRY_PREFIX)) != 0) {
- /* not interested in this key */
- return 0;
- }
-
- errno = 0;
- timestamp = strtoull((const char *)data.dptr, &ep, 0);
- if (errno != 0 || *ep != '\0') {
- /* Malformed entry, remove it */
- remove_key = true;
- goto done;
- }
-
- if (timestamp == 0) {
- /* a 0 timestamp means this is a permanent entry */
- remove_key = true;
- }
-
-done:
- if (remove_key) {
- return tdb_delete(tdb, key);
- }
-
- return 0;
-}
-
-int nss_ncache_reset_permament(struct nss_nc_ctx *ctx)
-{
- int ret;
-
- ret = tdb_traverse(ctx->tdb, delete_permanent, NULL);
- if (ret < 0)
- return EIO;
-
- return EOK;
-}
diff --git a/server/responder/nss/nsssrv_nc.h b/server/responder/nss/nsssrv_nc.h
deleted file mode 100644
index c0fa197c2..000000000
--- a/server/responder/nss/nsssrv_nc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- SSSD
-
- NSS Responder
-
- 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 _NSS_NEG_CACHE_H_
-#define _NSS_NEG_CACHE_H_
-
-struct nss_nc_ctx;
-
-/* init the in memory negative cache */
-int nss_ncache_init(TALLOC_CTX *memctx, struct nss_nc_ctx **_ctx);
-
-/* check if the user is expired according to the passed in time to live */
-int nss_ncache_check_user(struct nss_nc_ctx *ctx, int ttl,
- const char *domain, const char *name);
-int nss_ncache_check_group(struct nss_nc_ctx *ctx, int ttl,
- const char *domain, const char *name);
-int nss_ncache_check_uid(struct nss_nc_ctx *ctx, int ttl, uid_t uid);
-int nss_ncache_check_gid(struct nss_nc_ctx *ctx, int ttl, gid_t gid);
-
-/* add a new neg-cache entry setting the timestamp to "now" unless
- * "permanent" is set to true, in which case the timestamps is set to 0
- * and the negative cache never expires (used to permanently filter out
- * users and groups) */
-int nss_ncache_set_user(struct nss_nc_ctx *ctx, bool permanent,
- const char *domain, const char *name);
-int nss_ncache_set_group(struct nss_nc_ctx *ctx, bool permanent,
- const char *domain, const char *name);
-int nss_ncache_set_uid(struct nss_nc_ctx *ctx, bool permanent, uid_t uid);
-int nss_ncache_set_gid(struct nss_nc_ctx *ctx, bool permanent, gid_t gid);
-
-int nss_ncache_reset_permament(struct nss_nc_ctx *ctx);
-
-#endif /* _NSS_NEG_CACHE_H_ */
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
deleted file mode 100644
index 34f0c8dd5..000000000
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- SSSD
-
- PAM e credentials
-
- 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 <time.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "util/sha512crypt.h"
-#include "providers/data_provider.h"
-#include "responder/pam/pamsrv.h"
-
-
-#define NULL_CHECK_OR_JUMP(var, msg, ret, err, label) do { \
- if (var == NULL) { \
- DEBUG(1, (msg)); \
- ret = (err); \
- goto label; \
- } \
-} while(0)
-
-#define NEQ_CHECK_OR_JUMP(var, val, msg, ret, err, label) do { \
- if (var != (val)) { \
- DEBUG(1, (msg)); \
- ret = (err); \
- goto label; \
- } \
-} while(0)
-
-
-struct LOCAL_request {
- struct tevent_context *ev;
- struct sysdb_ctx *dbctx;
- struct sysdb_attrs *mod_attrs;
- struct sysdb_handle *handle;
-
- struct ldb_result *res;
- int error;
-
- struct pam_auth_req *preq;
-};
-
-static void prepare_reply(struct LOCAL_request *lreq)
-{
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- if (lreq->error != EOK && pd->pam_status == PAM_SUCCESS)
- pd->pam_status = PAM_SYSTEM_ERR;
-
- lreq->preq->callback(lreq->preq);
-}
-
-static void set_user_attr_done(struct tevent_req *req)
-{
- struct LOCAL_request *lreq;
- int ret;
-
- lreq = tevent_req_callback_data(req, struct LOCAL_request);
-
- ret = sysdb_transaction_commit_recv(req);
- if (ret) {
- DEBUG(2, ("set_user_attr failed.\n"));
- lreq->error =ret;
- }
-
- prepare_reply(lreq);
-}
-
-static void set_user_attr_req_done(struct tevent_req *subreq);
-static void set_user_attr_req(struct tevent_req *req)
-{
- struct LOCAL_request *lreq = tevent_req_callback_data(req,
- struct LOCAL_request);
- struct tevent_req *subreq;
- int ret;
-
- DEBUG(4, ("entering set_user_attr_req\n"));
-
- ret = sysdb_transaction_recv(req, lreq, &lreq->handle);
- if (ret) {
- lreq->error = ret;
- return prepare_reply(lreq);
- }
-
- subreq = sysdb_set_user_attr_send(lreq, lreq->ev, lreq->handle,
- lreq->preq->domain,
- lreq->preq->pd->user,
- lreq->mod_attrs, SYSDB_MOD_REP);
- if (!subreq) {
- /* cancel transaction */
- talloc_zfree(lreq->handle);
- lreq->error = ret;
- return prepare_reply(lreq);
- }
- tevent_req_set_callback(subreq, set_user_attr_req_done, lreq);
-}
-
-static void set_user_attr_req_done(struct tevent_req *subreq)
-{
- struct LOCAL_request *lreq = tevent_req_callback_data(subreq,
- struct LOCAL_request);
- struct tevent_req *req;
- int ret;
-
- ret = sysdb_set_user_attr_recv(subreq);
- talloc_zfree(subreq);
-
- DEBUG(4, ("set_user_attr_callback, status [%d][%s]\n", ret, strerror(ret)));
-
- if (ret) {
- lreq->error = ret;
- goto fail;
- }
-
- req = sysdb_transaction_commit_send(lreq, lreq->ev, lreq->handle);
- if (!req) {
- lreq->error = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, set_user_attr_done, lreq);
-
- return;
-
-fail:
- DEBUG(2, ("set_user_attr failed.\n"));
-
- /* cancel transaction */
- talloc_zfree(lreq->handle);
-
- prepare_reply(lreq);
-}
-
-static void do_successful_login(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_LAST_LOGIN, (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0L);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-
-done:
-
- prepare_reply(lreq);
-}
-
-static void do_failed_login(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
- int failedLoginAttempts;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
- pd->pam_status = PAM_AUTH_ERR;
-/* TODO: maybe add more inteligent delay calculation */
- pd->response_delay = 3;
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_LAST_FAILED_LOGIN, (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- failedLoginAttempts = ldb_msg_find_attr_as_int(lreq->res->msgs[0],
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- 0);
- failedLoginAttempts++;
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- (long)failedLoginAttempts);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-
-done:
-
- prepare_reply(lreq);
-}
-
-static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
-{
- const char *disabled;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- disabled = ldb_msg_find_attr_as_string(lreq->res->msgs[0],
- SYSDB_DISABLED, NULL);
- if ((disabled != NULL) &&
- (strncasecmp(disabled, "false",5) != 0) &&
- (strncasecmp(disabled, "no",2) != 0) ) {
- pd->pam_status = PAM_PERM_DENIED;
- }
-
- prepare_reply(lreq);
-}
-
-static void do_pam_chauthtok(struct LOCAL_request *lreq)
-{
- struct tevent_req *req;
- int ret;
- char *newauthtok;
- char *salt;
- char *new_hash;
- struct pam_data *pd;
-
- pd = lreq->preq->pd;
-
- newauthtok = talloc_strndup(lreq, (char *) pd->newauthtok,
- pd->newauthtok_size);
- NULL_CHECK_OR_JUMP(newauthtok, ("talloc_strndup failed.\n"), lreq->error,
- ENOMEM, done);
- memset(pd->newauthtok, 0, pd->newauthtok_size);
-
- if (strlen(newauthtok) == 0) {
- /* TODO: should we allow null passwords via a config option ? */
- DEBUG(1, ("Empty passwords are not allowed!"));
- ret = EINVAL;
- goto done;
- }
-
- ret = s3crypt_gen_salt(lreq, &salt);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("Salt generation failed.\n"),
- lreq->error, ret, done);
- DEBUG(4, ("Using salt [%s]\n", salt));
-
- ret = s3crypt_sha512(lreq, newauthtok, salt, &new_hash);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
- lreq->error, ret, done);
- DEBUG(4, ("New hash [%s]\n", new_hash));
- memset(newauthtok, 0, pd->newauthtok_size);
-
- lreq->mod_attrs = sysdb_new_attrs(lreq);
- NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
- lreq->error, ENOMEM, done);
-
- ret = sysdb_attrs_add_string(lreq->mod_attrs, SYSDB_PWD, new_hash);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_string failed.\n"),
- lreq->error, ret, done);
-
- ret = sysdb_attrs_add_long(lreq->mod_attrs,
- "lastPasswordChange", (long)time(NULL));
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
- lreq->error, ret, done);
-
- req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
- if (!req) {
- lreq->error = ENOMEM;
- goto done;
- }
- tevent_req_set_callback(req, set_user_attr_req, lreq);
-
- return;
-done:
-
- prepare_reply(lreq);
-}
-
-static void local_handler_callback(void *pvt, int ldb_status,
- struct ldb_result *res)
-{
- struct LOCAL_request *lreq;
- const char *username = NULL;
- const char *password = NULL;
- char *newauthtok = NULL;
- char *new_hash = NULL;
- char *authtok = NULL;
- struct pam_data *pd;
- int ret;
-
- lreq = talloc_get_type(pvt, struct LOCAL_request);
- pd = lreq->preq->pd;
-
- DEBUG(4, ("pam_handler_callback called with ldb_status [%d].\n",
- ldb_status));
-
- NEQ_CHECK_OR_JUMP(ldb_status, LDB_SUCCESS, ("ldb search failed.\n"),
- lreq->error, sysdb_error_to_errno(ldb_status), done);
-
-
- if (res->count < 1) {
- DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n",
- pd->user));
- pd->pam_status = PAM_USER_UNKNOWN;
- goto done;
- } else if (res->count > 1) {
- DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n"));
- lreq->error = EFAULT;
- goto done;
- }
-
- username = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
- if (strcmp(username, pd->user) != 0) {
- DEBUG(1, ("Expected username [%s] get [%s].\n", pd->user, username));
- lreq->error = EINVAL;
- goto done;
- }
-
- lreq->res = res;
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- case SSS_PAM_CHAUTHTOK:
- case SSS_PAM_CHAUTHTOK_PRELIM:
- if ((pd->cmd == SSS_PAM_CHAUTHTOK ||
- pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) &&
- lreq->preq->cctx->priv == 1) {
-/* TODO: maybe this is a candiate for an explicit audit message. */
- DEBUG(4, ("allowing root to reset a password.\n"));
- break;
- }
- authtok = talloc_strndup(lreq, (char *) pd->authtok,
- pd->authtok_size);
- NULL_CHECK_OR_JUMP(authtok, ("talloc_strndup failed.\n"),
- lreq->error, ENOMEM, done);
- memset(pd->authtok, 0, pd->authtok_size);
-
- password = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PWD, NULL);
- NULL_CHECK_OR_JUMP(password, ("No password stored.\n"),
- lreq->error, LDB_ERR_NO_SUCH_ATTRIBUTE, done);
- DEBUG(4, ("user: [%s], password hash: [%s]\n", username, password));
-
- ret = s3crypt_sha512(lreq, authtok, password, &new_hash);
- memset(authtok, 0, pd->authtok_size);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("nss_sha512_crypt failed.\n"),
- lreq->error, ret, done);
-
- DEBUG(4, ("user: [%s], new hash: [%s]\n", username, new_hash));
-
- if (strcmp(new_hash, password) != 0) {
- DEBUG(1, ("Passwords do not match.\n"));
- do_failed_login(lreq);
- return;
- }
-
- break;
- }
-
- switch (pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- do_successful_login(lreq);
- return;
- break;
- case SSS_PAM_CHAUTHTOK:
- do_pam_chauthtok(lreq);
- return;
- break;
- case SSS_PAM_ACCT_MGMT:
- do_pam_acct_mgmt(lreq);
- return;
- break;
- case SSS_PAM_SETCRED:
- break;
- case SSS_PAM_OPEN_SESSION:
- break;
- case SSS_PAM_CLOSE_SESSION:
- break;
- case SSS_PAM_CHAUTHTOK_PRELIM:
- break;
- default:
- lreq->error = EINVAL;
- DEBUG(1, ("Unknown PAM task [%d].\n"));
- }
-
-done:
- if (pd->authtok != NULL)
- memset(pd->authtok, 0, pd->authtok_size);
- if (authtok != NULL)
- memset(authtok, 0, pd->authtok_size);
- if (pd->newauthtok != NULL)
- memset(pd->newauthtok, 0, pd->newauthtok_size);
- if (newauthtok != NULL)
- memset(newauthtok, 0, pd->newauthtok_size);
-
- prepare_reply(lreq);
-}
-
-int LOCAL_pam_handler(struct pam_auth_req *preq)
-{
- int ret;
- struct LOCAL_request *lreq;
-
- static const char *attrs[] = {SYSDB_NAME,
- SYSDB_PWD,
- SYSDB_DISABLED,
- SYSDB_LAST_LOGIN,
- "lastPasswordChange",
- "accountExpires",
- SYSDB_FAILED_LOGIN_ATTEMPTS,
- "passwordHint",
- "passwordHistory",
- SYSDB_LAST_FAILED_LOGIN,
- NULL};
-
- DEBUG(4, ("LOCAL pam handler.\n"));
-
- lreq = talloc_zero(preq, struct LOCAL_request);
- if (!lreq) {
- return ENOMEM;
- }
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &lreq->dbctx);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- talloc_free(lreq);
- return ret;
- }
- lreq->ev = preq->cctx->ev;
- lreq->preq = preq;
-
- preq->pd->pam_status = PAM_SUCCESS;
-
- ret = sysdb_get_user_attr(lreq, lreq->dbctx,
- preq->domain, preq->pd->user, attrs,
- local_handler_callback, lreq);
-
- if (ret != EOK) {
- DEBUG(1, ("sysdb_get_user_attr failed.\n"));
- talloc_free(lreq);
- return ret;
- }
-
- return EOK;
-}
diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c
deleted file mode 100644
index 84b13dc45..000000000
--- a/server/responder/pam/pamsrv.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- SSSD
-
- PAM Responder
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
- 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 <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 "popt.h"
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "dbus/dbus.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "monitor/monitor_interfaces.h"
-#include "sbus/sbus_client.h"
-#include "responder/pam/pamsrv.h"
-
-#define SSS_PAM_SBUS_SERVICE_VERSION 0x0001
-#define SSS_PAM_SBUS_SERVICE_NAME "pam"
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn);
-
-struct sbus_method monitor_pam_methods[] = {
- { MON_CLI_METHOD_PING, monitor_common_pong },
- { MON_CLI_METHOD_RELOAD, service_reload },
- { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
- { NULL, NULL }
-};
-
-struct sbus_interface monitor_pam_interface = {
- MONITOR_INTERFACE,
- MONITOR_PATH,
- SBUS_DEFAULT_VTABLE,
- monitor_pam_methods,
- NULL
-};
-
-static int service_reload(DBusMessage *message, struct sbus_connection *conn) {
- /* Monitor calls this function when we need to reload
- * our configuration information. Perform whatever steps
- * are needed to update the configuration objects.
- */
-
- /* Send an empty reply to acknowledge receipt */
- return monitor_common_pong(message, conn);
-}
-
-static struct sbus_method pam_dp_methods[] = {
- { NULL, NULL }
-};
-
-struct sbus_interface pam_dp_interface = {
- DP_INTERFACE,
- DP_PATH,
- SBUS_DEFAULT_VTABLE,
- pam_dp_methods,
- NULL
-};
-
-
-static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void *pvt)
-{
- struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
- int ret;
-
- /* Did we reconnect successfully? */
- if (status == SBUS_RECONNECT_SUCCESS) {
- DEBUG(1, ("Reconnected to the Data Provider.\n"));
-
- /* Identify ourselves to the data provider */
- ret = dp_common_send_id(be_conn->conn,
- DATA_PROVIDER_VERSION,
- "PAM", be_conn->domain->name);
- /* all fine */
- if (ret == EOK) return;
- }
-
- /* Handle failure */
- DEBUG(0, ("Could not reconnect to %s provider.\n",
- be_conn->domain->name));
-
- /* FIXME: kill the frontend and let the monitor restart it ? */
- /* pam_shutdown(rctx); */
-}
-
-static errno_t pam_get_config(struct pam_ctx *pctx,
- struct resp_ctx *rctx,
- struct confdb_ctx *cdb)
-{
- int ret = EOK;
- ret = confdb_get_int(cdb, pctx, CONFDB_PAM_CONF_ENTRY,
- CONFDB_PAM_CRED_TIMEOUT, 0,
- &pctx->cred_expiration);
- return ret;
-}
-
-static int pam_process_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb)
-{
- struct sss_cmd_table *pam_cmds;
- struct be_conn *iter;
- struct pam_ctx *pctx;
- int ret, max_retries;
-
- pctx = talloc_zero(mem_ctx, struct pam_ctx);
- if (!pctx) {
- return ENOMEM;
- }
-
- pam_cmds = get_pam_cmds();
- ret = sss_process_init(pctx, ev, cdb,
- pam_cmds,
- SSS_PAM_SOCKET_NAME,
- SSS_PAM_PRIV_SOCKET_NAME,
- CONFDB_PAM_CONF_ENTRY,
- SSS_PAM_SBUS_SERVICE_NAME,
- SSS_PAM_SBUS_SERVICE_VERSION,
- &monitor_pam_interface,
- "PAM", &pam_dp_interface,
- &pctx->rctx);
- if (ret != EOK) {
- return ret;
- }
-
- pctx->rctx->pvt_ctx = pctx;
- ret = pam_get_config(pctx, pctx->rctx, pctx->rctx->cdb);
-
- /* Enable automatic reconnection to the Data Provider */
-
- /* FIXME: "retries" is too generic, either get it from a global config
- * or specify these retries are about the sbus connections to DP */
- ret = confdb_get_int(pctx->rctx->cdb, pctx->rctx, CONFDB_PAM_CONF_ENTRY,
- CONFDB_SERVICE_RECON_RETRIES, 3, &max_retries);
- if (ret != EOK) {
- DEBUG(0, ("Failed to set up automatic reconnection\n"));
- return ret;
- }
-
- for (iter = pctx->rctx->be_conns; iter; iter = iter->next) {
- sbus_reconnect_init(iter->conn, max_retries,
- pam_dp_reconnect_init, iter);
- }
-
- return EOK;
-}
-
-int main(int argc, const char *argv[])
-{
- int opt;
- poptContext pc;
- struct main_context *main_ctx;
- int ret;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- SSSD_MAIN_OPTS
- { NULL }
- };
-
- 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;
- }
- }
-
- poptFreeContext(pc);
-
- /* set up things like debug, signals, daemonization, etc... */
- debug_log_file = "sssd_pam";
-
- ret = server_setup("sssd[pam]", 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
- if (ret != EOK) 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 = pam_process_init(main_ctx,
- main_ctx->event_ctx,
- main_ctx->confdb_ctx);
- if (ret != EOK) return 3;
-
- /* loop on main */
- server_loop(main_ctx);
-
- return 0;
-}
-
diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h
deleted file mode 100644
index 60f9c66ae..000000000
--- a/server/responder/pam/pamsrv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Authors:
- Simo Sorce <ssorce@redhat.com>
- 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 __PAMSRV_H__
-#define __PAMSRV_H__
-
-#include <security/pam_appl.h>
-#include "util/util.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder.h"
-
-struct pam_auth_req;
-
-typedef void (pam_dp_callback_t)(struct pam_auth_req *preq);
-
-struct pam_ctx {
- int cred_expiration;
- struct resp_ctx *rctx;
-};
-
-struct pam_auth_req {
- struct cli_ctx *cctx;
- struct sss_domain_info *domain;
-
- struct pam_data *pd;
-
- pam_dp_callback_t *callback;
-
- bool check_provider;
- void *data;
-};
-
-struct sss_cmd_table *get_pam_cmds(void);
-
-int pam_dp_send_req(struct pam_auth_req *preq, int timeout);
-
-int LOCAL_pam_handler(struct pam_auth_req *preq);
-
-#endif /* __PAMSRV_H__ */
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
deleted file mode 100644
index 37aad8299..000000000
--- a/server/responder/pam/pamsrv_cmd.c
+++ /dev/null
@@ -1,1181 +0,0 @@
-/*
- SSSD
-
- PAM Responder
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
- 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 <time.h>
-#include "util/util.h"
-#include "db/sysdb.h"
-#include "confdb/confdb.h"
-#include "responder/common/responder_packet.h"
-#include "responder/common/responder.h"
-#include "providers/data_provider.h"
-#include "responder/pam/pamsrv.h"
-#include "db/sysdb.h"
-
-static void pam_reply(struct pam_auth_req *preq);
-
-static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok, uint8_t *body, size_t blen, size_t *c) {
- uint32_t data_size;
-
- if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;
-
- memcpy(&data_size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
- if (data_size < sizeof(uint32_t) || (*c)+(data_size) > blen) return EINVAL;
- *size = data_size - sizeof(uint32_t);
-
- memcpy(type, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- *tok = body+(*c);
-
- *c += (*size);
-
- return EOK;
-}
-
-static int extract_string(char **var, uint8_t *body, size_t blen, size_t *c) {
- uint32_t size;
- uint8_t *str;
-
- if (blen-(*c) < sizeof(uint32_t)+1) return EINVAL;
-
- memcpy(&size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
- if (*c+size > blen) return EINVAL;
-
- str = body+(*c);
-
- if (str[size-1]!='\0') return EINVAL;
-
- *c += size;
-
- *var = (char *) str;
-
- return EOK;
-}
-
-static int extract_uint32_t(uint32_t *var, uint8_t *body, size_t blen, size_t *c) {
- uint32_t size;
-
- if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;
-
- memcpy(&size, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- memcpy(var, &body[*c], sizeof(uint32_t));
- *c += sizeof(uint32_t);
-
- return EOK;
-}
-
-static int pam_parse_in_data_v2(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- size_t c;
- uint32_t type;
- uint32_t size;
- char *pam_user;
- int ret;
- uint32_t terminator = SSS_END_OF_PAM_REQUEST;
-
- if (blen < 4*sizeof(uint32_t)+2 ||
- ((uint32_t *)body)[0] != SSS_START_OF_PAM_REQUEST ||
- memcmp(&body[blen - sizeof(uint32_t)], &terminator, sizeof(uint32_t)) != 0) {
- DEBUG(1, ("Received data is invalid.\n"));
- return EINVAL;
- }
-
- c = sizeof(uint32_t);
- do {
- memcpy(&type, &body[c], sizeof(uint32_t));
- c += sizeof(uint32_t);
- if (c > blen) return EINVAL;
-
- switch(type) {
- case SSS_PAM_ITEM_USER:
- ret = extract_string(&pam_user, body, blen, &c);
- if (ret != EOK) return ret;
-
- ret = sss_parse_name(pd, snctx, pam_user,
- &pd->domain, &pd->user);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_SERVICE:
- ret = extract_string(&pd->service, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_TTY:
- ret = extract_string(&pd->tty, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_RUSER:
- ret = extract_string(&pd->ruser, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_RHOST:
- ret = extract_string(&pd->rhost, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_CLI_PID:
- ret = extract_uint32_t(&pd->cli_pid,
- body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_AUTHTOK:
- ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,
- &pd->authtok, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_PAM_ITEM_NEWAUTHTOK:
- ret = extract_authtok(&pd->newauthtok_type,
- &pd->newauthtok_size,
- &pd->newauthtok, body, blen, &c);
- if (ret != EOK) return ret;
- break;
- case SSS_END_OF_PAM_REQUEST:
- if (c != blen) return EINVAL;
- break;
- default:
- DEBUG(1,("Ignoring unknown data type [%d].\n", type));
- size = ((uint32_t *)&body[c])[0];
- c += size+sizeof(uint32_t);
- }
- } while(c < blen);
-
- if (pd->user == NULL || *pd->user == '\0') return EINVAL;
-
- DEBUG_PAM_DATA(4, pd);
-
- return EOK;
-
-}
-
-static int pam_parse_in_data_v3(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- int ret;
-
- ret = pam_parse_in_data_v2(snctx, pd, body, blen);
- if (ret != EOK) {
- DEBUG(1, ("pam_parse_in_data_v2 failed.\n"));
- return ret;
- }
-
- if (pd->cli_pid == 0) {
- DEBUG(1, ("Missing client PID.\n"));
- return EINVAL;
- }
-
- return EOK;
-}
-
-static int pam_parse_in_data(struct sss_names_ctx *snctx,
- struct pam_data *pd,
- uint8_t *body, size_t blen)
-{
- int start;
- int end;
- int last;
- int ret;
-
- last = blen - 1;
- end = 0;
-
- /* user name */
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
-
- ret = sss_parse_name(pd, snctx, (char *)&body[start], &pd->domain, &pd->user);
- if (ret != EOK) return ret;
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->service = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->tty = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->ruser = (char *) &body[start];
-
- for (start = end; end < last; end++) if (body[end] == '\0') break;
- if (body[end++] != '\0') return EINVAL;
- pd->rhost = (char *) &body[start];
-
- start = end;
- pd->authtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->authtok_size = (int) body[start];
-
- start += sizeof(uint32_t);
- end = start + pd->authtok_size;
- if (pd->authtok_size == 0) {
- pd->authtok = NULL;
- } else {
- if (end <= blen) {
- pd->authtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid authtok size: %d\n", pd->authtok_size));
- return EINVAL;
- }
- }
-
- start = end;
- pd->newauthtok_type = (int) body[start];
-
- start += sizeof(uint32_t);
- pd->newauthtok_size = (int) body[start];
-
- start += sizeof(uint32_t);
- end = start + pd->newauthtok_size;
-
- if (pd->newauthtok_size == 0) {
- pd->newauthtok = NULL;
- } else {
- if (end <= blen) {
- pd->newauthtok = (uint8_t *) &body[start];
- } else {
- DEBUG(1, ("Invalid newauthtok size: %d\n", pd->newauthtok_size));
- return EINVAL;
- }
- }
-
- DEBUG_PAM_DATA(4, pd);
-
- return EOK;
-}
-
-/*=Save-Last-Login-State===================================================*/
-
-struct set_last_login_state {
- struct tevent_context *ev;
- struct sysdb_ctx *dbctx;
-
- struct sss_domain_info *dom;
- const char *username;
- struct sysdb_attrs *attrs;
-
- struct sysdb_handle *handle;
-
- struct ldb_result *res;
-};
-
-static void set_last_login_trans_done(struct tevent_req *subreq);
-static void set_last_login_attrs_done(struct tevent_req *subreq);
-static void set_last_login_done(struct tevent_req *subreq);
-
-static struct tevent_req *set_last_login_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sysdb_ctx *dbctx,
- struct sss_domain_info *dom,
- const char *username,
- struct sysdb_attrs *attrs)
-{
- struct tevent_req *req, *subreq;
- struct set_last_login_state *state;
-
- req = tevent_req_create(memctx, &state, struct set_last_login_state);
- if (!req) {
- return NULL;
- }
-
- state->ev = ev;
- state->dbctx = dbctx;
- state->dom = dom;
- state->username = username;
- state->attrs = attrs;
- state->handle = NULL;
-
- subreq = sysdb_transaction_send(state, state->ev, state->dbctx);
- if (!subreq) {
- talloc_free(req);
- return NULL;
- }
- tevent_req_set_callback(subreq, set_last_login_trans_done, req);
-
- return req;
-}
-
-static void set_last_login_trans_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct set_last_login_state *state = tevent_req_data(req,
- struct set_last_login_state);
- int ret;
-
- ret = sysdb_transaction_recv(subreq, state, &state->handle);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(1, ("Unable to acquire sysdb transaction lock\n"));
- tevent_req_error(req, ret);
- return;
- }
-
- subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
- state->dom, state->username,
- state->attrs, SYSDB_MOD_REP);
- if (!subreq) {
- tevent_req_error(req, ENOMEM);
- return;
- }
- tevent_req_set_callback(subreq, set_last_login_attrs_done, req);
-}
-
-static void set_last_login_attrs_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct set_last_login_state *state = tevent_req_data(req,
- struct set_last_login_state);
- int ret;
-
- ret = sysdb_set_user_attr_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(4, ("set_user_attr_callback, status [%d][%s]\n",
- ret, strerror(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, set_last_login_done, req);
-}
-
-static void set_last_login_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);
- if (ret != EOK) {
- DEBUG(2, ("set_last_login failed.\n"));
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static int set_last_login_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-/*=========================================================================*/
-
-
-static void set_last_login_reply(struct tevent_req *req);
-
-static errno_t set_last_login(struct pam_auth_req *preq)
-{
- struct tevent_req *req;
- struct sysdb_ctx *dbctx;
- struct sysdb_attrs *attrs;
- errno_t ret;
-
- attrs = sysdb_new_attrs(preq);
- if (!attrs) {
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_ONLINE_AUTH, time(NULL));
- if (ret != EOK) {
- goto fail;
- }
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, preq->domain,
- &dbctx);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb context not found for this domain!\n"));
- goto fail;
- }
-
- req = set_last_login_send(preq, preq->cctx->ev, dbctx,
- preq->domain, preq->pd->user, attrs);
- if (!req) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(req, set_last_login_reply, preq);
-
- return EOK;
-
-fail:
- return ret;
-}
-
-static void set_last_login_reply(struct tevent_req *req)
-{
- struct pam_auth_req *preq = tevent_req_callback_data(req,
- struct pam_auth_req);
- int ret;
-
- ret = set_last_login_recv(req);
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- } else {
- preq->pd->last_auth_saved = true;
- }
-
- preq->callback(preq);
-}
-
-static void pam_reply_delay(struct tevent_context *ev, struct tevent_timer *te,
- struct timeval tv, void *pvt)
-{
- struct pam_auth_req *preq;
-
- DEBUG(4, ("pam_reply_delay get called.\n"));
-
- preq = talloc_get_type(pvt, struct pam_auth_req);
-
- pam_reply(preq);
-}
-
-static void pam_cache_auth_done(struct tevent_req *req);
-
-static void pam_reply(struct pam_auth_req *preq)
-{
- struct cli_ctx *cctx;
- uint8_t *body;
- size_t blen;
- int ret;
- int32_t resp_c;
- int32_t resp_size;
- struct response_data *resp;
- int p;
- struct timeval tv;
- struct tevent_timer *te;
- struct pam_data *pd;
- struct tevent_req *req;
- struct sysdb_ctx *sysdb;
- struct pam_ctx *pctx;
- uint32_t user_info_type;
-
- pd = preq->pd;
- cctx = preq->cctx;
-
- DEBUG(4, ("pam_reply get called.\n"));
-
- if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
- switch(pd->cmd) {
- case SSS_PAM_AUTHENTICATE:
- if ((preq->domain != NULL) &&
- (preq->domain->cache_credentials == true) &&
- (pd->offline_auth == false)) {
-
- /* do auth with offline credentials */
- pd->offline_auth = true;
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for "
- "domain [%s]!\n", preq->domain->name));
- goto done;
- }
-
- pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx,
- struct pam_ctx);
-
- req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb,
- preq->domain, pd->user,
- pd->authtok, pd->authtok_size,
- pctx->rctx->cdb);
- if (req == NULL) {
- DEBUG(1, ("Failed to setup offline auth.\n"));
- /* this error is not fatal, continue */
- } else {
- tevent_req_set_callback(req, pam_cache_auth_done, preq);
- return;
- }
- }
- break;
- case SSS_PAM_CHAUTHTOK_PRELIM:
- case SSS_PAM_CHAUTHTOK:
- DEBUG(5, ("Password change not possible while offline.\n"));
- pd->pam_status = PAM_AUTHTOK_ERR;
- user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
- pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
- (const uint8_t *) &user_info_type);
- break;
-/* TODO: we need the pam session cookie here to make sure that cached
- * authentication was successful */
- case SSS_PAM_SETCRED:
- case SSS_PAM_ACCT_MGMT:
- case SSS_PAM_OPEN_SESSION:
- case SSS_PAM_CLOSE_SESSION:
- DEBUG(2, ("Assuming offline authentication setting status for "
- "pam call %d to PAM_SUCCESS.\n", pd->cmd));
- pd->pam_status = PAM_SUCCESS;
- break;
- default:
- DEBUG(1, ("Unknown PAM call [%d].\n", pd->cmd));
- pd->pam_status = PAM_MODULE_UNKNOWN;
- }
- }
-
- if (pd->response_delay > 0) {
- ret = gettimeofday(&tv, NULL);
- if (ret != EOK) {
- DEBUG(1, ("gettimeofday failed [%d][%s].\n",
- errno, strerror(errno)));
- goto done;
- }
- tv.tv_sec += pd->response_delay;
- tv.tv_usec = 0;
- pd->response_delay = 0;
-
- te = tevent_add_timer(cctx->ev, cctx, tv, pam_reply_delay, preq);
- if (te == NULL) {
- DEBUG(1, ("Failed to add event pam_reply_delay.\n"));
- goto done;
- }
-
- return;
- }
-
- /* If this was a successful login, save the lastLogin time */
- if (pd->cmd == SSS_PAM_AUTHENTICATE &&
- pd->pam_status == PAM_SUCCESS &&
- preq->domain->cache_credentials &&
- !pd->offline_auth &&
- !pd->last_auth_saved &&
- NEED_CHECK_PROVIDER(preq->domain->provider)) {
- ret = set_last_login(preq);
- if (ret != EOK) {
- goto done;
- }
-
- return;
- }
-
- ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- goto done;
- }
-
- if (pd->domain != NULL) {
- pam_add_response(pd, SSS_PAM_DOMAIN_NAME, strlen(pd->domain)+1,
- (uint8_t *) pd->domain);
- }
-
- resp_c = 0;
- resp_size = 0;
- resp = pd->resp_list;
- while(resp != NULL) {
- resp_c++;
- resp_size += resp->len;
- resp = resp->next;
- }
-
- ret = sss_packet_grow(cctx->creq->out, sizeof(int32_t) +
- sizeof(int32_t) +
- resp_c * 2* sizeof(int32_t) +
- resp_size);
- if (ret != EOK) {
- goto done;
- }
-
- sss_packet_get_body(cctx->creq->out, &body, &blen);
- DEBUG(4, ("blen: %d\n", blen));
- p = 0;
-
- memcpy(&body[p], &pd->pam_status, sizeof(int32_t));
- p += sizeof(int32_t);
-
- memcpy(&body[p], &resp_c, sizeof(int32_t));
- p += sizeof(int32_t);
-
- resp = pd->resp_list;
- while(resp != NULL) {
- memcpy(&body[p], &resp->type, sizeof(int32_t));
- p += sizeof(int32_t);
- memcpy(&body[p], &resp->len, sizeof(int32_t));
- p += sizeof(int32_t);
- memcpy(&body[p], resp->data, resp->len);
- p += resp->len;
-
- resp = resp->next;
- }
-
-done:
- sss_cmd_done(cctx, preq);
-}
-
-static void pam_cache_auth_done(struct tevent_req *req)
-{
- int ret;
- struct pam_auth_req *preq = tevent_req_callback_data(req,
- struct pam_auth_req);
- uint32_t resp_type;
- size_t resp_len;
- uint8_t *resp;
- time_t expire_date = 0;
- time_t delayed_until = -1;
- long long dummy;
-
- ret = sysdb_cache_auth_recv(req, &expire_date, &delayed_until);
- talloc_zfree(req);
-
- switch (ret) {
- case EOK:
- preq->pd->pam_status = PAM_SUCCESS;
-
- resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH;
- resp_len = sizeof(uint32_t) + sizeof(long long);
- resp = talloc_size(preq->pd, resp_len);
- if (resp == NULL) {
- DEBUG(1, ("talloc_size failed, cannot prepare user info.\n"));
- } else {
- memcpy(resp, &resp_type, sizeof(uint32_t));
- dummy = (long long) expire_date;
- memcpy(resp+sizeof(uint32_t), &dummy, sizeof(long long));
- ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
- (const uint8_t *) resp);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- }
- break;
- case ENOENT:
- preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
- break;
- case EINVAL:
- preq->pd->pam_status = PAM_AUTH_ERR;
- break;
- case EACCES:
- preq->pd->pam_status = PAM_PERM_DENIED;
- if (delayed_until >= 0) {
- resp_type = SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED;
- resp_len = sizeof(uint32_t) + sizeof(long long);
- resp = talloc_size(preq->pd, resp_len);
- if (resp == NULL) {
- DEBUG(1, ("talloc_size failed, cannot prepare user info.\n"));
- } else {
- memcpy(resp, &resp_type, sizeof(uint32_t));
- dummy = (long long) delayed_until;
- memcpy(resp+sizeof(uint32_t), &dummy, sizeof(long long));
- ret = pam_add_response(preq->pd, SSS_PAM_USER_INFO, resp_len,
- (const uint8_t *) resp);
- if (ret != EOK) {
- DEBUG(1, ("pam_add_response failed.\n"));
- }
- }
- }
- break;
- default:
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
-
- pam_reply(preq);
- return;
-}
-
-static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
-static void pam_check_user_callback(void *ptr, int status,
- struct ldb_result *res);
-static void pam_dom_forwarder(struct pam_auth_req *preq);
-
-/* TODO: we should probably return some sort of cookie that is set in the
- * PAM_ENVIRONMENT, so that we can save performing some calls and cache
- * data. */
-
-static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-{
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- struct pam_auth_req *preq;
- struct pam_data *pd;
- uint8_t *body;
- size_t blen;
- int timeout;
- int ret;
- uint32_t terminator = SSS_END_OF_PAM_REQUEST;
- preq = talloc_zero(cctx, struct pam_auth_req);
- if (!preq) {
- return ENOMEM;
- }
- preq->cctx = cctx;
-
- preq->pd = talloc_zero(preq, struct pam_data);
- if (!preq->pd) {
- talloc_free(preq);
- return ENOMEM;
- }
- pd = preq->pd;
-
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen >= sizeof(uint32_t) &&
- memcmp(&body[blen - sizeof(uint32_t)], &terminator, sizeof(uint32_t)) != 0) {
- DEBUG(1, ("Received data not terminated.\n"));
- ret = EINVAL;
- goto done;
- }
-
- pd->cmd = pam_cmd;
- pd->priv = cctx->priv;
-
- switch (cctx->cli_protocol_version->version) {
- case 1:
- ret = pam_parse_in_data(cctx->rctx->names, pd, body, blen);
- break;
- case 2:
- ret = pam_parse_in_data_v2(cctx->rctx->names, pd, body, blen);
- break;
- case 3:
- ret = pam_parse_in_data_v3(cctx->rctx->names, pd, body, blen);
- break;
- default:
- DEBUG(1, ("Illegal protocol version [%d].\n",
- cctx->cli_protocol_version->version));
- ret = EINVAL;
- }
- if (ret != EOK) {
- ret = EINVAL;
- goto done;
- }
-
- /* now check user is valid */
- if (pd->domain) {
- for (dom = cctx->rctx->domains; dom; dom = dom->next) {
- if (strcasecmp(dom->name, pd->domain) == 0) break;
- }
- if (!dom) {
- ret = ENOENT;
- goto done;
- }
- preq->domain = dom;
- }
- else {
- for (dom = preq->cctx->rctx->domains; dom; dom = dom->next) {
- if (dom->fqnames) continue;
-
-/* FIXME: need to support negative cache */
-#if HAVE_NEG_CACHE
- ncret = sss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-#endif
- break;
- }
- if (!dom) {
- ret = ENOENT;
- goto done;
- }
- preq->domain = dom;
- }
-
- if (preq->domain->provider == NULL) {
- DEBUG(1, ("Domain [%s] has no auth provider.\n", preq->domain->name));
- ret = EINVAL;
- goto done;
- }
-
- /* When auth is requested always search the provider first,
- * do not rely on cached data unless the provider is completely
- * offline */
- if (NEED_CHECK_PROVIDER(preq->domain->provider) &&
- (pam_cmd == SSS_PAM_AUTHENTICATE || pam_cmd == SSS_PAM_SETCRED)) {
-
- /* no need to re-check later on */
- preq->check_provider = false;
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback, preq,
- timeout, preq->domain->name,
- false, SSS_DP_INITGROUPS,
- preq->pd->user, 0);
- }
- else {
- preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
-
- ret = sysdb_get_ctx_from_list(cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- goto done;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
- }
-
-done:
- if (ret != EOK) {
- switch (ret) {
- case ENOENT:
- pd->pam_status = PAM_USER_UNKNOWN;
- default:
- pd->pam_status = PAM_SYSTEM_ERR;
- }
- pam_reply(preq);
- }
- return EOK;
-}
-
-static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
-{
- struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req);
- struct sysdb_ctx *sysdb;
- int ret;
-
- if (err_maj) {
- DEBUG(2, ("Unable to get information from Data Provider\n"
- "Error: %u, %u, %s\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg));
- }
-
- /* always try to see if we have the user in cache even if the provider
- * returned an error */
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- goto done;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
-
-done:
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static void pam_check_user_callback(void *ptr, int status,
- struct ldb_result *res)
-{
- struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req);
- struct sss_domain_info *dom;
- struct sysdb_ctx *sysdb;
- uint64_t cacheExpire;
- bool call_provider = false;
- time_t timeout;
- int ret;
-
- if (status != LDB_SUCCESS) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
-
- timeout = SSS_CLI_SOCKET_TIMEOUT/2;
-
- if (preq->check_provider) {
- switch (res->count) {
- case 0:
- call_provider = true;
- break;
-
- case 1:
- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
- SYSDB_CACHE_EXPIRE, 0);
- if (cacheExpire < time(NULL)) {
- call_provider = true;
- }
- break;
-
- default:
- DEBUG(1, ("check user call returned more than one result !?!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
- }
-
- if (call_provider) {
-
- /* dont loop forever :-) */
- preq->check_provider = false;
-
- /* keep around current data in case backend is offline */
- if (res->count) {
- preq->data = talloc_steal(preq, res);
- }
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback, preq,
- timeout, preq->domain->name,
- false, SSS_DP_USER,
- preq->pd->user, 0);
- if (ret != EOK) {
- DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
- ret, strerror(ret)));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
- return;
- }
-
- switch (res->count) {
- case 0:
- if (!preq->pd->domain) {
- /* search next as the domain was unknown */
-
- ret = EOK;
-
- /* skip domains that require FQnames or have negative caches */
- for (dom = preq->domain->next; dom; dom = dom->next) {
-
- if (dom->fqnames) continue;
-
-#if HAVE_NEG_CACHE
- ncret = nss_ncache_check_user(nctx->ncache,
- nctx->neg_timeout,
- dom->name, cmdctx->name);
- if (ncret == ENOENT) break;
-
- neghit = true;
-#endif
- break;
- }
-#if HAVE_NEG_CACHE
- /* reset neghit if we still have a domain to check */
- if (dom) neghit = false;
-
- if (neghit) {
- DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
- cmdctx->name));
- ret = ENOENT;
- }
-#endif
- if (dom == NULL) {
- DEBUG(2, ("No matching domain found for [%s], fail!\n",
- preq->pd->user));
- ret = ENOENT;
- }
-
- if (ret == EOK) {
- preq->domain = dom;
- preq->data = NULL;
-
- DEBUG(4, ("Requesting info for [%s@%s]\n",
- preq->pd->user, preq->domain->name));
-
- /* When auth is requested always search the provider first,
- * do not rely on cached data unless the provider is
- * completely offline */
- if (NEED_CHECK_PROVIDER(preq->domain->provider) &&
- (preq->pd->cmd == SSS_PAM_AUTHENTICATE ||
- preq->pd->cmd == SSS_PAM_SETCRED)) {
-
- /* no need to re-check later on */
- preq->check_provider = false;
-
- ret = sss_dp_send_acct_req(preq->cctx->rctx, preq,
- pam_check_user_dp_callback,
- preq, timeout,
- preq->domain->name,
- false, SSS_DP_USER,
- preq->pd->user, 0);
- }
- else {
- preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider);
-
- ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
- preq->domain, &sysdb);
- if (ret != EOK) {
- DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- return;
- }
- ret = sysdb_getpwnam(preq, sysdb,
- preq->domain, preq->pd->user,
- pam_check_user_callback, preq);
- }
- if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
- }
- }
-
- /* we made another call, end here */
- if (ret == EOK) return;
- }
- else {
- ret = ENOENT;
- }
-
- DEBUG(2, ("No results for check user call\n"));
-
-#if HAVE_NEG_CACHE
- /* set negative cache only if not result of cache check */
- if (!neghit) {
- ret = nss_ncache_set_user(nctx->ncache, false,
- dctx->domain->name, cmdctx->name);
- if (ret != EOK) {
- NSS_CMD_FATAL_ERROR(cctx);
- }
- }
-#endif
-
- if (ret != EOK) {
- if (ret == ENOENT) {
- preq->pd->pam_status = PAM_USER_UNKNOWN;
- } else {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
- pam_reply(preq);
- return;
- }
- break;
-
- case 1:
-
- /* BINGO */
- preq->pd->pw_uid =
- ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_UIDNUM, -1);
- if (preq->pd->pw_uid == -1) {
- DEBUG(1, ("Failed to find uid for user [%s] in domain [%s].\n",
- preq->pd->user, preq->pd->domain));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-
- preq->pd->gr_gid =
- ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_GIDNUM, -1);
- if (preq->pd->gr_gid == -1) {
- DEBUG(1, ("Failed to find gid for user [%s] in domain [%s].\n",
- preq->pd->user, preq->pd->domain));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-
- pam_dom_forwarder(preq);
- return;
-
- default:
- DEBUG(1, ("check user call returned more than one result !?!\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static void pam_dom_forwarder(struct pam_auth_req *preq)
-{
- int ret;
-
- if (!preq->pd->domain) {
- preq->pd->domain = preq->domain->name;
- }
-
- if (!NEED_CHECK_PROVIDER(preq->domain->provider)) {
- preq->callback = pam_reply;
- ret = LOCAL_pam_handler(preq);
- }
- else {
- preq->callback = pam_reply;
- ret = pam_dp_send_req(preq, SSS_CLI_SOCKET_TIMEOUT/2);
- DEBUG(4, ("pam_dp_send_req returned %d\n", ret));
- }
-
- if (ret != EOK) {
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- pam_reply(preq);
- }
-}
-
-static int pam_cmd_authenticate(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_authenticate\n"));
- return pam_forwarder(cctx, SSS_PAM_AUTHENTICATE);
-}
-
-static int pam_cmd_setcred(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_setcred\n"));
- return pam_forwarder(cctx, SSS_PAM_SETCRED);
-}
-
-static int pam_cmd_acct_mgmt(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_acct_mgmt\n"));
- return pam_forwarder(cctx, SSS_PAM_ACCT_MGMT);
-}
-
-static int pam_cmd_open_session(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_open_session\n"));
- return pam_forwarder(cctx, SSS_PAM_OPEN_SESSION);
-}
-
-static int pam_cmd_close_session(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_close_session\n"));
- return pam_forwarder(cctx, SSS_PAM_CLOSE_SESSION);
-}
-
-static int pam_cmd_chauthtok(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_chauthtok\n"));
- return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK);
-}
-
-static int pam_cmd_chauthtok_prelim(struct cli_ctx *cctx) {
- DEBUG(4, ("entering pam_cmd_chauthtok_prelim\n"));
- return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK_PRELIM);
-}
-
-struct cli_protocol_version *register_cli_protocol_version(void)
-{
- static struct cli_protocol_version pam_cli_protocol_version[] = {
- {3, "2009-09-14", "make cli_pid mandatory"},
- {2, "2009-05-12", "new format <type><size><data>"},
- {1, "2008-09-05", "initial version, \\0 terminated strings"},
- {0, NULL, NULL}
- };
-
- return pam_cli_protocol_version;
-}
-
-struct sss_cmd_table *get_pam_cmds(void)
-{
- static struct sss_cmd_table sss_cmds[] = {
- {SSS_GET_VERSION, sss_cmd_get_version},
- {SSS_PAM_AUTHENTICATE, pam_cmd_authenticate},
- {SSS_PAM_SETCRED, pam_cmd_setcred},
- {SSS_PAM_ACCT_MGMT, pam_cmd_acct_mgmt},
- {SSS_PAM_OPEN_SESSION, pam_cmd_open_session},
- {SSS_PAM_CLOSE_SESSION, pam_cmd_close_session},
- {SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok},
- {SSS_PAM_CHAUTHTOK_PRELIM, pam_cmd_chauthtok_prelim},
- {SSS_CLI_NULL, NULL}
- };
-
- return sss_cmds;
-}
diff --git a/server/responder/pam/pamsrv_dp.c b/server/responder/pam/pamsrv_dp.c
deleted file mode 100644
index 071d09b8e..000000000
--- a/server/responder/pam/pamsrv_dp.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- SSSD
-
- NSS Responder - Data Provider Interfaces
-
- 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 <sys/time.h>
-#include <time.h>
-
-#include <talloc.h>
-#include <security/pam_modules.h>
-
-#include "util/util.h"
-#include "responder/common/responder_packet.h"
-#include "providers/data_provider.h"
-#include "sbus/sbus_client.h"
-#include "responder/pam/pamsrv.h"
-
-static void pam_dp_process_reply(DBusPendingCall *pending, void *ptr)
-{
- DBusError dbus_error;
- DBusMessage* msg;
- int ret;
- int type;
- struct pam_auth_req *preq;
-
- preq = talloc_get_type(ptr, struct pam_auth_req);
-
- dbus_error_init(&dbus_error);
-
- dbus_pending_call_block(pending);
- msg = dbus_pending_call_steal_reply(pending);
- if (msg == NULL) {
- DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
-
-
- type = dbus_message_get_type(msg);
- switch (type) {
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- ret = dp_unpack_pam_response(msg, preq->pd, &dbus_error);
- if (!ret) {
- DEBUG(0, ("Failed to parse reply.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- goto done;
- }
- DEBUG(4, ("received: [%d][%s]\n", preq->pd->pam_status, preq->pd->domain));
- break;
- case DBUS_MESSAGE_TYPE_ERROR:
- DEBUG(0, ("Reply error.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- break;
- default:
- DEBUG(0, ("Default... what now?.\n"));
- preq->pd->pam_status = PAM_SYSTEM_ERR;
- }
-
-
-done:
- dbus_pending_call_unref(pending);
- dbus_message_unref(msg);
- preq->callback(preq);
-}
-
-int pam_dp_send_req(struct pam_auth_req *preq, int timeout)
-{
- struct pam_data *pd = preq->pd;
- struct be_conn *be_conn;
- DBusMessage *msg;
- DBusPendingCall *pending_reply;
- DBusConnection *dbus_conn;
- dbus_bool_t ret;
- int res;
-
- /* double check dp_ctx has actually been initialized.
- * in some pathological cases it may happen that nss starts up before
- * dp connection code is actually able to establish a connection.
- */
- res = sss_dp_get_domain_conn(preq->cctx->rctx,
- preq->domain->name, &be_conn);
- if (res != EOK) {
- DEBUG(1, ("The Data Provider connection for %s is not available!"
- " This maybe a bug, it shouldn't happen!\n", preq->domain));
- return EIO;
- }
- dbus_conn = sbus_get_connection(be_conn->conn);
-
- msg = dbus_message_new_method_call(NULL,
- DP_PATH,
- DP_INTERFACE,
- DP_METHOD_PAMHANDLER);
- if (msg == NULL) {
- DEBUG(0,("Out of memory?!\n"));
- return ENOMEM;
- }
-
-
- DEBUG(4, ("Sending request with the following data:\n"));
- DEBUG_PAM_DATA(4, pd);
-
- ret = dp_pack_pam_request(msg, pd);
- if (!ret) {
- DEBUG(1,("Failed to build message\n"));
- return EIO;
- }
-
- ret = dbus_connection_send_with_reply(dbus_conn, msg, &pending_reply, timeout);
- if (!ret || pending_reply == NULL) {
- /*
- * 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;
- }
-
- dbus_pending_call_set_notify(pending_reply,
- pam_dp_process_reply, preq, NULL);
- dbus_message_unref(msg);
-
- return EOK;
-}
-