LCOV - code coverage report
Current view: top level - source4/dsdb/repl - drepl_service.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 147 195 75.4 %
Date: 2021-09-23 10:06:22 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS Implementation.
       3             :    DSDB replication service
       4             : 
       5             :    Copyright (C) Stefan Metzmacher 2007
       6             :    Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : 
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "dsdb/samdb/samdb.h"
      25             : #include "auth/auth.h"
      26             : #include "samba/service.h"
      27             : #include "lib/events/events.h"
      28             : #include "dsdb/repl/drepl_service.h"
      29             : #include <ldb_errors.h>
      30             : #include "../lib/util/dlinklist.h"
      31             : #include "librpc/gen_ndr/ndr_misc.h"
      32             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      33             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      34             : #include "librpc/gen_ndr/ndr_irpc.h"
      35             : #include "param/param.h"
      36             : #include "libds/common/roles.h"
      37             : 
      38             : #undef DBGC_CLASS
      39             : #define DBGC_CLASS            DBGC_DRS_REPL
      40             : 
      41             : /**
      42             :  * Call-back data for _drepl_replica_sync_done_cb()
      43             :  */
      44             : struct drepl_replica_sync_cb_data {
      45             :         struct irpc_message *msg;
      46             :         struct drsuapi_DsReplicaSync *r;
      47             : 
      48             :         /* number of ops left to be completed */
      49             :         int ops_count;
      50             : 
      51             :         /* last failure error code */
      52             :         WERROR werr_last_failure;
      53             : };
      54             : 
      55             : 
      56          55 : static WERROR dreplsrv_init_creds(struct dreplsrv_service *service)
      57             : {
      58          57 :         service->system_session_info = system_session(service->task->lp_ctx);
      59          57 :         if (service->system_session_info == NULL) {
      60           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      61             :         }
      62             : 
      63          55 :         return WERR_OK;
      64             : }
      65             : 
      66          57 : static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct loadparm_context *lp_ctx)
      67             : {
      68             :         const struct GUID *ntds_guid;
      69             :         struct drsuapi_DsBindInfo28 *bind_info28;
      70             : 
      71         114 :         service->samdb = samdb_connect(service,
      72          57 :                                        service->task->event_ctx,
      73             :                                        lp_ctx,
      74             :                                        service->system_session_info,
      75             :                                        NULL,
      76             :                                        0);
      77          57 :         if (!service->samdb) {
      78           0 :                 return WERR_DS_UNAVAILABLE;
      79             :         }
      80             : 
      81          57 :         ntds_guid = samdb_ntds_objectGUID(service->samdb);
      82          57 :         if (!ntds_guid) {
      83           0 :                 return WERR_DS_UNAVAILABLE;
      84             :         }
      85          57 :         service->ntds_guid = *ntds_guid;
      86             : 
      87          57 :         if (samdb_rodc(service->samdb, &service->am_rodc) != LDB_SUCCESS) {
      88           0 :                 DEBUG(0,(__location__ ": Failed to determine RODC status\n"));
      89           0 :                 return WERR_DS_UNAVAILABLE;
      90             :         }
      91             : 
      92          57 :         bind_info28                             = &service->bind_info28;
      93          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
      94          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
      95          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
      96          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
      97          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
      98          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
      99          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
     100          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
     101          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
     102          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
     103          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
     104          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
     105          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
     106          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
     107          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
     108          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
     109          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
     110          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
     111          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
     112          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5;
     113          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
     114          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
     115          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
     116          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
     117          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
     118          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
     119          57 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
     120          55 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
     121          55 :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
     122             : #if 0 /* we don't support XPRESS compression yet */
     123             :         bind_info28->supported_extensions    |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
     124             : #endif
     125             :         /* TODO: fill in site_guid */
     126          57 :         bind_info28->site_guid                       = GUID_zero();
     127             :         /* TODO: find out how this is really triggered! */
     128          57 :         bind_info28->pid                     = 0;
     129          57 :         bind_info28->repl_epoch                      = 0;
     130             : 
     131          57 :         return WERR_OK;
     132             : }
     133             : 
     134             : 
     135             : /**
     136             :  * Callback for dreplsrv_out_operation operation completion.
     137             :  *
     138             :  * We just need to complete a waiting IRPC message here.
     139             :  * In case pull operation has failed,
     140             :  * caller of this callback will dump
     141             :  * failure information.
     142             :  *
     143             :  * NOTE: cb_data is allocated in IRPC msg's context
     144             :  * and will be freed during irpc_send_reply() call.
     145             :  */
     146         922 : static void _drepl_replica_sync_done_cb(struct dreplsrv_service *service,
     147             :                                         WERROR werr,
     148             :                                         enum drsuapi_DsExtendedError ext_err,
     149             :                                         void *cb_data)
     150             : {
     151         922 :         struct drepl_replica_sync_cb_data *data = talloc_get_type(cb_data,
     152             :                                                                   struct drepl_replica_sync_cb_data);
     153         922 :         struct irpc_message *msg = data->msg;
     154         922 :         struct drsuapi_DsReplicaSync *r = data->r;
     155             : 
     156             :         /* store last bad result */
     157         922 :         if (!W_ERROR_IS_OK(werr)) {
     158           2 :                 data->werr_last_failure = werr;
     159             :         }
     160             : 
     161             :         /* decrement pending ops count */
     162         922 :         data->ops_count--;
     163             : 
     164         922 :         if (data->ops_count == 0) {
     165             :                 /* Return result to client */
     166         922 :                 r->out.result = data->werr_last_failure;
     167             : 
     168             :                 /* complete IRPC message */
     169         922 :                 irpc_send_reply(msg, NT_STATUS_OK);
     170             :         }
     171         922 : }
     172             : 
     173             : /**
     174             :  * Helper to schedule a replication operation with a source DSA.
     175             :  * If 'data' is valid pointer, then a callback
     176             :  * for the operation is passed and 'data->msg' is
     177             :  * marked as 'deferred' - defer_reply = true
     178             :  */
     179        2751 : static WERROR _drepl_schedule_replication(struct dreplsrv_service *service,
     180             :                                           struct dreplsrv_partition_source_dsa *dsa,
     181             :                                           struct drsuapi_DsReplicaObjectIdentifier *nc,
     182             :                                           uint32_t rep_options,
     183             :                                           struct drepl_replica_sync_cb_data *data,
     184             :                                           TALLOC_CTX *mem_ctx)
     185             : {
     186             :         WERROR werr;
     187        2751 :         dreplsrv_extended_callback_t fn_callback = NULL;
     188             : 
     189        2751 :         if (data) {
     190         922 :                 fn_callback = _drepl_replica_sync_done_cb;
     191             :         }
     192             : 
     193             :         /* schedule replication item */
     194        2751 :         werr = dreplsrv_schedule_partition_pull_source(service, dsa, rep_options,
     195             :                                                        DRSUAPI_EXOP_NONE, 0,
     196             :                                                        fn_callback, data);
     197        2751 :         if (!W_ERROR_IS_OK(werr)) {
     198           0 :                 DEBUG(0,("%s: failed setup of sync of partition (%s, %s, %s) - %s\n",
     199             :                          __FUNCTION__,
     200             :                          GUID_string(mem_ctx, &nc->guid),
     201             :                          nc->dn,
     202             :                          dsa->repsFrom1->other_info->dns_name,
     203             :                          win_errstr(werr)));
     204           0 :                 return werr;
     205             :         }
     206             :         /* log we've scheduled a replication item */
     207        2751 :         DEBUG(3,("%s: forcing sync of partition (%s, %s, %s)\n",
     208             :                  __FUNCTION__,
     209             :                  GUID_string(mem_ctx, &nc->guid),
     210             :                  nc->dn,
     211             :                  dsa->repsFrom1->other_info->dns_name));
     212             : 
     213             :         /* mark IRPC message as deferred if necessary */
     214        2751 :         if (data) {
     215         922 :                 data->ops_count++;
     216         922 :                 data->msg->defer_reply = true;
     217             :         }
     218             : 
     219        2751 :         return WERR_OK;
     220             : }
     221             : 
     222             : /*
     223             :   DsReplicaSync messages from the DRSUAPI server are forwarded here
     224             :  */
     225        2751 : static NTSTATUS drepl_replica_sync(struct irpc_message *msg,
     226             :                                    struct drsuapi_DsReplicaSync *r)
     227             : {
     228             :         WERROR werr;
     229             :         struct dreplsrv_partition *p;
     230             :         struct drepl_replica_sync_cb_data *cb_data;
     231             :         struct dreplsrv_partition_source_dsa *dsa;
     232             :         struct drsuapi_DsReplicaSyncRequest1 *req1;
     233             :         struct drsuapi_DsReplicaObjectIdentifier *nc;
     234        2751 :         struct dreplsrv_service *service = talloc_get_type(msg->private_data,
     235             :                                                            struct dreplsrv_service);
     236             : 
     237             : #define REPLICA_SYNC_FAIL(_msg, _werr) do {\
     238             :                 if (!W_ERROR_IS_OK(_werr)) { \
     239             :                         DEBUG(0,(__location__ ": Failure - %s. werr = %s\n", \
     240             :                                  _msg, win_errstr(_werr))); \
     241             :                         NDR_PRINT_IN_DEBUG(drsuapi_DsReplicaSync, r); \
     242             :                 } \
     243             :                 r->out.result = _werr; \
     244             :                 goto done;\
     245             :         } while(0)
     246             : 
     247             : 
     248        2751 :         if (r->in.level != 1) {
     249           0 :                 REPLICA_SYNC_FAIL("Unsupported level",
     250             :                                   WERR_DS_DRA_INVALID_PARAMETER);
     251             :         }
     252             : 
     253        2751 :         req1 = &r->in.req->req1;
     254        2751 :         nc   = req1->naming_context;
     255             : 
     256             :         /* Check input parameters */
     257        2751 :         if (!nc) {
     258           0 :                 REPLICA_SYNC_FAIL("Invalid Naming Context",
     259             :                                   WERR_DS_DRA_INVALID_PARAMETER);
     260             :         }
     261             : 
     262             :         /* Find Naming context to be synchronized */
     263        2751 :         werr = dreplsrv_partition_find_for_nc(service,
     264             :                                               &nc->guid, &nc->sid, nc->dn,
     265             :                                               &p);
     266        2751 :         if (!W_ERROR_IS_OK(werr)) {
     267           0 :                 REPLICA_SYNC_FAIL("Failed to find requested Naming Context",
     268             :                                   werr);
     269             :         }
     270             : 
     271             :         /* should we process it asynchronously? */
     272        2751 :         if (req1->options & DRSUAPI_DRS_ASYNC_OP) {
     273        1829 :                 cb_data = NULL;
     274             :         } else {
     275         922 :                 cb_data = talloc_zero(msg, struct drepl_replica_sync_cb_data);
     276         922 :                 if (!cb_data) {
     277           0 :                         REPLICA_SYNC_FAIL("Not enough memory",
     278             :                                           WERR_DS_DRA_INTERNAL_ERROR);
     279             :                 }
     280             : 
     281         922 :                 cb_data->msg = msg;
     282         922 :                 cb_data->r   = r;
     283         922 :                 cb_data->werr_last_failure = WERR_OK;
     284             :         }
     285             : 
     286             :         /* collect source DSAs to sync with */
     287        2751 :         if (req1->options & DRSUAPI_DRS_SYNC_ALL) {
     288           0 :                 for (dsa = p->sources; dsa; dsa = dsa->next) {
     289             :                         /* schedule replication item */
     290           0 :                         werr = _drepl_schedule_replication(service, dsa, nc,
     291             :                                                            req1->options, cb_data, msg);
     292           0 :                         if (!W_ERROR_IS_OK(werr)) {
     293           0 :                                 REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed",
     294             :                                                   werr);
     295             :                         }
     296             :                 }
     297             :         } else {
     298        2751 :                 if (req1->options & DRSUAPI_DRS_SYNC_BYNAME) {
     299             :                         /* client should pass at least valid string */
     300           0 :                         if (!req1->source_dsa_dns) {
     301           0 :                                 REPLICA_SYNC_FAIL("'source_dsa_dns' is not valid",
     302             :                                                   WERR_DS_DRA_INVALID_PARAMETER);
     303             :                         }
     304             : 
     305           0 :                         werr = dreplsrv_partition_source_dsa_by_dns(p,
     306             :                                                                     req1->source_dsa_dns,
     307             :                                                                     &dsa);
     308             :                 } else {
     309             :                         /* client should pass at least some GUID */
     310        2751 :                         if (GUID_all_zero(&req1->source_dsa_guid)) {
     311           0 :                                 REPLICA_SYNC_FAIL("'source_dsa_guid' is not valid",
     312             :                                                   WERR_DS_DRA_INVALID_PARAMETER);
     313             :                         }
     314             : 
     315        2751 :                         werr = dreplsrv_partition_source_dsa_by_guid(p,
     316        2751 :                                                                      &req1->source_dsa_guid,
     317             :                                                                      &dsa);
     318        2751 :                         if (W_ERROR_EQUAL(werr, WERR_DS_DRA_NO_REPLICA)) {
     319             :                                 /* we don't have this source setup as
     320             :                                    a replication partner. Create a
     321             :                                    temporary dsa structure for this
     322             :                                    replication */
     323           4 :                                 werr = dreplsrv_partition_source_dsa_temporary(p,
     324             :                                                                                msg,
     325           4 :                                                                                &req1->source_dsa_guid,
     326             :                                                                                &dsa);
     327             :                         }
     328             :                 }
     329        2751 :                 if (!W_ERROR_IS_OK(werr)) {
     330           0 :                         REPLICA_SYNC_FAIL("Failed to locate source DSA for given NC",
     331             :                                           werr);
     332             :                 }
     333             : 
     334             :                 /* schedule replication item */
     335        2751 :                 werr = _drepl_schedule_replication(service, dsa, nc,
     336             :                                                    req1->options, cb_data, msg);
     337        2751 :                 if (!W_ERROR_IS_OK(werr)) {
     338           0 :                         REPLICA_SYNC_FAIL("_drepl_schedule_replication() failed",
     339             :                                           werr);
     340             :                 }
     341             :         }
     342             : 
     343             :         /* if we got here, everything is OK */
     344        2751 :         r->out.result = WERR_OK;
     345             : 
     346             :         /*
     347             :          * schedule replication event to force
     348             :          * replication as soon as possible
     349             :          */
     350        2751 :         dreplsrv_pendingops_schedule_pull_now(service);
     351             : 
     352        2751 : done:
     353        2751 :         return NT_STATUS_OK;
     354             : }
     355             : 
     356             : /**
     357             :  * Called when drplsrv should refresh its state.
     358             :  * For example, when KCC change topology, dreplsrv
     359             :  * should update its cache
     360             :  *
     361             :  * @param partition_dn If not empty/NULL, partition to update
     362             :  */
     363        1957 : static NTSTATUS dreplsrv_refresh(struct irpc_message *msg,
     364             :                                  struct dreplsrv_refresh *r)
     365             : {
     366        1957 :         struct dreplsrv_service *s = talloc_get_type(msg->private_data,
     367             :                                                      struct dreplsrv_service);
     368             : 
     369        1957 :         r->out.result = dreplsrv_refresh_partitions(s);
     370             : 
     371        1957 :         return NT_STATUS_OK;
     372             : }
     373             : 
     374             : /**
     375             :  * Called when the auth code wants us to try and replicate
     376             :  * a users secrets
     377             :  */
     378        2038 : static NTSTATUS drepl_trigger_repl_secret(struct irpc_message *msg,
     379             :                                           struct drepl_trigger_repl_secret *r)
     380             : {
     381        2038 :         struct dreplsrv_service *service = talloc_get_type(msg->private_data,
     382             :                                                            struct dreplsrv_service);
     383             : 
     384             : 
     385        2038 :         drepl_repl_secret(service, r->in.user_dn);
     386             : 
     387             :         /* we are not going to be sending a reply to this request */
     388        2038 :         msg->no_reply = true;
     389             : 
     390        2038 :         return NT_STATUS_OK;
     391             : }
     392             : 
     393             : 
     394             : /*
     395             :   DsReplicaAdd messages from the DRSUAPI server are forwarded here
     396             :  */
     397           0 : static NTSTATUS dreplsrv_replica_add(struct irpc_message *msg,
     398             :                                   struct drsuapi_DsReplicaAdd *r)
     399             : {
     400           0 :         struct dreplsrv_service *service = talloc_get_type(msg->private_data,
     401             :                                                            struct dreplsrv_service);
     402           0 :         return drepl_replica_add(service, r);
     403             : }
     404             : 
     405             : /*
     406             :   DsReplicaDel messages from the DRSUAPI server are forwarded here
     407             :  */
     408           0 : static NTSTATUS dreplsrv_replica_del(struct irpc_message *msg,
     409             :                                   struct drsuapi_DsReplicaDel *r)
     410             : {
     411           0 :         struct dreplsrv_service *service = talloc_get_type(msg->private_data,
     412             :                                                            struct dreplsrv_service);
     413           0 :         return drepl_replica_del(service, r);
     414             : }
     415             : 
     416             : /*
     417             :   DsReplicaMod messages from the DRSUAPI server are forwarded here
     418             :  */
     419           0 : static NTSTATUS dreplsrv_replica_mod(struct irpc_message *msg,
     420             :                                   struct drsuapi_DsReplicaMod *r)
     421             : {
     422           0 :         struct dreplsrv_service *service = talloc_get_type(msg->private_data,
     423             :                                                            struct dreplsrv_service);
     424           0 :         return drepl_replica_mod(service, r);
     425             : }
     426             : 
     427             : 
     428             : /*
     429             :   startup the dsdb replicator service task
     430             : */
     431          63 : static NTSTATUS dreplsrv_task_init(struct task_server *task)
     432             : {
     433             :         WERROR status;
     434             :         struct dreplsrv_service *service;
     435             :         uint32_t periodic_startup_interval;
     436             : 
     437          63 :         switch (lpcfg_server_role(task->lp_ctx)) {
     438           0 :         case ROLE_STANDALONE:
     439           0 :                 task_server_terminate(task, "dreplsrv: no DSDB replication required in standalone configuration",
     440             :                                       false);
     441           0 :                 return NT_STATUS_INVALID_DOMAIN_ROLE;
     442           6 :         case ROLE_DOMAIN_MEMBER:
     443           6 :                 task_server_terminate(task, "dreplsrv: no DSDB replication required in domain member configuration",
     444             :                                       false);
     445           0 :                 return NT_STATUS_INVALID_DOMAIN_ROLE;
     446          55 :         case ROLE_ACTIVE_DIRECTORY_DC:
     447             :                 /* Yes, we want DSDB replication */
     448          55 :                 break;
     449             :         }
     450             : 
     451          57 :         task_server_set_title(task, "task[dreplsrv]");
     452             : 
     453          57 :         service = talloc_zero(task, struct dreplsrv_service);
     454          57 :         if (!service) {
     455           0 :                 task_server_terminate(task, "dreplsrv_task_init: out of memory", true);
     456           0 :                 return NT_STATUS_NO_MEMORY;
     457             :         }
     458          57 :         service->task                = task;
     459          57 :         service->startup_time        = timeval_current();
     460          57 :         task->private_data   = service;
     461             : 
     462          57 :         status = dreplsrv_init_creds(service);
     463          57 :         if (!W_ERROR_IS_OK(status)) {
     464           0 :                 task_server_terminate(task, talloc_asprintf(task,
     465             :                                       "dreplsrv: Failed to obtain server credentials: %s\n",
     466             :                                                             win_errstr(status)), true);
     467           0 :                 return werror_to_ntstatus(status);
     468             :         }
     469             : 
     470          57 :         status = dreplsrv_connect_samdb(service, task->lp_ctx);
     471          57 :         if (!W_ERROR_IS_OK(status)) {
     472           0 :                 task_server_terminate(task, talloc_asprintf(task,
     473             :                                       "dreplsrv: Failed to connect to local samdb: %s\n",
     474             :                                                             win_errstr(status)), true);
     475           0 :                 return werror_to_ntstatus(status);
     476             :         }
     477             : 
     478          57 :         status = dreplsrv_load_partitions(service);
     479          57 :         if (!W_ERROR_IS_OK(status)) {
     480           0 :                 task_server_terminate(task, talloc_asprintf(task,
     481             :                                       "dreplsrv: Failed to load partitions: %s\n",
     482             :                                                             win_errstr(status)), true);
     483           0 :                 return werror_to_ntstatus(status);
     484             :         }
     485             : 
     486          57 :         periodic_startup_interval       = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_startup_interval", 15); /* in seconds */
     487          57 :         service->periodic.interval   = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv", "periodic_interval", 300); /* in seconds */
     488             : 
     489          57 :         status = dreplsrv_periodic_schedule(service, periodic_startup_interval);
     490          57 :         if (!W_ERROR_IS_OK(status)) {
     491           0 :                 task_server_terminate(task, talloc_asprintf(task,
     492             :                                       "dreplsrv: Failed to periodic schedule: %s\n",
     493             :                                                             win_errstr(status)), true);
     494           0 :                 return werror_to_ntstatus(status);
     495             :         }
     496             : 
     497          57 :         service->pending.im = tevent_create_immediate(service);
     498          57 :         if (service->pending.im == NULL) {
     499           0 :                 task_server_terminate(task,
     500             :                                       "dreplsrv: Failed to create immediate "
     501             :                                       "task for future DsReplicaSync\n",
     502             :                                       true);
     503           0 :                 return NT_STATUS_NO_MEMORY;
     504             :         }
     505             : 
     506             :         /* if we are a RODC then we do not send DSReplicaSync*/
     507          57 :         if (!service->am_rodc) {
     508          56 :                 service->notify.interval = lpcfg_parm_int(task->lp_ctx, NULL, "dreplsrv",
     509             :                                                            "notify_interval", 5); /* in seconds */
     510          56 :                 status = dreplsrv_notify_schedule(service, service->notify.interval);
     511          56 :                 if (!W_ERROR_IS_OK(status)) {
     512           0 :                         task_server_terminate(task, talloc_asprintf(task,
     513             :                                                   "dreplsrv: Failed to setup notify schedule: %s\n",
     514             :                                                                         win_errstr(status)), true);
     515           0 :                         return werror_to_ntstatus(status);
     516             :                 }
     517             :         }
     518             : 
     519          57 :         irpc_add_name(task->msg_ctx, "dreplsrv");
     520             : 
     521          57 :         IRPC_REGISTER(task->msg_ctx, irpc, DREPLSRV_REFRESH, dreplsrv_refresh, service);
     522          57 :         IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service);
     523          57 :         IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAADD, dreplsrv_replica_add, service);
     524          57 :         IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICADEL, dreplsrv_replica_del, service);
     525          57 :         IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICAMOD, dreplsrv_replica_mod, service);
     526          57 :         IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TAKEFSMOROLE, drepl_take_FSMO_role, service);
     527          57 :         IRPC_REGISTER(task->msg_ctx, irpc, DREPL_TRIGGER_REPL_SECRET, drepl_trigger_repl_secret, service);
     528          57 :         imessaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid);
     529             : 
     530          57 :         return NT_STATUS_OK;
     531             : }
     532             : 
     533             : /*
     534             :   register ourselves as a available server
     535             : */
     536          64 : NTSTATUS server_service_drepl_init(TALLOC_CTX *ctx)
     537             : {
     538             :         static const struct service_details details = {
     539             :                 .inhibit_fork_on_accept = true,
     540             :                 .inhibit_pre_fork = true,
     541             :                 .task_init = dreplsrv_task_init,
     542             :                 .post_fork = NULL,
     543             :         };
     544          64 :         return register_server_service(ctx, "drepl", &details);
     545             : }

Generated by: LCOV version 1.13