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 2234 : static NTSTATUS dcesrv_interface_drsuapi_bind(struct dcesrv_connection_context *context,
49 : const struct dcesrv_interface *iface)
50 : {
51 2234 : return dcesrv_interface_bind_require_privacy(context, iface);
52 : }
53 :
54 : /*
55 : drsuapi_DsBind
56 : */
57 2208 : 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 2208 : r->out.bind_info = NULL;
80 2208 : ZERO_STRUCTP(r->out.bind_handle);
81 :
82 2208 : b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state);
83 2208 : W_ERROR_HAVE_NO_MEMORY(b_state);
84 :
85 : /* if this is a DC connecting, give them system level access */
86 2208 : werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL);
87 2208 : if (W_ERROR_IS_OK(werr)) {
88 2144 : DBG_NOTICE("doing DsBind with system_session\n");
89 2144 : b_state->sam_ctx_system = dcesrv_samdb_connect_as_system(b_state, dce_call);
90 2144 : if (b_state->sam_ctx_system == NULL) {
91 0 : return WERR_DS_UNAVAILABLE;
92 : }
93 2144 : 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 2208 : server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
120 2208 : W_ERROR_HAVE_NO_MEMORY(server_site_dn);
121 :
122 2208 : ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
123 : server_site_dn, LDB_SCOPE_BASE, site_attrs,
124 : "(objectClass=*)");
125 2208 : if (ret != LDB_SUCCESS) {
126 0 : return WERR_DS_DRA_INTERNAL_ERROR;
127 : }
128 2208 : if (site_res->count != 1) {
129 0 : return WERR_DS_DRA_INTERNAL_ERROR;
130 : }
131 2208 : site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID");
132 :
133 : /*
134 : * lookup the local servers Replication Epoch
135 : */
136 2208 : ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx, mem_ctx);
137 2208 : W_ERROR_HAVE_NO_MEMORY(ntds_dn);
138 :
139 2208 : ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
140 : ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
141 : "(objectClass=*)");
142 2208 : if (ret != LDB_SUCCESS) {
143 0 : return WERR_DS_DRA_INTERNAL_ERROR;
144 : }
145 2208 : if (ntds_res->count != 1) {
146 0 : return WERR_DS_DRA_INTERNAL_ERROR;
147 : }
148 2208 : 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 2208 : pid = 0;
158 :
159 : /*
160 : * store the clients bind_guid
161 : */
162 2208 : if (r->in.bind_guid) {
163 2208 : b_state->remote_bind_guid = *r->in.bind_guid;
164 : }
165 :
166 : /*
167 : * store the clients bind_info
168 : */
169 2208 : if (r->in.bind_info) {
170 1697 : b_state->remote_info = r->in.bind_info;
171 : }
172 :
173 : /*
174 : * fill in our local bind info
175 : */
176 2208 : local_info = talloc_zero(mem_ctx, struct drsuapi_DsBindInfoCtr);
177 2208 : W_ERROR_HAVE_NO_MEMORY(local_info);
178 :
179 : /*
180 : * Fill in supported extensions
181 : */
182 2208 : supported_extensions = 0;
183 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_BASE;
184 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
185 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
186 2208 : 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 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
191 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
192 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
193 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
194 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
195 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
196 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
197 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
198 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
199 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
200 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
201 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
202 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
203 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
204 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5;
205 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
206 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
207 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
208 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
209 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
210 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
211 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
212 2208 : supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
213 2208 : 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 2208 : 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 2208 : req_length = 28;
225 2208 : if (r->in.bind_info) {
226 1697 : req_length = r->in.bind_info->length;
227 : }
228 :
229 : /*
230 : * fill 28 or 48 info, depends on request
231 : */
232 2135 : if (req_length < 48) {
233 2205 : local_info->length = 28;
234 2205 : local_info->info.info28.supported_extensions = supported_extensions;
235 2205 : local_info->info.info28.site_guid = site_guid;
236 2205 : local_info->info.info28.pid = pid;
237 2205 : 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 2208 : b_state->local_info = local_info;
271 :
272 : /*
273 : * set bind_info
274 : */
275 2208 : bind_info = local_info;
276 :
277 : /*
278 : * allocate a bind handle
279 : */
280 2208 : handle = dcesrv_handle_create(dce_call, DRSUAPI_BIND_HANDLE);
281 2208 : W_ERROR_HAVE_NO_MEMORY(handle);
282 2208 : handle->data = talloc_steal(handle, b_state);
283 :
284 : /*
285 : * prepare reply
286 : */
287 2208 : r->out.bind_info = bind_info;
288 2208 : *r->out.bind_handle = handle->wire_handle;
289 :
290 2208 : 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 2101 : 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 2101 : status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER, NULL);
324 2101 : if (!W_ERROR_IS_OK(status)) {
325 0 : return status;
326 : }
327 :
328 2101 : 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 2101 : if (r->in.req->req1.options & DRSUAPI_DRS_ASYNC_OP) {
334 1137 : 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 2101 : 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 2101 : 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"
|