LCOV - code coverage report
Current view: top level - providers/ipa - ipa_hostid.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 142 0.0 %
Date: 2015-10-19 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Jan Cholasta <jcholast@redhat.com>
       4             : 
       5             :     Copyright (C) 2012 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 "util/util.h"
      22             : #include "util/crypto/sss_crypto.h"
      23             : #include "db/sysdb_ssh.h"
      24             : #include "providers/ldap/ldap_common.h"
      25             : #include "providers/ipa/ipa_common.h"
      26             : #include "providers/ipa/ipa_hostid.h"
      27             : #include "providers/ipa/ipa_hosts.h"
      28             : 
      29             : struct hosts_get_state {
      30             :     struct tevent_context *ev;
      31             :     struct ipa_hostid_ctx *ctx;
      32             :     struct sdap_id_op *op;
      33             :     struct sss_domain_info *domain;
      34             :     const char *name;
      35             :     const char *alias;
      36             : 
      37             :     size_t count;
      38             :     struct sysdb_attrs **hosts;
      39             :     int dp_error;
      40             : };
      41             : 
      42             : struct tevent_req *
      43             : hosts_get_send(TALLOC_CTX *memctx,
      44             :                struct tevent_context *ev,
      45             :                struct ipa_hostid_ctx *hostid_ctx,
      46             :                const char *name,
      47             :                const char *alias);
      48             : static errno_t
      49             : hosts_get_recv(struct tevent_req *req,
      50             :                int *dp_error_out);
      51             : 
      52             : static void
      53             : ipa_host_info_hosts_done(struct tevent_req *req);
      54             : 
      55             : void
      56           0 : ipa_host_info_handler(struct be_req *breq)
      57             : {
      58           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
      59             :     struct ipa_hostid_ctx *hostid_ctx;
      60             :     struct sdap_id_ctx *ctx;
      61             :     struct be_host_req *hr;
      62             :     struct tevent_req *req;
      63           0 :     int dp_error = DP_ERR_FATAL;
      64           0 :     errno_t ret = EOK;
      65           0 :     const char *err = "Unknown Error";
      66             : 
      67           0 :     hostid_ctx = talloc_get_type(be_ctx->bet_info[BET_HOSTID].pvt_bet_data,
      68             :                                  struct ipa_hostid_ctx);
      69           0 :     ctx = hostid_ctx->sdap_id_ctx;
      70             : 
      71           0 :     if (be_is_offline(ctx->be)) {
      72           0 :         dp_error = DP_ERR_OFFLINE;
      73           0 :         ret = EAGAIN;
      74           0 :         err = "Offline";
      75           0 :         goto done;
      76             :     }
      77             : 
      78           0 :     hr = talloc_get_type(be_req_get_data(breq), struct be_host_req);
      79             : 
      80           0 :     if (hr->filter_type != BE_FILTER_NAME) {
      81           0 :         ret = EINVAL;
      82           0 :         err = "Invalid filter type";
      83           0 :         goto done;
      84             :     }
      85             : 
      86           0 :     req = hosts_get_send(breq, be_ctx->ev, hostid_ctx,
      87           0 :                          hr->name, hr->alias);
      88           0 :     if (!req) {
      89           0 :         ret = ENOMEM;
      90           0 :         err = "Out of memory";
      91           0 :         goto done;
      92             :     }
      93             : 
      94           0 :     tevent_req_set_callback(req, ipa_host_info_hosts_done, breq);
      95             : 
      96           0 :     ret = EOK;
      97             : 
      98             : done:
      99           0 :     if (ret != EOK) return sdap_handler_done(breq, dp_error, ret, err);
     100             : }
     101             : 
     102             : static void
     103           0 : ipa_host_info_complete(struct be_req *breq, int dp_error,
     104             :                             errno_t ret, const char *default_error_text)
     105             : {
     106             :     const char* error_text;
     107             : 
     108           0 :     if (dp_error == DP_ERR_OK) {
     109           0 :         if (ret == EOK) {
     110           0 :             error_text = NULL;
     111             :         } else {
     112           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     113             :                   "Bug: dp_error is OK on failed request\n");
     114           0 :             dp_error = DP_ERR_FATAL;
     115           0 :             error_text = default_error_text;
     116             :         }
     117           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
     118           0 :         error_text = "Offline";
     119           0 :     } else if (dp_error == DP_ERR_FATAL && ret == ENOMEM) {
     120           0 :         error_text = "Out of memory";
     121             :     } else {
     122           0 :         error_text = default_error_text;
     123             :     }
     124             : 
     125           0 :     sdap_handler_done(breq, dp_error, ret, error_text);
     126           0 : }
     127             : 
     128             : static void
     129           0 : ipa_host_info_hosts_done(struct tevent_req *req)
     130             : {
     131           0 :     struct be_req *breq = tevent_req_callback_data(req, struct be_req);
     132             :     int ret, dp_error;
     133             : 
     134           0 :     ret = hosts_get_recv(req, &dp_error);
     135           0 :     talloc_zfree(req);
     136             : 
     137           0 :     ipa_host_info_complete(breq, dp_error, ret, "Host lookup failed");
     138           0 : }
     139             : 
     140             : static errno_t
     141             : hosts_get_retry(struct tevent_req *req);
     142             : static void
     143             : hosts_get_connect_done(struct tevent_req *subreq);
     144             : static void
     145             : hosts_get_done(struct tevent_req *subreq);
     146             : 
     147             : struct tevent_req *
     148           0 : hosts_get_send(TALLOC_CTX *memctx,
     149             :                struct tevent_context *ev,
     150             :                struct ipa_hostid_ctx *hostid_ctx,
     151             :                const char *name,
     152             :                const char *alias)
     153             : {
     154             :     struct tevent_req *req;
     155             :     struct hosts_get_state *state;
     156             :     struct sdap_id_ctx *ctx;
     157             :     errno_t ret;
     158             : 
     159           0 :     ctx = hostid_ctx->sdap_id_ctx;
     160             : 
     161           0 :     req = tevent_req_create(memctx, &state, struct hosts_get_state);
     162           0 :     if (!req) return NULL;
     163             : 
     164           0 :     state->ev = ev;
     165           0 :     state->ctx = hostid_ctx;
     166           0 :     state->dp_error = DP_ERR_FATAL;
     167             : 
     168           0 :     state->op = sdap_id_op_create(state, ctx->conn->conn_cache);
     169           0 :     if (!state->op) {
     170           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     171           0 :         ret = ENOMEM;
     172           0 :         goto fail;
     173             :     }
     174             : 
     175           0 :     state->domain = ctx->be->domain;
     176           0 :     state->name = name;
     177           0 :     state->alias = alias;
     178             : 
     179           0 :     ret = hosts_get_retry(req);
     180           0 :     if (ret != EOK) {
     181           0 :         goto fail;
     182             :     }
     183             : 
     184           0 :     return req;
     185             : 
     186             : fail:
     187           0 :     tevent_req_error(req, ret);
     188           0 :     tevent_req_post(req, ev);
     189           0 :     return req;
     190             : }
     191             : 
     192             : static errno_t
     193           0 : hosts_get_retry(struct tevent_req *req)
     194             : {
     195           0 :     struct hosts_get_state *state = tevent_req_data(req,
     196             :                                                     struct hosts_get_state);
     197             :     struct tevent_req *subreq;
     198           0 :     errno_t ret = EOK;
     199             : 
     200           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
     201           0 :     if (!subreq) {
     202           0 :         return ret;
     203             :     }
     204             : 
     205           0 :     tevent_req_set_callback(subreq, hosts_get_connect_done, req);
     206           0 :     return EOK;
     207             : }
     208             : 
     209             : static void
     210           0 : hosts_get_connect_done(struct tevent_req *subreq)
     211             : {
     212           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     213             :                                                       struct tevent_req);
     214           0 :     struct hosts_get_state *state = tevent_req_data(req,
     215             :                                                     struct hosts_get_state);
     216           0 :     int dp_error = DP_ERR_FATAL;
     217             :     errno_t ret;
     218             : 
     219           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     220           0 :     talloc_zfree(subreq);
     221             : 
     222           0 :     if (ret != EOK) {
     223           0 :         state->dp_error = dp_error;
     224           0 :         tevent_req_error(req, ret);
     225           0 :         return;
     226             :     }
     227             : 
     228           0 :     subreq = ipa_host_info_send(state, state->ev,
     229             :                                 sdap_id_op_handle(state->op),
     230           0 :                                 state->ctx->sdap_id_ctx->opts, state->name,
     231           0 :                                 state->ctx->ipa_opts->host_map, NULL,
     232           0 :                                 state->ctx->host_search_bases);
     233           0 :     if (!subreq) {
     234           0 :         tevent_req_error(req, ENOMEM);
     235           0 :         return;
     236             :     }
     237           0 :     tevent_req_set_callback(subreq, hosts_get_done, req);
     238             : }
     239             : 
     240             : static void
     241           0 : hosts_get_done(struct tevent_req *subreq)
     242             : {
     243           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     244             :                                                       struct tevent_req);
     245           0 :     struct hosts_get_state *state = tevent_req_data(req,
     246             :                                                     struct hosts_get_state);
     247           0 :     int dp_error = DP_ERR_FATAL;
     248             :     errno_t ret;
     249             :     struct sysdb_attrs *attrs;
     250           0 :     time_t now = time(NULL);
     251             : 
     252           0 :     ret = ipa_host_info_recv(subreq, state,
     253             :                              &state->count, &state->hosts,
     254             :                              NULL, NULL);
     255           0 :     talloc_zfree(subreq);
     256             : 
     257           0 :     ret = sdap_id_op_done(state->op, ret, &dp_error);
     258           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     259             :         /* retry */
     260           0 :         ret = hosts_get_retry(req);
     261           0 :         if (ret != EOK) {
     262           0 :             goto done;
     263             :         }
     264           0 :         return;
     265             :     }
     266             : 
     267           0 :     if (ret != EOK && ret != ENOENT) {
     268           0 :         goto done;
     269             :     }
     270             : 
     271           0 :     if (state->count == 0) {
     272           0 :         DEBUG(SSSDBG_OP_FAILURE,
     273             :               "No host with name [%s] found.\n", state->name);
     274             : 
     275           0 :         ret = sysdb_delete_ssh_host(state->domain, state->name);
     276           0 :         if (ret != EOK && ret != ENOENT) {
     277           0 :             goto done;
     278             :         }
     279             : 
     280           0 :         ret = EINVAL;
     281           0 :         goto done;
     282             :     }
     283             : 
     284           0 :     if (state->count > 1) {
     285           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     286             :               "Found more than one host with name [%s].\n", state->name);
     287           0 :         ret = EINVAL;
     288           0 :         goto done;
     289             :     }
     290             : 
     291           0 :     attrs = sysdb_new_attrs(state);
     292           0 :     if (!attrs) {
     293           0 :         ret = ENOMEM;
     294           0 :         goto done;
     295             :     }
     296             : 
     297             :     /* we are interested only in the host keys */
     298           0 :     ret = sysdb_attrs_copy_values(state->hosts[0], attrs, SYSDB_SSH_PUBKEY);
     299           0 :     if (ret != EOK) {
     300           0 :         goto done;
     301             :     }
     302             : 
     303           0 :     ret = sysdb_store_ssh_host(state->domain, state->name, state->alias,
     304           0 :                                state->domain->ssh_host_timeout, now, attrs);
     305           0 :     if (ret != EOK) {
     306           0 :         goto done;
     307             :     }
     308             : 
     309           0 :     dp_error = DP_ERR_OK;
     310             : 
     311             : done:
     312           0 :     state->dp_error = dp_error;
     313           0 :     if (ret == EOK) {
     314           0 :         tevent_req_done(req);
     315             :     } else {
     316           0 :         tevent_req_error(req, ret);
     317             :     }
     318             : }
     319             : 
     320             : static errno_t
     321           0 : hosts_get_recv(struct tevent_req *req,
     322             :                int *dp_error_out)
     323             : {
     324           0 :     struct hosts_get_state *state = tevent_req_data(req,
     325             :                                                     struct hosts_get_state);
     326             : 
     327           0 :     if (dp_error_out) {
     328           0 :         *dp_error_out = state->dp_error;
     329             :     }
     330             : 
     331           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     332             : 
     333           0 :     return EOK;
     334             : }

Generated by: LCOV version 1.10