LCOV - code coverage report
Current view: top level - responder/common - responder_common.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 33 383 8.6 %
Date: 2012-11-29 Functions: 1 20 5.0 %
Branches: 32 869 3.7 %

           Branch data     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 <unistd.h>
      26                 :            : #include <fcntl.h>
      27                 :            : #include <sys/types.h>
      28                 :            : #include <sys/stat.h>
      29                 :            : #include <sys/socket.h>
      30                 :            : #include <sys/un.h>
      31                 :            : #include <string.h>
      32                 :            : #include <sys/time.h>
      33                 :            : #include <errno.h>
      34                 :            : #include <popt.h>
      35                 :            : #include "util/util.h"
      36                 :            : #include "util/strtonum.h"
      37                 :            : #include "db/sysdb.h"
      38                 :            : #include "confdb/confdb.h"
      39                 :            : #include "dbus/dbus.h"
      40                 :            : #include "sbus/sssd_dbus.h"
      41                 :            : #include "responder/common/responder.h"
      42                 :            : #include "responder/common/responder_packet.h"
      43                 :            : #include "providers/data_provider.h"
      44                 :            : #include "monitor/monitor_interfaces.h"
      45                 :            : #include "sbus/sbus_client.h"
      46                 :            : 
      47                 :          0 : static errno_t set_nonblocking(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_GETFL, 0);
      55                 :            : 
      56                 :          0 :     errno = 0;
      57                 :            :     /* Set the non-blocking flag on this fd */
      58                 :          0 :     ferr = fcntl(fd, F_SETFL, v | O_NONBLOCK);
      59         [ #  # ]:          0 :     if (ferr < 0) {
      60                 :          0 :         error = errno;
      61 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Unable to set fd non-blocking: [%d][%s]\n",
         [ #  # ][ #  # ]
                 [ #  # ]
      62                 :            :                   error, strerror(error)));
      63                 :          0 :         return error;
      64                 :            :     }
      65                 :            :     return EOK;
      66                 :            : }
      67                 :            : 
      68                 :          0 : static errno_t set_close_on_exec(int fd)
      69                 :            : {
      70                 :            :     int v;
      71                 :            :     int ferr;
      72                 :            :     errno_t error;
      73                 :            : 
      74                 :            :     /* Get the current flags for this file descriptor */
      75                 :          0 :     v = fcntl(fd, F_GETFD, 0);
      76                 :            : 
      77                 :          0 :     errno = 0;
      78                 :            :     /* Set the close-on-exec flags on this fd */
      79                 :          0 :     ferr = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
      80         [ #  # ]:          0 :     if (ferr < 0) {
      81                 :          0 :         error = errno;
      82 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Unable to set fd close-on-exec: [%d][%s]\n",
         [ #  # ][ #  # ]
                 [ #  # ]
      83                 :            :                   error, strerror(error)));
      84                 :          0 :         return error;
      85                 :            :     }
      86                 :            :     return EOK;
      87                 :            : }
      88                 :            : 
      89                 :          0 : static int client_destructor(struct cli_ctx *ctx)
      90                 :            : {
      91                 :            :     errno_t ret;
      92                 :            : 
      93 [ #  # ][ #  # ]:          0 :     if ((ctx->cfd > 0) && close(ctx->cfd) < 0) {
      94                 :          0 :         ret = errno;
      95 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CRIT_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
      96                 :            :               ("Failed to close fd [%d]: [%s]\n",
      97                 :            :                ctx->cfd, strerror(ret)));
      98                 :            :     }
      99                 :            : 
     100 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
         [ #  # ][ #  # ]
                 [ #  # ]
     101                 :            :           ("Terminated client [%p][%d]\n",
     102                 :            :            ctx, ctx->cfd));
     103                 :          0 :     return 0;
     104                 :            : }
     105                 :            : 
     106                 :          0 : static errno_t get_client_cred(struct cli_ctx *cctx)
     107                 :            : {
     108                 :          0 :     cctx->client_euid = -1;
     109                 :          0 :     cctx->client_egid = -1;
     110                 :          0 :     cctx->client_pid = -1;
     111                 :            : 
     112                 :            : #ifdef HAVE_UCRED
     113                 :            :     int ret;
     114                 :            :     struct ucred client_cred;
     115                 :          0 :     socklen_t client_cred_len = sizeof(client_cred);
     116                 :            : 
     117                 :          0 :     ret = getsockopt(cctx->cfd, SOL_SOCKET, SO_PEERCRED, &client_cred,
     118                 :            :                      &client_cred_len);
     119         [ #  # ]:          0 :     if (ret != EOK) {
     120                 :          0 :         ret = errno;
     121 [ #  # ][ #  # ]:          0 :         DEBUG(1, ("getsock failed [%d][%s].\n", ret, strerror(ret)));
         [ #  # ][ #  # ]
                 [ #  # ]
     122                 :            :         return ret;
     123                 :            :     }
     124         [ #  # ]:          0 :     if (client_cred_len != sizeof(struct ucred)) {
     125 [ #  # ][ #  # ]:          0 :         DEBUG(1, ("getsockopt returned unexpected message size.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     126                 :            :         return ENOMSG;
     127                 :            :     }
     128                 :            : 
     129                 :          0 :     cctx->client_euid = client_cred.uid;
     130                 :          0 :     cctx->client_egid = client_cred.gid;
     131                 :          0 :     cctx->client_pid = client_cred.pid;
     132                 :            : 
     133 [ #  # ][ #  # ]:          0 :     DEBUG(9, ("Client creds: euid[%d] egid[%d] pid[%d].\n",
         [ #  # ][ #  # ]
                 [ #  # ]
     134                 :            :               cctx->client_euid, cctx->client_egid, cctx->client_pid));
     135                 :            : #endif
     136                 :            : 
     137                 :            :     return EOK;
     138                 :            : }
     139                 :            : 
     140                 :          0 : errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count,
     141                 :            :                            uid_t *allowed_uids)
     142                 :            : {
     143                 :            :     size_t c;
     144                 :            : 
     145 [ #  # ][ #  # ]:          0 :     if (allowed_uids == NULL) {
     146                 :            :         return EINVAL;
     147                 :            :     }
     148                 :            : 
     149 [ #  # ][ #  # ]:          0 :     for (c = 0; c < allowed_uids_count; c++) {
     150 [ #  # ][ #  # ]:          0 :         if (uid == allowed_uids[c]) {
     151                 :            :             return EOK;
     152                 :            :         }
     153                 :            :     }
     154                 :            : 
     155                 :            :     return EACCES;
     156                 :            : }
     157                 :            : 
     158                 :         12 : errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string,
     159                 :            :                                 bool allow_sss_loop,
     160                 :            :                                 size_t *_uid_count, uid_t **_uids)
     161                 :            : {
     162                 :            :     int ret;
     163                 :            :     size_t c;
     164                 :         12 :     char **list = NULL;
     165                 :            :     int list_size;
     166                 :         12 :     uid_t *uids = NULL;
     167                 :            :     char *endptr;
     168                 :            :     struct passwd *pwd;
     169                 :            : 
     170                 :         12 :     ret = split_on_separator(mem_ctx, cvs_string, ',', true, &list, &list_size);
     171         [ +  + ]:         12 :     if (ret != EOK) {
     172 [ +  - ][ +  - ]:          2 :         DEBUG(SSSDBG_OP_FAILURE, ("split_on_separator failed [%d][%s].\n",
         [ -  + ][ #  # ]
                 [ #  # ]
     173                 :            :                                   ret, strerror(ret)));
     174                 :            :         goto done;
     175                 :            :     }
     176                 :            : 
     177                 :         10 :     uids = talloc_array(mem_ctx, uint32_t, list_size);
     178         [ -  + ]:         10 :     if (uids == NULL) {
     179 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     180                 :            :         ret = ENOMEM;
     181                 :            :         goto done;
     182                 :            :     }
     183                 :            : 
     184         [ +  - ]:         10 :     if (allow_sss_loop) {
     185                 :         10 :         ret = unsetenv("_SSS_LOOPS");
     186         [ +  - ]:         10 :         if (ret != EOK) {
     187 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_OP_FAILURE, ("Failed to unset _SSS_LOOPS, getpwnam "
         [ #  # ][ #  # ]
                 [ #  # ]
     188                 :            :                                       "might not find sssd users.\n"));
     189                 :            :         }
     190                 :            :     }
     191                 :            : 
     192         [ +  + ]:         37 :     for (c = 0; c < list_size; c++) {
     193                 :         31 :         errno = 0;
     194         [ +  + ]:         31 :         if (*list[c] == '\0') {
     195 [ +  - ][ +  - ]:          1 :             DEBUG(SSSDBG_OP_FAILURE, ("Empty list item.\n"));
         [ -  + ][ #  # ]
                 [ #  # ]
     196                 :            :             ret = EINVAL;
     197                 :            :             goto done;
     198                 :            :         }
     199                 :            : 
     200                 :         30 :         uids[c] = strtouint32(list[c], &endptr, 10);
     201 [ +  + ][ +  + ]:         30 :         if (errno != 0 || *endptr != '\0') {
     202                 :          4 :             ret = errno;
     203         [ +  + ]:          4 :             if (ret == ERANGE) {
     204 [ +  - ][ +  - ]:          2 :                 DEBUG(SSSDBG_OP_FAILURE, ("List item [%s] is out of range.\n",
         [ -  + ][ #  # ]
                 [ #  # ]
     205                 :            :                                           list[c]));
     206                 :            :                 goto done;
     207                 :            :             }
     208                 :            : 
     209                 :          2 :             errno = 0;
     210                 :          2 :             pwd = getpwnam(list[c]);
     211         [ +  + ]:          2 :             if (pwd == NULL) {
     212 [ +  - ][ +  - ]:          1 :                 DEBUG(SSSDBG_OP_FAILURE, ("List item [%s] is neither a valid "
         [ -  + ][ #  # ]
                 [ #  # ]
     213                 :            :                                           "UID nor a user name which cloud be "
     214                 :            :                                           "resolved by getpwnam().\n", list[c]));
     215                 :            :                 ret = EINVAL;
     216                 :            :                 goto done;
     217                 :            :             }
     218                 :            : 
     219                 :          1 :             uids[c] = pwd->pw_uid;
     220                 :            :         }
     221                 :            :     }
     222                 :            : 
     223                 :          6 :     *_uid_count = list_size;
     224                 :          6 :     *_uids = uids;
     225                 :            : 
     226                 :          6 :     ret = EOK;
     227                 :            : 
     228                 :            : done:
     229         [ -  + ]:         12 :     if(setenv("_SSS_LOOPS", "NO", 0) != 0) {
     230 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE, ("Failed to set _SSS_LOOPS.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     231                 :            :     }
     232                 :         12 :     talloc_free(list);
     233         [ +  + ]:         12 :     if (ret != EOK) {
     234                 :          6 :         talloc_free(uids);
     235                 :            :     }
     236                 :            : 
     237                 :         12 :     return ret;
     238                 :            : }
     239                 :            : 
     240                 :            : 
     241                 :          0 : static void client_send(struct cli_ctx *cctx)
     242                 :            : {
     243                 :            :     int ret;
     244                 :            : 
     245                 :          0 :     ret = sss_packet_send(cctx->creq->out, cctx->cfd);
     246         [ #  # ]:          0 :     if (ret == EAGAIN) {
     247                 :            :         /* not all data was sent, loop again */
     248                 :            :         return;
     249                 :            :     }
     250         [ #  # ]:          0 :     if (ret != EOK) {
     251 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Failed to send data, aborting client!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     252                 :          0 :         talloc_free(cctx);
     253                 :          0 :         return;
     254                 :            :     }
     255                 :            : 
     256                 :            :     /* ok all sent */
     257                 :          0 :     TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
     258                 :          0 :     TEVENT_FD_READABLE(cctx->cfde);
     259                 :          0 :     talloc_free(cctx->creq);
     260                 :          0 :     cctx->creq = NULL;
     261                 :          0 :     return;
     262                 :            : }
     263                 :            : 
     264                 :          0 : static void client_recv(struct cli_ctx *cctx)
     265                 :            : {
     266                 :            :     int ret;
     267                 :            : 
     268         [ #  # ]:          0 :     if (!cctx->creq) {
     269                 :          0 :         cctx->creq = talloc_zero(cctx, struct cli_request);
     270         [ #  # ]:          0 :         if (!cctx->creq) {
     271 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("Failed to alloc request, aborting client!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     272                 :          0 :             talloc_free(cctx);
     273                 :          0 :             return;
     274                 :            :         }
     275                 :            :     }
     276                 :            : 
     277         [ #  # ]:          0 :     if (!cctx->creq->in) {
     278                 :          0 :         ret = sss_packet_new(cctx->creq, SSS_PACKET_MAX_RECV_SIZE,
     279                 :            :                              0, &cctx->creq->in);
     280         [ #  # ]:          0 :         if (ret != EOK) {
     281 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("Failed to alloc request, aborting client!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     282                 :          0 :             talloc_free(cctx);
     283                 :          0 :             return;
     284                 :            :         }
     285                 :            :     }
     286                 :            : 
     287                 :          0 :     ret = sss_packet_recv(cctx->creq->in, cctx->cfd);
     288   [ #  #  #  #  :          0 :     switch (ret) {
                      # ]
     289                 :            :     case EOK:
     290                 :            :         /* do not read anymore */
     291                 :          0 :         TEVENT_FD_NOT_READABLE(cctx->cfde);
     292                 :            :         /* execute command */
     293                 :          0 :         ret = sss_cmd_execute(cctx, cctx->rctx->sss_cmds);
     294         [ #  # ]:          0 :         if (ret != EOK) {
     295 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("Failed to execute request, aborting client!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     296                 :          0 :             talloc_free(cctx);
     297                 :            :         }
     298                 :            :         /* past this point cctx can be freed at any time by callbacks
     299                 :            :          * in case of error, do not use it */
     300                 :            :         return;
     301                 :            : 
     302                 :            :     case EAGAIN:
     303                 :            :         /* need to read still some data, loop again */
     304                 :            :         break;
     305                 :            : 
     306                 :            :     case EINVAL:
     307 [ #  # ][ #  # ]:          0 :         DEBUG(6, ("Invalid data from client, closing connection!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     308                 :          0 :         talloc_free(cctx);
     309                 :          0 :         break;
     310                 :            : 
     311                 :            :     case ENODATA:
     312 [ #  # ][ #  # ]:          0 :         DEBUG(5, ("Client disconnected!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     313                 :          0 :         talloc_free(cctx);
     314                 :          0 :         break;
     315                 :            : 
     316                 :            :     default:
     317 [ #  # ][ #  # ]:          0 :         DEBUG(6, ("Failed to read request, aborting client!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     318                 :          0 :         talloc_free(cctx);
     319                 :            :     }
     320                 :            : 
     321                 :            :     return;
     322                 :            : }
     323                 :            : 
     324                 :            : static errno_t reset_idle_timer(struct cli_ctx *cctx);
     325                 :            : 
     326                 :          0 : static void client_fd_handler(struct tevent_context *ev,
     327                 :            :                               struct tevent_fd *fde,
     328                 :            :                               uint16_t flags, void *ptr)
     329                 :            : {
     330                 :            :     errno_t ret;
     331                 :          0 :     struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
     332                 :            : 
     333                 :            :     /* Always reset the idle timer on any activity */
     334                 :          0 :     ret = reset_idle_timer(cctx);
     335         [ #  # ]:          0 :     if (ret != EOK) {
     336 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CRIT_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     337                 :            :               ("Could not create idle timer for client. "
     338                 :            :                "This connection may not auto-terminate\n"));
     339                 :            :         /* Non-fatal, continue */
     340                 :            :     }
     341                 :            : 
     342         [ #  # ]:          0 :     if (flags & TEVENT_FD_READ) {
     343                 :          0 :         client_recv(cctx);
     344                 :          0 :         return;
     345                 :            :     }
     346         [ #  # ]:          0 :     if (flags & TEVENT_FD_WRITE) {
     347                 :          0 :         client_send(cctx);
     348                 :          0 :         return;
     349                 :            :     }
     350                 :            : }
     351                 :            : 
     352                 :            : struct accept_fd_ctx {
     353                 :            :     struct resp_ctx *rctx;
     354                 :            :     bool is_private;
     355                 :            : };
     356                 :            : 
     357                 :            : static void idle_handler(struct tevent_context *ev,
     358                 :            :                          struct tevent_timer *te,
     359                 :            :                          struct timeval current_time,
     360                 :            :                          void *data);
     361                 :            : 
     362                 :          0 : static void accept_fd_handler(struct tevent_context *ev,
     363                 :            :                               struct tevent_fd *fde,
     364                 :            :                               uint16_t flags, void *ptr)
     365                 :            : {
     366                 :            :     /* accept and attach new event handler */
     367                 :          0 :     struct accept_fd_ctx *accept_ctx =
     368                 :            :             talloc_get_type(ptr, struct accept_fd_ctx);
     369                 :          0 :     struct resp_ctx *rctx = accept_ctx->rctx;
     370                 :            :     struct cli_ctx *cctx;
     371                 :            :     socklen_t len;
     372                 :            :     struct stat stat_buf;
     373                 :            :     int ret;
     374         [ #  # ]:          0 :     int fd = accept_ctx->is_private ? rctx->priv_lfd : rctx->lfd;
     375                 :            :     int client_fd;
     376                 :            : 
     377         [ #  # ]:          0 :     if (accept_ctx->is_private) {
     378                 :          0 :         ret = stat(rctx->priv_sock_name, &stat_buf);
     379         [ #  # ]:          0 :         if (ret == -1) {
     380 [ #  # ][ #  # ]:          0 :             DEBUG(1, ("stat on privileged pipe failed: [%d][%s].\n", errno,
         [ #  # ][ #  # ]
                 [ #  # ]
     381                 :            :                       strerror(errno)));
     382                 :            :             return;
     383                 :            :         }
     384                 :            : 
     385 [ #  # ][ #  # ]:          0 :         if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
                 [ #  # ]
     386                 :          0 :                (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
     387 [ #  # ][ #  # ]:          0 :             DEBUG(1, ("privileged pipe has an illegal status.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     388                 :            :     /* TODO: what is the best response to this condition? Terminate? */
     389                 :            :             return;
     390                 :            :         }
     391                 :            :     }
     392                 :            : 
     393                 :          0 :     cctx = talloc_zero(rctx, struct cli_ctx);
     394         [ #  # ]:          0 :     if (!cctx) {
     395                 :            :         struct sockaddr_un addr;
     396 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Out of memory trying to setup client context%s!\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     397                 :            :                   accept_ctx->is_private ? " on privileged pipe": ""));
     398                 :            :         /* accept and close to signal the client we have a problem */
     399                 :          0 :         memset(&addr, 0, sizeof(addr));
     400                 :          0 :         len = sizeof(addr);
     401                 :          0 :         client_fd = accept(fd, (struct sockaddr *)&addr, &len);
     402         [ #  # ]:          0 :         if (client_fd == -1) {
     403                 :            :             return;
     404                 :            :         }
     405                 :          0 :         close(client_fd);
     406                 :            :         return;
     407                 :            :     }
     408                 :            : 
     409                 :          0 :     len = sizeof(cctx->addr);
     410                 :          0 :     cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len);
     411         [ #  # ]:          0 :     if (cctx->cfd == -1) {
     412 [ #  # ][ #  # ]:          0 :         DEBUG(1, ("Accept failed [%s]\n", strerror(errno)));
         [ #  # ][ #  # ]
                 [ #  # ]
     413                 :          0 :         talloc_free(cctx);
     414                 :            :         return;
     415                 :            :     }
     416                 :            : 
     417                 :          0 :     cctx->priv = accept_ctx->is_private;
     418                 :            : 
     419                 :          0 :     ret = get_client_cred(cctx);
     420         [ #  # ]:          0 :     if (ret != EOK) {
     421 [ #  # ][ #  # ]:          0 :         DEBUG(2, ("get_client_cred failed, "
         [ #  # ][ #  # ]
                 [ #  # ]
     422                 :            :                   "client cred may not be available.\n"));
     423                 :            :     }
     424                 :            : 
     425         [ #  # ]:          0 :     if (rctx->allowed_uids_count != 0) {
     426         [ #  # ]:          0 :         if (cctx->client_euid == -1) {
     427 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_CRIT_FAILURE, ("allowed_uids configured, " \
         [ #  # ][ #  # ]
                 [ #  # ]
     428                 :            :                                         "but platform does not support " \
     429                 :            :                                         "reading peer credential from the " \
     430                 :            :                                         "socket. Access denied.\n"));
     431                 :          0 :             close(cctx->cfd);
     432                 :          0 :             talloc_free(cctx);
     433                 :            :             return;
     434                 :            :         }
     435                 :            : 
     436                 :          0 :         ret = check_allowed_uids(cctx->client_euid, rctx->allowed_uids_count,
     437                 :            :                                  rctx->allowed_uids);
     438         [ #  # ]:          0 :         if (ret != EOK) {
     439         [ #  # ]:          0 :             if (ret == EACCES) {
     440 [ #  # ][ #  # ]:          0 :                 DEBUG(SSSDBG_CRIT_FAILURE, ("Access denied for uid [%d].\n",
         [ #  # ][ #  # ]
                 [ #  # ]
     441                 :            :                                             cctx->client_euid));
     442                 :            :             } else {
     443 [ #  # ][ #  # ]:          0 :                 DEBUG(SSSDBG_OP_FAILURE, ("check_allowed_uids failed.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     444                 :            :             }
     445                 :          0 :             close(cctx->cfd);
     446                 :          0 :             talloc_free(cctx);
     447                 :            :             return;
     448                 :            :         }
     449                 :            :     }
     450                 :            : 
     451                 :          0 :     cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
     452                 :            :                                TEVENT_FD_READ, client_fd_handler, cctx);
     453         [ #  # ]:          0 :     if (!cctx->cfde) {
     454                 :          0 :         close(cctx->cfd);
     455                 :          0 :         talloc_free(cctx);
     456 [ #  # ][ #  # ]:          0 :         DEBUG(2, ("Failed to queue client handler%\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     457                 :            :                 accept_ctx->is_private ? " on privileged pipe" : ""));
     458                 :            :         return;
     459                 :            :     }
     460                 :            : 
     461                 :          0 :     cctx->ev = ev;
     462                 :          0 :     cctx->rctx = rctx;
     463                 :            : 
     464                 :          0 :     talloc_set_destructor(cctx, client_destructor);
     465                 :            : 
     466                 :            :     /* Set up the idle timer */
     467                 :          0 :     ret = reset_idle_timer(cctx);
     468         [ #  # ]:          0 :     if (ret != EOK) {
     469 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CRIT_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     470                 :            :               ("Could not create idle timer for client. "
     471                 :            :                "This connection may not auto-terminate\n"));
     472                 :            :         /* Non-fatal, continue */
     473                 :            :     }
     474                 :            : 
     475 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_FUNC,
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     476                 :            :           ("Client connected%s!\n",
     477                 :            :            accept_ctx->is_private ? " to privileged pipe" : ""));
     478                 :            : 
     479                 :            :     return;
     480                 :            : }
     481                 :            : 
     482                 :          0 : static errno_t reset_idle_timer(struct cli_ctx *cctx)
     483                 :            : {
     484                 :          0 :     struct timeval tv =
     485                 :          0 :             tevent_timeval_current_ofs(cctx->rctx->client_idle_timeout, 0);
     486                 :            : 
     487                 :          0 :     talloc_zfree(cctx->idle);
     488                 :            : 
     489                 :          0 :     cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, idle_handler, cctx);
     490         [ #  # ]:          0 :     if (!cctx->idle) return ENOMEM;
     491                 :            : 
     492 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_ALL,
         [ #  # ][ #  # ]
                 [ #  # ]
     493                 :            :           ("Idle timer re-set for client [%p][%d]\n",
     494                 :            :            cctx, cctx->cfd));
     495                 :            : 
     496                 :            :     return EOK;
     497                 :            : }
     498                 :            : 
     499                 :          0 : static void idle_handler(struct tevent_context *ev,
     500                 :            :                          struct tevent_timer *te,
     501                 :            :                          struct timeval current_time,
     502                 :            :                          void *data)
     503                 :            : {
     504                 :            :     /* This connection is idle. Terminate it */
     505                 :          0 :     struct cli_ctx *cctx =
     506                 :            :             talloc_get_type(data, struct cli_ctx);
     507                 :            : 
     508 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
         [ #  # ][ #  # ]
                 [ #  # ]
     509                 :            :           ("Terminating idle client [%p][%d]\n",
     510                 :            :            cctx, cctx->cfd));
     511                 :            : 
     512                 :            :     /* The cli_ctx destructor will handle the rest */
     513                 :          0 :     talloc_free(cctx);
     514                 :          0 : }
     515                 :            : 
     516                 :          0 : static int sss_dp_init(struct resp_ctx *rctx,
     517                 :            :                        struct sbus_interface *intf,
     518                 :            :                        const char *cli_name,
     519                 :            :                        struct sss_domain_info *domain)
     520                 :            : {
     521                 :            :     struct be_conn *be_conn;
     522                 :            :     int ret;
     523                 :            : 
     524                 :          0 :     be_conn = talloc_zero(rctx, struct be_conn);
     525         [ #  # ]:          0 :     if (!be_conn) return ENOMEM;
     526                 :            : 
     527                 :          0 :     be_conn->cli_name = cli_name;
     528                 :          0 :     be_conn->domain = domain;
     529                 :          0 :     be_conn->intf = intf;
     530                 :          0 :     be_conn->rctx = rctx;
     531                 :            : 
     532                 :            :     /* Set up SBUS connection to the monitor */
     533                 :          0 :     ret = dp_get_sbus_address(be_conn, &be_conn->sbus_address, domain->name);
     534         [ #  # ]:          0 :     if (ret != EOK) {
     535 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Could not locate DP address.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     536                 :          0 :         return ret;
     537                 :            :     }
     538                 :          0 :     ret = sbus_client_init(rctx, rctx->ev,
     539                 :          0 :                            be_conn->sbus_address,
     540                 :            :                            intf, &be_conn->conn,
     541                 :            :                            NULL, NULL);
     542         [ #  # ]:          0 :     if (ret != EOK) {
     543 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Failed to connect to monitor services.\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     544                 :          0 :         return ret;
     545                 :            :     }
     546                 :            : 
     547 [ #  # ][ #  # ]:          0 :     DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
     548                 :            : 
     549                 :            :     /* Identify ourselves to the DP */
     550                 :          0 :     ret = dp_common_send_id(be_conn->conn,
     551                 :            :                             DATA_PROVIDER_VERSION,
     552                 :            :                             cli_name);
     553         [ #  # ]:          0 :     if (ret != EOK) {
     554 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("Failed to identify to the DP!\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     555                 :          0 :         return ret;
     556                 :            :     }
     557                 :            : 
     558                 :            :     return EOK;
     559                 :            : }
     560                 :            : 
     561                 :            : /* create a unix socket and listen to it */
     562                 :          0 : static int set_unix_socket(struct resp_ctx *rctx)
     563                 :            : {
     564                 :            :     struct sockaddr_un addr;
     565                 :            :     errno_t ret;
     566                 :            :     struct accept_fd_ctx *accept_ctx;
     567                 :            : 
     568                 :            : /* for future use */
     569                 :            : #if 0
     570                 :            :     char *default_pipe;
     571                 :            :     int ret;
     572                 :            : 
     573                 :            :     default_pipe = talloc_asprintf(rctx, "%s/%s", PIPE_PATH,
     574                 :            :                                    rctx->sss_pipe_name);
     575                 :            :     if (!default_pipe) {
     576                 :            :         return ENOMEM;
     577                 :            :     }
     578                 :            : 
     579                 :            :     ret = confdb_get_string(rctx->cdb, rctx,
     580                 :            :                             rctx->confdb_socket_path, "unixSocket",
     581                 :            :                             default_pipe, &rctx->sock_name);
     582                 :            :     if (ret != EOK) {
     583                 :            :         talloc_free(default_pipe);
     584                 :            :         return ret;
     585                 :            :     }
     586                 :            :     talloc_free(default_pipe);
     587                 :            : 
     588                 :            :     default_pipe = talloc_asprintf(rctx, "%s/private/%s", PIPE_PATH,
     589                 :            :                                    rctx->sss_pipe_name);
     590                 :            :     if (!default_pipe) {
     591                 :            :         return ENOMEM;
     592                 :            :     }
     593                 :            : 
     594                 :            :     ret = confdb_get_string(rctx->cdb, rctx,
     595                 :            :                             rctx->confdb_socket_path, "privUnixSocket",
     596                 :            :                             default_pipe, &rctx->priv_sock_name);
     597                 :            :     if (ret != EOK) {
     598                 :            :         talloc_free(default_pipe);
     599                 :            :         return ret;
     600                 :            :     }
     601                 :            :     talloc_free(default_pipe);
     602                 :            : #endif
     603                 :            : 
     604         [ #  # ]:          0 :     if (rctx->sock_name != NULL ) {
     605                 :          0 :         rctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
     606         [ #  # ]:          0 :         if (rctx->lfd == -1) {
     607                 :            :             return EIO;
     608                 :            :         }
     609                 :            : 
     610                 :            :         /* Set the umask so that permissions are set right on the socket.
     611                 :            :          * It must be readable and writable by anybody on the system. */
     612                 :          0 :         umask(0111);
     613                 :            : 
     614                 :          0 :         ret = set_nonblocking(rctx->lfd);
     615         [ #  # ]:          0 :         if (ret != EOK) {
     616                 :            :             goto failed;
     617                 :            :         }
     618                 :            : 
     619                 :          0 :         ret = set_close_on_exec(rctx->lfd);
     620         [ #  # ]:          0 :         if (ret != EOK) {
     621                 :            :             goto failed;
     622                 :            :         }
     623                 :            : 
     624                 :          0 :         memset(&addr, 0, sizeof(addr));
     625                 :          0 :         addr.sun_family = AF_UNIX;
     626                 :          0 :         strncpy(addr.sun_path, rctx->sock_name, sizeof(addr.sun_path)-1);
     627                 :            :         addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
     628                 :            : 
     629                 :            :         /* make sure we have no old sockets around */
     630                 :          0 :         unlink(rctx->sock_name);
     631                 :            : 
     632         [ #  # ]:          0 :         if (bind(rctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
     633 [ #  # ][ #  # ]:          0 :             DEBUG(0,("Unable to bind on socket '%s'\n", rctx->sock_name));
         [ #  # ][ #  # ]
                 [ #  # ]
     634                 :            :             goto failed;
     635                 :            :         }
     636         [ #  # ]:          0 :         if (listen(rctx->lfd, 10) != 0) {
     637 [ #  # ][ #  # ]:          0 :             DEBUG(0,("Unable to listen on socket '%s'\n", rctx->sock_name));
         [ #  # ][ #  # ]
                 [ #  # ]
     638                 :            :             goto failed;
     639                 :            :         }
     640                 :            : 
     641                 :          0 :         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
     642         [ #  # ]:          0 :         if(!accept_ctx) goto failed;
     643                 :          0 :         accept_ctx->rctx = rctx;
     644                 :          0 :         accept_ctx->is_private = false;
     645                 :            : 
     646                 :          0 :         rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
     647                 :            :                                    TEVENT_FD_READ, accept_fd_handler,
     648                 :            :                                    accept_ctx);
     649         [ #  # ]:          0 :         if (!rctx->lfde) {
     650 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("Failed to queue handler on pipe\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     651                 :            :             goto failed;
     652                 :            :         }
     653                 :            :     }
     654                 :            : 
     655         [ #  # ]:          0 :     if (rctx->priv_sock_name != NULL ) {
     656                 :            :         /* create privileged pipe */
     657                 :          0 :         rctx->priv_lfd = socket(AF_UNIX, SOCK_STREAM, 0);
     658         [ #  # ]:          0 :         if (rctx->priv_lfd == -1) {
     659                 :          0 :             close(rctx->lfd);
     660                 :            :             return EIO;
     661                 :            :         }
     662                 :            : 
     663                 :          0 :         umask(0177);
     664                 :            : 
     665                 :          0 :         ret = set_nonblocking(rctx->priv_lfd);
     666         [ #  # ]:          0 :         if (ret != EOK) {
     667                 :            :             goto failed;
     668                 :            :         }
     669                 :            : 
     670                 :          0 :         ret = set_close_on_exec(rctx->priv_lfd);
     671         [ #  # ]:          0 :         if (ret != EOK) {
     672                 :            :             goto failed;
     673                 :            :         }
     674                 :            : 
     675                 :          0 :         memset(&addr, 0, sizeof(addr));
     676                 :          0 :         addr.sun_family = AF_UNIX;
     677                 :          0 :         strncpy(addr.sun_path, rctx->priv_sock_name, sizeof(addr.sun_path)-1);
     678                 :            :         addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
     679                 :            : 
     680                 :          0 :         unlink(rctx->priv_sock_name);
     681                 :            : 
     682         [ #  # ]:          0 :         if (bind(rctx->priv_lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
     683 [ #  # ][ #  # ]:          0 :             DEBUG(0,("Unable to bind on socket '%s'\n", rctx->priv_sock_name));
         [ #  # ][ #  # ]
                 [ #  # ]
     684                 :            :             goto failed;
     685                 :            :         }
     686         [ #  # ]:          0 :         if (listen(rctx->priv_lfd, 10) != 0) {
     687 [ #  # ][ #  # ]:          0 :             DEBUG(0,("Unable to listen on socket '%s'\n", rctx->priv_sock_name));
         [ #  # ][ #  # ]
                 [ #  # ]
     688                 :            :             goto failed;
     689                 :            :         }
     690                 :            : 
     691                 :          0 :         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
     692         [ #  # ]:          0 :         if(!accept_ctx) goto failed;
     693                 :          0 :         accept_ctx->rctx = rctx;
     694                 :          0 :         accept_ctx->is_private = true;
     695                 :            : 
     696                 :          0 :         rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
     697                 :            :                                    TEVENT_FD_READ, accept_fd_handler,
     698                 :            :                                    accept_ctx);
     699         [ #  # ]:          0 :         if (!rctx->priv_lfde) {
     700 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("Failed to queue handler on privileged pipe\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     701                 :            :             goto failed;
     702                 :            :         }
     703                 :            :     }
     704                 :            : 
     705                 :            :     /* we want default permissions on created files to be very strict,
     706                 :            :        so set our umask to 0177 */
     707                 :          0 :     umask(0177);
     708                 :            :     return EOK;
     709                 :            : 
     710                 :            : failed:
     711                 :            :     /* we want default permissions on created files to be very strict,
     712                 :            :        so set our umask to 0177 */
     713                 :          0 :     umask(0177);
     714                 :          0 :     close(rctx->lfd);
     715                 :          0 :     close(rctx->priv_lfd);
     716                 :            :     return EIO;
     717                 :            : }
     718                 :            : 
     719                 :          0 : static int sss_responder_ctx_destructor(void *ptr)
     720                 :            : {
     721                 :          0 :     struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
     722                 :            : 
     723                 :            :     /* mark that we are shutting down the responder, so it is propagated
     724                 :            :      * into underlying contexts that are freed right before rctx */
     725 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_FUNC, ("Responder is being shut down\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     726                 :          0 :     rctx->shutting_down = true;
     727                 :            : 
     728                 :          0 :     return 0;
     729                 :            : }
     730                 :            : 
     731                 :          0 : int sss_process_init(TALLOC_CTX *mem_ctx,
     732                 :            :                      struct tevent_context *ev,
     733                 :            :                      struct confdb_ctx *cdb,
     734                 :            :                      struct sss_cmd_table sss_cmds[],
     735                 :            :                      const char *sss_pipe_name,
     736                 :            :                      const char *sss_priv_pipe_name,
     737                 :            :                      const char *confdb_service_path,
     738                 :            :                      const char *svc_name,
     739                 :            :                      uint16_t svc_version,
     740                 :            :                      struct sbus_interface *monitor_intf,
     741                 :            :                      const char *cli_name,
     742                 :            :                      struct sbus_interface *dp_intf,
     743                 :            :                      struct resp_ctx **responder_ctx)
     744                 :            : {
     745                 :            :     struct resp_ctx *rctx;
     746                 :            :     struct sss_domain_info *dom;
     747                 :            :     int ret;
     748                 :            : 
     749                 :          0 :     rctx = talloc_zero(mem_ctx, struct resp_ctx);
     750         [ #  # ]:          0 :     if (!rctx) {
     751 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("fatal error initializing resp_ctx\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     752                 :            :         return ENOMEM;
     753                 :            :     }
     754                 :          0 :     rctx->ev = ev;
     755                 :          0 :     rctx->cdb = cdb;
     756                 :          0 :     rctx->sss_cmds = sss_cmds;
     757                 :          0 :     rctx->sock_name = sss_pipe_name;
     758                 :          0 :     rctx->priv_sock_name = sss_priv_pipe_name;
     759                 :          0 :     rctx->confdb_service_path = confdb_service_path;
     760                 :          0 :     rctx->shutting_down = false;
     761                 :            : 
     762                 :          0 :     talloc_set_destructor((TALLOC_CTX*)rctx, sss_responder_ctx_destructor);
     763                 :            : 
     764                 :          0 :     ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
     765                 :            :                          CONFDB_RESPONDER_CLI_IDLE_TIMEOUT,
     766                 :            :                          CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT,
     767                 :            :                          &rctx->client_idle_timeout);
     768         [ #  # ]:          0 :     if (ret != EOK) {
     769 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     770                 :            :               ("Cannot get the client idle timeout [%d]: %s\n",
     771                 :            :                ret, strerror(ret)));
     772                 :          0 :         return ret;
     773                 :            :     }
     774                 :            : 
     775                 :            :     /* Ensure that the client timeout is at least ten seconds */
     776         [ #  # ]:          0 :     if (rctx->client_idle_timeout < 10) {
     777                 :          0 :         rctx->client_idle_timeout = 10;
     778                 :            :     }
     779                 :            : 
     780                 :          0 :     ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
     781                 :            :                          CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT,
     782                 :            :                          GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout);
     783         [ #  # ]:          0 :     if (ret != EOK) {
     784 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     785                 :            :               ("Cannnot get the default domain timeout [%d]: %s\n",
     786                 :            :                ret, strerror(ret)));
     787                 :          0 :         return ret;
     788                 :            :     }
     789                 :            : 
     790         [ #  # ]:          0 :     if (rctx->domains_timeout < 0) {
     791 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CONF_SETTINGS, ("timeout can't be set to negative value, setting default\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     792                 :          0 :         rctx->domains_timeout = GET_DOMAINS_DEFAULT_TIMEOUT;
     793                 :            :     }
     794                 :            : 
     795                 :          0 :     ret = confdb_get_domains(rctx->cdb, &rctx->domains);
     796         [ #  # ]:          0 :     if (ret != EOK) {
     797 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("fatal error setting up domain map\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     798                 :          0 :         return ret;
     799                 :            :     }
     800                 :            : 
     801                 :          0 :     ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
     802                 :            :                             CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
     803                 :            :                             &rctx->default_domain);
     804         [ #  # ]:          0 :     if (ret != EOK) {
     805 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     806                 :            :               ("Cannnot get the default domain [%d]: %s\n",
     807                 :            :                ret, strerror(ret)));
     808                 :          0 :         return ret;
     809                 :            :     }
     810                 :            : 
     811                 :          0 :     ret = sss_monitor_init(rctx, rctx->ev, monitor_intf,
     812                 :            :                            svc_name, svc_version, rctx,
     813                 :            :                            &rctx->mon_conn);
     814         [ #  # ]:          0 :     if (ret != EOK) {
     815 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("fatal error setting up message bus\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     816                 :          0 :         return ret;
     817                 :            :     }
     818                 :            : 
     819         [ #  # ]:          0 :     for (dom = rctx->domains; dom; dom = dom->next) {
     820                 :          0 :         ret = sss_names_init(rctx->cdb, rctx->cdb, dom->name, &dom->names);
     821         [ #  # ]:          0 :         if (ret != EOK) {
     822 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_FATAL_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     823                 :            :                   ("fatal error initializing regex data for domain: %s\n",
     824                 :            :                    dom->name));
     825                 :          0 :             return ret;
     826                 :            :         }
     827                 :            : 
     828                 :            :         /* skip local domain, it doesn't have a backend */
     829         [ #  # ]:          0 :         if (strcasecmp(dom->provider, "local") == 0) {
     830                 :          0 :             continue;
     831                 :            :         }
     832                 :            : 
     833                 :          0 :         ret = sss_dp_init(rctx, dp_intf, cli_name, dom);
     834         [ #  # ]:          0 :         if (ret != EOK) {
     835 [ #  # ][ #  # ]:          0 :             DEBUG(0, ("fatal error setting up backend connector\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     836                 :          0 :             return ret;
     837                 :            :         }
     838                 :            :     }
     839                 :            : 
     840                 :          0 :     ret = sysdb_init(rctx, cdb, NULL, false, &rctx->db_list);
     841         [ #  # ]:          0 :     if (ret != EOK) {
     842         [ #  # ]:          0 :         SYSDB_VERSION_ERROR_DAEMON(ret);
     843 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("fatal error initializing resp_ctx\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     844                 :          0 :         return ret;
     845                 :            :     }
     846                 :            : 
     847                 :            :     /* after all initializations we are ready to listen on our socket */
     848                 :          0 :     ret = set_unix_socket(rctx);
     849         [ #  # ]:          0 :     if (ret != EOK) {
     850 [ #  # ][ #  # ]:          0 :         DEBUG(0, ("fatal error initializing socket\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     851                 :          0 :         return ret;
     852                 :            :     }
     853                 :            : 
     854                 :            :     /* Create DP request table */
     855                 :          0 :     ret = sss_hash_create(rctx, 30, &rctx->dp_request_table);
     856         [ #  # ]:          0 :     if (ret != EOK) {
     857 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_FATAL_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     858                 :            :               ("Could not create hash table for the request queue\n"));
     859                 :          0 :         return ret;
     860                 :            :     }
     861                 :            : 
     862 [ #  # ][ #  # ]:          0 :     DEBUG(SSSDBG_TRACE_FUNC, ("Responder Initialization complete\n"));
         [ #  # ][ #  # ]
                 [ #  # ]
     863                 :            : 
     864                 :          0 :     *responder_ctx = rctx;
     865                 :          0 :     return EOK;
     866                 :            : }
     867                 :            : 
     868                 :          0 : int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
     869                 :            :                            struct be_conn **_conn)
     870                 :            : {
     871                 :            :     struct be_conn *iter;
     872                 :            : 
     873         [ #  # ]:          0 :     if (!rctx->be_conns) return ENOENT;
     874                 :            : 
     875         [ #  # ]:          0 :     for (iter = rctx->be_conns; iter; iter = iter->next) {
     876         [ #  # ]:          0 :         if (strcasecmp(domain, iter->domain->name) == 0) break;
     877                 :            :     }
     878                 :            : 
     879         [ #  # ]:          0 :     if (!iter) return ENOENT;
     880                 :            : 
     881                 :          0 :     *_conn = iter;
     882                 :            : 
     883                 :          0 :     return EOK;
     884                 :            : }
     885                 :            : 
     886                 :            : struct sss_domain_info *
     887                 :          0 : responder_get_domain(TALLOC_CTX *sd_mem_ctx, struct resp_ctx *rctx,
     888                 :            :                      const char *domain)
     889                 :            : {
     890                 :          0 :     time_t now = time(NULL);
     891                 :            :     time_t time_diff;
     892                 :            :     struct sss_domain_info *dom;
     893                 :          0 :     struct sss_domain_info *ret_dom = NULL;
     894                 :            :     int i;
     895                 :            : 
     896         [ #  # ]:          0 :     for (dom = rctx->domains; dom; dom = dom->next) {
     897 [ #  # ][ #  # ]:          0 :         if (strcasecmp(dom->name, domain) == 0 ||
     898         [ #  # ]:          0 :             (dom->flat_name != NULL &&
     899                 :          0 :              strcasecmp(dom->flat_name, domain) == 0)) {
     900                 :            :             ret_dom = dom;
     901                 :            :             break;
     902                 :            :         }
     903                 :            : 
     904         [ #  # ]:          0 :         for (i = 0; i < dom->subdomain_count; i++) {
     905 [ #  # ][ #  # ]:          0 :             if (strcasecmp(dom->subdomains[i]->name, domain) == 0 ||
     906         [ #  # ]:          0 :                 (dom->subdomains[i]->flat_name != NULL &&
     907                 :          0 :                  strcasecmp(dom->subdomains[i]->flat_name, domain) == 0)) {
     908                 :            :                 /* Sub-domains may come and go, so we better copy the struct
     909                 :            :                  * for each request. */
     910                 :          0 :                 ret_dom = copy_subdomain(sd_mem_ctx, dom->subdomains[i]);
     911                 :          0 :                 break;
     912                 :            :             }
     913                 :            :         }
     914                 :            : 
     915                 :          0 :         time_diff = now - dom->subdomains_last_checked.tv_sec;
     916 [ #  # ][ #  # ]:          0 :         if (i < dom->subdomain_count && time_diff < rctx->domains_timeout) break;
     917                 :            :     }
     918                 :            :     /* FIXME: we might want to return a real error, e.g. if copy_subdomain
     919                 :            :      * fails. */
     920         [ #  # ]:          0 :     if (!ret_dom) {
     921 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_OP_FAILURE, ("Unknown domain [%s], checking for"
         [ #  # ][ #  # ]
                 [ #  # ]
     922                 :            :                                   "possible subdomains!\n", domain));
     923                 :            :     }
     924                 :            : 
     925                 :          0 :     return ret_dom;
     926                 :            : }
     927                 :            : 
     928                 :          0 : int responder_logrotate(DBusMessage *message,
     929                 :            :                         struct sbus_connection *conn)
     930                 :            : {
     931                 :            :     errno_t ret;
     932                 :          0 :     struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
     933                 :            :                                             struct resp_ctx);
     934                 :            : 
     935                 :          0 :     ret = monitor_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
     936         [ #  # ]:          0 :     if (ret != EOK) return ret;
     937                 :            : 
     938                 :          0 :     return monitor_common_pong(message, conn);
     939                 :            : }
     940                 :            : 
     941                 :          0 : void responder_set_fd_limit(rlim_t fd_limit)
     942                 :            : {
     943                 :            :     struct rlimit current_limit, new_limit;
     944                 :            :     int limret;
     945                 :            : 
     946                 :            :     /* First, let's see if we have permission to just set
     947                 :            :      * the value as-is.
     948                 :            :      */
     949                 :          0 :     new_limit.rlim_cur = fd_limit;
     950                 :          0 :     new_limit.rlim_max = fd_limit;
     951                 :          0 :     limret = setrlimit(RLIMIT_NOFILE, &new_limit);
     952         [ #  # ]:          0 :     if (limret == 0) {
     953 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CONF_SETTINGS,
         [ #  # ][ #  # ]
                 [ #  # ]
     954                 :            :               ("Maximum file descriptors set to [%d]\n",
     955                 :            :                new_limit.rlim_cur));
     956                 :          0 :         return;
     957                 :            :     }
     958                 :            : 
     959                 :            :     /* We couldn't set the soft and hard limits to this
     960                 :            :      * value. Let's see how high we CAN set it.
     961                 :            :      */
     962                 :            : 
     963                 :            :     /* Determine the maximum hard limit */
     964                 :          0 :     limret = getrlimit(RLIMIT_NOFILE, &current_limit);
     965         [ #  # ]:          0 :     if (limret == 0) {
     966 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
         [ #  # ][ #  # ]
                 [ #  # ]
     967                 :            :               ("Current fd limit: [%d]\n",
     968                 :            :                current_limit.rlim_cur));
     969                 :            :         /* Choose the lesser of the requested and the hard limit */
     970         [ #  # ]:          0 :         if (current_limit.rlim_max < fd_limit) {
     971                 :          0 :             new_limit.rlim_cur = current_limit.rlim_max;
     972                 :            :         } else {
     973                 :          0 :             new_limit.rlim_cur = fd_limit;
     974                 :            :         }
     975                 :          0 :         new_limit.rlim_max = current_limit.rlim_max;
     976                 :            : 
     977                 :          0 :         limret = setrlimit(RLIMIT_NOFILE, &new_limit);
     978         [ #  # ]:          0 :         if (limret == 0) {
     979 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_CONF_SETTINGS,
         [ #  # ][ #  # ]
                 [ #  # ]
     980                 :            :                   ("Maximum file descriptors set to [%d]\n",
     981                 :            :                    new_limit.rlim_cur));
     982                 :            :         } else {
     983 [ #  # ][ #  # ]:          0 :             DEBUG(SSSDBG_CRIT_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     984                 :            :                   ("Could not set new fd limits. Proceeding with [%d]\n",
     985                 :            :                    current_limit.rlim_cur));
     986                 :            :         }
     987                 :            :     } else {
     988 [ #  # ][ #  # ]:          0 :         DEBUG(SSSDBG_CRIT_FAILURE,
         [ #  # ][ #  # ]
                 [ #  # ]
     989                 :            :               ("Could not determine fd limits. "
     990                 :            :                "Proceeding with system values\n"));
     991                 :            :     }
     992                 :            : }

Generated by: LCOV version 1.9