LCOV - code coverage report
Current view: top level - source4/dsdb/repl - drepl_partitions.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 220 283 77.7 %
Date: 2024-06-13 04:01:37 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS Implementation.
       3             :    DSDB replication service
       4             :    
       5             :    Copyright (C) Stefan Metzmacher 2007
       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             : 
      22             : #include "includes.h"
      23             : #include "dsdb/samdb/samdb.h"
      24             : #include "auth/auth.h"
      25             : #include "samba/service.h"
      26             : #include "lib/events/events.h"
      27             : #include "dsdb/repl/drepl_service.h"
      28             : #include <ldb_errors.h>
      29             : #include "../lib/util/dlinklist.h"
      30             : #include "librpc/gen_ndr/ndr_misc.h"
      31             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      32             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      33             : #include "libcli/security/security.h"
      34             : #include "param/param.h"
      35             : #include "dsdb/common/util.h"
      36             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS            DBGC_DRS_REPL
      39             : 
      40             : #undef strcasecmp
      41             : 
      42             : /*
      43             :   load the partitions list based on replicated NC attributes in our
      44             :   NTDSDSA object
      45             :  */
      46          47 : WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
      47             : {
      48             :         WERROR status;
      49             :         static const char *attrs[] = { "hasMasterNCs", "msDS-hasMasterNCs", "hasPartialReplicaNCs", "msDS-HasFullReplicaNCs", NULL };
      50             :         unsigned int a;
      51             :         int ret;
      52             :         TALLOC_CTX *tmp_ctx;
      53             :         struct ldb_result *res;
      54             :         struct ldb_message_element *el;
      55             :         struct ldb_dn *ntds_dn;
      56             : 
      57          47 :         tmp_ctx = talloc_new(s);
      58          47 :         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
      59             : 
      60          47 :         ntds_dn = samdb_ntds_settings_dn(s->samdb, tmp_ctx);
      61          47 :         if (!ntds_dn) {
      62           0 :                 DEBUG(1,(__location__ ": Unable to find ntds_dn: %s\n", ldb_errstring(s->samdb)));
      63           0 :                 talloc_free(tmp_ctx);
      64           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
      65             :         }
      66             : 
      67          47 :         ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
      68          47 :         if (ret != LDB_SUCCESS) {
      69           0 :                 DEBUG(1,("Searching for hasMasterNCs in NTDS DN failed: %s\n", ldb_errstring(s->samdb)));
      70           0 :                 talloc_free(tmp_ctx);
      71           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
      72             :         }
      73             : 
      74         235 :         for (a=0; attrs[a]; a++) {
      75             :                 int i;
      76             : 
      77         188 :                 el = ldb_msg_find_element(res->msgs[0], attrs[a]);
      78         188 :                 if (el == NULL) {
      79          96 :                         continue;
      80             :                 }
      81         454 :                 for (i=0; i<el->num_values; i++) {
      82             :                         struct ldb_dn *pdn;
      83             :                         struct dreplsrv_partition *p, *tp;
      84             :                         bool found;
      85             : 
      86         362 :                         pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
      87         362 :                         if (pdn == NULL) {
      88           0 :                                 talloc_free(tmp_ctx);
      89           0 :                                 return WERR_DS_DRA_INTERNAL_ERROR;
      90             :                         }
      91         362 :                         if (!ldb_dn_validate(pdn)) {
      92           0 :                                 return WERR_DS_DRA_INTERNAL_ERROR;
      93             :                         }
      94             : 
      95         362 :                         p = talloc_zero(s, struct dreplsrv_partition);
      96         362 :                         W_ERROR_HAVE_NO_MEMORY(p);
      97             : 
      98         362 :                         p->dn = talloc_steal(p, pdn);
      99         362 :                         p->service = s;
     100             : 
     101         362 :                         if (strcasecmp(attrs[a], "hasPartialReplicaNCs") == 0) {
     102           0 :                                 p->partial_replica = true;
     103         362 :                         } else if (strcasecmp(attrs[a], "msDS-HasFullReplicaNCs") == 0) {
     104           5 :                                 p->rodc_replica = true;
     105             :                         }
     106             : 
     107             :                         /* Do not add partitions more than once */
     108         362 :                         found = false;
     109        1058 :                         for (tp = s->partitions; tp; tp = tp->next) {
     110         831 :                                 if (ldb_dn_compare(tp->dn, p->dn) == 0) {
     111         135 :                                         found = true;
     112         135 :                                         break;
     113             :                                 }
     114             :                         }
     115         362 :                         if (found) {
     116         135 :                                 talloc_free(p);
     117         135 :                                 continue;
     118             :                         }
     119             : 
     120         227 :                         DLIST_ADD(s->partitions, p);
     121         227 :                         DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn)));
     122             :                 }
     123             :         }
     124             : 
     125          47 :         talloc_free(tmp_ctx);
     126             : 
     127          47 :         status = dreplsrv_refresh_partitions(s);
     128          47 :         W_ERROR_NOT_OK_RETURN(status);
     129             : 
     130          47 :         return WERR_OK;
     131             : }
     132             : 
     133             : /*
     134             :   Check if particular SPN exists for an account
     135             :  */
     136          43 : static bool dreplsrv_spn_exists(struct ldb_context *samdb, struct ldb_dn *account_dn,
     137             :                                 const char *principal_name)
     138             : {
     139             :         TALLOC_CTX *tmp_ctx;
     140          43 :         const char *attrs_empty[] = { NULL };
     141             :         int ret;
     142             :         struct ldb_result *res;
     143             : 
     144          43 :         tmp_ctx = talloc_new(samdb);
     145             : 
     146          43 :         ret = dsdb_search(samdb, tmp_ctx, &res, account_dn, LDB_SCOPE_BASE, attrs_empty,
     147             :                         0, "servicePrincipalName=%s",
     148             :                         ldb_binary_encode_string(tmp_ctx, principal_name));
     149          43 :         if (ret != LDB_SUCCESS || res->count != 1) {
     150           0 :                 talloc_free(tmp_ctx);
     151           0 :                 return false;
     152             :         }
     153             : 
     154          43 :         talloc_free(tmp_ctx);
     155          43 :         return true;
     156             : }
     157             : 
     158             : /*
     159             :   work out the principal to use for DRS replication connections
     160             :  */
     161          49 : static NTSTATUS dreplsrv_get_target_principal(struct dreplsrv_service *s,
     162             :                                               TALLOC_CTX *mem_ctx,
     163             :                                               const struct repsFromTo1 *rft,
     164             :                                               char **target_principal)
     165             : {
     166             :         TALLOC_CTX *tmp_ctx;
     167             :         struct ldb_result *res;
     168          49 :         const char *attrs_server[] = { "dNSHostName", "serverReference", NULL };
     169          49 :         const char *attrs_ntds[] = { "msDS-HasDomainNCs", "hasMasterNCs", NULL };
     170             :         int ret;
     171          49 :         const char *hostname, *dnsdomain=NULL;
     172             :         struct ldb_dn *ntds_dn, *server_dn, *computer_dn;
     173             :         struct ldb_dn *forest_dn, *nc_dn;
     174             : 
     175          49 :         *target_principal = NULL;
     176             : 
     177          49 :         tmp_ctx = talloc_new(mem_ctx);
     178             : 
     179             :         /* we need to find their hostname */
     180          49 :         ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &rft->source_dsa_obj_guid, 0, &ntds_dn);
     181          49 :         if (ret != LDB_SUCCESS) {
     182           2 :                 talloc_free(tmp_ctx);
     183             :                 /* its OK for their NTDSDSA DN not to be in our database */
     184           2 :                 return NT_STATUS_OK;
     185             :         }
     186             : 
     187          47 :         server_dn = ldb_dn_copy(tmp_ctx, ntds_dn);
     188          47 :         if (server_dn == NULL) {
     189           0 :                 talloc_free(tmp_ctx);
     190           0 :                 return NT_STATUS_OK;
     191             :         }
     192             : 
     193             :         /* strip off the NTDS Settings */
     194          47 :         if (!ldb_dn_remove_child_components(server_dn, 1)) {
     195           0 :                 talloc_free(tmp_ctx);
     196           0 :                 return NT_STATUS_OK;
     197             :         }
     198             : 
     199          47 :         ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, server_dn, attrs_server, 0);
     200          47 :         if (ret != LDB_SUCCESS) {
     201           0 :                 talloc_free(tmp_ctx);
     202             :                 /* its OK for their server DN not to be in our database */
     203           0 :                 return NT_STATUS_OK;
     204             :         }
     205             : 
     206          47 :         forest_dn = ldb_get_root_basedn(s->samdb);
     207          47 :         if (forest_dn == NULL) {
     208           0 :                 talloc_free(tmp_ctx);
     209           0 :                 return NT_STATUS_OK;
     210             :         }
     211             : 
     212          47 :         hostname = ldb_msg_find_attr_as_string(res->msgs[0], "dNSHostName", NULL);
     213          47 :         computer_dn = ldb_msg_find_attr_as_dn(s->samdb, tmp_ctx, res->msgs[0], "serverReference");
     214          47 :         if (hostname != NULL && computer_dn != NULL) {
     215             :                 char *local_principal;
     216             : 
     217             :                 /*
     218             :                   if we have the dNSHostName attribute then we can use
     219             :                   the GC/hostname/realm SPN. All DCs should have this SPN
     220             : 
     221             :                   Windows DC may set up it's dNSHostName before setting up
     222             :                   GC/xx/xx SPN. So make sure it exists, before using it.
     223             :                  */
     224          43 :                 local_principal = talloc_asprintf(mem_ctx, "GC/%s/%s",
     225             :                                                     hostname,
     226             :                                                     samdb_dn_to_dns_domain(tmp_ctx, forest_dn));
     227          43 :                 if (dreplsrv_spn_exists(s->samdb, computer_dn, local_principal)) {
     228          43 :                         *target_principal = local_principal;
     229          43 :                         talloc_free(tmp_ctx);
     230          43 :                         return NT_STATUS_OK;
     231             :                 }
     232             : 
     233           0 :                 talloc_free(local_principal);
     234             :         }
     235             : 
     236             :         /*
     237             :            if we can't find the dNSHostName then we will try for the
     238             :            E3514235-4B06-11D1-AB04-00C04FC2DCD2/${NTDSGUID}/${DNSDOMAIN}
     239             :            SPN. To use that we need the DNS domain name of the target
     240             :            DC. We find that by first looking for the msDS-HasDomainNCs
     241             :            in the NTDSDSA object of the DC, and if we don't find that,
     242             :            then we look for the hasMasterNCs attribute, and eliminate
     243             :            the known schema and configuruation DNs. Despite how
     244             :            bizarre this seems, Hongwei tells us that this is in fact
     245             :            what windows does to find the SPN!!
     246             :         */
     247           4 :         ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs_ntds, 0);
     248           4 :         if (ret != LDB_SUCCESS) {
     249           0 :                 talloc_free(tmp_ctx);
     250           0 :                 return NT_STATUS_OK;
     251             :         }
     252             : 
     253           4 :         nc_dn = ldb_msg_find_attr_as_dn(s->samdb, tmp_ctx, res->msgs[0], "msDS-HasDomainNCs");
     254           4 :         if (nc_dn != NULL) {
     255           4 :                 dnsdomain = samdb_dn_to_dns_domain(tmp_ctx, nc_dn);
     256             :         }
     257             : 
     258           4 :         if (dnsdomain == NULL) {
     259             :                 struct ldb_message_element *el;
     260             :                 int i;
     261           0 :                 el = ldb_msg_find_element(res->msgs[0], "hasMasterNCs");
     262           0 :                 for (i=0; el && i<el->num_values; i++) {
     263           0 :                         nc_dn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
     264           0 :                         if (nc_dn == NULL ||
     265           0 :                             ldb_dn_compare(ldb_get_config_basedn(s->samdb), nc_dn) == 0 ||
     266           0 :                             ldb_dn_compare(ldb_get_schema_basedn(s->samdb), nc_dn) == 0) {
     267           0 :                                 continue;
     268             :                         }
     269             :                         /* it must be a domain DN, get the equivalent
     270             :                            DNS domain name */
     271           0 :                         dnsdomain = samdb_dn_to_dns_domain(tmp_ctx, nc_dn);
     272           0 :                         break;
     273             :                 }
     274             :         }
     275             : 
     276           4 :         if (dnsdomain != NULL) {
     277           4 :                 *target_principal = talloc_asprintf(mem_ctx,
     278             :                                                     "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s@%s",
     279             :                                                     GUID_string(tmp_ctx, &rft->source_dsa_obj_guid),
     280             :                                                     dnsdomain, dnsdomain);
     281             :         }
     282             : 
     283           4 :         talloc_free(tmp_ctx);
     284           4 :         return NT_STATUS_OK;
     285             : }
     286             : 
     287             : 
     288       25043 : WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s,
     289             :                                       const struct repsFromTo1 *rft,
     290             :                                       struct dreplsrv_out_connection **_conn)
     291             : {
     292       25043 :         struct dreplsrv_out_connection *cur, *conn = NULL;
     293             :         const char *hostname;
     294             : 
     295       25043 :         if (!rft->other_info) {
     296           0 :                 return WERR_FOOBAR;
     297             :         }
     298             : 
     299       25043 :         if (!rft->other_info->dns_name) {
     300           0 :                 return WERR_FOOBAR;
     301             :         }
     302             : 
     303       25043 :         hostname = rft->other_info->dns_name;
     304             : 
     305       54149 :         for (cur = s->connections; cur; cur = cur->next) {
     306             :                 const char *host;
     307             : 
     308       54100 :                 host = dcerpc_binding_get_string_option(cur->binding, "host");
     309       54100 :                 if (host == NULL) {
     310           0 :                         continue;
     311             :                 }
     312             : 
     313       54100 :                 if (strcmp(host, hostname) == 0) {
     314       24994 :                         conn = cur;
     315       24994 :                         break;
     316             :                 }
     317             :         }
     318             : 
     319       25043 :         if (!conn) {
     320             :                 NTSTATUS nt_status;
     321             :                 char *binding_str;
     322          49 :                 char *target_principal = NULL;
     323             : 
     324          49 :                 conn = talloc_zero(s, struct dreplsrv_out_connection);
     325          49 :                 W_ERROR_HAVE_NO_MEMORY(conn);
     326             : 
     327          49 :                 conn->service        = s;
     328             : 
     329          49 :                 binding_str = talloc_asprintf(conn, "ncacn_ip_tcp:%s[krb5,seal]",
     330             :                                               hostname);
     331          49 :                 W_ERROR_HAVE_NO_MEMORY(binding_str);
     332          49 :                 nt_status = dcerpc_parse_binding(conn, binding_str, &conn->binding);
     333          49 :                 talloc_free(binding_str);
     334          49 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     335           0 :                         return ntstatus_to_werror(nt_status);
     336             :                 }
     337             : 
     338             :                 /* use the GC principal for DRS replication */
     339          49 :                 nt_status = dreplsrv_get_target_principal(s, conn->binding,
     340             :                                                           rft, &target_principal);
     341          49 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     342           0 :                         return ntstatus_to_werror(nt_status);
     343             :                 }
     344             : 
     345          49 :                 nt_status = dcerpc_binding_set_string_option(conn->binding,
     346             :                                                              "target_principal",
     347             :                                                              target_principal);
     348          49 :                 TALLOC_FREE(target_principal);
     349          49 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     350           0 :                         return ntstatus_to_werror(nt_status);
     351             :                 }
     352             : 
     353          49 :                 DLIST_ADD_END(s->connections, conn);
     354             : 
     355          49 :                 DEBUG(4,("dreplsrv_out_connection_attach(%s): create\n", hostname));
     356             :         } else {
     357       24994 :                 DEBUG(4,("dreplsrv_out_connection_attach(%s): attach\n", hostname));
     358             :         }
     359             : 
     360       25043 :         *_conn = conn;
     361       25043 :         return WERR_OK;
     362             : }
     363             : 
     364             : /*
     365             :   find an existing source dsa in a list
     366             :  */
     367       12406 : static struct dreplsrv_partition_source_dsa *dreplsrv_find_source_dsa(struct dreplsrv_partition_source_dsa *list,
     368             :                                                                       struct GUID *guid)
     369             : {
     370             :         struct dreplsrv_partition_source_dsa *s;
     371       22677 :         for (s=list; s; s=s->next) {
     372       16906 :                 if (GUID_equal(&s->repsFrom1->source_dsa_obj_guid, guid)) {
     373        6635 :                         return s;
     374             :                 }
     375             :         }
     376        5771 :         return NULL;    
     377             : }
     378             : 
     379             : 
     380             : 
     381       23163 : static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s,
     382             :                                                 struct dreplsrv_partition *p,
     383             :                                                 struct dreplsrv_partition_source_dsa **listp,
     384             :                                                 struct dreplsrv_partition_source_dsa *check_list,
     385             :                                                 const struct ldb_val *val)
     386             : {
     387             :         WERROR status;
     388             :         enum ndr_err_code ndr_err;
     389             :         struct dreplsrv_partition_source_dsa *source, *s2;
     390             : 
     391       23163 :         source = talloc_zero(p, struct dreplsrv_partition_source_dsa);
     392       23163 :         W_ERROR_HAVE_NO_MEMORY(source);
     393             : 
     394       23163 :         ndr_err = ndr_pull_struct_blob(val, source, 
     395       23163 :                                        &source->_repsFromBlob,
     396             :                                        (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob);
     397       23163 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     398           0 :                 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
     399           0 :                 talloc_free(source);
     400           0 :                 return ntstatus_to_werror(nt_status);
     401             :         }
     402             :         /* NDR_PRINT_DEBUG(repsFromToBlob, &source->_repsFromBlob); */
     403       23163 :         if (source->_repsFromBlob.version != 1) {
     404           0 :                 talloc_free(source);
     405           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     406             :         }
     407             : 
     408       23163 :         source->partition    = p;
     409       23163 :         source->repsFrom1    = &source->_repsFromBlob.ctr.ctr1;
     410             : 
     411       23163 :         status = dreplsrv_out_connection_attach(s, source->repsFrom1, &source->conn);
     412       23163 :         W_ERROR_NOT_OK_RETURN(status);
     413             : 
     414       35569 :         if (check_list && 
     415       12406 :             dreplsrv_find_source_dsa(check_list, &source->repsFrom1->source_dsa_obj_guid)) {
     416             :                 /* its in the check list, don't add it again */
     417        6635 :                 talloc_free(source);
     418        6635 :                 return WERR_OK;
     419             :         }
     420             : 
     421             :         /* re-use an existing source if found */
     422       35779 :         for (s2=*listp; s2; s2=s2->next) {
     423       35547 :                 if (GUID_equal(&s2->repsFrom1->source_dsa_obj_guid,
     424       35547 :                                  &source->repsFrom1->source_dsa_obj_guid)) {
     425       16296 :                         talloc_free(s2->repsFrom1->other_info);
     426       16296 :                         *s2->repsFrom1 = *source->repsFrom1;
     427       16296 :                         talloc_steal(s2, s2->repsFrom1->other_info);
     428       16296 :                         talloc_free(source);
     429       16296 :                         return WERR_OK;
     430             :                 }
     431             :         }
     432             : 
     433         232 :         DLIST_ADD_END(*listp, source);
     434         232 :         return WERR_OK;
     435             : }
     436             : 
     437             : /**
     438             :  * Find a partition when given a NC
     439             :  * If the NC can't be found it will return BAD_NC
     440             :  * Initial checks for invalid parameters have to be done beforehand
     441             :  */
     442        2425 : WERROR dreplsrv_partition_find_for_nc(struct dreplsrv_service *s,
     443             :                                       struct GUID *nc_guid,
     444             :                                       struct dom_sid *nc_sid,
     445             :                                       const char *nc_dn_str,
     446             :                                       struct dreplsrv_partition **_p)
     447             : {
     448             :         struct dreplsrv_partition *p;
     449             :         bool valid_sid, valid_guid;
     450             : 
     451        2425 :         SMB_ASSERT(_p);
     452             : 
     453        2425 :         valid_sid  = nc_sid && !is_null_sid(nc_sid);
     454        2425 :         valid_guid = nc_guid && !GUID_all_zero(nc_guid);
     455             : 
     456        2425 :         if (!valid_sid && !valid_guid && (!nc_dn_str)) {
     457           0 :                 return WERR_DS_DRA_BAD_NC;
     458             :         }
     459             : 
     460        9698 :         for (p = s->partitions; p; p = p->next) {
     461        9698 :                 if ((valid_guid && GUID_equal(&p->nc.guid, nc_guid))
     462        8238 :                     || strequal(p->nc.dn, nc_dn_str)
     463        7273 :                     || (valid_sid && dom_sid_equal(&p->nc.sid, nc_sid)))
     464             :                 {
     465             :                         /* fill in he right guid and sid if possible */
     466        2425 :                         if (nc_guid && !valid_guid) {
     467         951 :                                 dsdb_get_extended_dn_guid(p->dn, nc_guid, "GUID");
     468             :                         }
     469        2425 :                         if (nc_sid && !valid_sid) {
     470        1677 :                                 dsdb_get_extended_dn_sid(p->dn, nc_sid, "SID");
     471             :                         }
     472        2425 :                         *_p = p;
     473        2425 :                         return WERR_OK;
     474             :                 }
     475             :         }
     476             : 
     477           0 :         return WERR_DS_DRA_BAD_NC;
     478             : }
     479             : 
     480        4303 : WERROR dreplsrv_partition_source_dsa_by_guid(struct dreplsrv_partition *p,
     481             :                                              const struct GUID *dsa_guid,
     482             :                                              struct dreplsrv_partition_source_dsa **_dsa)
     483             : {
     484             :         struct dreplsrv_partition_source_dsa *dsa;
     485             : 
     486        4303 :         SMB_ASSERT(dsa_guid != NULL);
     487        4303 :         SMB_ASSERT(!GUID_all_zero(dsa_guid));
     488        4303 :         SMB_ASSERT(_dsa);
     489             : 
     490        4313 :         for (dsa = p->sources; dsa; dsa = dsa->next) {
     491        4311 :                 if (GUID_equal(dsa_guid, &dsa->repsFrom1->source_dsa_obj_guid)) {
     492        4301 :                         *_dsa = dsa;
     493        4301 :                         return WERR_OK;
     494             :                 }
     495             :         }
     496             : 
     497           2 :         return WERR_DS_DRA_NO_REPLICA;
     498             : }
     499             : 
     500           0 : WERROR dreplsrv_partition_source_dsa_by_dns(const struct dreplsrv_partition *p,
     501             :                                             const char *dsa_dns,
     502             :                                             struct dreplsrv_partition_source_dsa **_dsa)
     503             : {
     504             :         struct dreplsrv_partition_source_dsa *dsa;
     505             : 
     506           0 :         SMB_ASSERT(dsa_dns != NULL);
     507           0 :         SMB_ASSERT(_dsa);
     508             : 
     509           0 :         for (dsa = p->sources; dsa; dsa = dsa->next) {
     510           0 :                 if (strequal(dsa_dns, dsa->repsFrom1->other_info->dns_name)) {
     511           0 :                         *_dsa = dsa;
     512           0 :                         return WERR_OK;
     513             :                 }
     514             :         }
     515             : 
     516           0 :         return WERR_DS_DRA_NO_REPLICA;
     517             : }
     518             : 
     519             : 
     520             : /*
     521             :   create a temporary dsa structure for a replication. This is needed
     522             :   for the initial replication of a new partition, such as when a new
     523             :   domain NC is created and we are a global catalog server
     524             :  */
     525           2 : WERROR dreplsrv_partition_source_dsa_temporary(struct dreplsrv_partition *p,
     526             :                                                TALLOC_CTX *mem_ctx,
     527             :                                                const struct GUID *dsa_guid,
     528             :                                                struct dreplsrv_partition_source_dsa **_dsa)
     529             : {
     530             :         struct dreplsrv_partition_source_dsa *dsa;
     531             :         WERROR werr;
     532             : 
     533           2 :         dsa = talloc_zero(mem_ctx, struct dreplsrv_partition_source_dsa);
     534           2 :         W_ERROR_HAVE_NO_MEMORY(dsa);
     535             : 
     536           2 :         dsa->partition = p;
     537           2 :         dsa->repsFrom1 = &dsa->_repsFromBlob.ctr.ctr1;
     538           2 :         dsa->repsFrom1->replica_flags = 0;
     539           2 :         dsa->repsFrom1->source_dsa_obj_guid = *dsa_guid;
     540             : 
     541           2 :         dsa->repsFrom1->other_info = talloc_zero(dsa, struct repsFromTo1OtherInfo);
     542           2 :         W_ERROR_HAVE_NO_MEMORY(dsa->repsFrom1->other_info);
     543             : 
     544           2 :         dsa->repsFrom1->other_info->dns_name = samdb_ntds_msdcs_dns_name(p->service->samdb,
     545           2 :                                                                          dsa->repsFrom1->other_info, dsa_guid);
     546           2 :         W_ERROR_HAVE_NO_MEMORY(dsa->repsFrom1->other_info->dns_name);
     547             : 
     548           2 :         werr = dreplsrv_out_connection_attach(p->service, dsa->repsFrom1, &dsa->conn);
     549           2 :         if (!W_ERROR_IS_OK(werr)) {
     550           0 :                 DEBUG(0,(__location__ ": Failed to attach connection to %s\n",
     551             :                          ldb_dn_get_linearized(p->dn)));
     552           0 :                 talloc_free(dsa);
     553           0 :                 return werr;
     554             :         }
     555             : 
     556           2 :         *_dsa = dsa;
     557             : 
     558           2 :         return WERR_OK;
     559             : }
     560             : 
     561             : 
     562        9137 : static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
     563             :                                          struct dreplsrv_partition *p)
     564             : {
     565             :         WERROR status;
     566             :         NTSTATUS ntstatus;
     567        9137 :         struct ldb_message_element *orf_el = NULL;
     568        9137 :         struct ldb_result *r = NULL;
     569             :         unsigned int i;
     570             :         int ret;
     571        9137 :         TALLOC_CTX *mem_ctx = talloc_new(p);
     572             :         static const char *attrs[] = {
     573             :                 "repsFrom",
     574             :                 "repsTo",
     575             :                 NULL
     576             :         };
     577             :         struct ldb_dn *dn;
     578             : 
     579        9137 :         DEBUG(4, ("dreplsrv_refresh_partition(%s)\n",
     580             :                 ldb_dn_get_linearized(p->dn)));
     581             : 
     582        9137 :         ret = dsdb_search_dn(s->samdb, mem_ctx, &r, p->dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
     583        9137 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     584             :                 /* we haven't replicated the partition yet, but we
     585             :                  * can fill in the guid, sid etc from the partition DN */
     586           0 :                 dn = p->dn;
     587        9137 :         } else if (ret != LDB_SUCCESS) {
     588           0 :                 talloc_free(mem_ctx);
     589           0 :                 return WERR_FOOBAR;
     590             :         } else {
     591        9137 :                 dn = r->msgs[0]->dn;
     592             :         }
     593             :         
     594        9137 :         talloc_free(discard_const(p->nc.dn));
     595        9137 :         ZERO_STRUCT(p->nc);
     596        9137 :         p->nc.dn     = ldb_dn_alloc_linearized(p, dn);
     597        9137 :         W_ERROR_HAVE_NO_MEMORY(p->nc.dn);
     598        9137 :         ntstatus = dsdb_get_extended_dn_guid(dn, &p->nc.guid, "GUID");
     599        9137 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     600           0 :                 DEBUG(0,(__location__ ": unable to get GUID for %s: %s\n",
     601             :                          p->nc.dn, nt_errstr(ntstatus)));
     602           0 :                 talloc_free(mem_ctx);
     603           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     604             :         }
     605        9137 :         dsdb_get_extended_dn_sid(dn, &p->nc.sid, "SID");
     606             : 
     607        9137 :         talloc_free(p->uptodatevector.cursors);
     608        9137 :         talloc_free(p->uptodatevector_ex.cursors);
     609        9137 :         ZERO_STRUCT(p->uptodatevector);
     610        9137 :         ZERO_STRUCT(p->uptodatevector_ex);
     611             : 
     612        9137 :         ret = dsdb_load_udv_v2(s->samdb, p->dn, p, &p->uptodatevector.cursors, &p->uptodatevector.count);
     613        9137 :         if (ret != LDB_SUCCESS) {
     614           0 :                 DEBUG(4,(__location__ ": no UDV available for %s\n", ldb_dn_get_linearized(p->dn)));
     615             :         }
     616             : 
     617        9137 :         status = WERR_OK;
     618             : 
     619        9137 :         if (r != NULL && (orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom"))) {
     620       16424 :                 for (i=0; i < orf_el->num_values; i++) {
     621        9172 :                         status = dreplsrv_partition_add_source_dsa(s, p, &p->sources,
     622        9172 :                                                                    NULL, &orf_el->values[i]);
     623        9172 :                         W_ERROR_NOT_OK_GOTO_DONE(status);
     624             :                 }
     625             :         }
     626             : 
     627       18045 :         if (r != NULL && (orf_el = ldb_msg_find_element(r->msgs[0], "repsTo"))) {
     628       21618 :                 for (i=0; i < orf_el->num_values; i++) {
     629       13991 :                         status = dreplsrv_partition_add_source_dsa(s, p, &p->notifies,
     630       13991 :                                                                    p->sources, &orf_el->values[i]);
     631       13991 :                         W_ERROR_NOT_OK_GOTO_DONE(status);
     632             :                 }
     633             :         }
     634             : 
     635        9137 : done:
     636        9137 :         talloc_free(mem_ctx);
     637        9137 :         return status;
     638             : }
     639             : 
     640        1861 : WERROR dreplsrv_refresh_partitions(struct dreplsrv_service *s)
     641             : {
     642             :         WERROR status;
     643             :         struct dreplsrv_partition *p;
     644             : 
     645       10998 :         for (p = s->partitions; p; p = p->next) {
     646        9137 :                 status = dreplsrv_refresh_partition(s, p);
     647        9137 :                 W_ERROR_NOT_OK_RETURN(status);
     648             :         }
     649             : 
     650        1861 :         return WERR_OK;
     651             : }

Generated by: LCOV version 1.13