LCOV - code coverage report
Current view: top level - source4/rpc_server/drsuapi - dcesrv_drsuapi.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 348 492 70.7 %
Date: 2024-02-28 12:06:22 Functions: 12 24 50.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    endpoint server for the drsuapi pipe
       5             : 
       6             :    Copyright (C) Stefan Metzmacher 2004
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
       8             :    
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      25             : #include "rpc_server/dcerpc_server.h"
      26             : #include "rpc_server/common/common.h"
      27             : #include "dsdb/samdb/samdb.h"
      28             : #include "dsdb/common/util.h"
      29             : #include "libcli/security/security.h"
      30             : #include "libcli/security/session.h"
      31             : #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
      32             : #include "auth/auth.h"
      33             : #include "param/param.h"
      34             : #include "lib/messaging/irpc.h"
      35             : 
      36             : #undef strcasecmp
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS            DBGC_DRS_REPL
      39             : 
      40             : #define DRSUAPI_UNSUPPORTED(fname) do { \
      41             :         DBG_WARNING(__location__ ": Unsupported DRS call %s\n", #fname); \
      42             :         if (DEBUGLVL(DBGLVL_NOTICE)) NDR_PRINT_IN_DEBUG(fname, r); \
      43             :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \
      44             : } while (0)
      45             : 
      46             : #define DCESRV_INTERFACE_DRSUAPI_BIND(context, iface) \
      47             :         dcesrv_interface_drsuapi_bind(context, iface)
      48        2232 : static NTSTATUS dcesrv_interface_drsuapi_bind(struct dcesrv_connection_context *context,
      49             :                                               const struct dcesrv_interface *iface)
      50             : {
      51        2232 :         return dcesrv_interface_bind_require_privacy(context, iface);
      52             : }
      53             : 
      54             : /* 
      55             :   drsuapi_DsBind 
      56             : */
      57        2206 : static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
      58             :                        struct drsuapi_DsBind *r)
      59             : {
      60          73 :         struct drsuapi_bind_state *b_state;
      61          73 :         struct dcesrv_handle *handle;
      62          73 :         struct drsuapi_DsBindInfoCtr *bind_info;
      63          73 :         struct drsuapi_DsBindInfoCtr *local_info;
      64          73 :         struct GUID site_guid, config_guid;
      65          73 :         struct ldb_result *site_res, *config_res;
      66          73 :         struct ldb_dn *server_site_dn, *config_dn;
      67          73 :         static const char *site_attrs[] = { "objectGUID", NULL };
      68          73 :         static const char *config_attrs[] = { "objectGUID", NULL };
      69          73 :         struct ldb_result *ntds_res;
      70          73 :         struct ldb_dn *ntds_dn;
      71          73 :         static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
      72          73 :         uint32_t pid;
      73          73 :         uint32_t repl_epoch;
      74          73 :         uint32_t supported_extensions;
      75          73 :         uint32_t req_length;
      76          73 :         int ret;
      77          73 :         WERROR werr;
      78             : 
      79        2206 :         r->out.bind_info = NULL;
      80        2206 :         ZERO_STRUCTP(r->out.bind_handle);
      81             : 
      82        2206 :         b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state);
      83        2206 :         W_ERROR_HAVE_NO_MEMORY(b_state);
      84             : 
      85             :         /* if this is a DC connecting, give them system level access */
      86        2206 :         werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL);
      87        2206 :         if (W_ERROR_IS_OK(werr)) {
      88        2142 :                 DBG_NOTICE("doing DsBind with system_session\n");
      89        2142 :                 b_state->sam_ctx_system = dcesrv_samdb_connect_as_system(b_state, dce_call);
      90        2142 :                 if (b_state->sam_ctx_system == NULL) {
      91           0 :                         return WERR_DS_UNAVAILABLE;
      92             :                 }
      93        2142 :                 b_state->sam_ctx = b_state->sam_ctx_system;
      94             :         } else {
      95          64 :                 b_state->sam_ctx = dcesrv_samdb_connect_as_user(b_state, dce_call);
      96          64 :                 if (b_state->sam_ctx == NULL) {
      97           0 :                         return WERR_DS_UNAVAILABLE;
      98             :                 }
      99             : 
     100             :                 /*
     101             :                  * an RODC also needs system samdb access for secret
     102             :                  * attribute replication
     103             :                  */
     104          64 :                 werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER,
     105             :                                                 samdb_domain_sid(b_state->sam_ctx));
     106          64 :                 if (W_ERROR_IS_OK(werr)) {
     107          51 :                         DBG_NOTICE("doing DsBind as RODC\n");
     108          51 :                         b_state->sam_ctx_system =
     109          51 :                                 dcesrv_samdb_connect_as_system(b_state, dce_call);
     110          51 :                         if (b_state->sam_ctx_system == NULL) {
     111           0 :                                 return WERR_DS_UNAVAILABLE;
     112             :                         }
     113             :                 }
     114             :         }
     115             : 
     116             :         /*
     117             :          * find out the guid of our own site
     118             :          */
     119        2206 :         server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
     120        2206 :         W_ERROR_HAVE_NO_MEMORY(server_site_dn);
     121             : 
     122        2206 :         ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
     123             :                                  server_site_dn, LDB_SCOPE_BASE, site_attrs,
     124             :                                  "(objectClass=*)");
     125        2206 :         if (ret != LDB_SUCCESS) {
     126           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     127             :         }
     128        2206 :         if (site_res->count != 1) {
     129           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     130             :         }
     131        2206 :         site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID");
     132             : 
     133             :         /*
     134             :          * lookup the local servers Replication Epoch
     135             :          */
     136        2206 :         ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx, mem_ctx);
     137        2206 :         W_ERROR_HAVE_NO_MEMORY(ntds_dn);
     138             : 
     139        2206 :         ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
     140             :                                  ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
     141             :                                  "(objectClass=*)");
     142        2206 :         if (ret != LDB_SUCCESS) {
     143           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     144             :         }
     145        2206 :         if (ntds_res->count != 1) {
     146           0 :                 return WERR_DS_DRA_INTERNAL_ERROR;
     147             :         }
     148        2206 :         repl_epoch = ldb_msg_find_attr_as_uint(ntds_res->msgs[0],
     149             :                                                "ms-DS-ReplicationEpoch", 0);
     150             : 
     151             :         /*
     152             :          * The "process identifier" of the client.
     153             :          * According to the WSPP docs, section 5.35, this is
     154             :          * for informational and debugging purposes only.
     155             :          * The assignment is implementation specific.
     156             :          */
     157        2206 :         pid = 0;
     158             : 
     159             :         /*
     160             :          * store the clients bind_guid
     161             :          */
     162        2206 :         if (r->in.bind_guid) {
     163        2206 :                 b_state->remote_bind_guid = *r->in.bind_guid;
     164             :         }
     165             : 
     166             :         /*
     167             :          * store the clients bind_info
     168             :          */
     169        2206 :         if (r->in.bind_info) {
     170        1695 :                 b_state->remote_info = r->in.bind_info;
     171             :         }
     172             : 
     173             :         /*
     174             :          * fill in our local bind info
     175             :          */
     176        2206 :         local_info = talloc_zero(mem_ctx, struct drsuapi_DsBindInfoCtr);
     177        2206 :         W_ERROR_HAVE_NO_MEMORY(local_info);
     178             : 
     179             :         /*
     180             :          * Fill in supported extensions
     181             :          */
     182        2206 :         supported_extensions = 0;
     183        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
     184        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
     185        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
     186        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
     187             : #if 0 /* we don't support MSZIP compression (only decompression) */
     188             :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
     189             : #endif
     190        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
     191        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
     192        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
     193        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
     194        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
     195        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
     196        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
     197        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
     198        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
     199        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
     200        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
     201        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
     202        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
     203        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
     204        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5;
     205        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
     206        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
     207        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
     208        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
     209        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
     210        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
     211        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
     212        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
     213        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
     214             : #if 0 /* we don't support XPRESS compression yet */
     215             :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
     216             : #endif
     217        2206 :         supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10;
     218             : 
     219             :         /*
     220             :          * There is a chance for r->in.bind_info == NULL
     221             :          * Currently we don't care, since it seems to be used nowhere else.
     222             :          * But we need a request length. So use 28 as default.
     223             :          */
     224        2206 :         req_length = 28;
     225        2206 :         if (r->in.bind_info) {
     226        1695 :                 req_length = r->in.bind_info->length;
     227             :         }
     228             : 
     229             :         /*
     230             :          * fill 28 or 48 info, depends on request
     231             :          */
     232        2133 :         if (req_length < 48) {
     233        2203 :                 local_info->length = 28;
     234        2203 :                 local_info->info.info28.supported_extensions = supported_extensions;
     235        2203 :                 local_info->info.info28.site_guid = site_guid;
     236        2203 :                 local_info->info.info28.pid = pid;
     237        2203 :                 local_info->info.info28.repl_epoch = repl_epoch;
     238             :         } else {
     239           3 :                 local_info->length = 48;
     240           3 :                 local_info->info.info48.supported_extensions = supported_extensions;
     241           3 :                 local_info->info.info48.site_guid = site_guid;
     242           3 :                 local_info->info.info48.pid = pid;
     243           3 :                 local_info->info.info48.repl_epoch = repl_epoch;
     244             : 
     245           3 :                 local_info->info.info48.supported_extensions_ext = 0;
     246           3 :                 local_info->info.info48.supported_extensions_ext |= DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2;
     247             : 
     248             :                 /*
     249             :                  * find out the guid of our own site
     250             :                  */
     251           3 :                 config_dn = ldb_get_config_basedn(b_state->sam_ctx);
     252           3 :                 W_ERROR_HAVE_NO_MEMORY(config_dn);
     253             : 
     254           3 :                 ret = ldb_search(b_state->sam_ctx, mem_ctx, &config_res,
     255             :                              config_dn, LDB_SCOPE_BASE, config_attrs,
     256             :                              "(objectClass=*)");
     257           3 :                 if (ret != LDB_SUCCESS) {
     258           0 :                         return WERR_DS_DRA_INTERNAL_ERROR;
     259             :                 }
     260           3 :                 if (config_res->count != 1) {
     261           0 :                         return WERR_DS_DRA_INTERNAL_ERROR;
     262             :                 }
     263           3 :                 config_guid = samdb_result_guid(config_res->msgs[0], "objectGUID");
     264           3 :                 local_info->info.info48.config_dn_guid = config_guid;
     265             :         }
     266             : 
     267             :         /*
     268             :          * set local_info
     269             :          */
     270        2206 :         b_state->local_info = local_info;
     271             : 
     272             :         /*
     273             :          * set bind_info
     274             :          */
     275        2206 :         bind_info = local_info;
     276             : 
     277             :         /*
     278             :          * allocate a bind handle
     279             :          */
     280        2206 :         handle = dcesrv_handle_create(dce_call, DRSUAPI_BIND_HANDLE);
     281        2206 :         W_ERROR_HAVE_NO_MEMORY(handle);
     282        2206 :         handle->data = talloc_steal(handle, b_state);
     283             : 
     284             :         /*
     285             :          * prepare reply
     286             :          */
     287        2206 :         r->out.bind_info = bind_info;
     288        2206 :         *r->out.bind_handle = handle->wire_handle;
     289             : 
     290        2206 :         return WERR_OK;
     291             : }
     292             : 
     293             : 
     294             : /* 
     295             :   drsuapi_DsUnbind 
     296             : */
     297          25 : static WERROR dcesrv_drsuapi_DsUnbind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     298             :                                struct drsuapi_DsUnbind *r)
     299             : {
     300           3 :         struct dcesrv_handle *h;
     301             : 
     302          25 :         *r->out.bind_handle = *r->in.bind_handle;
     303             : 
     304          25 :         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
     305             : 
     306          17 :         talloc_free(h);
     307             : 
     308          17 :         ZERO_STRUCTP(r->out.bind_handle);
     309             : 
     310          17 :         return WERR_OK;
     311             : }
     312             : 
     313             : 
     314             : /* 
     315             :   drsuapi_DsReplicaSync 
     316             : */
     317        2058 : static WERROR dcesrv_drsuapi_DsReplicaSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     318             :                                            struct drsuapi_DsReplicaSync *r)
     319             : {
     320           0 :         WERROR status;
     321           0 :         uint32_t timeout;
     322             : 
     323        2058 :         status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER, NULL);
     324        2058 :         if (!W_ERROR_IS_OK(status)) {
     325           0 :                 return status;
     326             :         }
     327             : 
     328        2058 :         if (r->in.level != 1) {
     329           0 :                 DBG_ERR("DsReplicaSync called with unsupported level %d\n", r->in.level);
     330           0 :                 return WERR_DS_DRA_INVALID_PARAMETER;
     331             :         }
     332             : 
     333        2058 :         if (r->in.req->req1.options & DRSUAPI_DRS_ASYNC_OP) {
     334        1094 :                 timeout = IRPC_CALL_TIMEOUT;
     335             :         } else {
     336             :                 /*
     337             :                  * use Infinite time for timeout in case
     338             :                  * the caller made a sync call
     339             :                  */
     340         964 :                 timeout = IRPC_CALL_TIMEOUT_INF;
     341             :         }
     342             : 
     343        2058 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     344             :                                      r, NDR_DRSUAPI_DSREPLICASYNC,
     345             :                                      &ndr_table_drsuapi,
     346             :                                      "dreplsrv", "DsReplicaSync",
     347             :                                      timeout);
     348             : 
     349        2058 :         return WERR_OK;
     350             : }
     351             : 
     352             : 
     353             : /* 
     354             :   drsuapi_DsReplicaAdd 
     355             : */
     356           0 : static WERROR dcesrv_drsuapi_DsReplicaAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     357             :                                           struct drsuapi_DsReplicaAdd *r)
     358             : {
     359           0 :         WERROR status;
     360             : 
     361           0 :         status = drs_security_level_check(dce_call, "DsReplicaAdd", SECURITY_DOMAIN_CONTROLLER, NULL);
     362           0 :         if (!W_ERROR_IS_OK(status)) {
     363           0 :                 return status;
     364             :         }
     365             : 
     366           0 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     367             :                                      r, NDR_DRSUAPI_DSREPLICAADD,
     368             :                                      &ndr_table_drsuapi,
     369             :                                      "dreplsrv", "DsReplicaAdd",
     370             :                                      IRPC_CALL_TIMEOUT);
     371             : 
     372           0 :         return WERR_OK;
     373             : }
     374             : 
     375             : 
     376             : /* 
     377             :   drsuapi_DsReplicaDel 
     378             : */
     379           0 : static WERROR dcesrv_drsuapi_DsReplicaDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     380             :                                           struct drsuapi_DsReplicaDel *r)
     381             : {
     382           0 :         WERROR status;
     383             : 
     384           0 :         status = drs_security_level_check(dce_call, "DsReplicaDel", SECURITY_DOMAIN_CONTROLLER, NULL);
     385           0 :         if (!W_ERROR_IS_OK(status)) {
     386           0 :                 return status;
     387             :         }
     388             : 
     389           0 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     390             :                                      r, NDR_DRSUAPI_DSREPLICADEL,
     391             :                                      &ndr_table_drsuapi,
     392             :                                      "dreplsrv", "DsReplicaDel",
     393             :                                      IRPC_CALL_TIMEOUT);
     394             : 
     395           0 :         return WERR_OK;
     396             : }
     397             : 
     398             : 
     399             : /* 
     400             :   drsuapi_DsReplicaModify 
     401             : */
     402           0 : static WERROR dcesrv_drsuapi_DsReplicaMod(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     403             :                                           struct drsuapi_DsReplicaMod *r)
     404             : {
     405           0 :         WERROR status;
     406             : 
     407           0 :         status = drs_security_level_check(dce_call, "DsReplicaMod", SECURITY_DOMAIN_CONTROLLER, NULL);
     408           0 :         if (!W_ERROR_IS_OK(status)) {
     409           0 :                 return status;
     410             :         }
     411             : 
     412           0 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     413             :                                      r, NDR_DRSUAPI_DSREPLICAMOD,
     414             :                                      &ndr_table_drsuapi,
     415             :                                      "dreplsrv", "DsReplicaMod",
     416             :                                      IRPC_CALL_TIMEOUT);
     417             : 
     418           0 :         return WERR_OK;
     419             : }
     420             : 
     421             : 
     422             : /* 
     423             :   DRSUAPI_VERIFY_NAMES 
     424             : */
     425           0 : static WERROR dcesrv_DRSUAPI_VERIFY_NAMES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     426             :                        struct DRSUAPI_VERIFY_NAMES *r)
     427             : {
     428           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_VERIFY_NAMES);
     429             : }
     430             : 
     431             : 
     432             : /* 
     433             :   drsuapi_DsGetMemberships 
     434             : */
     435           0 : static WERROR dcesrv_drsuapi_DsGetMemberships(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     436             :                        struct drsuapi_DsGetMemberships *r)
     437             : {
     438           0 :         DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships);
     439             : }
     440             : 
     441             : 
     442             : /* 
     443             :   DRSUAPI_INTER_DOMAIN_MOVE 
     444             : */
     445           0 : static WERROR dcesrv_DRSUAPI_INTER_DOMAIN_MOVE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     446             :                        struct DRSUAPI_INTER_DOMAIN_MOVE *r)
     447             : {
     448           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_INTER_DOMAIN_MOVE);
     449             : }
     450             : 
     451             : 
     452             : /* 
     453             :   drsuapi_DsGetNT4ChangeLog 
     454             : */
     455           3 : static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     456             :                        struct drsuapi_DsGetNT4ChangeLog *r)
     457             : {
     458           3 :         DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog);
     459             : }
     460             : 
     461             : /* 
     462             :   drsuapi_DsCrackNames 
     463             : */
     464        1395 : static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     465             :                             struct drsuapi_DsCrackNames *r)
     466             : {
     467         144 :         struct drsuapi_bind_state *b_state;
     468         144 :         struct dcesrv_handle *h;
     469             : 
     470        1395 :         *r->out.level_out = r->in.level;
     471             : 
     472        1395 :         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
     473        1395 :         b_state = h->data;
     474             : 
     475        1395 :         r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsNameCtr);
     476        1395 :         W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
     477             : 
     478        1395 :         switch (r->in.level) {
     479        1395 :                 case 1: {
     480        1395 :                         switch(r->in.req->req1.format_offered){
     481           0 :                         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX:
     482             :                         case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN:
     483             :                         case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME:
     484             :                         case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME:
     485             :                         case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID:
     486             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_NCS:
     487             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS:
     488             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS:
     489             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE:
     490             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE:
     491             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE:
     492             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE:
     493             :                         case DRSUAPI_DS_NAME_FORMAT_LIST_SITES:
     494             :                         case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID:
     495             :                         case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON:
     496           0 :                                 DBG_ERR("DsCrackNames: Unsupported operation requested: %X\n",
     497             :                                           r->in.req->req1.format_offered);
     498           0 :                                 return WERR_OK;
     499           0 :                         case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER:
     500           0 :                                 return dcesrv_drsuapi_ListInfoServer(b_state->sam_ctx, mem_ctx, &r->in.req->req1, &r->out.ctr->ctr1);
     501           0 :                         case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES:
     502           0 :                                 return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx,
     503           0 :                                                                 &r->in.req->req1, &r->out.ctr->ctr1);
     504        1395 :                         default:/* format_offered is in the enum drsuapi_DsNameFormat*/
     505        1395 :                                 return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx,
     506        1395 :                                                                              &r->in.req->req1, &r->out.ctr->ctr1);
     507             :                         }
     508             :                 }
     509             :         }
     510           0 :         return WERR_INVALID_LEVEL;
     511             : }
     512             : 
     513             : 
     514             : /* 
     515             :   drsuapi_DsRemoveDSServer
     516             : */
     517           7 : static WERROR dcesrv_drsuapi_DsRemoveDSServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     518             :                                        struct drsuapi_DsRemoveDSServer *r)
     519             : {
     520           0 :         struct drsuapi_bind_state *b_state;
     521           0 :         struct dcesrv_handle *h;
     522           0 :         struct ldb_dn *ntds_dn;
     523           0 :         int ret;
     524           0 :         bool ok;
     525           0 :         WERROR status;
     526             : 
     527           7 :         *r->out.level_out = 1;
     528             : 
     529           7 :         status = drs_security_level_check(dce_call, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER, NULL);
     530           7 :         if (!W_ERROR_IS_OK(status)) {
     531           0 :                 return status;
     532             :         }
     533             : 
     534           7 :         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
     535           7 :         b_state = h->data;
     536             : 
     537           7 :         switch (r->in.level) {
     538           7 :         case 1:
     539           7 :                 ntds_dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, r->in.req->req1.server_dn);
     540           7 :                 W_ERROR_HAVE_NO_MEMORY(ntds_dn);
     541             : 
     542           7 :                 ok = ldb_dn_validate(ntds_dn);
     543           7 :                 if (!ok) {
     544           0 :                         return WERR_FOOBAR;
     545             :                 }
     546             : 
     547             :                 /* TODO: it's likely that we need more checks here */
     548             : 
     549           7 :                 ok = ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings");
     550           7 :                 if (!ok) {
     551           0 :                         return WERR_FOOBAR;
     552             :                 }
     553             : 
     554           7 :                 if (r->in.req->req1.commit) {
     555           7 :                         ret = dsdb_delete(b_state->sam_ctx, ntds_dn, DSDB_TREE_DELETE);
     556           7 :                         if (ret != LDB_SUCCESS) {
     557           0 :                                 return WERR_FOOBAR;
     558             :                         }
     559             :                 }
     560             : 
     561           7 :                 return WERR_OK;
     562           0 :         default:
     563           0 :                 break;
     564             :         }
     565             : 
     566           0 :         return WERR_FOOBAR;
     567             : }
     568             : 
     569             : 
     570             : /* 
     571             :   DRSUAPI_REMOVE_DS_DOMAIN 
     572             : */
     573           0 : static WERROR dcesrv_DRSUAPI_REMOVE_DS_DOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     574             :                        struct DRSUAPI_REMOVE_DS_DOMAIN *r)
     575             : {
     576           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_REMOVE_DS_DOMAIN);
     577             : }
     578             : 
     579             : /* Obtain the site name from a server DN */
     580          12 : static const char *result_site_name(struct ldb_dn *server_dn)
     581             : {
     582             :         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
     583          12 :         const struct ldb_val *val = ldb_dn_get_component_val(server_dn, 2);
     584          12 :         const char *name = ldb_dn_get_component_name(server_dn, 2);
     585             : 
     586          12 :         if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
     587             :                 /* Ensure this matches the format.  This gives us a
     588             :                  * bit more confidence that a 'cn' value will be a
     589             :                  * ascii string */
     590           0 :                 return NULL;
     591             :         }
     592          12 :         if (val) {
     593          12 :                 return (char *)val->data;
     594             :         }
     595           0 :         return NULL;
     596             : }
     597             : 
     598             : /* 
     599             :   drsuapi_DsGetDomainControllerInfo 
     600             : */
     601           6 : static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_state, 
     602             :                                                 TALLOC_CTX *mem_ctx,
     603             :                                                 struct drsuapi_DsGetDomainControllerInfo *r)
     604             : {
     605           0 :         struct ldb_dn *sites_dn;
     606           0 :         struct ldb_result *res;
     607             : 
     608           6 :         const char *attrs_account_1[] = { "cn", "dnsHostName", NULL };
     609           6 :         const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL };
     610             : 
     611           6 :         const char *attrs_none[] = { NULL };
     612             : 
     613           6 :         const char *attrs_site[] = { "objectGUID", NULL };
     614             : 
     615           6 :         const char *attrs_ntds[] = { "options", "objectGUID", NULL };
     616             : 
     617           6 :         const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL };
     618           6 :         const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL };
     619           0 :         const char **attrs;
     620             : 
     621           0 :         struct drsuapi_DsGetDCInfoCtr1 *ctr1;
     622           0 :         struct drsuapi_DsGetDCInfoCtr2 *ctr2;
     623           0 :         struct drsuapi_DsGetDCInfoCtr3 *ctr3;
     624             : 
     625           0 :         int ret;
     626           0 :         unsigned int i;
     627             : 
     628           6 :         *r->out.level_out = r->in.req->req1.level;
     629           6 :         r->out.ctr = talloc_zero(mem_ctx, union drsuapi_DsGetDCInfoCtr);
     630           6 :         W_ERROR_HAVE_NO_MEMORY(r->out.ctr);
     631             : 
     632           6 :         switch (*r->out.level_out) {
     633           0 :         case -1:
     634             :                 /* this level is not like the others */
     635           0 :                 return WERR_INVALID_LEVEL;
     636           3 :         case 1:
     637           3 :                 attrs = attrs_1;
     638           3 :                 break;
     639           3 :         case 2:
     640             :         case 3:
     641           3 :                 attrs = attrs_2;
     642           3 :                 break;
     643           0 :         default:
     644           0 :                 return WERR_INVALID_LEVEL;
     645             :         }
     646             : 
     647           6 :         sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx);
     648           6 :         if (!sites_dn) {
     649           0 :                 return WERR_DS_OBJ_NOT_FOUND;
     650             :         }
     651             : 
     652           6 :         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
     653             :                                  "(&(objectClass=server)(serverReference=*))");
     654             :         
     655           6 :         if (ret) {
     656           0 :                 DBG_WARNING("searching for servers in sites DN %s failed: %s\n", 
     657             :                           ldb_dn_get_linearized(sites_dn), ldb_errstring(b_state->sam_ctx));
     658           0 :                 return WERR_GEN_FAILURE;
     659             :         }
     660             : 
     661           6 :         switch (*r->out.level_out) {
     662           3 :         case 1:
     663           3 :                 ctr1 = &r->out.ctr->ctr1;
     664           3 :                 ctr1->count = res->count;
     665           3 :                 ctr1->array = talloc_zero_array(mem_ctx, 
     666             :                                                 struct drsuapi_DsGetDCInfo1, 
     667             :                                                 res->count);
     668           9 :                 for (i=0; i < res->count; i++) {
     669           0 :                         struct ldb_dn *domain_dn;
     670           0 :                         struct ldb_result *res_domain;
     671           0 :                         struct ldb_result *res_account;
     672           6 :                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
     673             :                         
     674           0 :                         struct ldb_dn *ref_dn
     675           6 :                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
     676           6 :                                                           mem_ctx, res->msgs[i], 
     677             :                                                           "serverReference");
     678             : 
     679           6 :                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
     680           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     681             :                         }
     682             : 
     683           6 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
     684             :                                                  LDB_SCOPE_BASE, attrs_account_1,
     685             :                                                 "(&(objectClass=computer)(userAccountControl:"LDB_OID_COMPARATOR_AND":=%u))",
     686             :                                                 UF_SERVER_TRUST_ACCOUNT);
     687           6 :                         if (ret == LDB_SUCCESS && res_account->count == 1) {
     688           0 :                                 const char *errstr;
     689           6 :                                 ctr1->array[i].dns_name
     690           6 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
     691           6 :                                 ctr1->array[i].netbios_name
     692           6 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
     693           6 :                                 ctr1->array[i].computer_dn
     694           6 :                                         = ldb_dn_get_linearized(res_account->msgs[0]->dn);
     695             : 
     696             :                                 /* Determine if this is the PDC */
     697           6 :                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
     698           6 :                                                                      mem_ctx, res_account->msgs[0]->dn,
     699             :                                                                      &domain_dn, &errstr);
     700             :                                 
     701           6 :                                 if (ret == LDB_SUCCESS) {
     702           6 :                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
     703             :                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
     704             :                                                                  ldb_dn_get_linearized(ntds_dn));
     705           6 :                                         if (ret) {
     706           0 :                                                 return WERR_GEN_FAILURE;
     707             :                                         }
     708           6 :                                         if (res_domain->count == 1) {
     709           3 :                                                 ctr1->array[i].is_pdc = true;
     710             :                                         }
     711             :                                 }
     712             :                         }
     713           6 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     714           0 :                                 DBG_INFO("warning: searching for computer DN %s failed: %s\n", 
     715             :                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx));
     716             :                         }
     717             : 
     718             :                         /* Look at server DN and extract site component */
     719           6 :                         ctr1->array[i].site_name = result_site_name(res->msgs[i]->dn);
     720           6 :                         ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
     721             : 
     722             : 
     723           6 :                         ctr1->array[i].is_enabled = true;
     724             : 
     725             :                 }
     726           3 :                 break;
     727           2 :         case 2:
     728           2 :                 ctr2 = &r->out.ctr->ctr2;
     729           2 :                 ctr2->count = res->count;
     730           2 :                 ctr2->array = talloc_zero_array(mem_ctx, 
     731             :                                                  struct drsuapi_DsGetDCInfo2, 
     732             :                                                  res->count);
     733           6 :                 for (i=0; i < res->count; i++) {
     734           0 :                         struct ldb_dn *domain_dn;
     735           0 :                         struct ldb_result *res_domain;
     736           0 :                         struct ldb_result *res_account;
     737           4 :                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
     738           0 :                         struct ldb_result *res_ntds;
     739           4 :                         struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
     740           0 :                         struct ldb_result *res_site;
     741           0 :                         struct ldb_dn *ref_dn
     742           4 :                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
     743           4 :                                                           mem_ctx, res->msgs[i], 
     744             :                                                           "serverReference");
     745             : 
     746           4 :                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
     747           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     748             :                         }
     749             : 
     750             :                         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
     751           4 :                         if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
     752           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     753             :                         }
     754             : 
     755           4 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
     756             :                                                  LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
     757           4 :                         if (ret == LDB_SUCCESS && res_ntds->count == 1) {
     758           2 :                                 ctr2->array[i].is_gc
     759           2 :                                         = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC);
     760           2 :                                 ctr2->array[i].ntds_guid 
     761           2 :                                         = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
     762           2 :                                 ctr2->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
     763             :                         }
     764           4 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     765           0 :                                 DBG_INFO("warning: searching for NTDS DN %s failed: %s\n", 
     766             :                                           ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx));
     767             :                         }
     768             : 
     769           4 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
     770             :                                                  LDB_SCOPE_BASE, attrs_site, "objectClass=site");
     771           4 :                         if (ret == LDB_SUCCESS && res_site->count == 1) {
     772           4 :                                 ctr2->array[i].site_guid 
     773           4 :                                         = samdb_result_guid(res_site->msgs[0], "objectGUID");
     774           4 :                                 ctr2->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
     775             :                         }
     776           4 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     777           0 :                                 DBG_INFO("warning: searching for site DN %s failed: %s\n", 
     778             :                                           ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx));
     779             :                         }
     780             : 
     781           4 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
     782             :                                                  LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
     783           4 :                         if (ret == LDB_SUCCESS && res_account->count == 1) {
     784           0 :                                 const char *errstr;
     785           4 :                                 ctr2->array[i].dns_name
     786           4 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
     787           4 :                                 ctr2->array[i].netbios_name
     788           4 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
     789           4 :                                 ctr2->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
     790           4 :                                 ctr2->array[i].computer_guid 
     791           4 :                                         = samdb_result_guid(res_account->msgs[0], "objectGUID");
     792             : 
     793             :                                 /* Determine if this is the PDC */
     794           4 :                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
     795           4 :                                                                      mem_ctx, res_account->msgs[0]->dn,
     796             :                                                                      &domain_dn, &errstr);
     797             :                                 
     798           4 :                                 if (ret == LDB_SUCCESS) {
     799           4 :                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
     800             :                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
     801             :                                                                  ldb_dn_get_linearized(ntds_dn));
     802           4 :                                         if (ret == LDB_SUCCESS && res_domain->count == 1) {
     803           2 :                                                 ctr2->array[i].is_pdc = true;
     804             :                                         }
     805           4 :                                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     806           0 :                                                 DBG_INFO("warning: searching for domain DN %s failed: %s\n", 
     807             :                                                           ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx));
     808             :                                         }
     809             :                                 }
     810             :                         }
     811           4 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     812           0 :                                 DBG_INFO("warning: searching for computer account DN %s failed: %s\n", 
     813             :                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx));
     814             :                         }
     815             : 
     816             :                         /* Look at server DN and extract site component */
     817           4 :                         ctr2->array[i].site_name = result_site_name(res->msgs[i]->dn);
     818           4 :                         ctr2->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
     819           4 :                         ctr2->array[i].server_guid 
     820           4 :                                 = samdb_result_guid(res->msgs[i], "objectGUID");
     821             : 
     822           4 :                         ctr2->array[i].is_enabled = true;
     823             : 
     824             :                 }
     825           2 :                 break;
     826           1 :         case 3:
     827           1 :                 ctr3 = &r->out.ctr->ctr3;
     828           1 :                 ctr3->count = res->count;
     829           1 :                 ctr3->array = talloc_zero_array(mem_ctx,
     830             :                                                  struct drsuapi_DsGetDCInfo3,
     831             :                                                  res->count);
     832           3 :                 for (i=0; i<res->count; i++) {
     833           0 :                         struct ldb_dn *domain_dn;
     834           0 :                         struct ldb_result *res_domain;
     835           0 :                         struct ldb_result *res_account;
     836           2 :                         struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
     837           0 :                         struct ldb_result *res_ntds;
     838           2 :                         struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
     839           0 :                         struct ldb_result *res_site;
     840           0 :                         bool is_rodc;
     841           0 :                         struct ldb_dn *ref_dn
     842           2 :                                 = ldb_msg_find_attr_as_dn(b_state->sam_ctx,
     843           2 :                                                           mem_ctx, res->msgs[i],
     844             :                                                           "serverReference");
     845             : 
     846           2 :                         if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
     847           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     848             :                         }
     849             : 
     850             :                         /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
     851           2 :                         if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
     852           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     853             :                         }
     854             : 
     855           2 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
     856             :                                                  LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
     857           2 :                         if (ret == LDB_SUCCESS && res_ntds->count == 1) {
     858           1 :                                 ctr3->array[i].is_gc
     859           1 :                                         = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC);
     860           1 :                                 ctr3->array[i].ntds_guid
     861           1 :                                         = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
     862           1 :                                 ctr3->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
     863             :                         }
     864           2 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     865           0 :                                 DBG_INFO("warning: searching for NTDS DN %s failed: %s\n",
     866             :                                           ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx));
     867             :                         }
     868             : 
     869           2 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
     870             :                                                  LDB_SCOPE_BASE, attrs_site, "objectClass=site");
     871           2 :                         if (ret == LDB_SUCCESS && res_site->count == 1) {
     872           2 :                                 ctr3->array[i].site_guid
     873           2 :                                         = samdb_result_guid(res_site->msgs[0], "objectGUID");
     874           2 :                                 ctr3->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
     875             :                         }
     876           2 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     877           0 :                                 DBG_INFO("warning: searching for site DN %s failed: %s\n",
     878             :                                           ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx));
     879             :                         }
     880             : 
     881           2 :                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
     882             :                                                  LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
     883           2 :                         if (ret == LDB_SUCCESS && res_account->count == 1) {
     884           0 :                                 const char *errstr;
     885           2 :                                 ctr3->array[i].dns_name
     886           2 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
     887           2 :                                 ctr3->array[i].netbios_name
     888           2 :                                         = ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
     889           2 :                                 ctr3->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
     890           2 :                                 ctr3->array[i].computer_guid
     891           2 :                                         = samdb_result_guid(res_account->msgs[0], "objectGUID");
     892             : 
     893             :                                 /* Determine if this is the PDC */
     894           2 :                                 ret = samdb_search_for_parent_domain(b_state->sam_ctx,
     895           2 :                                                                      mem_ctx, res_account->msgs[0]->dn,
     896             :                                                                      &domain_dn, &errstr);
     897             : 
     898           2 :                                 if (ret == LDB_SUCCESS) {
     899           2 :                                         ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
     900             :                                                                  LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
     901             :                                                                  ldb_dn_get_linearized(ntds_dn));
     902           2 :                                         if (ret == LDB_SUCCESS && res_domain->count == 1) {
     903           1 :                                                 ctr3->array[i].is_pdc = true;
     904             :                                         }
     905           2 :                                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     906           0 :                                                 DBG_INFO("warning: searching for domain DN %s failed: %s\n",
     907             :                                                           ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx));
     908             :                                         }
     909             :                                 }
     910             :                         }
     911           2 :                         if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
     912           0 :                                 DBG_INFO("warning: searching for computer account DN %s failed: %s\n",
     913             :                                           ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx));
     914             :                         }
     915             : 
     916             :                         /* Look at server DN and extract site component */
     917           2 :                         ctr3->array[i].site_name = result_site_name(res->msgs[i]->dn);
     918           2 :                         ctr3->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
     919           2 :                         ctr3->array[i].server_guid
     920           2 :                                 = samdb_result_guid(res->msgs[i], "objectGUID");
     921             : 
     922           2 :                         ctr3->array[i].is_enabled = true;
     923             : 
     924             :                         /* rodc? */
     925           2 :                         ret = samdb_is_rodc(b_state->sam_ctx, &ctr3->array[i].server_guid, &is_rodc);
     926           2 :                         if (ret == LDB_SUCCESS && is_rodc) {
     927           0 :                                 ctr3->array[i].is_rodc = true;
     928             :                         }
     929             :                 }
     930           1 :                 break;
     931           0 :         default:
     932           0 :                 return WERR_INVALID_LEVEL;
     933             :         }
     934           6 :         return WERR_OK;
     935             : }
     936             : 
     937             : /* 
     938             :   drsuapi_DsGetDomainControllerInfo 
     939             : */
     940           6 : static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     941             :                                                 struct drsuapi_DsGetDomainControllerInfo *r)
     942             : {
     943           0 :         struct dcesrv_handle *h;
     944           0 :         struct drsuapi_bind_state *b_state;     
     945           6 :         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
     946           6 :         b_state = h->data;
     947             : 
     948           6 :         switch (r->in.level) {
     949           6 :         case 1:
     950           6 :                 return dcesrv_drsuapi_DsGetDomainControllerInfo_1(b_state, mem_ctx, r);
     951             :         }
     952             : 
     953           0 :         return WERR_INVALID_LEVEL;
     954             : }
     955             : 
     956             : 
     957             : 
     958             : /* 
     959             :   drsuapi_DsExecuteKCC 
     960             : */
     961           2 : static WERROR dcesrv_drsuapi_DsExecuteKCC(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     962             :                                   struct drsuapi_DsExecuteKCC *r)
     963             : {
     964           0 :         WERROR status;
     965           0 :         uint32_t timeout;
     966           2 :         status = drs_security_level_check(dce_call, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER, NULL);
     967             : 
     968           2 :         if (!W_ERROR_IS_OK(status)) {
     969           0 :                 return status;
     970             :         }
     971           2 :         if (r->in.req->ctr1.taskID != 0) {
     972           0 :                 return WERR_INVALID_PARAMETER;
     973             :         }
     974           2 :         if (r->in.req->ctr1.flags & DRSUAPI_DS_EXECUTE_KCC_ASYNCHRONOUS_OPERATION) {
     975           0 :                 timeout = IRPC_CALL_TIMEOUT;
     976             :         } else {
     977             :                 /*
     978             :                  * use Infinite time for timeout in case
     979             :                  * the caller made a sync call
     980             :                  */
     981           2 :                 timeout = IRPC_CALL_TIMEOUT_INF;
     982             :         }
     983             : 
     984           2 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSEXECUTEKCC,
     985             :                                      &ndr_table_drsuapi, "kccsrv", "DsExecuteKCC",
     986             :                                      timeout);
     987           2 :         DBG_DEBUG("Forwarded the call to execute the KCC\n");
     988           2 :         return WERR_OK;
     989             : }
     990             : 
     991             : 
     992             : /* 
     993             :   drsuapi_DsReplicaGetInfo 
     994             : */
     995          10 : static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     996             :                        struct drsuapi_DsReplicaGetInfo *r)
     997             : {
     998           0 :         struct auth_session_info *session_info =
     999          10 :                 dcesrv_call_session_info(dce_call);
    1000           0 :         enum security_user_level level;
    1001             : 
    1002          10 :         if (!lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
    1003             :                          "drs", "disable_sec_check", false)) {
    1004          10 :                 level = security_session_user_level(session_info, NULL);
    1005          10 :                 if (level < SECURITY_DOMAIN_CONTROLLER) {
    1006           0 :                         DBG_WARNING(__location__ ": Administrator access required for DsReplicaGetInfo\n");
    1007           0 :                         security_token_debug(DBGC_DRS_REPL, 2,
    1008           0 :                                              session_info->security_token);
    1009           0 :                         return WERR_DS_DRA_ACCESS_DENIED;
    1010             :                 }
    1011             :         }
    1012             : 
    1013          10 :         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO,
    1014             :                                      &ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo",
    1015             :                                      IRPC_CALL_TIMEOUT);
    1016             : 
    1017          10 :         return WERR_OK;
    1018             : }
    1019             : 
    1020             : 
    1021             : /* 
    1022             :   DRSUAPI_ADD_SID_HISTORY 
    1023             : */
    1024           0 : static WERROR dcesrv_DRSUAPI_ADD_SID_HISTORY(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1025             :                        struct DRSUAPI_ADD_SID_HISTORY *r)
    1026             : {
    1027           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_ADD_SID_HISTORY);
    1028             : }
    1029             : 
    1030             : /* 
    1031             :   drsuapi_DsGetMemberships2 
    1032             : */
    1033           0 : static WERROR dcesrv_drsuapi_DsGetMemberships2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1034             :                        struct drsuapi_DsGetMemberships2 *r)
    1035             : {
    1036           0 :         DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships2);
    1037             : }
    1038             : 
    1039             : /* 
    1040             :   DRSUAPI_REPLICA_VERIFY_OBJECTS 
    1041             : */
    1042           0 : static WERROR dcesrv_DRSUAPI_REPLICA_VERIFY_OBJECTS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1043             :                        struct DRSUAPI_REPLICA_VERIFY_OBJECTS *r)
    1044             : {
    1045           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_REPLICA_VERIFY_OBJECTS);
    1046             : }
    1047             : 
    1048             : 
    1049             : /* 
    1050             :   DRSUAPI_GET_OBJECT_EXISTENCE 
    1051             : */
    1052           0 : static WERROR dcesrv_DRSUAPI_GET_OBJECT_EXISTENCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1053             :                        struct DRSUAPI_GET_OBJECT_EXISTENCE *r)
    1054             : {
    1055           0 :         DRSUAPI_UNSUPPORTED(DRSUAPI_GET_OBJECT_EXISTENCE);
    1056             : }
    1057             : 
    1058             : 
    1059             : /* 
    1060             :   drsuapi_QuerySitesByCost 
    1061             : */
    1062           0 : static WERROR dcesrv_drsuapi_QuerySitesByCost(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1063             :                        struct drsuapi_QuerySitesByCost *r)
    1064             : {
    1065           0 :         DRSUAPI_UNSUPPORTED(drsuapi_QuerySitesByCost);
    1066             : }
    1067             : 
    1068             : 
    1069             : /* include the generated boilerplate */
    1070             : #include "librpc/gen_ndr/ndr_drsuapi_s.c"

Generated by: LCOV version 1.14