diff options
-rw-r--r-- | server/responder/common/responder_cmd.c | 15 | ||||
-rw-r--r-- | server/responder/common/responder_cmd.h | 22 | ||||
-rw-r--r-- | server/responder/common/responder_common.c | 9 | ||||
-rw-r--r-- | server/responder/common/responder_common.h | 2 | ||||
-rw-r--r-- | server/responder/nss/nsssrv.c | 373 | ||||
-rw-r--r-- | server/responder/nss/nsssrv.h | 49 | ||||
-rw-r--r-- | server/responder/nss/nsssrv_cmd.c | 342 | ||||
-rw-r--r-- | server/responder/nss/nsssrv_dp.c | 123 | ||||
-rw-r--r-- | server/responder/pam/pamsrv.c | 11 | ||||
-rw-r--r-- | server/responder/pam/pamsrv_cmd.c | 9 |
10 files changed, 221 insertions, 734 deletions
diff --git a/server/responder/common/responder_cmd.c b/server/responder/common/responder_cmd.c index f3fbf479..a434b3e1 100644 --- a/server/responder/common/responder_cmd.c +++ b/server/responder/common/responder_cmd.c @@ -24,29 +24,22 @@ #include "responder/common/responder_packet.h" -void sss_cmd_done(struct sss_cmd_ctx *nctx) +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(nctx->cctx->cfde); + TEVENT_FD_WRITEABLE(cctx->cfde); /* free all request related data through the talloc hierarchy */ - talloc_free(nctx); + talloc_free(freectx); } int sss_cmd_get_version(struct cli_ctx *cctx) { - struct sss_cmd_ctx *nctx; uint8_t *body; size_t blen; int ret; - nctx = talloc(cctx, struct sss_cmd_ctx); - if (!nctx) { - return ENOMEM; - } - nctx->cctx = cctx; - /* create response packet */ ret = sss_packet_new(cctx->creq, sizeof(uint32_t), sss_packet_get_cmd(cctx->creq->in), @@ -57,7 +50,7 @@ int sss_cmd_get_version(struct cli_ctx *cctx) sss_packet_get_body(cctx->creq->out, &body, &blen); ((uint32_t *)body)[0] = SSS_PROTOCOL_VERSION; - sss_cmd_done(nctx); + sss_cmd_done(cctx, NULL); return EOK; } diff --git a/server/responder/common/responder_cmd.h b/server/responder/common/responder_cmd.h index b91fc23a..eb3bd082 100644 --- a/server/responder/common/responder_cmd.h +++ b/server/responder/common/responder_cmd.h @@ -28,9 +28,9 @@ #include "tevent.h" #include "ldb.h" #include "../sss_client/sss_cli.h" +#include "util/btreemap.h" /* needed until nsssrv.h is updated */ -#ifndef __NSSSRV_H__ struct cli_request { /* original request from the wire */ @@ -52,18 +52,18 @@ struct resp_ctx { const char *priv_sock_name; struct service_sbus_ctx *ss_ctx; struct service_sbus_ctx *dp_ctx; + struct btreemap *domain_map; char *default_domain; - int cache_timeout; - struct sbus_method *sss_sbus_methods; struct sss_cmd_table *sss_cmds; const char *sss_pipe_name; - const char *confdb_socket_path; + const char *confdb_service_path; struct sbus_method *dp_methods; -}; + void *pvt_ctx; +}; struct cli_ctx { struct tevent_context *ev; @@ -72,18 +72,8 @@ struct cli_ctx { struct tevent_fd *cfde; struct sockaddr_un addr; struct cli_request *creq; - struct getent_ctx *gctx; int priv; }; -#endif - -struct sss_cmd_ctx { - struct cli_ctx *cctx; - const char *domain; - const char *name; - uid_t id; - bool check_expiration; -}; struct sss_cmd_table { enum sss_cli_command cmd; @@ -91,7 +81,7 @@ struct sss_cmd_table { }; int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds); -void sss_cmd_done(struct sss_cmd_ctx *nctx); +void sss_cmd_done(struct cli_ctx *cctx, void *freectx); int sss_cmd_get_version(struct cli_ctx *cctx); #endif /* __SSSSRV_CMD_H__ */ diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c index 3b566b9c..fa024d53 100644 --- a/server/responder/common/responder_common.c +++ b/server/responder/common/responder_common.c @@ -455,11 +455,9 @@ failed: static int sss_init_domains(struct resp_ctx *rctx) { - TALLOC_CTX *tmp_ctx; int ret; int retval; - tmp_ctx = talloc_new(rctx); ret = confdb_get_domains(rctx->cdb, rctx, &rctx->domain_map); if (ret != EOK) { retval = ret; @@ -486,7 +484,6 @@ static int sss_init_domains(struct resp_ctx *rctx) retval = EOK; done: - talloc_free(tmp_ctx); return retval; } @@ -497,7 +494,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, struct sss_cmd_table sss_cmds[], const char *sss_pipe_name, const char *sss_priv_pipe_name, - const char *confdb_socket_path, + const char *confdb_service_path, struct sbus_method dp_methods[], struct resp_ctx **responder_ctx) { @@ -515,7 +512,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, rctx->sss_cmds = sss_cmds; rctx->sock_name = sss_pipe_name; rctx->priv_sock_name = sss_priv_pipe_name; - rctx->confdb_socket_path = confdb_socket_path; + rctx->confdb_service_path = confdb_service_path; rctx->dp_methods = dp_methods; ret = sss_init_domains(rctx); @@ -549,8 +546,6 @@ int sss_process_init(TALLOC_CTX *mem_ctx, return ret; } - rctx->cache_timeout = 600; /* FIXME: read from conf */ - DEBUG(1, ("Responder Initialization complete\n")); *responder_ctx = rctx; diff --git a/server/responder/common/responder_common.h b/server/responder/common/responder_common.h index 66e01f9d..8a7af08a 100644 --- a/server/responder/common/responder_common.h +++ b/server/responder/common/responder_common.h @@ -16,7 +16,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, struct sss_cmd_table sss_cmds[], const char *sss_pipe_name, const char *sss_priv_pipe_name, - const char *confdb_socket_path, + const char *confdb_service_path, struct sbus_method dp_methods[], struct resp_ctx **responder_ctx); diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c index 979bd968..f5afc22f 100644 --- a/server/responder/nss/nsssrv.c +++ b/server/responder/nss/nsssrv.c @@ -49,7 +49,6 @@ static int service_identity(DBusMessage *message, struct sbus_conn_ctx *sconn); static int service_pong(DBusMessage *message, struct sbus_conn_ctx *sconn); static int service_reload(DBusMessage *message, struct sbus_conn_ctx *sconn); -static int nss_init_domains(struct nss_ctx *nctx); struct sbus_method nss_sbus_methods[] = { {SERVICE_METHOD_IDENTITY, service_identity}, @@ -58,176 +57,6 @@ struct sbus_method nss_sbus_methods[] = { {NULL, NULL} }; -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, NSS_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 = nss_cmd_execute(cctx); - 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; - } -} - -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 nss_ctx *nctx = talloc_get_type(ptr, struct nss_ctx); - struct cli_ctx *cctx; - socklen_t len; - - cctx = talloc_zero(nctx, 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(nctx->lfd, (struct sockaddr *)&addr, &len); - if (fd == -1) { - return; - } - close(fd); - return; - } - - len = sizeof(cctx->addr); - cctx->cfd = accept(nctx->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->nctx = nctx; - - talloc_set_destructor(cctx, client_destructor); - - DEBUG(4, ("Client connected!\n")); - - return; -} - static int service_identity(DBusMessage *message, struct sbus_conn_ctx *sconn) { dbus_uint16_t version = NSS_SBUS_SERVICE_VERSION; @@ -289,175 +118,25 @@ static int service_reload(DBusMessage *message, struct sbus_conn_ctx *sconn) return service_pong(message, sconn); } -static int nss_sbus_init(struct nss_ctx *nctx) +static int nss_get_config(struct nss_ctx *nctx, struct confdb_ctx *cdb) { int ret; - char *sbus_address; - struct service_sbus_ctx *ss_ctx; - struct sbus_method_ctx *sm_ctx; - /* Set up SBUS connection to the monitor */ - ret = monitor_get_sbus_address(nctx, nctx->cdb, &sbus_address); - if (ret != EOK) { - DEBUG(0, ("Could not locate monitor address.\n")); - return ret; - } - - ret = monitor_init_sbus_methods(nctx, nss_sbus_methods, &sm_ctx); - if (ret != EOK) { - DEBUG(0, ("Could not initialize SBUS methods.\n")); - return ret; - } - - ret = sbus_client_init(nctx, nctx->ev, - sbus_address, sm_ctx, - NULL /* Private Data */, - NULL /* Destructor */, - &ss_ctx); - if (ret != EOK) { - DEBUG(0, ("Failed to connect to monitor services.\n")); - return ret; - } - - /* Set up NSS-specific listeners */ - /* None currently used */ - - nctx->ss_ctx = ss_ctx; - - return EOK; -} - -/* create a unix socket and listen to it */ -static int set_unix_socket(struct nss_ctx *nctx) -{ - struct sockaddr_un addr; - -/* for future use */ -#if 0 - char *default_pipe; - int ret; - - default_pipe = talloc_asprintf(nctx, "%s/%s", PIPE_PATH, SSS_NSS_PIPE_NAME); - if (!default_pipe) { - return ENOMEM; - } - - ret = confdb_get_string(nctx->cdb, nctx, - "config/services/nss", "unixSocket", - default_pipe, &nctx->sock_name); - if (ret != EOK) { - talloc_free(default_pipe); - return ret; - } - talloc_free(default_pipe); -#endif - nctx->sock_name = SSS_NSS_SOCKET_NAME; - - nctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0); - if (nctx->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(nctx->lfd); - set_close_on_exec(nctx->lfd); - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, nctx->sock_name, sizeof(addr.sun_path)); - - /* make sure we have no old sockets around */ - unlink(nctx->sock_name); - - if (bind(nctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - DEBUG(0,("Unable to bind on socket '%s'\n", nctx->sock_name)); - goto failed; - } - if (listen(nctx->lfd, 10) != 0) { - DEBUG(0,("Unable to listen on socket '%s'\n", nctx->sock_name)); - goto failed; - } - - nctx->lfde = tevent_add_fd(nctx->ev, nctx, nctx->lfd, - TEVENT_FD_READ, accept_fd_handler, nctx); - - /* 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(nctx->lfd); - return EIO; -} - -static int nss_init_domains(struct nss_ctx *nctx) -{ - int ret; - int retval; - - ret = confdb_get_domains(nctx->cdb, nctx, &nctx->domain_map); - if (ret != EOK) { - retval = ret; - goto done; - } - - if (nctx->domain_map == NULL) { - /* No domains configured! - * Note: this should never happen, since LOCAL should - * always be configured */ - DEBUG(0, ("No domains configured on this client!\n")); - retval = EINVAL; - goto done; - } - - ret = confdb_get_string(nctx->cdb, nctx, - "config/domains", "default", - NULL, &nctx->default_domain); - if (ret != EOK) { - retval = ret; - goto done; - } - - retval = EOK; - -done: - return retval; -} - -static int nss_get_config(struct nss_ctx *nctx) -{ - int ret; - - ret = confdb_get_int(nctx->cdb, nctx, NSS_SRV_CONFIG, + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, "EnumCacheTimeout", 120, &nctx->enum_cache_timeout); if (ret != EOK) goto done; - ret = confdb_get_int(nctx->cdb, nctx, NSS_SRV_CONFIG, + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, "EntryCacheTimeout", 600, &nctx->enum_cache_timeout); if (ret != EOK) goto done; - ret = confdb_get_int(nctx->cdb, nctx, NSS_SRV_CONFIG, + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, "EntryNegativeTimeout", 15, &nctx->enum_cache_timeout); if (ret != EOK) goto done; - ret = confdb_get_param(nctx->cdb, nctx, NSS_SRV_CONFIG, - "filterUsers", &nctx->filter_users); - if (ret != EOK) goto done; - - ret = confdb_get_param(nctx->cdb, nctx, NSS_SRV_CONFIG, - "filterGroups", &nctx->filter_groups); - if (ret != EOK) goto done; - done: return ret; } @@ -466,6 +145,8 @@ int nss_process_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct confdb_ctx *cdb) { + struct sbus_method *nss_dp_methods; + struct sss_cmd_table *nss_cmds; struct nss_ctx *nctx; int ret; @@ -474,34 +155,8 @@ int nss_process_init(TALLOC_CTX *mem_ctx, DEBUG(0, ("fatal error initializing nss_ctx\n")); return ENOMEM; } - nctx->ev = ev; - nctx->cdb = cdb; - - ret = nss_init_domains(nctx); - if (ret != EOK) { - DEBUG(0, ("fatal error setting up domain map\n")); - return ret; - } - - ret = nss_sbus_init(nctx); - if (ret != EOK) { - DEBUG(0, ("fatal error setting up message bus\n")); - return ret; - } - - ret = nss_dp_init(nctx); - if (ret != EOK) { - DEBUG(0, ("fatal error setting up backend connector\n")); - return ret; - } - - ret = sysdb_init(nctx, ev, cdb, NULL, &nctx->sysdb); - if (ret != EOK) { - DEBUG(0, ("fatal error initializing nss_ctx\n")); - return ret; - } - ret = nss_get_config(nctx); + ret = nss_get_config(nctx, cdb); if (ret != EOK) { DEBUG(0, ("fatal error getting nss config\n")); return ret; @@ -513,12 +168,20 @@ int nss_process_init(TALLOC_CTX *mem_ctx, return ret; } - /* after all initializations we are ready to listen on our socket */ - ret = set_unix_socket(nctx); + nss_dp_methods = get_nss_dp_methods(); + nss_cmds = get_nss_cmds(); + + ret = sss_process_init(nctx, ev, cdb, + nss_sbus_methods, + nss_cmds, + SSS_NSS_SOCKET_NAME, NULL, + NSS_SRV_CONFIG, + nss_dp_methods, + &nctx->rctx); if (ret != EOK) { - DEBUG(0, ("fatal error initializing socket\n")); return ret; } + nctx->rctx->pvt_ctx = nctx; DEBUG(1, ("NSS Initialization complete\n")); diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h index ab9d3c96..b2aee382 100644 --- a/server/responder/nss/nsssrv.h +++ b/server/responder/nss/nsssrv.h @@ -31,7 +31,9 @@ #include "../sss_client/sss_cli.h" #include "dbus/dbus.h" #include "sbus/sssd_dbus.h" +#include "responder/common/responder_packet.h" #include "responder/common/responder_cmd.h" +#include "responder/nss/nsssrv_nc.h" #define NSS_SBUS_SERVICE_VERSION 0x0001 #define NSS_SBUS_SERVICE_NAME "nss" @@ -49,21 +51,10 @@ #define NSS_SRV_CONFIG "config/services/nss" -struct sysdb_ctx; -struct getpwent_ctx; -struct getgrent_ctx; +struct getent_ctx; struct nss_ctx { - struct tevent_context *ev; - struct tevent_fd *lfde; - int lfd; - struct sysdb_ctx *sysdb; - struct confdb_ctx *cdb; - const char *sock_name; - struct service_sbus_ctx *ss_ctx; - struct service_sbus_ctx *dp_ctx; - struct btreemap *domain_map; - char *default_domain; + struct resp_ctx *rctx; int cache_timeout; int neg_timeout; @@ -73,38 +64,12 @@ struct nss_ctx { time_t last_user_enum; time_t last_group_enum; - struct sbus_method *sss_sbus_methods; - struct sss_cmd_table *sss_cmds; - const char *sss_pipe_name; - const char *confdb_socket_path; - struct sbus_method *dp_methods; - - char **filter_users; - char **filter_groups; -}; - -struct cli_ctx { - struct tevent_context *ev; - struct nss_ctx *nctx; - int cfd; - struct tevent_fd *cfde; - struct sockaddr_un addr; - struct cli_request *creq; struct getent_ctx *pctx; struct getent_ctx *gctx; }; struct nss_packet; -struct cli_request { - - /* original request from the wire */ - struct sss_packet *in; - - /* reply data */ - struct sss_packet *out; -}; - int nss_cmd_execute(struct cli_ctx *cctx); /* from nsssrv_dp.c */ @@ -115,10 +80,12 @@ int nss_cmd_execute(struct cli_ctx *cctx); typedef void (*nss_dp_callback_t)(uint16_t err_maj, uint32_t err_min, const char *err_msg, void *ptr); -int nss_dp_send_acct_req(struct nss_ctx *nctx, TALLOC_CTX *memctx, +int nss_dp_send_acct_req(struct resp_ctx *rctx, TALLOC_CTX *memctx, nss_dp_callback_t callback, void *callback_ctx, int timeout, const char *domain, int type, const char *opt_name, uint32_t opt_id); -int nss_dp_init(struct nss_ctx *nctx); + +struct sbus_method *get_nss_dp_methods(void); +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 index a9378783..f98de8e9 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -20,13 +20,10 @@ */ #include "util/util.h" -#include "util/btreemap.h" -#include "responder/common/responder_packet.h" #include "responder/nss/nsssrv.h" -#include "responder/nss/nsssrv_nc.h" +#include "confdb/confdb.h" #include "db/sysdb.h" #include <time.h> -#include "confdb/confdb.h" struct nss_cmd_ctx { struct cli_ctx *cctx; @@ -60,21 +57,6 @@ struct nss_dom_ctx { struct ldb_result *res; }; -struct nss_cmd_table { - enum sss_cli_command cmd; - int (*fn)(struct cli_ctx *cctx); -}; - -static void nss_cmd_done(struct nss_cmd_ctx *cmdctx) -{ - /* now that the packet is in place, unlock queue - * making the event writable */ - TEVENT_FD_WRITEABLE(cmdctx->cctx->cfde); - - /* free all request related data through the talloc hierarchy */ - talloc_free(cmdctx); -} - static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err) { struct cli_ctx *cctx = cmdctx->cctx; @@ -107,7 +89,6 @@ static bool nss_add_domain(struct sss_domain_info *info) static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname) { struct nss_cmd_ctx *cmdctx = dctx->cmdctx; - struct nss_ctx *nctx = cmdctx->cctx->nctx; struct sss_domain_info *info; struct btreemap *domain_map; char *delim; @@ -116,12 +97,12 @@ static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname) /* TODO: add list of names to filter to configuration */ if (strcmp(fullname, "root") == 0) return ECANCELED; - domain_map = nctx->domain_map; + domain_map = cmdctx->cctx->rctx->domain_map; if ((delim = strchr(fullname, NSS_DOMAIN_DELIM)) != NULL) { domain = delim+1; } else { - domain = nctx->default_domain; + domain = cmdctx->cctx->rctx->default_domain; } /* Check for registered domain */ @@ -150,33 +131,6 @@ static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname) return EOK; } -static int nss_cmd_get_version(struct cli_ctx *cctx) -{ - struct nss_cmd_ctx *cmdctx; - uint8_t *body; - size_t blen; - int ret; - - cmdctx = talloc(cctx, struct nss_cmd_ctx); - if (!cmdctx) { - return ENOMEM; - } - cmdctx->cctx = cctx; - - /* 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] = SSS_PROTOCOL_VERSION; - - nss_cmd_done(cmdctx); - return EOK; -} - /**************************************************************************** * PASSWD db related functions ***************************************************************************/ @@ -279,6 +233,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, 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 nss_ctx *nctx; int timeout; uint64_t lastUpdate; uint8_t *body; @@ -287,6 +242,8 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, bool neghit = false; 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) { @@ -302,7 +259,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, break; case 1: - timeout = cmdctx->cctx->nctx->cache_timeout; + timeout = nctx->cache_timeout; lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); @@ -323,8 +280,8 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, if (call_provider && res->count == 0) { /* check negative cache before potentially expensive remote call */ - ret = nss_ncache_check_user(cctx->nctx->ncache, - cctx->nctx->neg_timeout, + ret = nss_ncache_check_user(nctx->ncache, + nctx->neg_timeout, dctx->domain->name, cmdctx->name); switch (ret) { case EEXIST: @@ -353,7 +310,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, dctx->res = talloc_steal(dctx, res); } - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getpwnam_dp_callback, dctx, timeout, dctx->domain->name, NSS_DP_USER, cmdctx->name, 0); @@ -376,7 +333,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, /* set negative cache only if not result of cache check */ if (!neghit) { - ret = nss_ncache_set_user(cctx->nctx->ncache, + ret = nss_ncache_set_user(nctx->ncache, dctx->domain->name, cmdctx->name); if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); @@ -419,7 +376,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, } done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -449,7 +406,7 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getpwnam_callback, dctx); @@ -462,7 +419,7 @@ done: if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -502,7 +459,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s] from [%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getpwnam_callback, dctx); @@ -514,7 +471,7 @@ done: if (ret != EOK) { ret = nss_cmd_send_error(cmdctx, ret); if (ret == EOK) { - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } return ret; } @@ -531,6 +488,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, 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 nss_ctx *nctx; int timeout; uint64_t lastUpdate; uint8_t *body; @@ -539,6 +497,8 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, bool neghit = false; int ret; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + /* one less to go */ cmdctx->nr--; @@ -566,7 +526,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, break; case 1: - timeout = cmdctx->cctx->nctx->cache_timeout; + timeout = nctx->cache_timeout; lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); @@ -587,8 +547,8 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, if (call_provider && res->count == 0) { /* check negative cache before potentially expensive remote call */ - ret = nss_ncache_check_uid(cctx->nctx->ncache, - cctx->nctx->neg_timeout, + ret = nss_ncache_check_uid(nctx->ncache, + nctx->neg_timeout, cmdctx->id); switch (ret) { case EEXIST: @@ -620,7 +580,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, dctx->res = talloc_steal(dctx, res); } - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getpwuid_dp_callback, dctx, timeout, dctx->domain->name, NSS_DP_USER, NULL, cmdctx->id); @@ -647,7 +607,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, /* set negative cache only if not result of cache check */ if (!neghit) { - ret = nss_ncache_set_uid(cctx->nctx->ncache, cmdctx->id); + ret = nss_ncache_set_uid(nctx->ncache, cmdctx->id); if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } @@ -694,7 +654,7 @@ done: cmdctx->done = true; /* signal that we are done */ return; } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -724,7 +684,7 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->id, nss_cmd_getpwuid_callback, dctx); @@ -740,7 +700,7 @@ done: cmdctx->done = true; /* signal that we are done */ return; } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -774,7 +734,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) domains = NULL; num = 0; /* get domains list */ - ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + ret = btreemap_get_keys(cmdctx, cctx->rctx->domain_map, (const void ***)&domains, &num); if (ret != EOK) return ret; @@ -782,7 +742,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) cmdctx->nr = num; for (i = 0; i < num; i++) { - info = btreemap_get_value(cctx->nctx->domain_map, domains[i]); + info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); dctx = talloc_zero(cmdctx, struct nss_dom_ctx); if (!dctx) return ENOMEM; @@ -795,7 +755,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%lu@%s]\n", cmdctx->id, dctx->domain->name)); - ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->id, nss_cmd_getpwuid_callback, dctx); if (ret != EOK) { @@ -804,7 +764,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) ret = nss_cmd_send_error(cmdctx, ret); if (ret == EOK) { - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } return ret; } @@ -832,9 +792,13 @@ static void nss_cmd_setpwent_callback(void *ptr, int status, 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 getent_ctx *pctx = cctx->pctx; + struct getent_ctx *pctx; + struct nss_ctx *nctx; int ret; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + pctx = nctx->pctx; + cmdctx->nr--; if (cmdctx->done) { @@ -873,7 +837,7 @@ static void nss_cmd_setpwent_callback(void *ptr, int status, if (cmdctx->nr) return; /* set cache mark */ - cctx->nctx->last_user_enum = time(NULL); + nctx->last_user_enum = time(NULL); if (cmdctx->immediate) { /* this was a getpwent call w/o setpwent, @@ -892,7 +856,7 @@ static void nss_cmd_setpwent_callback(void *ptr, int status, } done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -910,7 +874,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_enumpwent(cmdctx, cctx->nctx->sysdb, + ret = sysdb_enumpwent(cmdctx, cctx->rctx->sysdb, dctx->domain, NULL, nss_cmd_setpwent_callback, dctx); if (ret != EOK) { @@ -920,7 +884,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -930,6 +894,7 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct getent_ctx *pctx; + struct nss_ctx *nctx; const char **domains; time_t now = time(NULL); bool cached = false; @@ -938,42 +903,44 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) DEBUG(4, ("Requesting info for all users\n")); + 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; - talloc_free(cctx->pctx); - cctx->pctx = talloc_zero(cctx, struct getent_ctx); - if (!cctx->pctx) { + talloc_free(nctx->pctx); + pctx = talloc_zero(nctx, struct getent_ctx); + if (!pctx) { talloc_free(cmdctx); return ENOMEM; } - pctx = cctx->pctx; + nctx->pctx = pctx; cmdctx->immediate = immediate; domains = NULL; num = 0; /* get domains list */ - ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + ret = btreemap_get_keys(cmdctx, cctx->rctx->domain_map, (const void ***)&domains, &num); if (ret != EOK) { return ret; } /* do not query backends if we have a recent enumeration */ - if (cctx->nctx->enum_cache_timeout) { - if (cctx->nctx->last_user_enum + - cctx->nctx->enum_cache_timeout > now) { + if (nctx->enum_cache_timeout) { + if (nctx->last_user_enum + + nctx->enum_cache_timeout > now) { cached = true; } } /* check if enumeration is enabled in any domain */ for (i = 0; i < num; i++) { - info = btreemap_get_value(cctx->nctx->domain_map, domains[i]); + info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); if ((info->enumerate & NSS_ENUM_USERS) == 0) { continue; @@ -997,12 +964,12 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) if (dctx->check_provider) { timeout = SSS_CLI_SOCKET_TIMEOUT/(i+2); - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_setpw_dp_callback, dctx, timeout, domains[i], NSS_DP_USER, NULL, 0); } else { - ret = sysdb_enumpwent(dctx, cctx->nctx->sysdb, + ret = sysdb_enumpwent(dctx, cctx->rctx->sysdb, dctx->domain, NULL, nss_cmd_setpwent_callback, dctx); } @@ -1027,7 +994,7 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) } sss_packet_set_error(cctx->creq->out, ret); - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); return EOK; } @@ -1042,13 +1009,17 @@ static int nss_cmd_setpwent(struct cli_ctx *cctx) static int nss_cmd_retpwent(struct cli_ctx *cctx, int num) { - struct getent_ctx *pctx = cctx->pctx; + struct nss_ctx *nctx; + struct getent_ctx *pctx; struct ldb_message **msgs = NULL; struct dom_ctx *pdom; const char *dom = NULL; bool add = false; int n = 0; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + pctx = nctx->pctx; + if (pctx->cur >= pctx->num) goto done; pdom = &pctx->doms[pctx->cur]; @@ -1102,21 +1073,24 @@ static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx) ret = nss_cmd_retpwent(cctx, num); sss_packet_set_error(cctx->creq->out, ret); - nss_cmd_done(cmdctx); + 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 (cctx->gctx == NULL) { - cctx->gctx = talloc_zero(cctx, struct getent_ctx); - if (!cctx->gctx) return ENOMEM; + if (nctx->gctx == NULL) { + nctx->gctx = talloc_zero(nctx, struct getent_ctx); + if (!nctx->gctx) return ENOMEM; return nss_cmd_setpwent_ext(cctx, true); } @@ -1132,30 +1106,26 @@ static int nss_cmd_getpwent(struct cli_ctx *cctx) static int nss_cmd_endpwent(struct cli_ctx *cctx) { - struct nss_cmd_ctx *cmdctx; + struct nss_ctx *nctx; int ret; DEBUG(4, ("Terminating request info for all accounts\n")); - cmdctx = talloc(cctx, struct nss_cmd_ctx); - if (!cmdctx) { - return ENOMEM; - } - cmdctx->cctx = cctx; + 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 (cctx->pctx == NULL) goto done; + if (nctx->pctx == NULL) goto done; /* free results and reset */ - talloc_free(cctx->pctx); - cctx->pctx = NULL; + talloc_free(nctx->pctx); + nctx->pctx = NULL; done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, NULL); return EOK; } @@ -1353,6 +1323,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, 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 nss_ctx *nctx; int timeout; uint64_t lastUpdate; uint8_t *body; @@ -1361,12 +1332,14 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, bool neghit = false; 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); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); return; } @@ -1377,7 +1350,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, break; default: - timeout = cmdctx->cctx->nctx->cache_timeout; + timeout = nctx->cache_timeout; lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); @@ -1389,8 +1362,8 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, if (call_provider && res->count == 0) { /* check negative cache before potentially expensive remote call */ - ret = nss_ncache_check_group(cctx->nctx->ncache, - cctx->nctx->neg_timeout, + ret = nss_ncache_check_group(nctx->ncache, + nctx->neg_timeout, dctx->domain->name, cmdctx->name); switch (ret) { case EEXIST: @@ -1419,7 +1392,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, dctx->res = talloc_steal(dctx, res); } - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getgrnam_dp_callback, dctx, timeout, dctx->domain->name, NSS_DP_GROUP, cmdctx->name, 0); @@ -1443,7 +1416,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, /* set negative cache only if not result of cache check */ if (!neghit) { - ret = nss_ncache_set_group(cctx->nctx->ncache, + ret = nss_ncache_set_group(nctx->ncache, dctx->domain->name, cmdctx->name); if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); @@ -1481,7 +1454,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, } done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -1511,7 +1484,7 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getgrnam_callback, dctx); @@ -1523,7 +1496,7 @@ done: if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -1563,7 +1536,7 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s] from [%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getgrnam_callback, dctx); if (ret != EOK) { @@ -1574,7 +1547,7 @@ done: if (ret != EOK) { ret = nss_cmd_send_error(cmdctx, ret); if (ret == EOK) { - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } return ret; } @@ -1591,6 +1564,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, 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 nss_ctx *nctx; int timeout; uint64_t lastUpdate; uint8_t *body; @@ -1599,6 +1573,8 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, bool neghit = false; int ret; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + /* one less to go */ cmdctx->nr--; @@ -1626,7 +1602,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, break; default: - timeout = cmdctx->cctx->nctx->cache_timeout; + timeout = nctx->cache_timeout; lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); @@ -1638,8 +1614,8 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, if (call_provider && res->count == 0) { /* check negative cache before potentially expensive remote call */ - ret = nss_ncache_check_gid(cctx->nctx->ncache, - cctx->nctx->neg_timeout, + ret = nss_ncache_check_gid(nctx->ncache, + nctx->neg_timeout, cmdctx->id); switch (ret) { case EEXIST: @@ -1671,7 +1647,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, dctx->res = talloc_steal(dctx, res); } - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getgrgid_dp_callback, dctx, timeout, dctx->domain->name, NSS_DP_GROUP, NULL, cmdctx->id); @@ -1698,7 +1674,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, /* set negative cache only if not result of cache check */ if (!neghit) { - ret = nss_ncache_set_gid(cctx->nctx->ncache, cmdctx->id); + ret = nss_ncache_set_gid(nctx->ncache, cmdctx->id); if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } @@ -1739,7 +1715,7 @@ done: cmdctx->done = true; /* signal that we are done */ return; } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -1769,7 +1745,7 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->id, nss_cmd_getgrgid_callback, dctx); @@ -1781,7 +1757,7 @@ done: if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -1815,7 +1791,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) domains = NULL; num = 0; /* get domains list */ - ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + ret = btreemap_get_keys(cmdctx, cctx->rctx->domain_map, (const void ***)&domains, &num); if (ret != EOK) { return ret; @@ -1824,7 +1800,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) cmdctx->nr = num; for (i = 0; i < num; i++) { - info = btreemap_get_value(cctx->nctx->domain_map, domains[i]); + info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); dctx = talloc_zero(cmdctx, struct nss_dom_ctx); if (!dctx) return ENOMEM; @@ -1837,7 +1813,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%lu@%s]\n", cmdctx->id, dctx->domain->name)); - ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->id, nss_cmd_getgrgid_callback, dctx); if (ret != EOK) { @@ -1846,7 +1822,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) ret = nss_cmd_send_error(cmdctx, ret); if (ret == EOK) { - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } return ret; } @@ -1875,9 +1851,13 @@ static void nss_cmd_setgrent_callback(void *ptr, int status, 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 getent_ctx *gctx = cctx->gctx; + struct getent_ctx *gctx; + struct nss_ctx *nctx; int ret; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + gctx = nctx->gctx; + cmdctx->nr--; if (cmdctx->done) { @@ -1916,7 +1896,7 @@ static void nss_cmd_setgrent_callback(void *ptr, int status, if (cmdctx->nr) return; /* set cache mark */ - cctx->nctx->last_group_enum = time(NULL); + nctx->last_group_enum = time(NULL); if (cmdctx->immediate) { /* this was a getgrent call w/o setgrent, @@ -1935,7 +1915,7 @@ static void nss_cmd_setgrent_callback(void *ptr, int status, } done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, @@ -1953,7 +1933,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb, + ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb, dctx->domain, nss_cmd_setgrent_callback, dctx); if (ret != EOK) { @@ -1963,7 +1943,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -1973,6 +1953,7 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct getent_ctx *gctx; + struct nss_ctx *nctx; const char **domains; time_t now = time(NULL); bool cached = false; @@ -1981,42 +1962,44 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) DEBUG(4, ("Requesting info for all groups\n")); + 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; - talloc_free(cctx->gctx); - cctx->gctx = talloc_zero(cctx, struct getent_ctx); - if (!cctx->gctx) { + talloc_free(nctx->gctx); + gctx = talloc_zero(nctx, struct getent_ctx); + if (!gctx) { talloc_free(cmdctx); return ENOMEM; } - gctx = cctx->gctx; + nctx->gctx = gctx; cmdctx->immediate = immediate; domains = NULL; num = 0; /* get domains list */ - ret = btreemap_get_keys(cmdctx, cctx->nctx->domain_map, + ret = btreemap_get_keys(cmdctx, cctx->rctx->domain_map, (const void ***)&domains, &num); if(ret != EOK) { return ret; } /* do not query backends if we have a recent enumeration */ - if (cctx->nctx->enum_cache_timeout) { - if (cctx->nctx->last_group_enum + - cctx->nctx->enum_cache_timeout > now) { + if (nctx->enum_cache_timeout) { + if (nctx->last_group_enum + + nctx->enum_cache_timeout > now) { cached = true; } } /* check if enumeration is enabled in any domain */ for (i = 0; i < num; i++) { - info = btreemap_get_value(cctx->nctx->domain_map, domains[i]); + info = btreemap_get_value(cctx->rctx->domain_map, domains[i]); if ((info->enumerate & NSS_ENUM_GROUPS) == 0) { continue; @@ -2040,12 +2023,12 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) if (dctx->check_provider) { timeout = SSS_CLI_SOCKET_TIMEOUT/(i+2); - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_setgr_dp_callback, dctx, timeout, domains[i], NSS_DP_GROUP, NULL, 0); } else { - ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb, + ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb, dctx->domain, nss_cmd_setgrent_callback, dctx); } @@ -2069,7 +2052,7 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) } sss_packet_set_error(cctx->creq->out, ret); - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); return EOK; } @@ -2083,13 +2066,17 @@ static int nss_cmd_setgrent(struct cli_ctx *cctx) static int nss_cmd_retgrent(struct cli_ctx *cctx, int num) { - struct getent_ctx *gctx = cctx->gctx; + struct nss_ctx *nctx; + struct getent_ctx *gctx; struct ldb_message **msgs = NULL; struct dom_ctx *gdom; const char *dom = NULL; bool add = false; int n = 0; + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + gctx = nctx->gctx; + if (gctx->cur >= gctx->num) goto done; gdom = &gctx->doms[gctx->cur]; @@ -2143,21 +2130,24 @@ static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx) ret = nss_cmd_retgrent(cctx, num); sss_packet_set_error(cctx->creq->out, ret); - nss_cmd_done(cmdctx); + 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 (cctx->gctx == NULL) { - cctx->gctx = talloc_zero(cctx, struct getent_ctx); - if (!cctx->gctx) return ENOMEM; + if (nctx->gctx == NULL) { + nctx->gctx = talloc_zero(nctx, struct getent_ctx); + if (!nctx->gctx) return ENOMEM; return nss_cmd_setgrent_ext(cctx, true); } @@ -2173,30 +2163,26 @@ static int nss_cmd_getgrent(struct cli_ctx *cctx) static int nss_cmd_endgrent(struct cli_ctx *cctx) { - struct nss_cmd_ctx *cmdctx; + struct nss_ctx *nctx; int ret; DEBUG(4, ("Terminating request info for all groups\n")); - cmdctx = talloc(cctx, struct nss_cmd_ctx); - if (!cmdctx) { - return ENOMEM; - } - cmdctx->cctx = cctx; + 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 (cctx->gctx == NULL) goto done; + if (nctx->gctx == NULL) goto done; /* free results and reset */ - talloc_free(cctx->gctx); - cctx->gctx = NULL; + talloc_free(nctx->gctx); + nctx->gctx = NULL; done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, NULL); return EOK; } @@ -2247,7 +2233,7 @@ static void nss_cmd_initgr_callback(void *ptr, int status, ((uint32_t *)body)[1] = 0; /* reserved */ done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min, @@ -2265,7 +2251,7 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_initgroups(cmdctx, cctx->nctx->sysdb, + ret = sysdb_initgroups(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_initgr_callback, cmdctx); if (ret != EOK) { @@ -2275,7 +2261,7 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min, if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -2309,7 +2295,7 @@ static void nss_cmd_getinitnam_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getinit_callback, dctx); @@ -2321,7 +2307,7 @@ done: if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); } - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } } @@ -2331,6 +2317,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, 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 nss_ctx *nctx; int timeout; uint64_t lastUpdate; uint8_t *body; @@ -2339,6 +2326,8 @@ static void nss_cmd_getinit_callback(void *ptr, int status, bool neghit = false; 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) { @@ -2354,7 +2343,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, break; default: - timeout = cmdctx->cctx->nctx->cache_timeout; + timeout = nctx->cache_timeout; lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_LAST_UPDATE, 0); @@ -2366,8 +2355,8 @@ static void nss_cmd_getinit_callback(void *ptr, int status, if (call_provider && res->count == 0) { /* check negative cache before potentially expensive remote call */ - ret = nss_ncache_check_user(cctx->nctx->ncache, - cctx->nctx->neg_timeout, + ret = nss_ncache_check_user(nctx->ncache, + nctx->neg_timeout, dctx->domain->name, cmdctx->name); switch (ret) { case EEXIST: @@ -2396,7 +2385,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, dctx->res = talloc_steal(dctx, res); } - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getinitnam_callback, dctx, timeout, dctx->domain->name, NSS_DP_USER, cmdctx->name, 0); @@ -2420,7 +2409,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, /* set negative cache only if not result of cache check */ if (!neghit) { - ret = nss_ncache_set_user(cctx->nctx->ncache, + ret = nss_ncache_set_user(nctx->ncache, dctx->domain->name, cmdctx->name); if (ret != EOK) { NSS_CMD_FATAL_ERROR(cctx); @@ -2441,7 +2430,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, case 1: timeout = SSS_CLI_SOCKET_TIMEOUT/2; - ret = nss_dp_send_acct_req(cctx->nctx, cmdctx, + ret = nss_dp_send_acct_req(cctx->rctx, cmdctx, nss_cmd_getinitgr_callback, dctx, timeout, dctx->domain->name, NSS_DP_INITGROUPS, @@ -2467,7 +2456,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, } done: - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } /* for now, if we are online, try to always query the backend */ @@ -2506,7 +2495,7 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s] from [%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb, + ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, dctx->domain, cmdctx->name, nss_cmd_getinit_callback, dctx); if (ret != EOK) { @@ -2517,7 +2506,7 @@ done: if (ret != EOK) { ret = nss_cmd_send_error(cmdctx, ret); if (ret == EOK) { - nss_cmd_done(cmdctx); + sss_cmd_done(cctx, cmdctx); } return ret; } @@ -2525,9 +2514,8 @@ done: return EOK; } -struct nss_cmd_table sss_cmds[] = {}; -struct nss_cmd_table nss_cmds[] = { - {SSS_GET_VERSION, nss_cmd_get_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}, @@ -2542,6 +2530,10 @@ struct nss_cmd_table nss_cmds[] = { {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; diff --git a/server/responder/nss/nsssrv_dp.c b/server/responder/nss/nsssrv_dp.c index d4406e40..0668a5b5 100644 --- a/server/responder/nss/nsssrv_dp.c +++ b/server/responder/nss/nsssrv_dp.c @@ -93,7 +93,7 @@ static void nss_dp_send_acct_callback(DBusPendingCall *pending, void *ptr) talloc_free(ndp_req); } -int nss_dp_send_acct_req(struct nss_ctx *nctx, TALLOC_CTX *memctx, +int nss_dp_send_acct_req(struct resp_ctx *rctx, TALLOC_CTX *memctx, nss_dp_callback_t callback, void *callback_ctx, int timeout, const char *domain, int type, const char *opt_name, uint32_t opt_id) @@ -139,11 +139,10 @@ int nss_dp_send_acct_req(struct nss_ctx *nctx, TALLOC_CTX *memctx, filter = talloc_strdup(memctx, "name=*"); } if (!filter) { - talloc_free(nctx); return ENOMEM; } - conn = sbus_get_connection(nctx->dp_ctx->scon_ctx); + conn = sbus_get_connection(rctx->dp_ctx->scon_ctx); /* create the message */ msg = dbus_message_new_method_call(NULL, @@ -198,8 +197,8 @@ int nss_dp_send_acct_req(struct nss_ctx *nctx, TALLOC_CTX *memctx, gettimeofday(&tv, NULL); tv.tv_sec += timeout/1000; tv.tv_usec += (timeout%1000) * 1000; - ndp_req->te = tevent_add_timer(nctx->ev, memctx, tv, - nss_dp_send_acct_timeout, ndp_req); + ndp_req->te = tevent_add_timer(rctx->ev, memctx, tv, + nss_dp_send_acct_timeout, ndp_req); /* Set up the reply handler */ dbus_pending_call_set_notify(pending_reply, @@ -314,120 +313,12 @@ static int nss_dp_identity(DBusMessage *message, struct sbus_conn_ctx *sconn) return EOK; } -struct sbus_method nss_dp_methods[] = { +static struct sbus_method nss_dp_methods[] = { { DP_CLI_METHOD_IDENTITY, nss_dp_identity }, { NULL, NULL } }; -struct nss_dp_pvt_ctx { - struct nss_ctx *nctx; - struct sbus_method *methods; - time_t last_retry; - int retries; -}; - -static int nss_dp_conn_destructor(void *data); -static void nss_dp_reconnect(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *data); - -static void nss_dp_conn_reconnect(struct nss_dp_pvt_ctx *pvt) -{ - struct nss_ctx *nctx; - struct tevent_timer *te; - struct timeval tv; - struct sbus_method_ctx *sm_ctx; - char *sbus_address; - time_t now; - int ret; - - now = time(NULL); - - /* reset retry if last reconnect was > 60 sec. ago */ - if (pvt->last_retry + 60 < now) pvt->retries = 0; - if (pvt->retries >= 3) { - DEBUG(4, ("Too many reconnect retries! Giving up\n")); - return; - } - - pvt->last_retry = now; - pvt->retries++; - - nctx = pvt->nctx; - - ret = dp_get_sbus_address(nctx, nctx->cdb, &sbus_address); - if (ret != EOK) { - DEBUG(0, ("Could not locate data provider address.\n")); - return; - } - - ret = dp_init_sbus_methods(nctx, pvt->methods, &sm_ctx); - if (ret != EOK) { - DEBUG(0, ("Could not initialize SBUS methods.\n")); - return; - } - - ret = sbus_client_init(nctx, nctx->ev, - sbus_address, sm_ctx, - pvt, nss_dp_conn_destructor, - &nctx->dp_ctx); - if (ret != EOK) { - DEBUG(4, ("Failed to reconnect [%d(%s)]!\n", ret, strerror(ret))); - - tv.tv_sec = now +5; - tv.tv_usec = 0; - te = tevent_add_timer(nctx->ev, nctx, tv, nss_dp_reconnect, pvt); - if (te == NULL) { - DEBUG(4, ("Failed to add timed event! Giving up\n")); - } else { - DEBUG(4, ("Retrying in 5 seconds\n")); - } - } -} - -static void nss_dp_reconnect(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *data) -{ - struct nss_dp_pvt_ctx *pvt; - - pvt = talloc_get_type(data, struct nss_dp_pvt_ctx); - - nss_dp_conn_reconnect(pvt); -} - -int nss_dp_conn_destructor(void *data) -{ - struct nss_dp_pvt_ctx *pvt; - struct sbus_conn_ctx *scon; - - scon = talloc_get_type(data, struct sbus_conn_ctx); - if (!scon) return 0; - - /* if this is a regular disconnect just quit */ - if (sbus_conn_disconnecting(scon)) return 0; - - pvt = talloc_get_type(sbus_conn_get_private_data(scon), - struct nss_dp_pvt_ctx); - if (pvt) return 0; - - nss_dp_conn_reconnect(pvt); - - return 0; -} - -int nss_dp_init(struct nss_ctx *nctx) +struct sbus_method *get_nss_dp_methods(void) { - struct nss_dp_pvt_ctx *pvt; - - pvt = talloc_zero(nctx, struct nss_dp_pvt_ctx); - if (!pvt) return ENOMEM; - - pvt->nctx = nctx; - pvt->methods = nss_dp_methods; - - nss_dp_conn_reconnect(pvt); - - return EOK; + return nss_dp_methods; } - diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c index 4abc0a2f..d653a008 100644 --- a/server/responder/pam/pamsrv.c +++ b/server/responder/pam/pamsrv.c @@ -48,7 +48,7 @@ #define PAM_SBUS_SERVICE_VERSION 0x0001 #define PAM_SBUS_SERVICE_NAME "pam" -#define CONFDB_SOCKET_PATH "config/services/pam" +#define PAM_SRV_CONFIG "config/services/pam" static int service_identity(DBusMessage *message, struct sbus_conn_ctx *sconn); static int service_pong(DBusMessage *message, struct sbus_conn_ctx *sconn); @@ -161,7 +161,10 @@ static int pam_process_init(struct main_context *main_ctx, int ret, max_retries; /* Enable automatic reconnection to the Data Provider */ - ret = confdb_get_int(rctx->cdb, rctx, rctx->confdb_socket_path, + + /* 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(rctx->cdb, rctx, rctx->confdb_service_path, "retries", 3, &max_retries); if (ret != EOK) { DEBUG(0, ("Failed to set up automatic reconnection\n")); @@ -204,7 +207,7 @@ int main(int argc, const char *argv[]) poptFreeContext(pc); /* set up things like debug , signals, daemonization, etc... */ - ret = server_setup("sssd[pam]", 0, CONFDB_SOCKET_PATH, &main_ctx); + ret = server_setup("sssd[pam]", 0, PAM_SRV_CONFIG, &main_ctx); if (ret != EOK) return 2; pam_dp_methods = register_pam_dp_methods(); @@ -216,7 +219,7 @@ int main(int argc, const char *argv[]) sss_cmds, SSS_PAM_SOCKET_NAME, SSS_PAM_PRIV_SOCKET_NAME, - CONFDB_SOCKET_PATH, + PAM_SRV_CONFIG, pam_dp_methods, &rctx); if (ret != EOK) return 3; diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c index 1f7be166..06a230b6 100644 --- a/server/responder/pam/pamsrv_cmd.c +++ b/server/responder/pam/pamsrv_cmd.c @@ -134,13 +134,6 @@ static void pam_reply(struct pam_data *pd) } cctx = pd->cctx; - rctx = talloc_zero(cctx, struct sss_cmd_ctx); - if (!rctx) { - err = ENOMEM; - goto done; - } - rctx->cctx = cctx; - rctx->check_expiration = true; ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in), &cctx->creq->out); @@ -196,7 +189,7 @@ static void pam_reply(struct pam_data *pd) done: talloc_free(pd); - sss_cmd_done(rctx); + sss_cmd_done(cctx, NULL); } static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) |