LCOV - code coverage report
Current view: top level - providers/data_provider - dp_target_auth.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 139 0.0 %
Date: 2016-06-29 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2016 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <talloc.h>
      22             : #include <tevent.h>
      23             : #include <security/pam_appl.h>
      24             : #include <security/pam_modules.h>
      25             : 
      26             : #include "sbus/sssd_dbus.h"
      27             : #include "providers/data_provider/dp_private.h"
      28             : #include "providers/data_provider/dp_iface.h"
      29             : #include "providers/backend.h"
      30             : #include "util/util.h"
      31             : 
      32           0 : static void dp_pam_reply(struct sbus_request *sbus_req,
      33             :                          const char *request_name,
      34             :                          struct pam_data *pd)
      35             : {
      36             :     DBusMessage *reply;
      37             :     dbus_bool_t dbret;
      38             : 
      39           0 :     DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name,
      40             :                  "Sending result [%d][%s]", pd->pam_status, pd->domain);
      41             : 
      42           0 :     reply = dbus_message_new_method_return(sbus_req->message);
      43           0 :     if (reply == NULL) {
      44           0 :         DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name,
      45             :                      "Unable to acquire reply message");
      46           0 :         return;
      47             :     }
      48             : 
      49           0 :     dbret = dp_pack_pam_response(reply, pd);
      50           0 :     if (!dbret) {
      51           0 :         DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name,
      52             :                      "Unable to generate reply message");
      53           0 :         dbus_message_unref(reply);
      54           0 :         return;
      55             :     }
      56             : 
      57           0 :     sbus_request_finish(sbus_req, reply);
      58           0 :     dbus_message_unref(reply);
      59           0 :     return;
      60             : }
      61             : 
      62           0 : static errno_t pam_data_create(TALLOC_CTX *mem_ctx,
      63             :                                struct sbus_request *sbus_req,
      64             :                                struct be_ctx *be_ctx,
      65             :                                struct pam_data **_pd)
      66             : {
      67             :     DBusError dbus_error;
      68             :     struct pam_data *pd;
      69             :     bool bret;
      70             : 
      71           0 :     dbus_error_init(&dbus_error);
      72           0 :     bret = dp_unpack_pam_request(sbus_req->message, mem_ctx, &pd, &dbus_error);
      73           0 :     if (bret == false) {
      74           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse message!\n");
      75           0 :         return EINVAL;
      76             :     }
      77             : 
      78           0 :     pd->pam_status = PAM_SYSTEM_ERR;
      79           0 :     if (pd->domain == NULL) {
      80           0 :         pd->domain = talloc_strdup(pd, be_ctx->domain->name);
      81           0 :         if (pd->domain == NULL) {
      82           0 :             talloc_free(pd);
      83           0 :             return ENOMEM;
      84             :         }
      85             :     }
      86             : 
      87           0 :     *_pd = pd;
      88             : 
      89           0 :     return EOK;
      90             : }
      91             : 
      92           0 : static void choose_target(struct data_provider *provider,
      93             :                           struct pam_data *pd,
      94             :                           enum dp_targets *_target,
      95             :                           enum dp_methods *_method,
      96             :                           const char **_req_name)
      97             : {
      98             :     enum dp_targets target;
      99             :     enum dp_methods method;
     100             :     const char *name;
     101             : 
     102           0 :     switch (pd->cmd) {
     103             :         case SSS_PAM_AUTHENTICATE:
     104           0 :             target = DPT_AUTH;
     105           0 :             method = DPM_AUTH_HANDLER;
     106           0 :             name = "PAM Authenticate";
     107           0 :             break;
     108             :         case SSS_PAM_PREAUTH:
     109           0 :             target = DPT_AUTH;
     110           0 :             method = DPM_AUTH_HANDLER;
     111           0 :             name = "PAM Preauth";
     112           0 :             break;
     113             :         case SSS_PAM_ACCT_MGMT:
     114           0 :             target = DPT_ACCESS;
     115           0 :             method = DPM_ACCESS_HANDLER;
     116           0 :             name = "PAM Account";
     117           0 :             break;
     118             :         case SSS_PAM_CHAUTHTOK_PRELIM:
     119           0 :             target = DPT_CHPASS;
     120           0 :             method = DPM_AUTH_HANDLER;
     121           0 :             name = "PAM Chpass 1st";
     122           0 :             break;
     123             :         case SSS_PAM_CHAUTHTOK:
     124           0 :             target = DPT_CHPASS;
     125           0 :             method = DPM_AUTH_HANDLER;
     126           0 :             name = "PAM Chpass 2nd";
     127           0 :             break;
     128             :         case SSS_PAM_OPEN_SESSION:
     129           0 :             target = DP_TARGET_SENTINEL;
     130           0 :             method = DP_METHOD_SENTINEL;
     131           0 :             name = "PAM Open Session";
     132           0 :             pd->pam_status = PAM_SUCCESS;
     133           0 :             break;
     134             :         case SSS_PAM_SETCRED:
     135           0 :             target = DP_TARGET_SENTINEL;
     136           0 :             method = DP_METHOD_SENTINEL;
     137           0 :             name = "PAM Set Credentials";
     138           0 :             pd->pam_status = PAM_SUCCESS;
     139           0 :             break;
     140             :         case SSS_PAM_CLOSE_SESSION:
     141           0 :             target = DP_TARGET_SENTINEL;
     142           0 :             method = DP_METHOD_SENTINEL;
     143           0 :             name = "PAM Close Session";
     144           0 :             pd->pam_status = PAM_SUCCESS;
     145           0 :             break;
     146             :         default:
     147           0 :             DEBUG(SSSDBG_TRACE_LIBS, "Unsupported PAM command [%d].\n",
     148             :                   pd->cmd);
     149           0 :             target = DP_TARGET_SENTINEL;
     150           0 :             method = DP_METHOD_SENTINEL;
     151           0 :             name = "PAM Unsupported";
     152           0 :             pd->pam_status = PAM_MODULE_UNKNOWN;
     153           0 :             break;
     154             :     }
     155             : 
     156             :     /* Check that target is configured. */
     157           0 :     if (target != DP_TARGET_SENTINEL
     158           0 :             && !dp_target_enabled(provider, NULL, target)) {
     159           0 :         target = DP_TARGET_SENTINEL;
     160           0 :         method = DP_METHOD_SENTINEL;
     161           0 :         pd->pam_status = PAM_MODULE_UNKNOWN;
     162             :     }
     163             : 
     164           0 :     *_target = target;
     165           0 :     *_method = method;
     166           0 :     *_req_name = name;
     167           0 : }
     168             : 
     169             : struct dp_pam_handler_state {
     170             :     struct data_provider *provider;
     171             :     struct dp_client *dp_cli;
     172             :     struct sbus_request *sbus_req;
     173             :     const char *request_name;
     174             : };
     175             : 
     176             : void dp_pam_handler_step_done(struct tevent_req *req);
     177             : void dp_pam_handler_selinux_done(struct tevent_req *req);
     178             : 
     179           0 : errno_t dp_pam_handler(struct sbus_request *sbus_req, void *sbus_data)
     180             : {
     181             :     struct dp_pam_handler_state *state;
     182             :     struct data_provider *provider;
     183           0 :     struct pam_data *pd = NULL;
     184             :     struct dp_client *dp_cli;
     185             :     enum dp_targets target;
     186             :     enum dp_methods method;
     187             :     const char *req_name;
     188             :     struct tevent_req *req;
     189             :     errno_t ret;
     190             : 
     191           0 :     dp_cli = talloc_get_type(sbus_data, struct dp_client);
     192           0 :     provider = dp_client_provider(dp_cli);
     193             : 
     194           0 :     state = talloc_zero(sbus_req, struct dp_pam_handler_state);
     195           0 :     if (state == NULL) {
     196           0 :         ret = ENOMEM;
     197           0 :         goto done;
     198             :     }
     199             : 
     200           0 :     ret = pam_data_create(state, sbus_req, provider->be_ctx, &pd);
     201           0 :     if (ret != EOK) {
     202           0 :         return ret;
     203             :     }
     204             : 
     205           0 :     state->provider = provider;
     206           0 :     state->dp_cli = dp_cli;
     207           0 :     state->sbus_req = sbus_req;
     208             : 
     209           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Got request with the following data\n");
     210           0 :     DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
     211             : 
     212           0 :     choose_target(provider, pd, &target, &method, &req_name);
     213           0 :     if (target == DP_TARGET_SENTINEL) {
     214             :         /* Just send the result. Pam data are freed with this call. */
     215           0 :         dp_pam_reply(sbus_req, req_name, pd);
     216           0 :         return EOK;
     217             :     }
     218             : 
     219           0 :     req = dp_req_send(state, provider, dp_cli, pd->domain, req_name,
     220             :                       target, method, 0, pd, &state->request_name);
     221           0 :     if (req == NULL) {
     222           0 :         ret = ENOMEM;
     223           0 :         goto done;
     224             :     }
     225             : 
     226           0 :     tevent_req_set_callback(req, dp_pam_handler_step_done, state);
     227             : 
     228             : done:
     229           0 :     if (ret != EOK) {
     230           0 :         talloc_free(pd);
     231             :     }
     232             : 
     233           0 :     return ret;
     234             : }
     235             : 
     236           0 : static bool should_invoke_selinux(struct data_provider *provider,
     237             :                                   struct pam_data *pd)
     238             : {
     239           0 :     if (!dp_method_enabled(provider, DPT_SELINUX, DPM_SELINUX_HANDLER)) {
     240           0 :         return false;
     241             :     }
     242             : 
     243           0 :     if (pd->cmd == SSS_PAM_ACCT_MGMT && pd->pam_status == PAM_SUCCESS) {
     244           0 :         return true;
     245             :     }
     246             : 
     247           0 :     return false;
     248             : }
     249             : 
     250           0 : void dp_pam_handler_step_done(struct tevent_req *req)
     251             : {
     252             :     struct dp_pam_handler_state *state;
     253             :     struct pam_data *pd;
     254             :     errno_t ret;
     255             : 
     256           0 :     state = tevent_req_callback_data(req, struct dp_pam_handler_state);
     257             : 
     258           0 :     ret = dp_req_recv(state, req, struct pam_data *, &pd);
     259           0 :     talloc_zfree(req);
     260           0 :     if (ret != EOK) {
     261           0 :         dp_req_reply_error(state->sbus_req, state->request_name, ret);
     262           0 :         return;
     263             :     }
     264             : 
     265           0 :     if (!should_invoke_selinux(state->provider, pd)) {
     266             :         /* State and request related data are freed with sbus_req. */
     267           0 :         dp_pam_reply(state->sbus_req, state->request_name, pd);
     268           0 :         return;
     269             :     }
     270             : 
     271           0 :     req = dp_req_send(state, state->provider, state->dp_cli, pd->domain,
     272             :                       "PAM SELinux", DPT_SELINUX, DPM_SELINUX_HANDLER,
     273             :                       0, pd, NULL);
     274           0 :     if (req == NULL) {
     275           0 :         DP_REQ_DEBUG(SSSDBG_CRIT_FAILURE, state->request_name,
     276             :                      "Unable to process SELinux, killing request...");
     277           0 :         talloc_free(state->sbus_req);
     278           0 :         return;
     279             :     }
     280             : 
     281           0 :     tevent_req_set_callback(req, dp_pam_handler_selinux_done, state);
     282             : }
     283             : 
     284           0 : void dp_pam_handler_selinux_done(struct tevent_req *req)
     285             : {
     286             :     struct dp_pam_handler_state *state;
     287             :     struct pam_data *pd;
     288             :     errno_t ret;
     289             : 
     290           0 :     state = tevent_req_callback_data(req, struct dp_pam_handler_state);
     291             : 
     292           0 :     ret = dp_req_recv(state, req, struct pam_data *, &pd);
     293           0 :     talloc_zfree(req);
     294           0 :     if (ret != EOK) {
     295           0 :         dp_req_reply_error(state->sbus_req, state->request_name, ret);
     296           0 :         return;
     297             :     }
     298             : 
     299             :     /* State and request related data are freed with sbus_req. */
     300           0 :     dp_pam_reply(state->sbus_req, state->request_name, pd);
     301           0 :     return;
     302             : }

Generated by: LCOV version 1.10