LCOV - code coverage report
Current view: top level - responder/pam - pamsrv.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 147 0.0 %
Date: 2015-10-19 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    PAM Responder
       5             : 
       6             :    Copyright (C) Simo Sorce <ssorce@redhat.com>   2009
       7             :    Copyright (C) Sumit Bose <sbose@redhat.com>    2009
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include <stdio.h>
      24             : #include <unistd.h>
      25             : #include <fcntl.h>
      26             : #include <sys/types.h>
      27             : #include <sys/stat.h>
      28             : #include <sys/socket.h>
      29             : #include <sys/un.h>
      30             : #include <string.h>
      31             : #include <sys/time.h>
      32             : #include <errno.h>
      33             : #include <popt.h>
      34             : #include <dbus/dbus.h>
      35             : 
      36             : #include "util/util.h"
      37             : #include "db/sysdb.h"
      38             : #include "confdb/confdb.h"
      39             : #include "sbus/sssd_dbus.h"
      40             : #include "responder/common/responder_packet.h"
      41             : #include "providers/data_provider.h"
      42             : #include "monitor/monitor_interfaces.h"
      43             : #include "sbus/sbus_client.h"
      44             : #include "responder/pam/pamsrv.h"
      45             : #include "responder/common/negcache.h"
      46             : #include "responder/common/responder_sbus.h"
      47             : 
      48             : #define DEFAULT_PAM_FD_LIMIT 8192
      49             : #define ALL_UIDS_ALLOWED "all"
      50             : #define ALL_DOMAIMS_ARE_PUBLIC "all"
      51             : #define NO_DOMAIMS_ARE_PUBLIC "none"
      52             : #define DEFAULT_ALLOWED_UIDS ALL_UIDS_ALLOWED
      53             : #define DEFAULT_PAM_CERT_AUTH false
      54             : #define DEFAULT_PAM_CERT_DB_PATH SYSCONFDIR"/pki/nssdb"
      55             : 
      56             : struct mon_cli_iface monitor_pam_methods = {
      57             :     { &mon_cli_iface_meta, 0 },
      58             :     .ping = monitor_common_pong,
      59             :     .resInit = monitor_common_res_init,
      60             :     .shutDown = NULL,
      61             :     .goOffline = NULL,
      62             :     .resetOffline = NULL,
      63             :     .rotateLogs = responder_logrotate,
      64             :     .clearMemcache = NULL,
      65             :     .clearEnumCache = NULL,
      66             :     .sysbusReconnect = NULL,
      67             : };
      68             : 
      69             : static struct data_provider_iface pam_dp_methods = {
      70             :     { &data_provider_iface_meta, 0 },
      71             :     .RegisterService = NULL,
      72             :     .pamHandler = NULL,
      73             :     .sudoHandler = NULL,
      74             :     .autofsHandler = NULL,
      75             :     .hostHandler = NULL,
      76             :     .getDomains = NULL,
      77             :     .getAccountInfo = NULL,
      78             : };
      79             : 
      80           0 : static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void *pvt)
      81             : {
      82           0 :     struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
      83             :     int ret;
      84             : 
      85             :     /* Did we reconnect successfully? */
      86           0 :     if (status == SBUS_RECONNECT_SUCCESS) {
      87           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Reconnected to the Data Provider.\n");
      88             : 
      89             :         /* Identify ourselves to the data provider */
      90           0 :         ret = dp_common_send_id(be_conn->conn,
      91             :                                 DATA_PROVIDER_VERSION,
      92             :                                 "PAM");
      93             :         /* all fine */
      94           0 :         if (ret == EOK) {
      95           0 :             handle_requests_after_reconnect(be_conn->rctx);
      96           0 :             return;
      97             :         }
      98             :     }
      99             : 
     100             :     /* Handle failure */
     101           0 :     DEBUG(SSSDBG_FATAL_FAILURE, "Could not reconnect to %s provider.\n",
     102             :               be_conn->domain->name);
     103             : 
     104             :     /* FIXME: kill the frontend and let the monitor restart it ? */
     105             :     /* pam_shutdown(rctx); */
     106             : }
     107             : 
     108           0 : static errno_t get_trusted_uids(struct pam_ctx *pctx)
     109             : {
     110             :     char *uid_str;
     111             :     errno_t ret;
     112             : 
     113           0 :     ret = confdb_get_string(pctx->rctx->cdb, pctx->rctx,
     114             :                             CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_TRUSTED_USERS,
     115             :                             DEFAULT_ALLOWED_UIDS, &uid_str);
     116           0 :     if (ret != EOK) {
     117           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get allowed UIDs.\n");
     118           0 :         goto done;
     119             :     }
     120             : 
     121           0 :     if (strcmp(uid_str, ALL_UIDS_ALLOWED) == 0) {
     122           0 :          DEBUG(SSSDBG_TRACE_FUNC, "All UIDs are allowed.\n");
     123           0 :          pctx->trusted_uids_count = 0;
     124             :     } else {
     125           0 :         ret = csv_string_to_uid_array(pctx->rctx, uid_str, true,
     126             :                                       &pctx->trusted_uids_count,
     127             :                                       &pctx->trusted_uids);
     128             :     }
     129             : 
     130           0 :     talloc_free(uid_str);
     131           0 :     if (ret != EOK) {
     132           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
     133           0 :         goto done;
     134             :     }
     135             : 
     136             : done:
     137           0 :     return ret;
     138             : }
     139             : 
     140           0 : static errno_t get_public_domains(TALLOC_CTX *mem_ctx, struct pam_ctx *pctx)
     141             : {
     142           0 :     char *domains_str = NULL;
     143             :     errno_t ret;
     144             : 
     145           0 :     ret = confdb_get_string(pctx->rctx->cdb, pctx->rctx,
     146             :                             CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_PUBLIC_DOMAINS,
     147             :                             NO_DOMAIMS_ARE_PUBLIC, &domains_str);
     148           0 :     if (ret != EOK) {
     149           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get allowed UIDs.\n");
     150           0 :         goto done;
     151             :     }
     152             : 
     153           0 :     if (strcmp(domains_str, ALL_DOMAIMS_ARE_PUBLIC) == 0) { /* all */
     154             :         /* copy all domains */
     155           0 :         ret = get_dom_names(mem_ctx,
     156           0 :                             pctx->rctx->domains,
     157             :                             &pctx->public_domains,
     158             :                             &pctx->public_domains_count);
     159           0 :         if (ret != EOK) {
     160           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "get_dom_names failed.\n");
     161           0 :             goto done;
     162             :         }
     163           0 :     } else if (strcmp(domains_str, NO_DOMAIMS_ARE_PUBLIC) == 0) { /* none */
     164           0 :         pctx->public_domains = NULL;
     165           0 :         pctx->public_domains_count = 0;
     166             :     } else {
     167           0 :         ret = split_on_separator(mem_ctx, domains_str, ',', true, false,
     168             :                                  &pctx->public_domains,
     169             :                                  &pctx->public_domains_count);
     170           0 :         if (ret != EOK) {
     171           0 :             DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
     172             :                   ret, strerror(ret));
     173           0 :             goto done;
     174             :         }
     175             :     }
     176             : 
     177           0 :     ret = EOK;
     178             : 
     179             : done:
     180           0 :     talloc_free(domains_str);
     181           0 :     return ret;
     182             : }
     183             : 
     184           0 : static int pam_process_init(TALLOC_CTX *mem_ctx,
     185             :                             struct tevent_context *ev,
     186             :                             struct confdb_ctx *cdb,
     187             :                             int pipe_fd, int priv_pipe_fd)
     188             : {
     189             :     struct resp_ctx *rctx;
     190             :     struct sss_cmd_table *pam_cmds;
     191             :     struct be_conn *iter;
     192             :     struct pam_ctx *pctx;
     193             :     int ret, max_retries;
     194             :     int id_timeout;
     195             :     int fd_limit;
     196             : 
     197           0 :     pam_cmds = get_pam_cmds();
     198           0 :     ret = sss_process_init(mem_ctx, ev, cdb,
     199             :                            pam_cmds,
     200             :                            SSS_PAM_SOCKET_NAME, pipe_fd,
     201             :                            SSS_PAM_PRIV_SOCKET_NAME, priv_pipe_fd,
     202             :                            CONFDB_PAM_CONF_ENTRY,
     203             :                            SSS_PAM_SBUS_SERVICE_NAME,
     204             :                            SSS_PAM_SBUS_SERVICE_VERSION,
     205             :                            &monitor_pam_methods,
     206             :                            "PAM", &pam_dp_methods.vtable,
     207             :                            &rctx);
     208           0 :     if (ret != EOK) {
     209           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "sss_process_init() failed\n");
     210           0 :         return ret;
     211             :     }
     212             : 
     213           0 :     pctx = talloc_zero(rctx, struct pam_ctx);
     214           0 :     if (!pctx) {
     215           0 :         ret = ENOMEM;
     216           0 :         goto done;
     217             :     }
     218             : 
     219           0 :     pctx->rctx = rctx;
     220           0 :     pctx->rctx->pvt_ctx = pctx;
     221             : 
     222           0 :     ret = get_trusted_uids(pctx);
     223           0 :     if (ret != EOK) {
     224           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "get_trusted_uids failed: %d:[%s].\n",
     225             :               ret, sss_strerror(ret));
     226           0 :         goto done;
     227             :     }
     228             : 
     229           0 :     ret = get_public_domains(pctx, pctx);
     230           0 :     if (ret != EOK) {
     231           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "get_public_domains failed: %d:[%s].\n",
     232             :               ret, sss_strerror(ret));
     233           0 :         goto done;
     234             :     }
     235             : 
     236             :     /* Enable automatic reconnection to the Data Provider */
     237             : 
     238             :     /* FIXME: "retries" is too generic, either get it from a global config
     239             :      * or specify these retries are about the sbus connections to DP */
     240           0 :     ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY,
     241             :                          CONFDB_SERVICE_RECON_RETRIES, 3, &max_retries);
     242           0 :     if (ret != EOK) {
     243           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     244             :               "Failed to set up automatic reconnection\n");
     245           0 :         goto done;
     246             :     }
     247             : 
     248           0 :     for (iter = pctx->rctx->be_conns; iter; iter = iter->next) {
     249           0 :         sbus_reconnect_init(iter->conn, max_retries,
     250             :                             pam_dp_reconnect_init, iter);
     251             :     }
     252             : 
     253             :     /* Set up the negative cache */
     254           0 :     ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
     255             :                          CONFDB_NSS_ENTRY_NEG_TIMEOUT, 15,
     256             :                          &pctx->neg_timeout);
     257           0 :     if (ret != EOK) goto done;
     258             : 
     259             :     /* Set up the PAM identity timeout */
     260           0 :     ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
     261             :                          CONFDB_PAM_ID_TIMEOUT, 5,
     262             :                          &id_timeout);
     263           0 :     if (ret != EOK) goto done;
     264             : 
     265           0 :     pctx->id_timeout = (size_t)id_timeout;
     266             : 
     267           0 :     ret = sss_ncache_init(pctx, &pctx->ncache);
     268           0 :     if (ret != EOK) {
     269           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     270             :               "fatal error initializing negative cache\n");
     271           0 :         goto done;
     272             :     }
     273             : 
     274           0 :     ret = sss_ncache_prepopulate(pctx->ncache, cdb, pctx->rctx);
     275           0 :     if (ret != EOK) {
     276           0 :         goto done;
     277             :     }
     278             : 
     279             :     /* Create table for initgroup lookups */
     280           0 :     ret = sss_hash_create(pctx, 10, &pctx->id_table);
     281           0 :     if (ret != EOK) {
     282           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     283             :               "Could not create initgroups hash table: [%s]\n",
     284             :               strerror(ret));
     285           0 :         goto done;
     286             :     }
     287             : 
     288             :     /* Set up file descriptor limits */
     289           0 :     ret = confdb_get_int(pctx->rctx->cdb,
     290             :                          CONFDB_PAM_CONF_ENTRY,
     291             :                          CONFDB_SERVICE_FD_LIMIT,
     292             :                          DEFAULT_PAM_FD_LIMIT,
     293             :                          &fd_limit);
     294           0 :     if (ret != EOK) {
     295           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     296             :               "Failed to set up file descriptor limit\n");
     297           0 :         goto done;
     298             :     }
     299           0 :     responder_set_fd_limit(fd_limit);
     300             : 
     301           0 :     ret = schedule_get_domains_task(rctx, rctx->ev, rctx, pctx->ncache);
     302           0 :     if (ret != EOK) {
     303           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n");
     304           0 :         goto done;
     305             :     }
     306             : 
     307             :     /* Check if certificate based authentication is enabled */
     308           0 :     ret = confdb_get_bool(pctx->rctx->cdb,
     309             :                           CONFDB_PAM_CONF_ENTRY,
     310             :                           CONFDB_PAM_CERT_AUTH,
     311             :                           DEFAULT_PAM_CERT_AUTH,
     312             :                           &pctx->cert_auth);
     313           0 :     if (ret != EOK) {
     314           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to determine get cert db path.\n");
     315           0 :         goto done;
     316             :     }
     317             : 
     318           0 :     pctx->p11_child_debug_fd = -1;
     319           0 :     if (pctx->cert_auth) {
     320           0 :         ret = p11_child_init(pctx);
     321           0 :         if (ret != EOK) {
     322           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "p11_child_init failed.\n");
     323           0 :             goto done;
     324             :         }
     325             : 
     326           0 :         ret = confdb_get_string(pctx->rctx->cdb, pctx,
     327             :                                 CONFDB_PAM_CONF_ENTRY,
     328             :                                 CONFDB_PAM_CERT_DB_PATH,
     329             :                                 DEFAULT_PAM_CERT_DB_PATH,
     330             :                                 &pctx->nss_db);
     331           0 :         if (ret != EOK) {
     332           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     333             :                   "Failed to determine if certificate based authentication is " \
     334             :                   "enabled or not.\n");
     335           0 :             goto done;
     336             :         }
     337             :     }
     338             : 
     339           0 :     ret = EOK;
     340             : 
     341             : done:
     342           0 :     if (ret != EOK) {
     343           0 :         talloc_free(rctx);
     344             :     }
     345           0 :     return ret;
     346             : }
     347             : 
     348           0 : int main(int argc, const char *argv[])
     349             : {
     350             :     int opt;
     351             :     poptContext pc;
     352             :     struct main_context *main_ctx;
     353             :     int ret;
     354             :     uid_t uid;
     355             :     gid_t gid;
     356             :     int pipe_fd;
     357             :     int priv_pipe_fd;
     358             : 
     359           0 :     struct poptOption long_options[] = {
     360             :         POPT_AUTOHELP
     361           0 :         SSSD_MAIN_OPTS
     362           0 :         SSSD_SERVER_OPTS(uid, gid)
     363             :         POPT_TABLEEND
     364             :     };
     365             : 
     366             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
     367           0 :     debug_level = SSSDBG_INVALID;
     368             : 
     369           0 :     umask(DFL_RSP_UMASK);
     370             : 
     371           0 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     372           0 :     while((opt = poptGetNextOpt(pc)) != -1) {
     373             :         switch(opt) {
     374             :         default:
     375           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     376             :                              poptBadOption(pc, 0), poptStrerror(opt));
     377           0 :             poptPrintUsage(pc, stderr, 0);
     378           0 :             return 1;
     379             :         }
     380             :     }
     381             : 
     382           0 :     poptFreeContext(pc);
     383             : 
     384           0 :     DEBUG_INIT(debug_level);
     385             : 
     386             :     /* set up things like debug, signals, daemonization, etc... */
     387           0 :     debug_log_file = "sssd_pam";
     388             : 
     389             :     /* Crate pipe file descriptors here before privileges are dropped
     390             :      * in server_setup() */
     391           0 :     ret = create_pipe_fd(SSS_PAM_SOCKET_NAME, &pipe_fd, SCKT_RSP_UMASK);
     392           0 :     if (ret != EOK) {
     393           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     394             :               "create_pipe_fd failed [%d]: %s.\n",
     395             :               ret, sss_strerror(ret));
     396           0 :         return 2;
     397             :     }
     398             : 
     399           0 :     ret = create_pipe_fd(SSS_PAM_PRIV_SOCKET_NAME, &priv_pipe_fd,
     400             :                          DFL_RSP_UMASK);
     401           0 :     if (ret != EOK) {
     402           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     403             :               "create_pipe_fd failed (priviledged pipe) [%d]: %s.\n",
     404             :               ret, sss_strerror(ret));
     405           0 :         return 2;
     406             :     }
     407             : 
     408           0 :     ret = server_setup("sssd[pam]", 0, uid, gid, CONFDB_PAM_CONF_ENTRY, &main_ctx);
     409           0 :     if (ret != EOK) return 2;
     410             : 
     411           0 :     ret = die_if_parent_died();
     412           0 :     if (ret != EOK) {
     413             :         /* This is not fatal, don't return */
     414           0 :         DEBUG(SSSDBG_OP_FAILURE,
     415             :               "Could not set up to exit when parent process does\n");
     416             :     }
     417             : 
     418           0 :     ret = pam_process_init(main_ctx,
     419           0 :                            main_ctx->event_ctx,
     420           0 :                            main_ctx->confdb_ctx,
     421             :                            pipe_fd, priv_pipe_fd);
     422           0 :     if (ret != EOK) return 3;
     423             : 
     424             :     /* loop on main */
     425           0 :     server_loop(main_ctx);
     426             : 
     427           0 :     return 0;
     428             : }
     429             : 

Generated by: LCOV version 1.10