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

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     AD Domain Info Module
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2013 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             : 
      25             : #include <errno.h>
      26             : #include <tevent.h>
      27             : #include <ctype.h>
      28             : #include <ndr.h>
      29             : #include <ndr/ndr_nbt.h>
      30             : 
      31             : #include "providers/ldap/sdap.h"
      32             : #include "providers/ldap/sdap_async.h"
      33             : #include "providers/ldap/sdap_idmap.h"
      34             : #include "providers/ad/ad_domain_info.h"
      35             : #include "providers/ad/ad_common.h"
      36             : #include "util/util.h"
      37             : 
      38             : static errno_t
      39           0 : netlogon_get_domain_info(TALLOC_CTX *mem_ctx,
      40             :                          struct sysdb_attrs *reply,
      41             :                          char **_flat_name,
      42             :                          char **_site,
      43             :                          char **_forest)
      44             : {
      45             :     errno_t ret;
      46             :     struct ldb_message_element *el;
      47             :     DATA_BLOB blob;
      48           0 :     struct ndr_pull *ndr_pull = NULL;
      49             :     enum ndr_err_code ndr_err;
      50             :     struct netlogon_samlogon_response response;
      51             :     const char *flat_name;
      52             :     const char *site;
      53             :     const char *forest;
      54             : 
      55           0 :     ret = sysdb_attrs_get_el(reply, AD_AT_NETLOGON, &el);
      56           0 :     if (ret != EOK) {
      57           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el() failed\n");
      58           0 :         return ret;
      59             :     }
      60             : 
      61           0 :     if (el->num_values == 0) {
      62           0 :         DEBUG(SSSDBG_OP_FAILURE, "netlogon has no value\n");
      63           0 :         return ENOENT;
      64           0 :     } else if (el->num_values > 1) {
      65           0 :         DEBUG(SSSDBG_OP_FAILURE, "More than one netlogon value?\n");
      66           0 :         return EIO;
      67             :     }
      68             : 
      69           0 :     blob.data = el->values[0].data;
      70           0 :     blob.length = el->values[0].length;
      71             : 
      72           0 :     ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
      73           0 :     if (ndr_pull == NULL) {
      74           0 :         DEBUG(SSSDBG_OP_FAILURE, "ndr_pull_init_blob() failed.\n");
      75           0 :         return ENOMEM;
      76             :     }
      77             : 
      78           0 :     ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS,
      79             :                                                   &response);
      80           0 :     if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      81           0 :         DEBUG(SSSDBG_OP_FAILURE, "ndr_pull_netlogon_samlogon_response() "
      82             :                                   "failed [%d]\n", ndr_err);
      83           0 :         ret = EBADMSG;
      84           0 :         goto done;
      85             :     }
      86             : 
      87           0 :     if (!(response.ntver & NETLOGON_NT_VERSION_5EX)) {
      88           0 :         DEBUG(SSSDBG_OP_FAILURE, "Wrong version returned [%x]\n",
      89             :                                   response.ntver);
      90           0 :         ret = EBADMSG;
      91           0 :         goto done;
      92             :     }
      93             : 
      94             :     /* get flat name */
      95           0 :     if (response.data.nt5_ex.domain_name != NULL &&
      96           0 :         *response.data.nt5_ex.domain_name != '\0') {
      97           0 :         flat_name = response.data.nt5_ex.domain_name;
      98             :     } else {
      99           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     100             :               "No netlogon domain name data available\n");
     101           0 :         ret = ENOENT;
     102           0 :         goto done;
     103             :     }
     104             : 
     105           0 :     *_flat_name = talloc_strdup(mem_ctx, flat_name);
     106           0 :     if (*_flat_name == NULL) {
     107           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     108           0 :         ret = ENOMEM;
     109           0 :         goto done;
     110             :     }
     111             : 
     112             :     /* get forest */
     113           0 :     if (response.data.nt5_ex.forest != NULL &&
     114           0 :         *response.data.nt5_ex.forest != '\0') {
     115           0 :         forest = response.data.nt5_ex.forest;
     116             :     } else {
     117           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No netlogon forest data available\n");
     118           0 :         ret = ENOENT;
     119           0 :         goto done;
     120             :     }
     121             : 
     122           0 :     *_forest = talloc_strdup(mem_ctx, forest);
     123           0 :     if (*_forest == NULL) {
     124           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     125           0 :         ret = ENOMEM;
     126           0 :         goto done;
     127             :     }
     128             : 
     129             :     /* get site name */
     130           0 :     if (response.data.nt5_ex.client_site != NULL
     131           0 :         && response.data.nt5_ex.client_site[0] != '\0') {
     132           0 :         site = response.data.nt5_ex.client_site;
     133             :     } else {
     134           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     135             :               "No netlogon site name data available\n");
     136           0 :         ret = ENOENT;
     137           0 :         goto done;
     138             :     }
     139             : 
     140           0 :     *_site = talloc_strdup(mem_ctx, site);
     141           0 :     if (*_site == NULL) {
     142           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     143           0 :         ret = ENOMEM;
     144           0 :         goto done;
     145             :     }
     146             : 
     147           0 :     ret = EOK;
     148             : done:
     149           0 :     talloc_free(ndr_pull);
     150           0 :     return ret;
     151             : }
     152             : 
     153             : struct ad_master_domain_state {
     154             :     struct tevent_context *ev;
     155             :     struct sdap_id_conn_ctx *conn;
     156             :     struct sdap_id_op *id_op;
     157             :     struct sdap_id_ctx *id_ctx;
     158             :     struct sdap_options *opts;
     159             : 
     160             :     const char *dom_name;
     161             :     int base_iter;
     162             : 
     163             :     char *flat;
     164             :     char *site;
     165             :     char *forest;
     166             :     char *sid;
     167             : };
     168             : 
     169             : static errno_t ad_master_domain_next(struct tevent_req *req);
     170             : static void ad_master_domain_next_done(struct tevent_req *subreq);
     171             : static void ad_master_domain_netlogon_done(struct tevent_req *req);
     172             : 
     173             : struct tevent_req *
     174           0 : ad_master_domain_send(TALLOC_CTX *mem_ctx,
     175             :                       struct tevent_context *ev,
     176             :                       struct sdap_id_conn_ctx *conn,
     177             :                       struct sdap_id_op *op,
     178             :                       const char *dom_name)
     179             : {
     180             :     errno_t ret;
     181             :     struct tevent_req *req;
     182             :     struct ad_master_domain_state *state;
     183             : 
     184           0 :     req = tevent_req_create(mem_ctx, &state, struct ad_master_domain_state);
     185           0 :     if (!req) return NULL;
     186             : 
     187           0 :     state->ev = ev;
     188           0 :     state->id_op = op;
     189           0 :     state->conn = conn;
     190           0 :     state->id_ctx = conn->id_ctx;
     191           0 :     state->opts = conn->id_ctx->opts;
     192           0 :     state->dom_name = dom_name;
     193             : 
     194           0 :     ret = ad_master_domain_next(req);
     195           0 :     if (ret != EOK && ret != EAGAIN) {
     196           0 :         goto immediate;
     197             :     }
     198             : 
     199           0 :     return req;
     200             : 
     201             : immediate:
     202           0 :     if (ret != EOK) {
     203           0 :         tevent_req_error(req, ret);
     204             :     } else {
     205           0 :         tevent_req_done(req);
     206             :     }
     207           0 :     tevent_req_post(req, ev);
     208           0 :     return req;
     209             : }
     210             : 
     211             : static errno_t
     212           0 : ad_master_domain_next(struct tevent_req *req)
     213             : {
     214             :     struct tevent_req *subreq;
     215             :     struct sdap_search_base *base;
     216           0 :     const char *master_sid_attrs[] = {AD_AT_OBJECT_SID, NULL};
     217             : 
     218           0 :     struct ad_master_domain_state *state =
     219           0 :         tevent_req_data(req, struct ad_master_domain_state);
     220             : 
     221           0 :     base = state->opts->sdom->search_bases[state->base_iter];
     222           0 :     if (base == NULL) {
     223           0 :         return EOK;
     224             :     }
     225             : 
     226           0 :     subreq = sdap_get_generic_send(state, state->ev,
     227           0 :                                    state->id_ctx->opts,
     228             :                                    sdap_id_op_handle(state->id_op),
     229             :                                    base->basedn, LDAP_SCOPE_BASE,
     230             :                                    MASTER_DOMAIN_SID_FILTER, master_sid_attrs,
     231             :                                    NULL, 0,
     232           0 :                                    dp_opt_get_int(state->opts->basic,
     233             :                                                   SDAP_SEARCH_TIMEOUT),
     234             :                                    false);
     235           0 :     if (subreq == NULL) {
     236           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
     237           0 :         return ENOMEM;
     238             :     }
     239           0 :     tevent_req_set_callback(subreq, ad_master_domain_next_done, req);
     240             : 
     241           0 :     return EAGAIN;
     242             : }
     243             : 
     244             : static void
     245           0 : ad_master_domain_next_done(struct tevent_req *subreq)
     246             : {
     247             :     errno_t ret;
     248             :     size_t reply_count;
     249           0 :     struct sysdb_attrs **reply = NULL;
     250             :     struct ldb_message_element *el;
     251             :     char *sid_str;
     252             :     enum idmap_error_code err;
     253             :     static const char *attrs[] = {AD_AT_NETLOGON, NULL};
     254             :     char *filter;
     255             :     char *ntver;
     256             : 
     257           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     258             :                                                       struct tevent_req);
     259           0 :     struct ad_master_domain_state *state =
     260           0 :         tevent_req_data(req, struct ad_master_domain_state);
     261             : 
     262           0 :     ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
     263           0 :     talloc_zfree(subreq);
     264           0 :     if (ret != EOK) {
     265           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
     266           0 :         goto done;
     267             :     }
     268             : 
     269           0 :     if (reply_count == 0) {
     270           0 :         state->base_iter++;
     271           0 :         ret = ad_master_domain_next(req);
     272           0 :         if (ret == EAGAIN) {
     273             :             /* Async request will get us back here again */
     274           0 :             return;
     275           0 :         } else if (ret != EOK) {
     276           0 :             goto done;
     277             :         }
     278             : 
     279             :         /* EOK */
     280           0 :         tevent_req_done(req);
     281           0 :         return;
     282           0 :     } else if (reply_count == 1) {
     283           0 :         ret = sysdb_attrs_get_el(reply[0], AD_AT_OBJECT_SID, &el);
     284           0 :         if (ret != EOK || el->num_values != 1) {
     285           0 :             DEBUG(SSSDBG_OP_FAILURE, "sdap_attrs_get_el failed.\n");
     286           0 :             goto done;
     287             :         }
     288             : 
     289           0 :         err = sss_idmap_bin_sid_to_sid(state->opts->idmap_ctx->map,
     290           0 :                                        el->values[0].data,
     291           0 :                                        el->values[0].length,
     292             :                                        &sid_str);
     293           0 :         if (err != IDMAP_SUCCESS) {
     294           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     295             :                   "Could not convert SID: [%s].\n", idmap_error_string(err));
     296           0 :             ret = EFAULT;
     297           0 :             goto done;
     298             :         }
     299             : 
     300           0 :         state->sid = talloc_steal(state, sid_str);
     301             :     } else {
     302           0 :         DEBUG(SSSDBG_OP_FAILURE,
     303             :               "More than one result for domain SID found.\n");
     304           0 :         ret = EINVAL;
     305           0 :         goto done;
     306             :     }
     307             : 
     308           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Found SID [%s].\n", state->sid);
     309             : 
     310           0 :     ntver = sss_ldap_encode_ndr_uint32(state, NETLOGON_NT_VERSION_5EX |
     311             :                                        NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
     312           0 :     if (ntver == NULL) {
     313           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_ldap_encode_ndr_uint32 failed.\n");
     314           0 :         ret = ENOMEM;
     315           0 :         goto done;
     316             :     }
     317             : 
     318           0 :     filter = talloc_asprintf(state, "(&(%s=%s)(%s=%s))",
     319             :                              AD_AT_DNS_DOMAIN, state->dom_name,
     320             :                              AD_AT_NT_VERSION, ntver);
     321           0 :     if (filter == NULL) {
     322           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
     323           0 :         ret = ENOMEM;
     324           0 :         goto done;
     325             :     }
     326             : 
     327           0 :     subreq = sdap_get_generic_send(state, state->ev,
     328           0 :                                    state->id_ctx->opts,
     329             :                                    sdap_id_op_handle(state->id_op),
     330             :                                    "", LDAP_SCOPE_BASE, filter, attrs, NULL, 0,
     331           0 :                                    dp_opt_get_int(state->opts->basic,
     332             :                                                   SDAP_SEARCH_TIMEOUT),
     333             :                                    false);
     334           0 :     if (subreq == NULL) {
     335           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
     336           0 :         ret = ENOMEM;
     337           0 :         goto done;
     338             :     }
     339             : 
     340           0 :     tevent_req_set_callback(subreq, ad_master_domain_netlogon_done, req);
     341           0 :     return;
     342             : 
     343             : done:
     344           0 :     tevent_req_error(req, ret);
     345             : }
     346             : 
     347             : static void
     348           0 : ad_master_domain_netlogon_done(struct tevent_req *subreq)
     349             : {
     350             :     int ret;
     351             :     size_t reply_count;
     352           0 :     struct sysdb_attrs **reply = NULL;
     353             : 
     354           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     355             :                                                       struct tevent_req);
     356           0 :     struct ad_master_domain_state *state =
     357           0 :         tevent_req_data(req, struct ad_master_domain_state);
     358             : 
     359           0 :     ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
     360           0 :     talloc_zfree(subreq);
     361           0 :     if (ret != EOK) {
     362           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
     363           0 :         tevent_req_error(req, ret);
     364           0 :         return;
     365             :     }
     366             : 
     367             :     /* Failure to get the flat name is not fatal. Just quit. */
     368           0 :     if (reply_count == 0) {
     369           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No netlogon data available. Flat name " \
     370             :                                      "might not be usable\n");
     371           0 :         goto done;
     372           0 :     } else if (reply_count > 1) {
     373           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     374             :                 "More than one netlogon info returned.\n");
     375           0 :         goto done;
     376             :     }
     377             : 
     378             :     /* Exactly one flat name. Carry on */
     379             : 
     380           0 :     ret = netlogon_get_domain_info(state, reply[0], &state->flat,
     381             :                                    &state->site, &state->forest);
     382           0 :     if (ret != EOK) {
     383           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     384             :               "Could not get the flat name or forest: %d:[%s]\n",
     385             :               ret, sss_strerror(ret));
     386             :         /* Not fatal. Just quit. */
     387           0 :         goto done;
     388             :     }
     389             : 
     390           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Found flat name [%s].\n", state->flat);
     391           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Found site [%s].\n", state->site);
     392           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Found forest [%s].\n", state->forest);
     393             : 
     394             : done:
     395           0 :     tevent_req_done(req);
     396           0 :     return;
     397             : }
     398             : 
     399             : errno_t
     400           0 : ad_master_domain_recv(struct tevent_req *req,
     401             :                       TALLOC_CTX *mem_ctx,
     402             :                       char **_flat,
     403             :                       char **_id,
     404             :                       char **_site,
     405             :                       char **_forest)
     406             : {
     407           0 :     struct ad_master_domain_state *state = tevent_req_data(req,
     408             :                                               struct ad_master_domain_state);
     409             : 
     410           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     411             : 
     412           0 :     if (_flat) {
     413           0 :         *_flat = talloc_steal(mem_ctx, state->flat);
     414             :     }
     415             : 
     416           0 :     if (_site) {
     417           0 :         *_site = talloc_steal(mem_ctx, state->site);
     418             :     }
     419             : 
     420           0 :     if (_forest) {
     421           0 :         *_forest = talloc_steal(mem_ctx, state->forest);
     422             :     }
     423             : 
     424           0 :     if (_id) {
     425           0 :         *_id = talloc_steal(mem_ctx, state->sid);
     426             :     }
     427             : 
     428           0 :     return EOK;
     429             : }

Generated by: LCOV version 1.10