LCOV - code coverage report
Current view: top level - source3/winbindd - wb_dsgetdcname.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 48 110 43.6 %
Date: 2024-04-21 15:09:00 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    async dsgetdcname
       4             :    Copyright (C) Volker Lendecke 2009
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "winbindd.h"
      22             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      23             : #include "librpc/gen_ndr/ndr_netlogon.h"
      24             : #include "lib/gencache.h"
      25             : 
      26             : struct wb_dsgetdcname_state {
      27             :         const char *domain_name;
      28             :         struct GUID domain_guid;
      29             :         struct netr_DsRGetDCNameInfo *dcinfo;
      30             : };
      31             : 
      32             : static void wb_dsgetdcname_done(struct tevent_req *subreq);
      33             : 
      34          18 : struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx,
      35             :                                        struct tevent_context *ev,
      36             :                                        const char *domain_name,
      37             :                                        const struct GUID *domain_guid,
      38             :                                        const char *site_name,
      39             :                                        uint32_t flags)
      40             : {
      41           0 :         struct tevent_req *req, *subreq;
      42           0 :         struct wb_dsgetdcname_state *state;
      43          18 :         struct dcerpc_binding_handle *child_binding_handle = NULL;
      44          18 :         struct GUID *guid_ptr = NULL;
      45             : 
      46          18 :         req = tevent_req_create(mem_ctx, &state, struct wb_dsgetdcname_state);
      47          18 :         if (req == NULL) {
      48           0 :                 return NULL;
      49             :         }
      50             : 
      51          18 :         D_INFO("WB command dsgetdcname start.\n"
      52             :                "Search domain name %s and site name %s.\n",
      53             :                domain_name,
      54             :                site_name);
      55          18 :         if (strequal(domain_name, "BUILTIN")) {
      56             :                 /*
      57             :                  * This makes no sense
      58             :                  */
      59           0 :                 tevent_req_nterror(req, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
      60           0 :                 return tevent_req_post(req, ev);
      61             :         }
      62             : 
      63          18 :         if (strequal(domain_name, get_global_sam_name())) {
      64           4 :                 int role = lp_server_role();
      65           4 :                 if ( role != ROLE_ACTIVE_DIRECTORY_DC ) {
      66             :                         /*
      67             :                          * Two options here: Give back our own address, or say there's
      68             :                          * nobody around. Right now opting for the latter, one measure
      69             :                          * to prevent the loopback connects. This might change if
      70             :                          * needed.
      71             :                          */
      72           4 :                         tevent_req_nterror(req, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
      73           4 :                         return tevent_req_post(req, ev);
      74             :                 }
      75             :         }
      76             : 
      77          14 :         if (IS_DC) {
      78             :                 /*
      79             :                  * We have to figure out the DC ourselves
      80             :                  */
      81           0 :                 child_binding_handle = locator_child_handle();
      82             :         } else {
      83          14 :                 struct winbindd_domain *domain = find_our_domain();
      84          14 :                 child_binding_handle = dom_child_handle(domain);
      85             :         }
      86             : 
      87          14 :         if (domain_guid != NULL) {
      88             :                 /* work around a const issue in rpccli_ autogenerated code */
      89           0 :                 state->domain_guid = *domain_guid;
      90           0 :                 guid_ptr = &state->domain_guid;
      91             :         }
      92             : 
      93          14 :         state->domain_name = talloc_strdup(state, domain_name);
      94          14 :         if (tevent_req_nomem(state->domain_name, req)) {
      95           0 :                 return tevent_req_post(req, ev);
      96             :         }
      97             : 
      98          14 :         subreq = dcerpc_wbint_DsGetDcName_send(
      99             :                 state, ev, child_binding_handle, domain_name, guid_ptr, site_name,
     100          14 :                 flags, &state->dcinfo);
     101          14 :         if (tevent_req_nomem(subreq, req)) {
     102           0 :                 return tevent_req_post(req, ev);
     103             :         }
     104          14 :         tevent_req_set_callback(subreq, wb_dsgetdcname_done, req);
     105          14 :         return req;
     106             : }
     107             : 
     108          14 : static void wb_dsgetdcname_done(struct tevent_req *subreq)
     109             : {
     110          14 :         struct tevent_req *req = tevent_req_callback_data(
     111             :                 subreq, struct tevent_req);
     112          14 :         struct wb_dsgetdcname_state *state = tevent_req_data(
     113             :                 req, struct wb_dsgetdcname_state);
     114           0 :         NTSTATUS status, result;
     115             : 
     116          14 :         status = dcerpc_wbint_DsGetDcName_recv(subreq, state, &result);
     117          14 :         TALLOC_FREE(subreq);
     118          14 :         if (any_nt_status_not_ok(status, result, &status)) {
     119           0 :                 tevent_req_nterror(req, status);
     120           0 :                 return;
     121             :         }
     122          14 :         tevent_req_done(req);
     123             : }
     124             : 
     125          18 : NTSTATUS wb_dsgetdcname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     126             :                              struct netr_DsRGetDCNameInfo **pdcinfo)
     127             : {
     128          18 :         struct wb_dsgetdcname_state *state = tevent_req_data(
     129             :                 req, struct wb_dsgetdcname_state);
     130           0 :         NTSTATUS status;
     131             : 
     132          18 :         D_INFO("WB command dsgetdcname for %s end.\n",
     133             :                state->domain_name);
     134          18 :         if (tevent_req_is_nterror(req, &status)) {
     135           4 :                 D_NOTICE("Failed for %s with %s.\n",
     136             :                          state->domain_name,
     137             :                          nt_errstr(status));
     138           4 :                 return status;
     139             :         }
     140          14 :         *pdcinfo = talloc_move(mem_ctx, &state->dcinfo);
     141          14 :         return NT_STATUS_OK;
     142             : }
     143             : 
     144           4 : NTSTATUS wb_dsgetdcname_gencache_set(const char *domname,
     145             :                                      struct netr_DsRGetDCNameInfo *dcinfo)
     146             : {
     147           0 :         DATA_BLOB blob;
     148           0 :         enum ndr_err_code ndr_err;
     149           0 :         char *key;
     150           0 :         bool ok;
     151             : 
     152           4 :         key = talloc_asprintf_strupper_m(talloc_tos(), "DCINFO/%s", domname);
     153           4 :         if (key == NULL) {
     154           0 :                 return NT_STATUS_NO_MEMORY;
     155             :         }
     156             : 
     157           4 :         if (DEBUGLEVEL >= DBGLVL_DEBUG) {
     158           0 :                 NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, dcinfo);
     159             :         }
     160             : 
     161           4 :         ndr_err = ndr_push_struct_blob(
     162             :                 &blob, key, dcinfo,
     163             :                 (ndr_push_flags_fn_t)ndr_push_netr_DsRGetDCNameInfo);
     164           4 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     165           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     166           0 :                 DBG_WARNING("ndr_push_struct_blob failed: %s\n",
     167             :                             ndr_errstr(ndr_err));
     168           0 :                 TALLOC_FREE(key);
     169           0 :                 return status;
     170             :         }
     171             : 
     172           4 :         ok = gencache_set_data_blob(key, blob, time(NULL)+3600);
     173             : 
     174           4 :         if (!ok) {
     175           0 :                 DBG_WARNING("gencache_set_data_blob for key %s failed\n", key);
     176           0 :                 TALLOC_FREE(key);
     177           0 :                 return NT_STATUS_UNSUCCESSFUL;
     178             :         }
     179             : 
     180           4 :         TALLOC_FREE(key);
     181           4 :         return NT_STATUS_OK;
     182             : }
     183             : 
     184             : struct dcinfo_parser_state {
     185             :         NTSTATUS status;
     186             :         TALLOC_CTX *mem_ctx;
     187             :         struct netr_DsRGetDCNameInfo *dcinfo;
     188             : };
     189             : 
     190           0 : static void dcinfo_parser(const struct gencache_timeout *timeout,
     191             :                           DATA_BLOB blob,
     192             :                           void *private_data)
     193             : {
     194           0 :         struct dcinfo_parser_state *state = private_data;
     195           0 :         enum ndr_err_code ndr_err;
     196             : 
     197           0 :         if (gencache_timeout_expired(timeout)) {
     198           0 :                 return;
     199             :         }
     200             : 
     201           0 :         state->dcinfo = talloc(state->mem_ctx, struct netr_DsRGetDCNameInfo);
     202           0 :         if (state->dcinfo == NULL) {
     203           0 :                 state->status = NT_STATUS_NO_MEMORY;
     204           0 :                 return;
     205             :         }
     206             : 
     207           0 :         ndr_err = ndr_pull_struct_blob_all(
     208           0 :                 &blob, state->dcinfo, state->dcinfo,
     209             :                 (ndr_pull_flags_fn_t)ndr_pull_netr_DsRGetDCNameInfo);
     210             : 
     211           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     212           0 :                 DBG_ERR("ndr_pull_struct_blob failed\n");
     213           0 :                 state->status = ndr_map_error2ntstatus(ndr_err);
     214           0 :                 TALLOC_FREE(state->dcinfo);
     215           0 :                 return;
     216             :         }
     217             : 
     218           0 :         state->status = NT_STATUS_OK;
     219             : }
     220             : 
     221           0 : NTSTATUS wb_dsgetdcname_gencache_get(TALLOC_CTX *mem_ctx,
     222             :                                      const char *domname,
     223             :                                      struct netr_DsRGetDCNameInfo **dcinfo)
     224             : {
     225           0 :         struct dcinfo_parser_state state;
     226           0 :         char *key;
     227           0 :         bool ok;
     228             : 
     229           0 :         key = talloc_asprintf_strupper_m(mem_ctx, "DCINFO/%s", domname);
     230           0 :         if (key == NULL) {
     231           0 :                 return NT_STATUS_NO_MEMORY;
     232             :         }
     233             : 
     234           0 :         state = (struct dcinfo_parser_state) {
     235             :                 .status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND,
     236             :                 .mem_ctx = mem_ctx,
     237             :         };
     238             : 
     239           0 :         ok = gencache_parse(key, dcinfo_parser, &state);
     240           0 :         TALLOC_FREE(key);
     241           0 :         if (!ok) {
     242           0 :                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
     243             :         }
     244             : 
     245           0 :         if (!NT_STATUS_IS_OK(state.status)) {
     246           0 :                 return state.status;
     247             :         }
     248             : 
     249           0 :         if (DEBUGLEVEL >= DBGLVL_DEBUG) {
     250           0 :                 NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, state.dcinfo);
     251             :         }
     252             : 
     253           0 :         *dcinfo = state.dcinfo;
     254           0 :         return NT_STATUS_OK;
     255             : }

Generated by: LCOV version 1.14