LCOV - code coverage report
Current view: top level - responder/common - responder_common.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 501 15.6 %
Date: 2016-06-29 Functions: 6 24 25.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    Common Responder methods
       5             : 
       6             :    Copyright (C) Simo Sorce <ssorce@redhat.com>   2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "config.h"
      23             : 
      24             : #include <stdio.h>
      25             : #include <sys/types.h>
      26             : #include <sys/stat.h>
      27             : #include <sys/socket.h>
      28             : #include <sys/un.h>
      29             : #include <string.h>
      30             : #include <sys/time.h>
      31             : #include <errno.h>
      32             : #include <popt.h>
      33             : #include <dbus/dbus.h>
      34             : 
      35             : #include "util/util.h"
      36             : #include "util/strtonum.h"
      37             : #include "db/sysdb.h"
      38             : #include "confdb/confdb.h"
      39             : #include "sbus/sssd_dbus.h"
      40             : #include "responder/common/responder.h"
      41             : #include "responder/common/responder_packet.h"
      42             : #include "providers/data_provider.h"
      43             : #include "monitor/monitor_interfaces.h"
      44             : #include "sbus/sbus_client.h"
      45             : #include "util/util_creds.h"
      46             : 
      47           0 : static errno_t set_close_on_exec(int fd)
      48             : {
      49             :     int v;
      50             :     int ferr;
      51             :     errno_t error;
      52             : 
      53             :     /* Get the current flags for this file descriptor */
      54           0 :     v = fcntl(fd, F_GETFD, 0);
      55             : 
      56           0 :     errno = 0;
      57             :     /* Set the close-on-exec flags on this fd */
      58           0 :     ferr = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
      59           0 :     if (ferr < 0) {
      60           0 :         error = errno;
      61           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
      62             :               "Unable to set fd close-on-exec: [%d][%s]\n",
      63             :                   error, strerror(error));
      64           0 :         return error;
      65             :     }
      66           0 :     return EOK;
      67             : }
      68             : 
      69           0 : static void client_close_fn(struct tevent_context *ev,
      70             :                             struct tevent_fd *fde, int fd,
      71             :                             void *ptr)
      72             : {
      73             :     errno_t ret;
      74           0 :     struct cli_ctx *ctx = talloc_get_type(ptr, struct cli_ctx);
      75             : 
      76           0 :     if ((ctx->cfd > 0) && close(ctx->cfd) < 0) {
      77           0 :         ret = errno;
      78           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      79             :               "Failed to close fd [%d]: [%s]\n",
      80             :                ctx->cfd, strerror(ret));
      81             :     }
      82             : 
      83           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
      84             :           "Terminated client [%p][%d]\n",
      85             :            ctx, ctx->cfd);
      86             : 
      87           0 :     ctx->cfd = -1;
      88           0 : }
      89             : 
      90           0 : static errno_t get_client_cred(struct cli_ctx *cctx)
      91             : {
      92             :     SEC_CTX secctx;
      93             :     int ret;
      94             : 
      95           0 :     cctx->creds = talloc(cctx, struct cli_creds);
      96           0 :     if (!cctx->creds) return ENOMEM;
      97             : 
      98             : #ifdef HAVE_UCRED
      99           0 :     socklen_t client_cred_len = sizeof(struct ucred);
     100             : 
     101           0 :     cctx->creds->ucred.uid = -1;
     102           0 :     cctx->creds->ucred.gid = -1;
     103           0 :     cctx->creds->ucred.pid = -1;
     104             : 
     105           0 :     ret = getsockopt(cctx->cfd, SOL_SOCKET, SO_PEERCRED, &cctx->creds->ucred,
     106             :                      &client_cred_len);
     107           0 :     if (ret != EOK) {
     108           0 :         ret = errno;
     109           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     110             :               "getsock failed [%d][%s].\n", ret, strerror(ret));
     111           0 :         return ret;
     112             :     }
     113           0 :     if (client_cred_len != sizeof(struct ucred)) {
     114           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     115             :               "getsockopt returned unexpected message size.\n");
     116           0 :         return ENOMSG;
     117             :     }
     118             : 
     119           0 :     DEBUG(SSSDBG_TRACE_ALL,
     120             :           "Client creds: euid[%d] egid[%d] pid[%d].\n",
     121             :           cctx->creds->ucred.uid, cctx->creds->ucred.gid,
     122             :           cctx->creds->ucred.pid);
     123             : #endif
     124             : 
     125           0 :     ret = SELINUX_getpeercon(cctx->cfd, &secctx);
     126           0 :     if (ret != 0) {
     127           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     128             :               "SELINUX_getpeercon failed [%d][%s].\n", ret, strerror(ret));
     129             :         /* This is not fatal, as SELinux may simply be disabled */
     130           0 :         ret = EOK;
     131             :     } else {
     132           0 :         cctx->creds->selinux_ctx = SELINUX_context_new(secctx);
     133           0 :         SELINUX_freecon(secctx);
     134             :     }
     135             : 
     136           0 :     return ret;
     137             : }
     138             : 
     139          40 : uid_t client_euid(struct cli_creds *creds)
     140             : {
     141          40 :     if (!creds) return -1;
     142           0 :     return cli_creds_get_uid(creds);
     143             : }
     144             : 
     145           8 : errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count,
     146             :                            uid_t *allowed_uids)
     147             : {
     148             :     size_t c;
     149             : 
     150           8 :     if (allowed_uids == NULL) {
     151           1 :         return EINVAL;
     152             :     }
     153             : 
     154          14 :     for (c = 0; c < allowed_uids_count; c++) {
     155          12 :         if (uid == allowed_uids[c]) {
     156           5 :             return EOK;
     157             :         }
     158             :     }
     159             : 
     160           2 :     return EACCES;
     161             : }
     162             : 
     163          12 : errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
     164             :                                 bool allow_sss_loop,
     165             :                                 size_t *_uid_count, uid_t **_uids)
     166             : {
     167             :     int ret;
     168             :     size_t c;
     169          12 :     char **list = NULL;
     170             :     int list_size;
     171          12 :     uid_t *uids = NULL;
     172             :     char *endptr;
     173             : 
     174          12 :     ret = split_on_separator(mem_ctx, csv_string, ',', true, false,
     175             :                              &list, &list_size);
     176          12 :     if (ret != EOK) {
     177           2 :         DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
     178             :                                   ret, strerror(ret));
     179           2 :         goto done;
     180             :     }
     181             : 
     182          10 :     uids = talloc_array(mem_ctx, uint32_t, list_size);
     183          10 :     if (uids == NULL) {
     184           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     185           0 :         ret = ENOMEM;
     186           0 :         goto done;
     187             :     }
     188             : 
     189          10 :     if (allow_sss_loop) {
     190          10 :         ret = unsetenv("_SSS_LOOPS");
     191          10 :         if (ret != EOK) {
     192           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to unset _SSS_LOOPS, getpwnam "
     193             :                                       "might not find sssd users.\n");
     194             :         }
     195             :     }
     196             : 
     197          37 :     for (c = 0; c < list_size; c++) {
     198          31 :         errno = 0;
     199          31 :         if (*list[c] == '\0') {
     200           1 :             DEBUG(SSSDBG_OP_FAILURE, "Empty list item.\n");
     201           1 :             ret = EINVAL;
     202           1 :             goto done;
     203             :         }
     204             : 
     205          30 :         uids[c] = strtouint32(list[c], &endptr, 10);
     206          30 :         if (errno != 0 || *endptr != '\0') {
     207           4 :             ret = errno;
     208           4 :             if (ret == ERANGE) {
     209           2 :                 DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is out of range.\n",
     210             :                                           list[c]);
     211           2 :                 goto done;
     212             :             }
     213             : 
     214           2 :             ret = sss_user_by_name_or_uid(list[c], &uids[c], NULL);
     215           2 :             if (ret != EOK) {
     216           1 :                 DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is neither a valid "
     217             :                                          "UID nor a user name which could be "
     218             :                                          "resolved by getpwnam().\n", list[c]);
     219           1 :                 sss_log(SSS_LOG_WARNING, "List item [%s] is neither a valid "
     220             :                                          "UID nor a user name which could be "
     221           1 :                                          "resolved by getpwnam().\n", list[c]);
     222           1 :                 goto done;
     223             :             }
     224             :         }
     225             :     }
     226             : 
     227           6 :     *_uid_count = list_size;
     228           6 :     *_uids = uids;
     229             : 
     230           6 :     ret = EOK;
     231             : 
     232             : done:
     233          12 :     if(setenv("_SSS_LOOPS", "NO", 0) != 0) {
     234           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to set _SSS_LOOPS.\n");
     235             :     }
     236          12 :     talloc_free(list);
     237          12 :     if (ret != EOK) {
     238           6 :         talloc_free(uids);
     239             :     }
     240             : 
     241          12 :     return ret;
     242             : }
     243             : 
     244             : 
     245           0 : static void client_send(struct cli_ctx *cctx)
     246             : {
     247             :     int ret;
     248             : 
     249           0 :     ret = sss_packet_send(cctx->creq->out, cctx->cfd);
     250           0 :     if (ret == EAGAIN) {
     251             :         /* not all data was sent, loop again */
     252           0 :         return;
     253             :     }
     254           0 :     if (ret != EOK) {
     255           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
     256           0 :         talloc_free(cctx);
     257           0 :         return;
     258             :     }
     259             : 
     260             :     /* ok all sent */
     261           0 :     TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
     262           0 :     TEVENT_FD_READABLE(cctx->cfde);
     263           0 :     talloc_free(cctx->creq);
     264           0 :     cctx->creq = NULL;
     265           0 :     return;
     266             : }
     267             : 
     268           0 : static int client_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
     269             : {
     270             :     enum sss_cli_command cmd;
     271             : 
     272           0 :     cmd = sss_packet_get_cmd(cctx->creq->in);
     273           0 :     return sss_cmd_execute(cctx, cmd, sss_cmds);
     274             : }
     275             : 
     276           0 : static void client_recv(struct cli_ctx *cctx)
     277             : {
     278             :     int ret;
     279             : 
     280           0 :     if (!cctx->creq) {
     281           0 :         cctx->creq = talloc_zero(cctx, struct cli_request);
     282           0 :         if (!cctx->creq) {
     283           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     284             :                   "Failed to alloc request, aborting client!\n");
     285           0 :             talloc_free(cctx);
     286           0 :             return;
     287             :         }
     288             :     }
     289             : 
     290           0 :     if (!cctx->creq->in) {
     291           0 :         ret = sss_packet_new(cctx->creq, SSS_PACKET_MAX_RECV_SIZE,
     292           0 :                              0, &cctx->creq->in);
     293           0 :         if (ret != EOK) {
     294           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     295             :                   "Failed to alloc request, aborting client!\n");
     296           0 :             talloc_free(cctx);
     297           0 :             return;
     298             :         }
     299             :     }
     300             : 
     301           0 :     ret = sss_packet_recv(cctx->creq->in, cctx->cfd);
     302           0 :     switch (ret) {
     303             :     case EOK:
     304             :         /* do not read anymore */
     305           0 :         TEVENT_FD_NOT_READABLE(cctx->cfde);
     306             :         /* execute command */
     307           0 :         ret = client_cmd_execute(cctx, cctx->rctx->sss_cmds);
     308           0 :         if (ret != EOK) {
     309           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     310             :                   "Failed to execute request, aborting client!\n");
     311           0 :             talloc_free(cctx);
     312             :         }
     313             :         /* past this point cctx can be freed at any time by callbacks
     314             :          * in case of error, do not use it */
     315           0 :         return;
     316             : 
     317             :     case EAGAIN:
     318             :         /* need to read still some data, loop again */
     319           0 :         break;
     320             : 
     321             :     case EINVAL:
     322           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     323             :               "Invalid data from client, closing connection!\n");
     324           0 :         talloc_free(cctx);
     325           0 :         break;
     326             : 
     327             :     case ENODATA:
     328           0 :         DEBUG(SSSDBG_FUNC_DATA, "Client disconnected!\n");
     329           0 :         talloc_free(cctx);
     330           0 :         break;
     331             : 
     332             :     default:
     333           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Failed to read request, aborting client!\n");
     334           0 :         talloc_free(cctx);
     335             :     }
     336             : 
     337           0 :     return;
     338             : }
     339             : 
     340             : static errno_t reset_idle_timer(struct cli_ctx *cctx);
     341             : 
     342           0 : static void client_fd_handler(struct tevent_context *ev,
     343             :                               struct tevent_fd *fde,
     344             :                               uint16_t flags, void *ptr)
     345             : {
     346             :     errno_t ret;
     347           0 :     struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
     348             : 
     349             :     /* Always reset the idle timer on any activity */
     350           0 :     ret = reset_idle_timer(cctx);
     351           0 :     if (ret != EOK) {
     352           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     353             :               "Could not create idle timer for client. "
     354             :                "This connection may not auto-terminate\n");
     355             :         /* Non-fatal, continue */
     356             :     }
     357             : 
     358           0 :     if (flags & TEVENT_FD_READ) {
     359           0 :         client_recv(cctx);
     360           0 :         return;
     361             :     }
     362           0 :     if (flags & TEVENT_FD_WRITE) {
     363           0 :         client_send(cctx);
     364           0 :         return;
     365             :     }
     366             : }
     367             : 
     368             : struct accept_fd_ctx {
     369             :     struct resp_ctx *rctx;
     370             :     bool is_private;
     371             : };
     372             : 
     373             : static void idle_handler(struct tevent_context *ev,
     374             :                          struct tevent_timer *te,
     375             :                          struct timeval current_time,
     376             :                          void *data);
     377             : 
     378           0 : static void accept_fd_handler(struct tevent_context *ev,
     379             :                               struct tevent_fd *fde,
     380             :                               uint16_t flags, void *ptr)
     381             : {
     382             :     /* accept and attach new event handler */
     383           0 :     struct accept_fd_ctx *accept_ctx =
     384             :             talloc_get_type(ptr, struct accept_fd_ctx);
     385           0 :     struct resp_ctx *rctx = accept_ctx->rctx;
     386             :     struct cli_ctx *cctx;
     387             :     socklen_t len;
     388             :     struct stat stat_buf;
     389             :     int ret;
     390           0 :     int fd = accept_ctx->is_private ? rctx->priv_lfd : rctx->lfd;
     391             :     int client_fd;
     392             : 
     393           0 :     if (accept_ctx->is_private) {
     394           0 :         ret = stat(rctx->priv_sock_name, &stat_buf);
     395           0 :         if (ret == -1) {
     396           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     397             :                   "stat on privileged pipe failed: [%d][%s].\n", errno,
     398             :                       strerror(errno));
     399           0 :             return;
     400             :         }
     401             : 
     402           0 :         if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
     403           0 :                (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
     404           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     405             :                   "privileged pipe has an illegal status.\n");
     406             :     /* TODO: what is the best response to this condition? Terminate? */
     407           0 :             return;
     408             :         }
     409             :     }
     410             : 
     411           0 :     cctx = talloc_zero(rctx, struct cli_ctx);
     412           0 :     if (!cctx) {
     413             :         struct sockaddr_un addr;
     414           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     415             :               "Out of memory trying to setup client context%s!\n",
     416             :                   accept_ctx->is_private ? " on privileged pipe": "");
     417             :         /* accept and close to signal the client we have a problem */
     418           0 :         memset(&addr, 0, sizeof(addr));
     419           0 :         len = sizeof(addr);
     420           0 :         client_fd = accept(fd, (struct sockaddr *)&addr, &len);
     421           0 :         if (client_fd == -1) {
     422           0 :             return;
     423             :         }
     424           0 :         close(client_fd);
     425           0 :         return;
     426             :     }
     427             : 
     428           0 :     len = sizeof(cctx->addr);
     429           0 :     cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len);
     430           0 :     if (cctx->cfd == -1) {
     431           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Accept failed [%s]\n", strerror(errno));
     432           0 :         talloc_free(cctx);
     433           0 :         return;
     434             :     }
     435             : 
     436           0 :     cctx->priv = accept_ctx->is_private;
     437             : 
     438           0 :     ret = get_client_cred(cctx);
     439           0 :     if (ret != EOK) {
     440           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_client_cred failed, "
     441             :                   "client cred may not be available.\n");
     442             :     }
     443             : 
     444           0 :     if (rctx->allowed_uids_count != 0) {
     445           0 :         if (client_euid(cctx->creds) == -1) {
     446           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "allowed_uids configured, " \
     447             :                                         "but platform does not support " \
     448             :                                         "reading peer credential from the " \
     449             :                                         "socket. Access denied.\n");
     450           0 :             close(cctx->cfd);
     451           0 :             talloc_free(cctx);
     452           0 :             return;
     453             :         }
     454             : 
     455           0 :         ret = check_allowed_uids(client_euid(cctx->creds), rctx->allowed_uids_count,
     456             :                                  rctx->allowed_uids);
     457           0 :         if (ret != EOK) {
     458           0 :             if (ret == EACCES) {
     459           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     460             :                       "Access denied for uid [%"SPRIuid"].\n",
     461             :                       client_euid(cctx->creds));
     462             :             } else {
     463           0 :                 DEBUG(SSSDBG_OP_FAILURE, "check_allowed_uids failed.\n");
     464             :             }
     465           0 :             close(cctx->cfd);
     466           0 :             talloc_free(cctx);
     467           0 :             return;
     468             :         }
     469             :     }
     470             : 
     471           0 :     cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
     472             :                                TEVENT_FD_READ, client_fd_handler, cctx);
     473           0 :     if (!cctx->cfde) {
     474           0 :         close(cctx->cfd);
     475           0 :         talloc_free(cctx);
     476           0 :         DEBUG(SSSDBG_OP_FAILURE,
     477             :               "Failed to queue client handler%s\n",
     478             :                accept_ctx->is_private ? " on privileged pipe" : "");
     479           0 :         return;
     480             :     }
     481           0 :     tevent_fd_set_close_fn(cctx->cfde, client_close_fn);
     482             : 
     483           0 :     cctx->ev = ev;
     484           0 :     cctx->rctx = rctx;
     485             : 
     486             :     /* Set up the idle timer */
     487           0 :     ret = reset_idle_timer(cctx);
     488           0 :     if (ret != EOK) {
     489           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     490             :               "Could not create idle timer for client. "
     491             :                "This connection may not auto-terminate\n");
     492             :         /* Non-fatal, continue */
     493             :     }
     494             : 
     495           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     496             :           "Client connected%s!\n",
     497             :            accept_ctx->is_private ? " to privileged pipe" : "");
     498             : 
     499           0 :     return;
     500             : }
     501             : 
     502           0 : static errno_t reset_idle_timer(struct cli_ctx *cctx)
     503             : {
     504           0 :     struct timeval tv =
     505           0 :             tevent_timeval_current_ofs(cctx->rctx->client_idle_timeout, 0);
     506             : 
     507           0 :     talloc_zfree(cctx->idle);
     508             : 
     509           0 :     cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, idle_handler, cctx);
     510           0 :     if (!cctx->idle) return ENOMEM;
     511             : 
     512           0 :     DEBUG(SSSDBG_TRACE_ALL,
     513             :           "Idle timer re-set for client [%p][%d]\n",
     514             :            cctx, cctx->cfd);
     515             : 
     516           0 :     return EOK;
     517             : }
     518             : 
     519           0 : static void idle_handler(struct tevent_context *ev,
     520             :                          struct tevent_timer *te,
     521             :                          struct timeval current_time,
     522             :                          void *data)
     523             : {
     524             :     /* This connection is idle. Terminate it */
     525           0 :     struct cli_ctx *cctx =
     526             :             talloc_get_type(data, struct cli_ctx);
     527             : 
     528           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
     529             :           "Terminating idle client [%p][%d]\n",
     530             :            cctx, cctx->cfd);
     531             : 
     532             :     /* The cli_ctx destructor will handle the rest */
     533           0 :     talloc_free(cctx);
     534           0 : }
     535             : 
     536           0 : static int sss_dp_init(struct resp_ctx *rctx,
     537             :                        struct sbus_vtable *dp_intf,
     538             :                        const char *cli_name,
     539             :                        struct sss_domain_info *domain)
     540             : {
     541             :     struct be_conn *be_conn;
     542             :     int ret;
     543             : 
     544           0 :     be_conn = talloc_zero(rctx, struct be_conn);
     545           0 :     if (!be_conn) return ENOMEM;
     546             : 
     547           0 :     be_conn->cli_name = cli_name;
     548           0 :     be_conn->domain = domain;
     549           0 :     be_conn->rctx = rctx;
     550             : 
     551             :     /* Set up SBUS connection to the monitor */
     552           0 :     ret = dp_get_sbus_address(be_conn, &be_conn->sbus_address, domain->name);
     553           0 :     if (ret != EOK) {
     554           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not locate DP address.\n");
     555           0 :         return ret;
     556             :     }
     557           0 :     ret = sbus_client_init(rctx, rctx->ev,
     558           0 :                            be_conn->sbus_address,
     559             :                            &be_conn->conn);
     560           0 :     if (ret != EOK) {
     561           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to connect to monitor services.\n");
     562           0 :         return ret;
     563             :     }
     564             : 
     565           0 :     ret = sbus_conn_register_iface(be_conn->conn, dp_intf, DP_PATH, rctx);
     566           0 :     if (ret != EOK) {
     567           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to export data provider.\n");
     568           0 :         return ret;
     569             :     }
     570             : 
     571           0 :     DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
     572             : 
     573             :     /* Identify ourselves to the DP */
     574           0 :     ret = rdp_register_client(be_conn, cli_name);
     575           0 :     if (ret != EOK) {
     576           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to identify to the DP!\n");
     577           0 :         return ret;
     578             :     }
     579             : 
     580           0 :     return EOK;
     581             : }
     582             : 
     583           0 : int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
     584             : {
     585             :     struct sockaddr_un addr;
     586             :     mode_t orig_umaskval;
     587             :     errno_t ret;
     588             :     int fd;
     589             : 
     590           0 :     fd = socket(AF_UNIX, SOCK_STREAM, 0);
     591           0 :     if (fd == -1) {
     592           0 :         return EIO;
     593             :     }
     594             : 
     595           0 :     orig_umaskval = umask(umaskval);
     596             : 
     597           0 :     ret = sss_fd_nonblocking(fd);
     598           0 :     if (ret != EOK) {
     599           0 :         goto done;
     600             :     }
     601             : 
     602           0 :     ret = set_close_on_exec(fd);
     603           0 :     if (ret != EOK) {
     604           0 :         goto done;
     605             :     }
     606             : 
     607           0 :     memset(&addr, 0, sizeof(addr));
     608           0 :     addr.sun_family = AF_UNIX;
     609           0 :     strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path) - 1);
     610           0 :     addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
     611             : 
     612             :     /* make sure we have no old sockets around */
     613           0 :     ret = unlink(sock_name);
     614           0 :     if (ret != 0 && errno != ENOENT) {
     615           0 :         ret = errno;
     616           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     617             :               "Cannot remove old socket (errno=%d), bind might fail!\n", ret);
     618             :     }
     619             : 
     620           0 :     if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
     621           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     622             :               "Unable to bind on socket '%s'\n", sock_name);
     623           0 :         ret = EIO;
     624           0 :         goto done;
     625             :     }
     626           0 :     if (listen(fd, 10) == -1) {
     627           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     628             :               "Unable to listen on socket '%s'\n", sock_name);
     629           0 :         ret = EIO;
     630           0 :         goto done;
     631             :     }
     632             : 
     633           0 :     ret = EOK;
     634             : 
     635             : done:
     636             :     /* restore previous umask value */
     637           0 :     umask(orig_umaskval);
     638           0 :     if (ret == EOK) {
     639           0 :         *_fd = fd;
     640             :     } else {
     641           0 :         close(fd);
     642             :     }
     643           0 :     return ret;
     644             : }
     645             : 
     646             : /* create a unix socket and listen to it */
     647           0 : static int set_unix_socket(struct resp_ctx *rctx)
     648             : {
     649             :     errno_t ret;
     650             :     struct accept_fd_ctx *accept_ctx;
     651             : 
     652             : /* for future use */
     653             : #if 0
     654             :     char *default_pipe;
     655             :     int ret;
     656             : 
     657             :     default_pipe = talloc_asprintf(rctx, "%s/%s", PIPE_PATH,
     658             :                                    rctx->sss_pipe_name);
     659             :     if (!default_pipe) {
     660             :         return ENOMEM;
     661             :     }
     662             : 
     663             :     ret = confdb_get_string(rctx->cdb, rctx,
     664             :                             rctx->confdb_socket_path, "unixSocket",
     665             :                             default_pipe, &rctx->sock_name);
     666             :     if (ret != EOK) {
     667             :         talloc_free(default_pipe);
     668             :         return ret;
     669             :     }
     670             :     talloc_free(default_pipe);
     671             : 
     672             :     default_pipe = talloc_asprintf(rctx, "%s/private/%s", PIPE_PATH,
     673             :                                    rctx->sss_pipe_name);
     674             :     if (!default_pipe) {
     675             :         return ENOMEM;
     676             :     }
     677             : 
     678             :     ret = confdb_get_string(rctx->cdb, rctx,
     679             :                             rctx->confdb_socket_path, "privUnixSocket",
     680             :                             default_pipe, &rctx->priv_sock_name);
     681             :     if (ret != EOK) {
     682             :         talloc_free(default_pipe);
     683             :         return ret;
     684             :     }
     685             :     talloc_free(default_pipe);
     686             : #endif
     687             : 
     688           0 :     if (rctx->sock_name != NULL ) {
     689             :         /* Set the umask so that permissions are set right on the socket.
     690             :          * It must be readable and writable by anybody on the system. */
     691           0 :         if (rctx->lfd == -1) {
     692           0 :             ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, SCKT_RSP_UMASK);
     693           0 :             if (ret != EOK) {
     694           0 :                 return ret;
     695             :             }
     696             :         }
     697             : 
     698           0 :         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
     699           0 :         if(!accept_ctx) goto failed;
     700           0 :         accept_ctx->rctx = rctx;
     701           0 :         accept_ctx->is_private = false;
     702             : 
     703           0 :         rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
     704             :                                    TEVENT_FD_READ, accept_fd_handler,
     705             :                                    accept_ctx);
     706           0 :         if (!rctx->lfde) {
     707           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Failed to queue handler on pipe\n");
     708           0 :             goto failed;
     709             :         }
     710             :     }
     711             : 
     712           0 :     if (rctx->priv_sock_name != NULL ) {
     713             :         /* create privileged pipe */
     714           0 :         if (rctx->priv_lfd == -1) {
     715           0 :             ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd,
     716             :                                  DFL_RSP_UMASK);
     717           0 :             if (ret != EOK) {
     718           0 :                 goto failed;
     719             :             }
     720             :         }
     721             : 
     722           0 :         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
     723           0 :         if(!accept_ctx) goto failed;
     724           0 :         accept_ctx->rctx = rctx;
     725           0 :         accept_ctx->is_private = true;
     726             : 
     727           0 :         rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
     728             :                                    TEVENT_FD_READ, accept_fd_handler,
     729             :                                    accept_ctx);
     730           0 :         if (!rctx->priv_lfde) {
     731           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     732             :                   "Failed to queue handler on privileged pipe\n");
     733           0 :             goto failed;
     734             :         }
     735             :     }
     736             : 
     737           0 :     return EOK;
     738             : 
     739             : failed:
     740           0 :     close(rctx->lfd);
     741           0 :     close(rctx->priv_lfd);
     742           0 :     return EIO;
     743             : }
     744             : 
     745           0 : static int sss_responder_ctx_destructor(void *ptr)
     746             : {
     747           0 :     struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
     748             : 
     749             :     /* mark that we are shutting down the responder, so it is propagated
     750             :      * into underlying contexts that are freed right before rctx */
     751           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Responder is being shut down\n");
     752           0 :     rctx->shutting_down = true;
     753             : 
     754           0 :     return 0;
     755             : }
     756             : 
     757           0 : static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
     758             :                                      struct confdb_ctx *cdb,
     759             :                                      struct sss_nc_ctx **ncache)
     760             : {
     761             :     uint32_t neg_timeout;
     762             :     uint32_t locals_timeout;
     763             :     int tmp_value;
     764             :     int ret;
     765             : 
     766             :     /* neg_timeout */
     767           0 :     ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
     768             :                          CONFDB_NSS_ENTRY_NEG_TIMEOUT,
     769             :                          15, &tmp_value);
     770           0 :     if (ret != EOK) {
     771           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     772             :               "Fatal failure of setup negative cache timeout.\n");
     773           0 :         ret = ENOENT;
     774           0 :         goto done;
     775             :     }
     776             : 
     777           0 :     if (tmp_value < 0) {
     778           0 :         ret = EINVAL;
     779           0 :         goto done;
     780             :     }
     781             : 
     782           0 :     neg_timeout = tmp_value;
     783           0 :     ret = EOK;
     784             : 
     785             :     /* local_timeout */
     786           0 :     ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
     787             :                          CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT,
     788             :                          0, &tmp_value);
     789           0 :     if (ret != EOK) {
     790           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     791             :               "Fatal failure of setup negative cache timeout.\n");
     792           0 :         ret = ENOENT;
     793           0 :         goto done;
     794             :     }
     795             : 
     796           0 :     if (tmp_value < 0) {
     797           0 :         ret = EINVAL;
     798           0 :         goto done;
     799             :     }
     800             : 
     801           0 :     locals_timeout = tmp_value;
     802           0 :     ret = EOK;
     803             : 
     804             :     /* negative cache init */
     805           0 :     ret = sss_ncache_init(mem_ctx, neg_timeout, locals_timeout, ncache);
     806           0 :     if (ret != EOK) {
     807           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     808             :               "Fatal failure of initializing negative cache.\n");
     809           0 :         goto done;
     810             :     }
     811             : 
     812           0 :     ret = EOK;
     813             : 
     814             : done:
     815           0 :     return ret;
     816             : }
     817             : 
     818           0 : int sss_process_init(TALLOC_CTX *mem_ctx,
     819             :                      struct tevent_context *ev,
     820             :                      struct confdb_ctx *cdb,
     821             :                      struct sss_cmd_table sss_cmds[],
     822             :                      const char *sss_pipe_name,
     823             :                      int pipe_fd,
     824             :                      const char *sss_priv_pipe_name,
     825             :                      int priv_pipe_fd,
     826             :                      const char *confdb_service_path,
     827             :                      const char *svc_name,
     828             :                      uint16_t svc_version,
     829             :                      struct mon_cli_iface *monitor_intf,
     830             :                      const char *cli_name,
     831             :                      struct sbus_vtable *dp_intf,
     832             :                      struct resp_ctx **responder_ctx)
     833             : {
     834             :     struct resp_ctx *rctx;
     835             :     struct sss_domain_info *dom;
     836             :     int ret;
     837           0 :     char *tmp = NULL;
     838             : 
     839           0 :     rctx = talloc_zero(mem_ctx, struct resp_ctx);
     840           0 :     if (!rctx) {
     841           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing resp_ctx\n");
     842           0 :         return ENOMEM;
     843             :     }
     844           0 :     rctx->ev = ev;
     845           0 :     rctx->cdb = cdb;
     846           0 :     rctx->sss_cmds = sss_cmds;
     847           0 :     rctx->sock_name = sss_pipe_name;
     848           0 :     rctx->priv_sock_name = sss_priv_pipe_name;
     849           0 :     rctx->lfd = pipe_fd;
     850           0 :     rctx->priv_lfd = priv_pipe_fd;
     851           0 :     rctx->confdb_service_path = confdb_service_path;
     852           0 :     rctx->shutting_down = false;
     853             : 
     854           0 :     talloc_set_destructor((TALLOC_CTX*)rctx, sss_responder_ctx_destructor);
     855             : 
     856           0 :     ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
     857             :                          CONFDB_RESPONDER_CLI_IDLE_TIMEOUT,
     858             :                          CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT,
     859             :                          &rctx->client_idle_timeout);
     860           0 :     if (ret != EOK) {
     861           0 :         DEBUG(SSSDBG_OP_FAILURE,
     862             :               "Cannot get the client idle timeout [%d]: %s\n",
     863             :                ret, strerror(ret));
     864           0 :         goto fail;
     865             :     }
     866             : 
     867             :     /* Ensure that the client timeout is at least ten seconds */
     868           0 :     if (rctx->client_idle_timeout < 10) {
     869           0 :         rctx->client_idle_timeout = 10;
     870             :     }
     871             : 
     872           0 :     ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
     873             :                          CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT,
     874             :                          GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout);
     875           0 :     if (ret != EOK) {
     876           0 :         DEBUG(SSSDBG_OP_FAILURE,
     877             :               "Cannnot get the default domain timeout [%d]: %s\n",
     878             :                ret, strerror(ret));
     879           0 :         goto fail;
     880             :     }
     881             : 
     882           0 :     if (rctx->domains_timeout < 0) {
     883           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "timeout can't be set to negative value, setting default\n");
     884           0 :         rctx->domains_timeout = GET_DOMAINS_DEFAULT_TIMEOUT;
     885             :     }
     886             : 
     887           0 :     ret = confdb_get_domains(rctx->cdb, &rctx->domains);
     888           0 :     if (ret != EOK) {
     889           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up domain map\n");
     890           0 :         goto fail;
     891             :     }
     892             : 
     893           0 :     ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
     894             :                             CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
     895             :                             &rctx->default_domain);
     896           0 :     if (ret != EOK) {
     897           0 :         DEBUG(SSSDBG_OP_FAILURE,
     898             :               "Cannnot get the default domain [%d]: %s\n",
     899             :                ret, strerror(ret));
     900           0 :         goto fail;
     901             :     }
     902             : 
     903           0 :     ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
     904             :                             CONFDB_MONITOR_OVERRIDE_SPACE, NULL,
     905             :                             &tmp);
     906           0 :     if (ret != EOK) {
     907           0 :         DEBUG(SSSDBG_OP_FAILURE,
     908             :               "Cannnot get the space substitution character [%d]: %s\n",
     909             :                ret, strerror(ret));
     910           0 :         goto fail;
     911             :     }
     912             : 
     913           0 :     if (tmp != NULL) {
     914           0 :         if (strlen(tmp) > 1) {
     915           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Option %s is longer than 1 character "
     916             :                   "only the first character %c will be used\n",
     917             :                   CONFDB_MONITOR_OVERRIDE_SPACE, tmp[0]);
     918             :         }
     919             : 
     920           0 :         rctx->override_space = tmp[0];
     921             :     }
     922             : 
     923           0 :     ret = sss_monitor_init(rctx, rctx->ev, monitor_intf,
     924             :                            svc_name, svc_version, rctx,
     925             :                            &rctx->mon_conn);
     926           0 :     if (ret != EOK) {
     927           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up message bus\n");
     928           0 :         goto fail;
     929             :     }
     930             : 
     931           0 :     for (dom = rctx->domains; dom; dom = get_next_domain(dom, 0)) {
     932           0 :         ret = sss_names_init(rctx->cdb, rctx->cdb, dom->name, &dom->names);
     933           0 :         if (ret != EOK) {
     934           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     935             :                   "fatal error initializing regex data for domain: %s\n",
     936             :                    dom->name);
     937           0 :             goto fail;
     938             :         }
     939             : 
     940             :         /* skip local domain, it doesn't have a backend */
     941           0 :         if (strcasecmp(dom->provider, "local") == 0) {
     942           0 :             continue;
     943             :         }
     944             : 
     945           0 :         ret = sss_dp_init(rctx, dp_intf, cli_name, dom);
     946           0 :         if (ret != EOK) {
     947           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     948             :                   "fatal error setting up backend connector\n");
     949           0 :             goto fail;
     950             :         }
     951             :     }
     952             : 
     953           0 :     ret = sysdb_init(rctx, rctx->domains, false);
     954           0 :     if (ret != EOK) {
     955           0 :         SYSDB_VERSION_ERROR_DAEMON(ret);
     956           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     957             :               "fatal error initializing sysdb connection\n");
     958           0 :         goto fail;
     959             :     }
     960             : 
     961             :     /* after all initializations we are ready to listen on our socket */
     962           0 :     ret = set_unix_socket(rctx);
     963           0 :     if (ret != EOK) {
     964           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing socket\n");
     965           0 :         goto fail;
     966             :     }
     967             : 
     968             :     /* Create DP request table */
     969           0 :     ret = sss_hash_create(rctx, 30, &rctx->dp_request_table);
     970           0 :     if (ret != EOK) {
     971           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     972             :               "Could not create hash table for the request queue\n");
     973           0 :         goto fail;
     974             :     }
     975             : 
     976           0 :     ret = responder_init_ncache(rctx, rctx->cdb, &rctx->ncache);
     977           0 :     if (ret != EOK) {
     978           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "fatal error initializing negcache\n");
     979           0 :         goto fail;
     980             :     }
     981             : 
     982           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Responder Initialization complete\n");
     983             : 
     984           0 :     *responder_ctx = rctx;
     985           0 :     return EOK;
     986             : 
     987             : fail:
     988           0 :     talloc_free(rctx);
     989           0 :     return ret;
     990             : }
     991             : 
     992           3 : int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
     993             :                            struct be_conn **_conn)
     994             : {
     995             :     struct be_conn *iter;
     996             : 
     997           3 :     if (!rctx->be_conns) return ENOENT;
     998             : 
     999           0 :     for (iter = rctx->be_conns; iter; iter = iter->next) {
    1000           0 :         if (strcasecmp(domain, iter->domain->name) == 0) break;
    1001             :     }
    1002             : 
    1003           0 :     if (!iter) return ENOENT;
    1004             : 
    1005           0 :     *_conn = iter;
    1006             : 
    1007           0 :     return EOK;
    1008             : }
    1009             : 
    1010             : struct sss_domain_info *
    1011          71 : responder_get_domain(struct resp_ctx *rctx, const char *name)
    1012             : {
    1013             :     struct sss_domain_info *dom;
    1014          71 :     struct sss_domain_info *ret_dom = NULL;
    1015             : 
    1016         164 :     for (dom = rctx->domains; dom;
    1017          22 :             dom = get_next_domain(dom, SSS_GND_DESCEND)) {
    1018          87 :         if (sss_domain_get_state(dom) == DOM_DISABLED) {
    1019           0 :             continue;
    1020             :         }
    1021             : 
    1022         109 :         if (strcasecmp(dom->name, name) == 0 ||
    1023          22 :             (dom->flat_name != NULL &&
    1024           0 :              strcasecmp(dom->flat_name, name) == 0)) {
    1025          65 :             ret_dom = dom;
    1026          65 :             break;
    1027             :         }
    1028             :     }
    1029             : 
    1030          71 :     if (!ret_dom) {
    1031           6 :         DEBUG(SSSDBG_OP_FAILURE, "Unknown domain [%s]\n", name);
    1032             :     }
    1033             : 
    1034          71 :     return ret_dom;
    1035             : }
    1036             : 
    1037           4 : errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
    1038             :                                    struct sss_domain_info **_ret_dom)
    1039             : {
    1040             :     struct sss_domain_info *dom;
    1041           4 :     struct sss_domain_info *ret_dom = NULL;
    1042             :     size_t id_len;
    1043             :     size_t dom_id_len;
    1044             :     int ret;
    1045             : 
    1046           4 :     if (id == NULL || _ret_dom == NULL) {
    1047           0 :         return EINVAL;
    1048             :     }
    1049             : 
    1050           4 :     id_len = strlen(id);
    1051             : 
    1052           8 :     for (dom = rctx->domains; dom;
    1053           0 :             dom = get_next_domain(dom, SSS_GND_DESCEND)) {
    1054           8 :         if (sss_domain_get_state(dom) == DOM_DISABLED ||
    1055           4 :                 dom->domain_id == NULL) {
    1056           0 :             continue;
    1057             :         }
    1058             : 
    1059           4 :         dom_id_len = strlen(dom->domain_id);
    1060           8 :         if ((id_len >= dom_id_len) &&
    1061           4 :             strncasecmp(dom->domain_id, id, dom_id_len) == 0) {
    1062           4 :             if (IS_SUBDOMAIN(dom) &&
    1063           0 :                 ((time(NULL) - dom->parent->subdomains_last_checked.tv_sec) >
    1064           0 :                                                       rctx->domains_timeout)) {
    1065           0 :                 DEBUG(SSSDBG_TRACE_FUNC, "Domain entry with id [%s] " \
    1066             :                                           "is expired.\n", id);
    1067           0 :                 ret = EAGAIN;
    1068           0 :                 goto done;
    1069             :             }
    1070           4 :             ret_dom = dom;
    1071           4 :             break;
    1072             :         }
    1073             :     }
    1074             : 
    1075           4 :     if (ret_dom == NULL) {
    1076           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unknown domain id [%s], checking for "
    1077             :                                   "possible subdomains!\n", id);
    1078           0 :         ret = ENOENT;
    1079             :     } else {
    1080           4 :         *_ret_dom = ret_dom;
    1081           4 :         ret = EOK;
    1082             :     }
    1083             : 
    1084             : done:
    1085           4 :     return ret;
    1086             : }
    1087             : 
    1088           0 : int responder_logrotate(struct sbus_request *dbus_req, void *data)
    1089             : {
    1090             :     errno_t ret;
    1091           0 :     struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx);
    1092             : 
    1093           0 :     ret = server_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
    1094           0 :     if (ret != EOK) return ret;
    1095             : 
    1096           0 :     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
    1097             : }
    1098             : 
    1099           0 : void responder_set_fd_limit(rlim_t fd_limit)
    1100             : {
    1101             :     struct rlimit current_limit, new_limit;
    1102             :     int limret;
    1103             : 
    1104             :     /* First, let's see if we have permission to just set
    1105             :      * the value as-is.
    1106             :      */
    1107           0 :     new_limit.rlim_cur = fd_limit;
    1108           0 :     new_limit.rlim_max = fd_limit;
    1109           0 :     limret = setrlimit(RLIMIT_NOFILE, &new_limit);
    1110           0 :     if (limret == 0) {
    1111           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
    1112             :               "Maximum file descriptors set to [%"SPRIrlim"]\n",
    1113             :                new_limit.rlim_cur);
    1114           0 :         return;
    1115             :     }
    1116             : 
    1117             :     /* We couldn't set the soft and hard limits to this
    1118             :      * value. Let's see how high we CAN set it.
    1119             :      */
    1120             : 
    1121             :     /* Determine the maximum hard limit */
    1122           0 :     limret = getrlimit(RLIMIT_NOFILE, &current_limit);
    1123           0 :     if (limret == 0) {
    1124           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    1125             :               "Current fd limit: [%"SPRIrlim"]\n",
    1126             :                current_limit.rlim_cur);
    1127             :         /* Choose the lesser of the requested and the hard limit */
    1128           0 :         if (current_limit.rlim_max < fd_limit) {
    1129           0 :             new_limit.rlim_cur = current_limit.rlim_max;
    1130             :         } else {
    1131           0 :             new_limit.rlim_cur = fd_limit;
    1132             :         }
    1133           0 :         new_limit.rlim_max = current_limit.rlim_max;
    1134             : 
    1135           0 :         limret = setrlimit(RLIMIT_NOFILE, &new_limit);
    1136           0 :         if (limret == 0) {
    1137           0 :             DEBUG(SSSDBG_CONF_SETTINGS,
    1138             :                   "Maximum file descriptors set to [%"SPRIrlim"]\n",
    1139             :                    new_limit.rlim_cur);
    1140             :         } else {
    1141           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    1142             :                   "Could not set new fd limits. Proceeding with "
    1143             :                    "[%"SPRIrlim"]\n", current_limit.rlim_cur);
    1144             :         }
    1145             :     } else {
    1146           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1147             :               "Could not determine fd limits. "
    1148             :                "Proceeding with system values\n");
    1149             :     }
    1150             : }

Generated by: LCOV version 1.10