"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.4.2/src/providers/ipa/ipa_session.c" (19 Feb 2021, 28265 Bytes) of package /linux/misc/sssd-2.4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ipa_session.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.1_vs_2.4.2.

    1 /*
    2     SSSD
    3 
    4     IPA Backend Module -- Session Management
    5 
    6     Authors:
    7         Fabiano FidĂȘncio <fidencio@redhat.com>
    8 
    9     Copyright (C) 2017 Red Hat
   10 
   11     This program is free software; you can redistribute it and/or modify
   12     it under the terms of the GNU General Public License as published by
   13     the Free Software Foundation; either version 3 of the License, or
   14     (at your option) any later version.
   15 
   16     This program is distributed in the hope that it will be useful,
   17     but WITHOUT ANY WARRANTY; without even the implied warranty of
   18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19     GNU General Public License for more details.
   20 
   21     You should have received a copy of the GNU General Public License
   22     along with this program.  If not, see <http://www.gnu.org/licenses/>.
   23 */
   24 #include <security/pam_modules.h>
   25 
   26 #include "util/child_common.h"
   27 #include "providers/ldap/sdap_async.h"
   28 #include "providers/ipa/ipa_common.h"
   29 #include "providers/ipa/ipa_config.h"
   30 #include "providers/ipa/ipa_hosts.h"
   31 #include "providers/ipa/ipa_subdomains.h"
   32 #include "providers/ipa/ipa_session.h"
   33 #include "providers/ipa/ipa_rules_common.h"
   34 #include "providers/ipa/ipa_deskprofile_private.h"
   35 #include "providers/ipa/ipa_deskprofile_config.h"
   36 #include "providers/ipa/ipa_deskprofile_rules.h"
   37 #include "providers/ipa/ipa_deskprofile_rules_util.h"
   38 #include "sss_iface/sss_iface_async.h"
   39 
   40 
   41 /* Those here are used for sending a message to the deskprofile client
   42  * informing that our side is done. */
   43 #define SSS_FLEETCOMMANDERCLIENT_BUS "org.freedesktop.FleetCommanderClient"
   44 #define SSS_FLEETCOMMANDERCLIENT_PATH "/org/freedesktop/FleetCommanderClient"
   45 #define SSS_FLEETCOMMANDERCLIENT_IFACE "org.freedesktop.FleetCommanderClient"
   46 
   47 #define MINUTE_IN_SECONDS 60
   48 
   49 struct ipa_fetch_deskprofile_state {
   50     struct tevent_context *ev;
   51     struct be_ctx *be_ctx;
   52     struct sdap_id_ctx *sdap_ctx;
   53     struct ipa_session_ctx *session_ctx;
   54     struct sdap_id_op *sdap_op;
   55     struct dp_option *ipa_options;
   56     struct sdap_search_base **search_bases;
   57     const char *username;
   58 
   59     /* Hosts */
   60     struct ipa_common_entries *hosts;
   61     struct sysdb_attrs *ipa_host;
   62 
   63     /* Rules */
   64     struct ipa_common_entries *rules;
   65     struct sysdb_attrs *config;
   66     uint16_t priority;
   67 };
   68 
   69 static errno_t ipa_fetch_deskprofile_retry(struct tevent_req *req);
   70 static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq);
   71 static errno_t ipa_fetch_deskprofile_hostinfo(struct tevent_req *req);
   72 static void ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq);
   73 static void ipa_fetch_deskprofile_config_done(struct tevent_req *subreq);
   74 static void ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq);
   75 
   76 static struct tevent_req *
   77 ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx,
   78                            struct tevent_context *ev,
   79                            struct be_ctx *be_ctx,
   80                            struct ipa_session_ctx *session_ctx,
   81                            const char *username)
   82 {
   83     struct ipa_fetch_deskprofile_state *state;
   84     struct tevent_req *req;
   85     time_t now;
   86     time_t refresh_interval;
   87     time_t request_interval;
   88     time_t next_request;
   89     bool offline;
   90     errno_t ret;
   91 
   92     req = tevent_req_create(mem_ctx, &state,
   93                             struct ipa_fetch_deskprofile_state);
   94     if (req == NULL) {
   95         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
   96         return NULL;
   97     }
   98 
   99     state->ev = ev;
  100     state->be_ctx = be_ctx;
  101     state->session_ctx = session_ctx;
  102     state->sdap_ctx = session_ctx->sdap_ctx;
  103     state->ipa_options = session_ctx->ipa_options;
  104     state->search_bases = session_ctx->deskprofile_search_bases;
  105     state->username = username;
  106     state->hosts = talloc_zero(state, struct ipa_common_entries);
  107     if (state->hosts == NULL) {
  108         ret = ENOMEM;
  109         goto immediately;
  110     }
  111     state->rules = talloc_zero(state, struct ipa_common_entries);
  112     if (state->rules == NULL) {
  113         ret = ENOMEM;
  114         goto immediately;
  115     }
  116 
  117     if (state->search_bases == NULL) {
  118         DEBUG(SSSDBG_CRIT_FAILURE, "No Desktop Profile search base found.\n");
  119         ret = EINVAL;
  120         goto immediately;
  121     }
  122 
  123     state->sdap_op = sdap_id_op_create(state,
  124                                        state->sdap_ctx->conn->conn_cache);
  125     if (state->sdap_op == NULL) {
  126         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
  127         ret = ENOMEM;
  128         goto immediately;
  129     }
  130 
  131     now = time(NULL);
  132 
  133     request_interval = dp_opt_get_int(state->ipa_options,
  134                                       IPA_DESKPROFILE_REQUEST_INTERVAL);
  135     /* This value is in minutes ... */
  136     request_interval *= MINUTE_IN_SECONDS;
  137 
  138     if (state->session_ctx->no_rules_found &&
  139         now < session_ctx->last_request + request_interval) {
  140         next_request = (session_ctx->last_request + request_interval - now);
  141         /* This value is in seconds ... */
  142         next_request /= 60;
  143         DEBUG(SSSDBG_TRACE_FUNC,
  144               "No rules were found in the last request.\n"
  145               "Next request will happen in any login after %ld minutes\n",
  146               next_request);
  147         ret = ENOENT;
  148         goto immediately;
  149     }
  150 
  151     state->session_ctx->no_rules_found = false;
  152 
  153     offline = be_is_offline(be_ctx);
  154     DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n",
  155           offline ? "offline" : "online");
  156 
  157     refresh_interval = dp_opt_get_int(state->ipa_options,
  158                                       IPA_DESKPROFILE_REFRESH);
  159 
  160     if (offline || now < session_ctx->last_update + refresh_interval) {
  161         DEBUG(SSSDBG_TRACE_FUNC,
  162               "Performing cached Desktop Profile evaluation\n");
  163         ret = EOK;
  164         goto immediately;
  165     }
  166 
  167     ret = ipa_fetch_deskprofile_retry(req);
  168     if (ret != EAGAIN) {
  169         goto immediately;
  170     }
  171 
  172     return req;
  173 
  174 immediately:
  175     if (ret == EOK) {
  176         tevent_req_done(req);
  177     } else {
  178         tevent_req_error(req, ret);
  179     }
  180     tevent_req_post(req, ev);
  181 
  182     return req;
  183 }
  184 
  185 static errno_t
  186 ipa_fetch_deskprofile_retry(struct tevent_req *req)
  187 {
  188     struct tevent_req *subreq;
  189     struct ipa_fetch_deskprofile_state *state;
  190     int ret;
  191 
  192     state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
  193 
  194     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
  195     if (subreq == NULL) {
  196         DEBUG(SSSDBG_CRIT_FAILURE,
  197               "sdap_id_op_connect_send() failed: %d (%s)\n",
  198               ret, strerror(ret));
  199 
  200         return ret;
  201     }
  202 
  203     tevent_req_set_callback(subreq, ipa_fetch_deskprofile_connect_done, req);
  204 
  205     return EAGAIN;
  206 }
  207 
  208 static void
  209 ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq)
  210 {
  211     struct tevent_req *req = NULL;
  212     int dp_error;
  213     errno_t ret;
  214 
  215     req = tevent_req_callback_data(subreq, struct tevent_req);
  216 
  217     ret = sdap_id_op_connect_recv(subreq, &dp_error);
  218     talloc_zfree(subreq);
  219     if (ret != EOK) {
  220         goto done;
  221     }
  222 
  223     ret = ipa_fetch_deskprofile_hostinfo(req);
  224     if (ret == EAGAIN) {
  225         return;
  226     }
  227 
  228 done:
  229     if (ret == EOK) {
  230         tevent_req_done(req);
  231     } else {
  232         tevent_req_error(req, ret);
  233     }
  234 }
  235 
  236 static errno_t
  237 ipa_fetch_deskprofile_hostinfo(struct tevent_req *req)
  238 {
  239     struct tevent_req *subreq;
  240     struct ipa_fetch_deskprofile_state *state;
  241     const char *hostname;
  242 
  243     state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
  244     hostname = dp_opt_get_string(state->ipa_options, IPA_HOSTNAME);
  245 
  246     subreq = ipa_host_info_send(state,
  247                                 state->ev,
  248                                 sdap_id_op_handle(state->sdap_op),
  249                                 state->sdap_ctx->opts,
  250                                 hostname,
  251                                 state->session_ctx->host_map,
  252                                 state->session_ctx->hostgroup_map,
  253                                 state->session_ctx->host_search_bases);
  254     if (subreq == NULL) {
  255         return ENOMEM;
  256     }
  257 
  258     tevent_req_set_callback(subreq, ipa_fetch_deskprofile_hostinfo_done, req);
  259 
  260     return EAGAIN;
  261 }
  262 
  263 static void
  264 ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq)
  265 {
  266     struct tevent_req *req;
  267     struct ipa_fetch_deskprofile_state *state;
  268     errno_t ret;
  269 
  270     req = tevent_req_callback_data(subreq, struct tevent_req);
  271     state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
  272 
  273     ret = ipa_host_info_recv(subreq, state,
  274                              &state->hosts->entry_count,
  275                              &state->hosts->entries,
  276                              &state->hosts->group_count,
  277                              &state->hosts->groups);
  278     state->hosts->entry_subdir = DESKPROFILE_HOSTS_SUBDIR;
  279     state->hosts->group_subdir = DESKPROFILE_HOSTGROUPS_SUBDIR;
  280     talloc_zfree(subreq);
  281     if (ret != EOK) {
  282         goto done;
  283     }
  284 
  285     ret = ipa_get_host_attrs(state->ipa_options,
  286                              state->hosts->entry_count,
  287                              state->hosts->entries,
  288                              &state->ipa_host);
  289     if (ret != EOK) {
  290         DEBUG(SSSDBG_CRIT_FAILURE, "Could not locate IPA host.\n");
  291         goto done;
  292     }
  293 
  294     subreq = ipa_deskprofile_get_config_send(state,
  295                                              state->ev,
  296                                              sdap_id_op_handle(state->sdap_op),
  297                                              state->sdap_ctx->opts,
  298                                              state->ipa_options);
  299     if (subreq == NULL) {
  300         ret = ENOMEM;
  301         goto done;
  302     }
  303 
  304     tevent_req_set_callback(subreq, ipa_fetch_deskprofile_config_done, req);
  305     return;
  306 
  307 done:
  308     tevent_req_error(req, ret);
  309 }
  310 
  311 static void
  312 ipa_fetch_deskprofile_config_done(struct tevent_req *subreq)
  313 {
  314     struct tevent_req *req;
  315     struct ipa_fetch_deskprofile_state *state;
  316     errno_t ret;
  317 
  318     req = tevent_req_callback_data(subreq, struct tevent_req);
  319     state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
  320 
  321     ret = ipa_deskprofile_get_config_recv(subreq, state, &state->config);
  322     talloc_zfree(subreq);
  323     if (ret != EOK) {
  324         goto done;
  325     }
  326 
  327     ret = sysdb_store_custom(state->be_ctx->domain, IPA_DESKPROFILE_PRIORITY,
  328                              DESKPROFILE_CONFIG_SUBDIR, state->config);
  329     if (ret != EOK) {
  330         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile policy\n");
  331         goto done;
  332     }
  333 
  334     subreq = ipa_deskprofile_rule_info_send(state,
  335                                             state->ev,
  336                                             sdap_id_op_handle(state->sdap_op),
  337                                             state->sdap_ctx->opts,
  338                                             state->search_bases,
  339                                             state->ipa_host,
  340                                             state->be_ctx->domain,
  341                                             state->username);
  342     if (subreq == NULL) {
  343         ret = ENOMEM;
  344         goto done;
  345     }
  346 
  347     tevent_req_set_callback(subreq, ipa_fetch_deskprofile_rules_done, req);
  348     return;
  349 
  350 done:
  351     tevent_req_error(req, ret);
  352 }
  353 
  354 static void
  355 ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq)
  356 {
  357     struct tevent_req *req;
  358     struct ipa_fetch_deskprofile_state *state;
  359     int dp_error;
  360     errno_t ret;
  361     bool found;
  362 
  363     req = tevent_req_callback_data(subreq, struct tevent_req);
  364     state = tevent_req_data(req, struct ipa_fetch_deskprofile_state);
  365 
  366     ret = ipa_deskprofile_rule_info_recv(subreq,
  367                                          state,
  368                                          &state->rules->entry_count,
  369                                          &state->rules->entries);
  370     state->rules->entry_subdir = DESKPROFILE_RULES_SUBDIR;
  371     talloc_zfree(subreq);
  372     if (ret == ENOENT) {
  373         /* Set ret to EOK so we can safely call sdap_id_op_done. */
  374         ret = EOK;
  375         found = false;
  376     } else if (ret == EOK) {
  377         found = true;
  378     } else {
  379         goto done;
  380     }
  381 
  382     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
  383     if (dp_error == DP_ERR_OK && ret != EOK) {
  384         /* retry */
  385         ret = ipa_fetch_deskprofile_retry(req);
  386         if (ret != EAGAIN) {
  387             tevent_req_error(req, ret);
  388         }
  389         return;
  390     } else if (ret != EOK) {
  391         tevent_req_error(req, ret);
  392         return;
  393     }
  394 
  395    /* For now, let's completely purge the previous stored
  396     * rules before saving the new ones */
  397     ret = ipa_common_purge_rules(state->be_ctx->domain,
  398                                  DESKPROFILE_RULES_SUBDIR);
  399     if (ret != EOK) {
  400         DEBUG(SSSDBG_CRIT_FAILURE,
  401               "Unable to remove Desktop Profile rules\n");
  402         goto done;
  403     }
  404 
  405     if (!found) {
  406         ret = ENOENT;
  407         goto done;
  408     }
  409 
  410     ret = ipa_common_save_rules(state->be_ctx->domain,
  411                                 state->hosts, NULL, state->rules,
  412                                 &state->session_ctx->last_update);
  413     if (ret != EOK) {
  414         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile rules\n");
  415         goto done;
  416     }
  417 
  418     ret = EOK;
  419 
  420 done:
  421     if (ret != EOK) {
  422         tevent_req_error(req, ret);
  423         return;
  424     }
  425 
  426     tevent_req_done(req);
  427 }
  428 
  429 static errno_t
  430 ipa_fetch_deskprofile_recv(struct tevent_req *req)
  431 {
  432     TEVENT_REQ_RETURN_ON_ERROR(req);
  433 
  434     return EOK;
  435 }
  436 
  437 struct ipa_pam_session_handler_state {
  438     struct tevent_context *ev;
  439     struct be_ctx *be_ctx;
  440     struct ipa_session_ctx *session_ctx;
  441     struct pam_data *pd;
  442 
  443     /* Those attributes are used for:
  444      * - saving the deskprofile rules to the disk;
  445      * - deleting the deskprofile rules from the disk;
  446      * - contacting the deskprofile client that everything is ready;
  447      */
  448     char *shortname;
  449     char *domain;
  450     char *user_dir;
  451     uid_t uid;
  452     gid_t gid;
  453 };
  454 
  455 static errno_t
  456 ipa_pam_session_handler_get_deskprofile_user_info(
  457                                                 TALLOC_CTX *mem_ctx,
  458                                                 struct sss_domain_info *domain,
  459                                                 const char *username,
  460                                                 char **_shortname,
  461                                                 char **_domain,
  462                                                 char **_user_dir,
  463                                                 uid_t *uid,
  464                                                 gid_t *gid);
  465 static void ipa_pam_session_handler_done(struct tevent_req *subreq);
  466 static errno_t
  467 ipa_pam_session_handler_save_deskprofile_rules(
  468                                     struct be_ctx *be_ctx,
  469                                     struct sss_domain_info *domain,
  470                                     const char *username, /* fully-qualified */
  471                                     const char *user_dir,
  472                                     const char *hostname,
  473                                     uid_t uid,
  474                                     gid_t gid);
  475 static errno_t
  476 ipa_pam_session_handler_notify_deskprofile_client(TALLOC_CTX *mem_ctx,
  477                                                   struct tevent_context *ev,
  478                                                   uid_t uid,
  479                                                   const char *user_dir,
  480                                                   uint16_t prio);
  481 
  482 
  483 struct tevent_req *
  484 ipa_pam_session_handler_send(TALLOC_CTX *mem_ctx,
  485                              struct ipa_session_ctx *session_ctx,
  486                              struct pam_data *pd,
  487                              struct dp_req_params *params)
  488 {
  489     struct tevent_req *req;
  490     struct tevent_req *subreq;
  491     struct ipa_pam_session_handler_state *state;
  492     errno_t ret;
  493 
  494     DEBUG(SSSDBG_TRACE_FUNC, "Retrieving Desktop Profile rules\n");
  495     req = tevent_req_create(mem_ctx, &state,
  496                             struct ipa_pam_session_handler_state);
  497     if (req == NULL) {
  498         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
  499         return NULL;
  500     }
  501 
  502     state->pd = pd;
  503     state->ev = params->ev;
  504     state->be_ctx = params->be_ctx;
  505     state->session_ctx = session_ctx;
  506 
  507     /* Get all the user info that will be needed in order the delete the
  508      * user's deskprofile directory from the disk, create the user's directory,
  509      * save the fetched rules to the disk and notify the deskprofile client
  510      * that this operation is done. */
  511     ret = ipa_pam_session_handler_get_deskprofile_user_info(
  512                                                         state,
  513                                                         params->domain,
  514                                                         pd->user,
  515                                                         &state->shortname,
  516                                                         &state->domain,
  517                                                         &state->user_dir,
  518                                                         &state->uid,
  519                                                         &state->gid);
  520     if (ret != EOK) {
  521         DEBUG(SSSDBG_CRIT_FAILURE,
  522               "ipa_deskprofile_get_user_info() failed [%d]: %s\n",
  523               ret, sss_strerror(ret));
  524         state->pd->pam_status = PAM_SESSION_ERR;
  525         goto done;
  526     }
  527 
  528     /* As no proper merging mechanism has been implemented yet ...
  529      * let's just remove the user directory stored in the disk as it's
  530      * going to be created again in case there's any rule fetched. */
  531     ret = ipa_deskprofile_rules_remove_user_dir(state->user_dir,
  532                                                 state->uid,
  533                                                 state->gid);
  534     if (ret != EOK) {
  535         DEBUG(SSSDBG_CRIT_FAILURE,
  536               "ipa_deskprofile_rules_remove_user_dir() failed.\n");
  537         state->pd->pam_status = PAM_SESSION_ERR;
  538         goto done;
  539     }
  540 
  541     subreq = ipa_fetch_deskprofile_send(state, state->ev, state->be_ctx,
  542                                         state->session_ctx, pd->user);
  543     if (subreq == NULL) {
  544         state->pd->pam_status = PAM_SESSION_ERR;
  545         goto done;
  546     }
  547 
  548     tevent_req_set_callback(subreq, ipa_pam_session_handler_done, req);
  549     return req;
  550 
  551 done:
  552     tevent_req_done(req);
  553     tevent_req_post(req, params->ev);
  554 
  555     return req;
  556 }
  557 
  558 static void
  559 ipa_pam_session_handler_done(struct tevent_req *subreq)
  560 {
  561     struct tevent_req *req;
  562     struct ipa_pam_session_handler_state *state;
  563     const char *hostname;
  564     errno_t ret;
  565 
  566     req = tevent_req_callback_data(subreq, struct tevent_req);
  567     state = tevent_req_data(req, struct ipa_pam_session_handler_state);
  568 
  569     ret = ipa_fetch_deskprofile_recv(subreq);
  570     talloc_free(subreq);
  571 
  572     if (ret == ENOENT) {
  573         DEBUG(SSSDBG_FUNC_DATA, "No Desktop Profile rules found\n");
  574         if (!state->session_ctx->no_rules_found) {
  575             state->session_ctx->no_rules_found = true;
  576             state->session_ctx->last_request = time(NULL);
  577         }
  578         state->pd->pam_status = PAM_SUCCESS;
  579         goto done;
  580     } else if (ret != EOK) {
  581         DEBUG(SSSDBG_CRIT_FAILURE,
  582               "Unable to fetch Desktop Profile rules [%d]: %s\n",
  583               ret, sss_strerror(ret));
  584         state->pd->pam_status = PAM_SYSTEM_ERR;
  585         goto done;
  586     }
  587 
  588     state->session_ctx->last_request = time(NULL);
  589 
  590     hostname = dp_opt_get_string(state->session_ctx->ipa_options, IPA_HOSTNAME);
  591     ret = ipa_pam_session_handler_save_deskprofile_rules(state->be_ctx,
  592                                                          state->be_ctx->domain,
  593                                                          state->pd->user,
  594                                                          state->user_dir,
  595                                                          hostname,
  596                                                          state->uid,
  597                                                          state->gid);
  598 
  599     state->pd->pam_status = (ret == EOK) ? PAM_SUCCESS : PAM_SESSION_ERR;
  600 
  601 done:
  602     /* TODO For backward compatibility we always return EOK to DP now. */
  603     tevent_req_done(req);
  604 }
  605 
  606 errno_t
  607 ipa_pam_session_handler_recv(TALLOC_CTX *mem_ctx,
  608                              struct tevent_req *req,
  609                              struct pam_data **_data)
  610 {
  611     struct ipa_pam_session_handler_state *state = NULL;
  612 
  613     state = tevent_req_data(req, struct ipa_pam_session_handler_state);
  614 
  615     TEVENT_REQ_RETURN_ON_ERROR(req);
  616 
  617     *_data = talloc_steal(mem_ctx, state->pd);
  618 
  619     return EOK;
  620 }
  621 
  622 static errno_t
  623 ipa_pam_session_handler_get_deskprofile_user_info(TALLOC_CTX *mem_ctx,
  624                                                   struct sss_domain_info *domain,
  625                                                   const char *username,
  626                                                   char **_shortname,
  627                                                   char **_domain,
  628                                                   char **_user_dir,
  629                                                   uid_t *_uid,
  630                                                   gid_t *_gid)
  631 {
  632     TALLOC_CTX *tmp_ctx;
  633     struct ldb_result *res = NULL;
  634     char *shortname;
  635     char *domain_name;
  636     char *user_dir;
  637     uid_t uid;
  638     gid_t gid;
  639     errno_t ret;
  640 
  641     tmp_ctx = talloc_new(NULL);
  642     if (tmp_ctx == NULL) {
  643         return ENOMEM;
  644     }
  645 
  646     ret = sss_parse_internal_fqname(tmp_ctx, username,
  647                                     &shortname, &domain_name);
  648     if (ret != EOK) {
  649         DEBUG(SSSDBG_TRACE_FUNC, "Failed to parse \"%s\" [%d]: %s\n",
  650               username, ret, sss_strerror(ret));
  651         goto done;
  652     }
  653 
  654     user_dir = talloc_asprintf(tmp_ctx, IPA_DESKPROFILE_RULES_USER_DIR"/%s/%s",
  655                                domain_name, shortname);
  656     if (user_dir == NULL) {
  657         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed!\n");
  658         ret = ENOMEM;
  659         goto done;
  660     }
  661 
  662     ret = sysdb_getpwnam(tmp_ctx, domain, username, &res);
  663     if (ret != EOK) {
  664         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam() failed [%d]: %s\n",
  665               ret, sss_strerror(ret));
  666         goto done;
  667     }
  668 
  669     if (res->count != 1) {
  670         DEBUG(SSSDBG_CRIT_FAILURE,
  671               "sysdb_getpwnam() returned unexpected amount of users. "
  672               "Expected [%d], got [%d]\n", 1, res->count);
  673         ret = EINVAL;
  674         goto done;
  675     }
  676 
  677     uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);
  678     gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
  679     if (uid == 0 || gid == 0) {
  680         /* As IPA doesn't handle root users ou groups, we know for sure that's
  681          * something wrong in case we get uid = 0 or gid = 0.
  682          */
  683         ret = EINVAL;
  684         goto done;
  685     }
  686 
  687     ret = EOK;
  688 
  689     *_shortname = talloc_steal(mem_ctx, shortname);
  690     *_domain = talloc_steal(mem_ctx, domain_name);
  691     *_user_dir = talloc_steal(mem_ctx, user_dir);
  692     *_uid = uid;
  693     *_gid = gid;
  694 
  695 done:
  696     talloc_free(tmp_ctx);
  697     return ret;
  698 }
  699 
  700 static errno_t
  701 ipa_pam_session_handler_save_deskprofile_rules(
  702                                     struct be_ctx *be_ctx,
  703                                     struct sss_domain_info *domain,
  704                                     const char *username, /* fully-qualified */
  705                                     const char *user_dir,
  706                                     const char *hostname,
  707                                     uid_t uid,
  708                                     gid_t gid)
  709 {
  710     TALLOC_CTX *tmp_ctx;
  711     const char **attrs_get_cached_rules;
  712     size_t rule_count;
  713     struct sysdb_attrs **rules;
  714     uint16_t priority;
  715     errno_t ret;
  716 
  717     tmp_ctx = talloc_new(NULL);
  718     if (tmp_ctx == NULL) {
  719         return ENOMEM;
  720     }
  721 
  722     /* Get Desktop Profile priority from sysdb */
  723     ret = deskprofile_get_cached_priority(be_ctx->domain, &priority);
  724     if (ret != EOK) {
  725         DEBUG(SSSDBG_CRIT_FAILURE,
  726               "deskprofile_get_cached_priority() failed [%d]: %s\n",
  727               ret, sss_strerror(ret));
  728         goto done;
  729     }
  730 
  731 
  732     /* Get Desktop Profile rules from sysdb */
  733     attrs_get_cached_rules = deskprofile_get_attrs_to_get_cached_rules(tmp_ctx);
  734     if (attrs_get_cached_rules == NULL) {
  735         DEBUG(SSSDBG_CRIT_FAILURE,
  736               "deskprofile_get_attrs_get_cached_rules() failed\n");
  737         ret = ENOMEM;
  738         goto done;
  739     }
  740     ret = ipa_common_get_cached_rules(tmp_ctx, be_ctx->domain,
  741                                       IPA_DESKPROFILE_RULE,
  742                                       DESKPROFILE_RULES_SUBDIR,
  743                                       attrs_get_cached_rules,
  744                                       &rule_count,
  745                                       &rules);
  746     if (ret != EOK) {
  747         DEBUG(SSSDBG_CRIT_FAILURE,
  748               "Could not retrieve Desktop Profile rules from the cache\n");
  749         goto done;
  750     }
  751 
  752     /* Create the user directory where the rules are going to be stored */
  753     ret = ipa_deskprofile_rules_create_user_dir(username, uid, gid);
  754     if (ret != EOK) {
  755         DEBUG(SSSDBG_CRIT_FAILURE,
  756               "Cannot create the user directory [%d]: %s\n",
  757               ret, sss_strerror(ret));
  758         goto done;
  759     }
  760 
  761     /* Save the rules to the disk */
  762     for (size_t i = 0; i < rule_count; i++) {
  763         ret = ipa_deskprofile_rules_save_rule_to_disk(tmp_ctx,
  764                                                       priority,
  765                                                       rules[i],
  766                                                       domain,
  767                                                       hostname,
  768                                                       username,
  769                                                       uid,
  770                                                       gid);
  771         if (ret != EOK) {
  772             DEBUG(SSSDBG_OP_FAILURE,
  773                   "Failed to save a Desktop Profile Rule to disk [%d]: %s\n",
  774                   ret, sss_strerror(ret));
  775             continue;
  776         }
  777     }
  778 
  779     /* Notify FleetCommander that our side is done */
  780     ret = ipa_pam_session_handler_notify_deskprofile_client(be_ctx,
  781                                                             be_ctx->ev,
  782                                                             uid,
  783                                                             user_dir,
  784                                                             priority);
  785     if (ret != EOK) {
  786         DEBUG(SSSDBG_CRIT_FAILURE,
  787               "ipa_pam_session_handler_notify_deskprofile_client() "
  788               "failed [%d]: %s\n",
  789               ret, sss_strerror(ret));
  790         goto done;
  791     }
  792 
  793     ret = EOK;
  794 
  795 done:
  796     talloc_free(tmp_ctx);
  797     return ret;
  798 }
  799 
  800 static void
  801 ipa_pam_session_handler_notify_deskprofile_client_done(struct tevent_req *subreq);
  802 
  803 static errno_t
  804 ipa_pam_session_handler_notify_deskprofile_client(TALLOC_CTX *mem_ctx,
  805                                                   struct tevent_context *ev,
  806                                                   uid_t uid,
  807                                                   const char *user_dir,
  808                                                   uint16_t prio)
  809 {
  810     struct sbus_connection *conn;
  811     struct tevent_req *subreq;
  812 
  813     conn = sbus_connect_system(mem_ctx, ev, NULL, NULL);
  814     if (conn == NULL) {
  815         return ENOMEM;
  816     }
  817 
  818     subreq = sbus_call_fleet_ProcessSSSDFiles_send(mem_ctx, conn,
  819                  SSS_FLEETCOMMANDERCLIENT_BUS, SSS_FLEETCOMMANDERCLIENT_PATH,
  820                  uid, user_dir, prio);
  821     if (subreq == NULL) {
  822         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
  823         talloc_free(conn);
  824         return ENOMEM;
  825     }
  826 
  827     tevent_req_set_callback(subreq, ipa_pam_session_handler_notify_deskprofile_client_done,
  828                             conn);
  829 
  830     return EOK;
  831 }
  832 
  833 static void ipa_pam_session_handler_notify_deskprofile_client_done(struct tevent_req *subreq)
  834 {
  835     struct sbus_connection *conn;
  836     errno_t ret;
  837 
  838     conn = tevent_req_callback_data(subreq, struct sbus_connection);
  839 
  840     ret = sbus_call_fleet_ProcessSSSDFiles_recv(subreq);
  841     if (ret != EOK) {
  842         DEBUG(SSSDBG_OP_FAILURE, "Error sending sbus message [%d]: %s\n",
  843               ret, sss_strerror(ret));
  844     }
  845 
  846     talloc_free(conn);
  847 }