s4:rpc_server/netlogon: implement NETLOGON_CONTROL_{QUERY,REDISCOVER,TC_QUERY,TC_VERI...
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobd3cd866efef20cb0ac2f71684a72b9d834e38b6b
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../lib/util/memcache.h"
31 #include "../libcli/auth/schannel.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc_c.h"
36 #include "../libcli/ldap/ldap_ndr.h"
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40 #include "librpc/gen_ndr/ndr_lsa.h"
41 #include "librpc/gen_ndr/ndr_samr.h"
42 #include "librpc/gen_ndr/ndr_irpc.h"
43 #include "librpc/gen_ndr/ndr_winbind.h"
44 #include "librpc/gen_ndr/ndr_winbind_c.h"
45 #include "lib/socket/netif.h"
47 static struct memcache *global_challenge_table;
49 struct netlogon_server_pipe_state {
50 struct netr_Credential client_challenge;
51 struct netr_Credential server_challenge;
54 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
55 struct netr_ServerReqChallenge *r)
57 struct netlogon_server_pipe_state *pipe_state =
58 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
59 DATA_BLOB key, val;
61 ZERO_STRUCTP(r->out.return_credentials);
63 if (global_challenge_table == NULL) {
65 * We maintain a global challenge table
66 * with a fixed size (8k)
68 * This is required for the strange clients
69 * which use different connections for
70 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
73 global_challenge_table = memcache_init(talloc_autofree_context(),
74 8192);
75 if (global_challenge_table == NULL) {
76 return NT_STATUS_NO_MEMORY;
80 /* destroyed on pipe shutdown */
82 if (pipe_state) {
83 talloc_free(pipe_state);
84 dce_call->context->private_data = NULL;
87 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
88 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
90 pipe_state->client_challenge = *r->in.credentials;
92 generate_random_buffer(pipe_state->server_challenge.data,
93 sizeof(pipe_state->server_challenge.data));
95 *r->out.return_credentials = pipe_state->server_challenge;
97 dce_call->context->private_data = pipe_state;
99 key = data_blob_string_const(r->in.computer_name);
100 val = data_blob_const(pipe_state, sizeof(*pipe_state));
102 memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
104 return NT_STATUS_OK;
107 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
108 struct netr_ServerAuthenticate3 *r)
110 struct netlogon_server_pipe_state *pipe_state =
111 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
112 DATA_BLOB challenge_key;
113 bool challenge_valid = false;
114 struct netlogon_server_pipe_state challenge;
115 struct netlogon_creds_CredentialState *creds;
116 struct ldb_context *sam_ctx;
117 struct samr_Password *curNtHash = NULL;
118 struct samr_Password *prevNtHash = NULL;
119 uint32_t user_account_control;
120 int num_records;
121 struct ldb_message **msgs;
122 NTSTATUS nt_status;
123 const char *attrs[] = {"unicodePwd", "userAccountControl",
124 "objectSid", NULL};
125 const char *account_name;
126 uint32_t server_flags = 0;
127 uint32_t negotiate_flags = 0;
128 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
129 bool reject_des_client = !allow_nt4_crypto;
130 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
132 ZERO_STRUCTP(r->out.return_credentials);
133 *r->out.rid = 0;
135 challenge_key = data_blob_string_const(r->in.computer_name);
136 if (pipe_state != NULL) {
137 dce_call->context->private_data = NULL;
140 * If we had a challenge remembered on the connection
141 * consider this for usage. This can't be cleanup
142 * by other clients.
144 * This is the default code path for typical clients
145 * which call netr_ServerReqChallenge() and
146 * netr_ServerAuthenticate3() on the same dcerpc connection.
148 challenge = *pipe_state;
149 TALLOC_FREE(pipe_state);
150 challenge_valid = true;
151 } else {
152 DATA_BLOB val;
153 bool ok;
156 * Fallback and try to get the challenge from
157 * the global cache.
159 * If too many clients are using this code path,
160 * they may destroy their cache entries as the
161 * global_challenge_table memcache has a fixed size.
163 * Note: this handles global_challenge_table == NULL fine
165 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
166 challenge_key, &val);
167 if (ok && val.length == sizeof(challenge)) {
168 memcpy(&challenge, val.data, sizeof(challenge));
169 challenge_valid = true;
170 } else {
171 ZERO_STRUCT(challenge);
176 * At this point we can cleanup the cache entry,
177 * if we fail the client needs to call netr_ServerReqChallenge
178 * again.
180 * Note: this handles global_challenge_table == NULL
181 * and also a non existing record just fine.
183 memcache_delete(global_challenge_table,
184 SINGLETON_CACHE, challenge_key);
186 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
187 NETLOGON_NEG_PERSISTENT_SAMREPL |
188 NETLOGON_NEG_ARCFOUR |
189 NETLOGON_NEG_PROMOTION_COUNT |
190 NETLOGON_NEG_CHANGELOG_BDC |
191 NETLOGON_NEG_FULL_SYNC_REPL |
192 NETLOGON_NEG_MULTIPLE_SIDS |
193 NETLOGON_NEG_REDO |
194 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
195 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
196 NETLOGON_NEG_GENERIC_PASSTHROUGH |
197 NETLOGON_NEG_CONCURRENT_RPC |
198 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
199 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
200 NETLOGON_NEG_STRONG_KEYS |
201 NETLOGON_NEG_TRANSITIVE_TRUSTS |
202 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
203 NETLOGON_NEG_PASSWORD_SET2 |
204 NETLOGON_NEG_GETDOMAININFO |
205 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
206 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
207 NETLOGON_NEG_RODC_PASSTHROUGH |
208 NETLOGON_NEG_SUPPORTS_AES |
209 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
210 NETLOGON_NEG_AUTHENTICATED_RPC;
212 negotiate_flags = *r->in.negotiate_flags & server_flags;
214 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
215 reject_des_client = false;
218 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
219 reject_des_client = false;
220 reject_md5_client = false;
223 if (reject_des_client || reject_md5_client) {
225 * Here we match Windows 2012 and return no flags.
227 *r->out.negotiate_flags = 0;
228 return NT_STATUS_DOWNGRADE_DETECTED;
232 * According to Microsoft (see bugid #6099)
233 * Windows 7 looks at the negotiate_flags
234 * returned in this structure *even if the
235 * call fails with access denied!
237 *r->out.negotiate_flags = negotiate_flags;
239 switch (r->in.secure_channel_type) {
240 case SEC_CHAN_WKSTA:
241 case SEC_CHAN_DNS_DOMAIN:
242 case SEC_CHAN_DOMAIN:
243 case SEC_CHAN_BDC:
244 case SEC_CHAN_RODC:
245 break;
246 case SEC_CHAN_NULL:
247 return NT_STATUS_INVALID_PARAMETER;
248 default:
249 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
250 r->in.secure_channel_type));
251 return NT_STATUS_INVALID_PARAMETER;
254 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
255 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
256 if (sam_ctx == NULL) {
257 return NT_STATUS_INVALID_SYSTEM_SERVICE;
260 if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
261 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
263 struct ldb_message *tdo_msg = NULL;
264 const char * const tdo_attrs[] = {
265 "trustAuthIncoming",
266 "trustAttributes",
267 "flatName",
268 NULL
270 char *encoded_name = NULL;
271 size_t len;
272 const char *flatname = NULL;
273 char trailer = '$';
274 bool require_trailer = true;
275 const char *netbios = NULL;
276 const char *dns = NULL;
278 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
279 trailer = '.';
280 require_trailer = false;
283 encoded_name = ldb_binary_encode_string(mem_ctx,
284 r->in.account_name);
285 if (encoded_name == NULL) {
286 return NT_STATUS_NO_MEMORY;
289 len = strlen(encoded_name);
290 if (len < 2) {
291 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
294 if (require_trailer && encoded_name[len - 1] != trailer) {
295 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
297 encoded_name[len - 1] = '\0';
299 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
300 dns = encoded_name;
301 } else {
302 netbios = encoded_name;
305 nt_status = dsdb_trust_search_tdo(sam_ctx,
306 netbios, dns,
307 tdo_attrs, mem_ctx, &tdo_msg);
308 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
309 DEBUG(2, ("Client asked for a trusted domain secure channel, "
310 "but there's no tdo for [%s] => [%s] \n",
311 r->in.account_name, encoded_name));
312 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
314 if (!NT_STATUS_IS_OK(nt_status)) {
315 return nt_status;
318 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
319 &curNtHash,
320 &prevNtHash);
321 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
322 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
324 if (!NT_STATUS_IS_OK(nt_status)) {
325 return nt_status;
328 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
329 if (flatname == NULL) {
330 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
333 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
334 if (account_name == NULL) {
335 return NT_STATUS_NO_MEMORY;
337 } else {
338 account_name = r->in.account_name;
341 /* pull the user attributes */
342 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
343 "(&(sAMAccountName=%s)(objectclass=user))",
344 ldb_binary_encode_string(mem_ctx, account_name));
346 if (num_records == 0) {
347 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
348 r->in.account_name));
349 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
352 if (num_records > 1) {
353 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
354 return NT_STATUS_INTERNAL_DB_CORRUPTION;
357 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
359 if (user_account_control & UF_ACCOUNTDISABLE) {
360 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
361 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
364 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
365 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
366 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
367 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
369 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
370 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
371 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
372 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
374 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
376 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
377 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
378 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
379 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
381 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
382 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
383 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
384 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
386 } else {
387 /* we should never reach this */
388 return NT_STATUS_INTERNAL_ERROR;
391 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
392 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
393 dce_call->conn->dce_ctx->lp_ctx,
394 msgs[0], NULL, &curNtHash);
395 if (!NT_STATUS_IS_OK(nt_status)) {
396 return NT_STATUS_ACCESS_DENIED;
400 if (curNtHash == NULL) {
401 return NT_STATUS_ACCESS_DENIED;
404 if (!challenge_valid) {
405 DEBUG(1, ("No challenge requested by client [%s/%s], "
406 "cannot authenticate\n",
407 r->in.computer_name,
408 r->in.account_name));
409 return NT_STATUS_ACCESS_DENIED;
412 creds = netlogon_creds_server_init(mem_ctx,
413 r->in.account_name,
414 r->in.computer_name,
415 r->in.secure_channel_type,
416 &challenge.client_challenge,
417 &challenge.server_challenge,
418 curNtHash,
419 r->in.credentials,
420 r->out.return_credentials,
421 negotiate_flags);
422 if (creds == NULL && prevNtHash != NULL) {
424 * We fallback to the previous password for domain trusts.
426 * Note that lpcfg_old_password_allowed_period() doesn't
427 * apply here.
429 creds = netlogon_creds_server_init(mem_ctx,
430 r->in.account_name,
431 r->in.computer_name,
432 r->in.secure_channel_type,
433 &challenge.client_challenge,
434 &challenge.server_challenge,
435 prevNtHash,
436 r->in.credentials,
437 r->out.return_credentials,
438 negotiate_flags);
440 if (creds == NULL) {
441 return NT_STATUS_ACCESS_DENIED;
444 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
446 nt_status = schannel_save_creds_state(mem_ctx,
447 dce_call->conn->dce_ctx->lp_ctx,
448 creds);
449 if (!NT_STATUS_IS_OK(nt_status)) {
450 ZERO_STRUCTP(r->out.return_credentials);
451 return nt_status;
454 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
455 "objectSid", 0);
457 return NT_STATUS_OK;
460 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
461 struct netr_ServerAuthenticate *r)
463 struct netr_ServerAuthenticate3 a;
464 uint32_t rid;
465 /* TODO:
466 * negotiate_flags is used as an [in] parameter
467 * so it need to be initialised.
469 * (I think ... = 0; seems wrong here --metze)
471 uint32_t negotiate_flags_in = 0;
472 uint32_t negotiate_flags_out = 0;
474 a.in.server_name = r->in.server_name;
475 a.in.account_name = r->in.account_name;
476 a.in.secure_channel_type = r->in.secure_channel_type;
477 a.in.computer_name = r->in.computer_name;
478 a.in.credentials = r->in.credentials;
479 a.in.negotiate_flags = &negotiate_flags_in;
481 a.out.return_credentials = r->out.return_credentials;
482 a.out.rid = &rid;
483 a.out.negotiate_flags = &negotiate_flags_out;
485 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
488 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
489 struct netr_ServerAuthenticate2 *r)
491 struct netr_ServerAuthenticate3 r3;
492 uint32_t rid = 0;
494 r3.in.server_name = r->in.server_name;
495 r3.in.account_name = r->in.account_name;
496 r3.in.secure_channel_type = r->in.secure_channel_type;
497 r3.in.computer_name = r->in.computer_name;
498 r3.in.credentials = r->in.credentials;
499 r3.out.return_credentials = r->out.return_credentials;
500 r3.in.negotiate_flags = r->in.negotiate_flags;
501 r3.out.negotiate_flags = r->out.negotiate_flags;
502 r3.out.rid = &rid;
504 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
508 * NOTE: The following functions are nearly identical to the ones available in
509 * source3/rpc_server/srv_nelog_nt.c
510 * The reason we keep 2 copies is that they use different structures to
511 * represent the auth_info and the decrpc pipes.
515 * If schannel is required for this call test that it actually is available.
517 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
518 const char *computer_name,
519 bool integrity, bool privacy)
522 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
523 if (!privacy && !integrity) {
524 return NT_STATUS_OK;
527 if ((!privacy && integrity) &&
528 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
529 return NT_STATUS_OK;
532 if ((privacy || integrity) &&
533 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
534 return NT_STATUS_OK;
538 /* test didn't pass */
539 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
540 computer_name));
542 return NT_STATUS_ACCESS_DENIED;
545 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
546 TALLOC_CTX *mem_ctx,
547 const char *computer_name,
548 struct netr_Authenticator *received_authenticator,
549 struct netr_Authenticator *return_authenticator,
550 struct netlogon_creds_CredentialState **creds_out)
552 NTSTATUS nt_status;
553 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
554 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
556 if (schannel_global_required) {
557 nt_status = schannel_check_required(auth_info,
558 computer_name,
559 true, false);
560 if (!NT_STATUS_IS_OK(nt_status)) {
561 return nt_status;
565 nt_status = schannel_check_creds_state(mem_ctx,
566 dce_call->conn->dce_ctx->lp_ctx,
567 computer_name,
568 received_authenticator,
569 return_authenticator,
570 creds_out);
571 return nt_status;
575 Change the machine account password for the currently connected
576 client. Supplies only the NT#.
579 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
580 struct netr_ServerPasswordSet *r)
582 struct netlogon_creds_CredentialState *creds;
583 struct ldb_context *sam_ctx;
584 const char * const attrs[] = { "unicodePwd", NULL };
585 struct ldb_message **res;
586 struct samr_Password *oldNtHash;
587 NTSTATUS nt_status;
588 int ret;
590 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
591 mem_ctx,
592 r->in.computer_name,
593 r->in.credential, r->out.return_authenticator,
594 &creds);
595 NT_STATUS_NOT_OK_RETURN(nt_status);
597 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
598 if (sam_ctx == NULL) {
599 return NT_STATUS_INVALID_SYSTEM_SERVICE;
602 netlogon_creds_des_decrypt(creds, r->in.new_password);
604 /* fetch the old password hashes (the NT hash has to exist) */
606 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
607 "(&(objectClass=user)(objectSid=%s))",
608 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
609 if (ret != 1) {
610 return NT_STATUS_WRONG_PASSWORD;
613 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
614 dce_call->conn->dce_ctx->lp_ctx,
615 res[0], NULL, &oldNtHash);
616 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
617 return NT_STATUS_WRONG_PASSWORD;
620 /* Using the sid for the account as the key, set the password */
621 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
622 creds->sid,
623 NULL, /* Don't have version */
624 NULL, /* Don't have plaintext */
625 NULL, r->in.new_password,
626 NULL, oldNtHash, /* Password change */
627 NULL, NULL);
628 return nt_status;
632 Change the machine account password for the currently connected
633 client. Supplies new plaintext.
635 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636 struct netr_ServerPasswordSet2 *r)
638 struct netlogon_creds_CredentialState *creds;
639 struct ldb_context *sam_ctx;
640 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
641 struct ldb_message **res;
642 struct samr_Password *oldLmHash, *oldNtHash;
643 struct NL_PASSWORD_VERSION version = {};
644 const uint32_t *new_version = NULL;
645 NTSTATUS nt_status;
646 DATA_BLOB new_password;
647 int ret;
648 struct samr_CryptPassword password_buf;
650 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
651 mem_ctx,
652 r->in.computer_name,
653 r->in.credential, r->out.return_authenticator,
654 &creds);
655 NT_STATUS_NOT_OK_RETURN(nt_status);
657 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
658 if (sam_ctx == NULL) {
659 return NT_STATUS_INVALID_SYSTEM_SERVICE;
662 memcpy(password_buf.data, r->in.new_password->data, 512);
663 SIVAL(password_buf.data, 512, r->in.new_password->length);
665 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
666 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
667 } else {
668 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
671 switch (creds->secure_channel_type) {
672 case SEC_CHAN_DOMAIN:
673 case SEC_CHAN_DNS_DOMAIN: {
674 uint32_t len = IVAL(password_buf.data, 512);
675 if (len <= 500) {
676 uint32_t ofs = 500 - len;
677 uint8_t *p;
679 p = password_buf.data + ofs;
681 version.ReservedField = IVAL(p, 0);
682 version.PasswordVersionNumber = IVAL(p, 4);
683 version.PasswordVersionPresent = IVAL(p, 8);
685 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
686 new_version = &version.PasswordVersionNumber;
689 break;
690 default:
691 break;
694 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
695 DEBUG(3,("samr: failed to decode password buffer\n"));
696 return NT_STATUS_WRONG_PASSWORD;
699 /* fetch the old password hashes (at least one of both has to exist) */
701 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
702 "(&(objectClass=user)(objectSid=%s))",
703 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
704 if (ret != 1) {
705 return NT_STATUS_WRONG_PASSWORD;
708 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
709 dce_call->conn->dce_ctx->lp_ctx,
710 res[0], &oldLmHash, &oldNtHash);
711 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
712 return NT_STATUS_WRONG_PASSWORD;
715 /* Using the sid for the account as the key, set the password */
716 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
717 creds->sid,
718 new_version,
719 &new_password, /* we have plaintext */
720 NULL, NULL,
721 oldLmHash, oldNtHash, /* Password change */
722 NULL, NULL);
723 return nt_status;
728 netr_LogonUasLogon
730 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
731 struct netr_LogonUasLogon *r)
733 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
738 netr_LogonUasLogoff
740 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
741 struct netr_LogonUasLogoff *r)
743 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
747 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
749 switch (r->in.logon_level) {
750 case NetlogonInteractiveInformation:
751 case NetlogonServiceInformation:
752 case NetlogonInteractiveTransitiveInformation:
753 case NetlogonServiceTransitiveInformation:
754 if (r->in.logon->password == NULL) {
755 return NT_STATUS_INVALID_PARAMETER;
758 switch (r->in.validation_level) {
759 case NetlogonValidationSamInfo: /* 2 */
760 case NetlogonValidationSamInfo2: /* 3 */
761 case NetlogonValidationSamInfo4: /* 6 */
762 break;
763 default:
764 return NT_STATUS_INVALID_INFO_CLASS;
767 break;
768 case NetlogonNetworkInformation:
769 case NetlogonNetworkTransitiveInformation:
770 if (r->in.logon->network == NULL) {
771 return NT_STATUS_INVALID_PARAMETER;
774 switch (r->in.validation_level) {
775 case NetlogonValidationSamInfo: /* 2 */
776 case NetlogonValidationSamInfo2: /* 3 */
777 case NetlogonValidationSamInfo4: /* 6 */
778 break;
779 default:
780 return NT_STATUS_INVALID_INFO_CLASS;
783 break;
785 case NetlogonGenericInformation:
786 if (r->in.logon->generic == NULL) {
787 return NT_STATUS_INVALID_PARAMETER;
790 switch (r->in.validation_level) {
791 /* TODO: case NetlogonValidationGenericInfo: 4 */
792 case NetlogonValidationGenericInfo2: /* 5 */
793 break;
794 default:
795 return NT_STATUS_INVALID_INFO_CLASS;
798 break;
799 default:
800 return NT_STATUS_INVALID_PARAMETER;
803 return NT_STATUS_OK;
807 netr_LogonSamLogon_base
809 This version of the function allows other wrappers to say 'do not check the credentials'
811 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
813 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
814 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
816 struct auth4_context *auth_context;
817 struct auth_usersupplied_info *user_info;
818 struct auth_user_info_dc *user_info_dc;
819 NTSTATUS nt_status;
820 struct netr_SamBaseInfo *sam;
821 struct netr_SamInfo2 *sam2;
822 struct netr_SamInfo3 *sam3;
823 struct netr_SamInfo6 *sam6;
825 *r->out.authoritative = 1;
827 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
828 NT_STATUS_HAVE_NO_MEMORY(user_info);
830 netlogon_creds_decrypt_samlogon_logon(creds,
831 r->in.logon_level,
832 r->in.logon);
834 switch (r->in.logon_level) {
835 case NetlogonInteractiveInformation:
836 case NetlogonServiceInformation:
837 case NetlogonInteractiveTransitiveInformation:
838 case NetlogonServiceTransitiveInformation:
840 /* TODO: we need to deny anonymous access here */
841 nt_status = auth_context_create(mem_ctx,
842 dce_call->event_ctx, dce_call->msg_ctx,
843 dce_call->conn->dce_ctx->lp_ctx,
844 &auth_context);
845 NT_STATUS_NOT_OK_RETURN(nt_status);
847 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
848 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
849 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
850 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
852 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
853 user_info->password_state = AUTH_PASSWORD_HASH;
855 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
856 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
857 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
859 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
860 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
861 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
863 break;
864 case NetlogonNetworkInformation:
865 case NetlogonNetworkTransitiveInformation:
867 /* TODO: we need to deny anonymous access here */
868 nt_status = auth_context_create(mem_ctx,
869 dce_call->event_ctx, dce_call->msg_ctx,
870 dce_call->conn->dce_ctx->lp_ctx,
871 &auth_context);
872 NT_STATUS_NOT_OK_RETURN(nt_status);
874 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
875 NT_STATUS_NOT_OK_RETURN(nt_status);
877 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
878 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
879 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
880 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
882 user_info->password_state = AUTH_PASSWORD_RESPONSE;
883 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
884 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
886 break;
889 case NetlogonGenericInformation:
891 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
892 /* OK */
893 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
894 /* OK */
895 } else {
896 /* Using DES to verify kerberos tickets makes no sense */
897 return NT_STATUS_INVALID_PARAMETER;
900 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
901 NTSTATUS status;
902 struct dcerpc_binding_handle *irpc_handle;
903 struct kdc_check_generic_kerberos check;
904 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
905 NT_STATUS_HAVE_NO_MEMORY(generic);
906 *r->out.authoritative = 1;
908 /* TODO: Describe and deal with these flags */
909 *r->out.flags = 0;
911 r->out.validation->generic = generic;
913 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
914 dce_call->msg_ctx,
915 "kdc_server",
916 &ndr_table_irpc);
917 if (irpc_handle == NULL) {
918 return NT_STATUS_NO_LOGON_SERVERS;
921 check.in.generic_request =
922 data_blob_const(r->in.logon->generic->data,
923 r->in.logon->generic->length);
926 * TODO: make this async and avoid
927 * dcerpc_binding_handle_set_sync_ev()
929 dcerpc_binding_handle_set_sync_ev(irpc_handle,
930 dce_call->event_ctx);
931 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
932 mem_ctx,
933 &check);
934 if (!NT_STATUS_IS_OK(status)) {
935 return status;
937 generic->length = check.out.generic_reply.length;
938 generic->data = check.out.generic_reply.data;
939 return NT_STATUS_OK;
942 /* Until we get an implemetnation of these other packages */
943 return NT_STATUS_INVALID_PARAMETER;
945 default:
946 return NT_STATUS_INVALID_PARAMETER;
949 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
950 /* TODO: set *r->out.authoritative = 0 on specific errors */
951 NT_STATUS_NOT_OK_RETURN(nt_status);
953 switch (r->in.validation_level) {
954 case 2:
955 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
956 NT_STATUS_NOT_OK_RETURN(nt_status);
958 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
959 NT_STATUS_HAVE_NO_MEMORY(sam2);
960 sam2->base = *sam;
962 /* And put into the talloc tree */
963 talloc_steal(sam2, sam);
964 r->out.validation->sam2 = sam2;
966 sam = &sam2->base;
967 break;
969 case 3:
970 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
971 user_info_dc,
972 &sam3);
973 NT_STATUS_NOT_OK_RETURN(nt_status);
975 r->out.validation->sam3 = sam3;
977 sam = &sam3->base;
978 break;
980 case 6:
981 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
982 user_info_dc,
983 &sam3);
984 NT_STATUS_NOT_OK_RETURN(nt_status);
986 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
987 NT_STATUS_HAVE_NO_MEMORY(sam6);
988 sam6->base = sam3->base;
989 sam = &sam6->base;
990 sam6->sidcount = sam3->sidcount;
991 sam6->sids = sam3->sids;
993 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
994 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
995 sam->account_name.string, sam6->dns_domainname.string);
996 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
997 /* And put into the talloc tree */
998 talloc_steal(sam6, sam3);
1000 r->out.validation->sam6 = sam6;
1001 break;
1003 default:
1004 return NT_STATUS_INVALID_INFO_CLASS;
1007 netlogon_creds_encrypt_samlogon_validation(creds,
1008 r->in.validation_level,
1009 r->out.validation);
1011 /* TODO: Describe and deal with these flags */
1012 *r->out.flags = 0;
1014 return NT_STATUS_OK;
1017 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1018 struct netr_LogonSamLogonEx *r)
1020 NTSTATUS nt_status;
1021 struct netlogon_creds_CredentialState *creds;
1023 *r->out.authoritative = 1;
1025 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1026 if (!NT_STATUS_IS_OK(nt_status)) {
1027 return nt_status;
1030 nt_status = schannel_get_creds_state(mem_ctx,
1031 dce_call->conn->dce_ctx->lp_ctx,
1032 r->in.computer_name, &creds);
1033 if (!NT_STATUS_IS_OK(nt_status)) {
1034 return nt_status;
1037 if (!dce_call->conn->auth_state.auth_info ||
1038 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1039 return NT_STATUS_ACCESS_DENIED;
1041 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1045 netr_LogonSamLogonWithFlags
1048 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1049 struct netr_LogonSamLogonWithFlags *r)
1051 NTSTATUS nt_status;
1052 struct netlogon_creds_CredentialState *creds;
1053 struct netr_LogonSamLogonEx r2;
1055 struct netr_Authenticator *return_authenticator;
1057 ZERO_STRUCT(r2);
1059 r2.in.server_name = r->in.server_name;
1060 r2.in.computer_name = r->in.computer_name;
1061 r2.in.logon_level = r->in.logon_level;
1062 r2.in.logon = r->in.logon;
1063 r2.in.validation_level = r->in.validation_level;
1064 r2.in.flags = r->in.flags;
1065 r2.out.validation = r->out.validation;
1066 r2.out.authoritative = r->out.authoritative;
1067 r2.out.flags = r->out.flags;
1069 *r->out.authoritative = 1;
1071 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1072 if (!NT_STATUS_IS_OK(nt_status)) {
1073 return nt_status;
1076 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1077 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1079 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1080 mem_ctx,
1081 r->in.computer_name,
1082 r->in.credential, return_authenticator,
1083 &creds);
1084 NT_STATUS_NOT_OK_RETURN(nt_status);
1086 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1088 r->out.return_authenticator = return_authenticator;
1090 return nt_status;
1094 netr_LogonSamLogon
1096 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1097 struct netr_LogonSamLogon *r)
1099 struct netr_LogonSamLogonWithFlags r2;
1100 uint32_t flags = 0;
1101 NTSTATUS status;
1103 ZERO_STRUCT(r2);
1105 r2.in.server_name = r->in.server_name;
1106 r2.in.computer_name = r->in.computer_name;
1107 r2.in.credential = r->in.credential;
1108 r2.in.return_authenticator = r->in.return_authenticator;
1109 r2.in.logon_level = r->in.logon_level;
1110 r2.in.logon = r->in.logon;
1111 r2.in.validation_level = r->in.validation_level;
1112 r2.in.flags = &flags;
1113 r2.out.validation = r->out.validation;
1114 r2.out.authoritative = r->out.authoritative;
1115 r2.out.flags = &flags;
1117 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1119 r->out.return_authenticator = r2.out.return_authenticator;
1121 return status;
1126 netr_LogonSamLogoff
1128 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1129 struct netr_LogonSamLogoff *r)
1131 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1137 netr_DatabaseDeltas
1139 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140 struct netr_DatabaseDeltas *r)
1142 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1147 netr_DatabaseSync2
1149 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct netr_DatabaseSync2 *r)
1152 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1153 return NT_STATUS_NOT_IMPLEMENTED;
1158 netr_DatabaseSync
1160 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1161 struct netr_DatabaseSync *r)
1163 struct netr_DatabaseSync2 r2;
1164 NTSTATUS status;
1166 ZERO_STRUCT(r2);
1168 r2.in.logon_server = r->in.logon_server;
1169 r2.in.computername = r->in.computername;
1170 r2.in.credential = r->in.credential;
1171 r2.in.database_id = r->in.database_id;
1172 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1173 r2.in.sync_context = r->in.sync_context;
1174 r2.out.sync_context = r->out.sync_context;
1175 r2.out.delta_enum_array = r->out.delta_enum_array;
1176 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1178 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1180 return status;
1185 netr_AccountDeltas
1187 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1188 struct netr_AccountDeltas *r)
1190 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1191 return NT_STATUS_NOT_IMPLEMENTED;
1196 netr_AccountSync
1198 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1199 struct netr_AccountSync *r)
1201 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1202 return NT_STATUS_NOT_IMPLEMENTED;
1207 netr_GetDcName
1209 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210 struct netr_GetDcName *r)
1212 const char * const attrs[] = { NULL };
1213 struct ldb_context *sam_ctx;
1214 struct ldb_message **res;
1215 struct ldb_dn *domain_dn;
1216 int ret;
1217 const char *dcname;
1220 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1221 * that the domainname needs to be a valid netbios domain
1222 * name, if it is not NULL.
1224 if (r->in.domainname) {
1225 const char *dot = strchr(r->in.domainname, '.');
1226 size_t len = strlen(r->in.domainname);
1228 if (dot || len > 15) {
1229 return WERR_DCNOTFOUND;
1233 * TODO: Should we also varify that only valid
1234 * netbios name characters are used?
1238 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1239 dce_call->conn->dce_ctx->lp_ctx,
1240 dce_call->conn->auth_state.session_info, 0);
1241 if (sam_ctx == NULL) {
1242 return WERR_DS_UNAVAILABLE;
1245 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1246 r->in.domainname);
1247 if (domain_dn == NULL) {
1248 return WERR_NO_SUCH_DOMAIN;
1251 ret = gendb_search_dn(sam_ctx, mem_ctx,
1252 domain_dn, &res, attrs);
1253 if (ret != 1) {
1254 return WERR_NO_SUCH_DOMAIN;
1257 /* TODO: - return real IP address
1258 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1260 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1261 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1262 W_ERROR_HAVE_NO_MEMORY(dcname);
1264 *r->out.dcname = dcname;
1265 return WERR_OK;
1268 struct dcesrv_netr_LogonControl_base_state {
1269 struct dcesrv_call_state *dce_call;
1271 TALLOC_CTX *mem_ctx;
1273 struct netr_LogonControl2Ex r;
1275 struct {
1276 struct netr_LogonControl *l;
1277 struct netr_LogonControl2 *l2;
1278 struct netr_LogonControl2Ex *l2ex;
1279 } _r;
1282 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
1284 static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
1286 struct dcesrv_connection *conn = state->dce_call->conn;
1287 struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
1288 struct auth_session_info *session_info = conn->auth_state.session_info;
1289 enum security_user_level security_level;
1290 struct dcerpc_binding_handle *irpc_handle;
1291 struct tevent_req *subreq;
1292 bool ok;
1294 /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
1296 if (state->_r.l != NULL) {
1298 * netr_LogonControl
1300 if (state->r.in.level == 0x00000002) {
1301 return WERR_NOT_SUPPORTED;
1302 } else if (state->r.in.level != 0x00000001) {
1303 return WERR_INVALID_LEVEL;
1306 switch (state->r.in.function_code) {
1307 case NETLOGON_CONTROL_QUERY:
1308 case NETLOGON_CONTROL_REPLICATE:
1309 case NETLOGON_CONTROL_SYNCHRONIZE:
1310 case NETLOGON_CONTROL_PDC_REPLICATE:
1311 case NETLOGON_CONTROL_BREAKPOINT:
1312 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
1313 case NETLOGON_CONTROL_TRUNCATE_LOG:
1314 break;
1315 default:
1316 return WERR_NOT_SUPPORTED;
1320 if (state->r.in.level < 0x00000001) {
1321 return WERR_INVALID_LEVEL;
1324 if (state->r.in.level > 0x00000004) {
1325 return WERR_INVALID_LEVEL;
1328 if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
1329 struct netr_NETLOGON_INFO_1 *info1 = NULL;
1330 struct netr_NETLOGON_INFO_3 *info3 = NULL;
1332 switch (state->r.in.level) {
1333 case 0x00000001:
1334 info1 = talloc_zero(state->mem_ctx,
1335 struct netr_NETLOGON_INFO_1);
1336 if (info1 == NULL) {
1337 return WERR_NOMEM;
1339 state->r.out.query->info1 = info1;
1340 return WERR_OK;
1342 case 0x00000003:
1343 info3 = talloc_zero(state->mem_ctx,
1344 struct netr_NETLOGON_INFO_3);
1345 if (info3 == NULL) {
1346 return WERR_NOMEM;
1348 state->r.out.query->info3 = info3;
1349 return WERR_OK;
1351 default:
1352 return WERR_INVALID_PARAMETER;
1357 * Some validations are done before the access check
1358 * and some after the access check
1360 security_level = security_session_user_level(session_info, NULL);
1361 if (security_level < SECURITY_ADMINISTRATOR) {
1362 return WERR_ACCESS_DENIED;
1365 if (state->_r.l2 != NULL) {
1367 * netr_LogonControl2
1369 if (state->r.in.level == 0x00000004) {
1370 return WERR_INVALID_LEVEL;
1374 switch (state->r.in.level) {
1375 case 0x00000001:
1376 break;
1378 case 0x00000002:
1379 switch (state->r.in.function_code) {
1380 case NETLOGON_CONTROL_REDISCOVER:
1381 case NETLOGON_CONTROL_TC_QUERY:
1382 case NETLOGON_CONTROL_TC_VERIFY:
1383 break;
1384 default:
1385 return WERR_INVALID_PARAMETER;
1388 break;
1390 case 0x00000003:
1391 break;
1393 case 0x00000004:
1394 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
1395 return WERR_INVALID_PARAMETER;
1398 break;
1400 default:
1401 return WERR_INVALID_LEVEL;
1404 switch (state->r.in.function_code) {
1405 case NETLOGON_CONTROL_REDISCOVER:
1406 case NETLOGON_CONTROL_TC_QUERY:
1407 case NETLOGON_CONTROL_TC_VERIFY:
1408 if (state->r.in.level != 2) {
1409 return WERR_INVALID_PARAMETER;
1412 if (state->r.in.data == NULL) {
1413 return WERR_INVALID_PARAMETER;
1416 if (state->r.in.data->domain == NULL) {
1417 return WERR_INVALID_PARAMETER;
1420 break;
1422 case NETLOGON_CONTROL_CHANGE_PASSWORD:
1423 if (state->r.in.level != 1) {
1424 return WERR_INVALID_PARAMETER;
1427 if (state->r.in.data == NULL) {
1428 return WERR_INVALID_PARAMETER;
1431 if (state->r.in.data->domain == NULL) {
1432 return WERR_INVALID_PARAMETER;
1435 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
1436 state->r.in.data->domain);
1437 if (!ok) {
1438 struct ldb_context *sam_ctx;
1440 sam_ctx = samdb_connect(state, state->dce_call->event_ctx,
1441 lp_ctx, system_session(lp_ctx), 0);
1442 if (sam_ctx == NULL) {
1443 return WERR_DS_UNAVAILABLE;
1447 * Secrets for trusted domains can only be triggered on
1448 * the PDC.
1450 ok = samdb_is_pdc(sam_ctx);
1451 TALLOC_FREE(sam_ctx);
1452 if (!ok) {
1453 return WERR_INVALID_DOMAIN_ROLE;
1457 break;
1458 default:
1459 return WERR_NOT_SUPPORTED;
1462 irpc_handle = irpc_binding_handle_by_name(state,
1463 state->dce_call->msg_ctx,
1464 "winbind_server",
1465 &ndr_table_winbind);
1466 if (irpc_handle == NULL) {
1467 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
1468 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1469 return WERR_SERVICE_NOT_FOUND;
1473 * 60 seconds timeout should be enough
1475 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
1477 subreq = dcerpc_winbind_LogonControl_send(state,
1478 state->dce_call->event_ctx,
1479 irpc_handle,
1480 state->r.in.function_code,
1481 state->r.in.level,
1482 state->r.in.data,
1483 state->r.out.query);
1484 if (subreq == NULL) {
1485 return WERR_NOMEM;
1487 state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
1488 tevent_req_set_callback(subreq,
1489 dcesrv_netr_LogonControl_base_done,
1490 state);
1492 return WERR_OK;
1495 static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
1497 struct dcesrv_netr_LogonControl_base_state *state =
1498 tevent_req_callback_data(subreq,
1499 struct dcesrv_netr_LogonControl_base_state);
1500 NTSTATUS status;
1502 status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
1503 &state->r.out.result);
1504 TALLOC_FREE(subreq);
1505 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
1506 state->r.out.result = WERR_TIMEOUT;
1507 } else if (!NT_STATUS_IS_OK(status)) {
1508 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
1509 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
1510 nt_errstr(status)));
1513 if (state->_r.l2ex != NULL) {
1514 struct netr_LogonControl2Ex *r = state->_r.l2ex;
1515 r->out.result = state->r.out.result;
1516 } else if (state->_r.l2 != NULL) {
1517 struct netr_LogonControl2 *r = state->_r.l2;
1518 r->out.result = state->r.out.result;
1519 } else if (state->_r.l != NULL) {
1520 struct netr_LogonControl *r = state->_r.l;
1521 r->out.result = state->r.out.result;
1524 status = dcesrv_reply(state->dce_call);
1525 if (!NT_STATUS_IS_OK(status)) {
1526 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
1531 netr_LogonControl
1533 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1534 struct netr_LogonControl *r)
1536 struct dcesrv_netr_LogonControl_base_state *state;
1537 WERROR werr;
1539 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1540 if (state == NULL) {
1541 return WERR_NOMEM;
1544 state->dce_call = dce_call;
1545 state->mem_ctx = mem_ctx;
1547 state->r.in.logon_server = r->in.logon_server;
1548 state->r.in.function_code = r->in.function_code;
1549 state->r.in.level = r->in.level;
1550 state->r.in.data = NULL;
1551 state->r.out.query = r->out.query;
1553 state->_r.l = r;
1555 werr = dcesrv_netr_LogonControl_base_call(state);
1557 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1558 return werr;
1561 return werr;
1565 netr_LogonControl2
1567 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1568 struct netr_LogonControl2 *r)
1570 struct dcesrv_netr_LogonControl_base_state *state;
1571 WERROR werr;
1573 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1574 if (state == NULL) {
1575 return WERR_NOMEM;
1578 state->dce_call = dce_call;
1579 state->mem_ctx = mem_ctx;
1581 state->r.in.logon_server = r->in.logon_server;
1582 state->r.in.function_code = r->in.function_code;
1583 state->r.in.level = r->in.level;
1584 state->r.in.data = r->in.data;
1585 state->r.out.query = r->out.query;
1587 state->_r.l2 = r;
1589 werr = dcesrv_netr_LogonControl_base_call(state);
1591 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1592 return werr;
1595 return werr;
1599 netr_LogonControl2Ex
1601 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1602 struct netr_LogonControl2Ex *r)
1604 struct dcesrv_netr_LogonControl_base_state *state;
1605 WERROR werr;
1607 state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
1608 if (state == NULL) {
1609 return WERR_NOMEM;
1612 state->dce_call = dce_call;
1613 state->mem_ctx = mem_ctx;
1615 state->r = *r;
1616 state->_r.l2ex = r;
1618 werr = dcesrv_netr_LogonControl_base_call(state);
1620 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
1621 return werr;
1624 return werr;
1627 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1628 struct ldb_context *sam_ctx,
1629 struct netr_DomainTrustList *trusts,
1630 uint32_t trust_flags);
1633 netr_GetAnyDCName
1635 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1636 struct netr_GetAnyDCName *r)
1638 struct netr_DomainTrustList *trusts;
1639 struct ldb_context *sam_ctx;
1640 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1641 uint32_t i;
1642 WERROR werr;
1644 *r->out.dcname = NULL;
1646 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1647 /* if the domainname parameter wasn't set assume our domain */
1648 r->in.domainname = lpcfg_workgroup(lp_ctx);
1651 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1652 dce_call->conn->auth_state.session_info, 0);
1653 if (sam_ctx == NULL) {
1654 return WERR_DS_UNAVAILABLE;
1657 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1658 /* well we asked for a DC of our own domain */
1659 if (samdb_is_pdc(sam_ctx)) {
1660 /* we are the PDC of the specified domain */
1661 return WERR_NO_SUCH_DOMAIN;
1664 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1665 lpcfg_netbios_name(lp_ctx));
1666 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1668 return WERR_OK;
1671 /* Okay, now we have to consider the trusted domains */
1673 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1674 W_ERROR_HAVE_NO_MEMORY(trusts);
1676 trusts->count = 0;
1678 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1679 NETR_TRUST_FLAG_INBOUND
1680 | NETR_TRUST_FLAG_OUTBOUND);
1681 W_ERROR_NOT_OK_RETURN(werr);
1683 for (i = 0; i < trusts->count; i++) {
1684 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1685 /* FIXME: Here we need to find a DC for the specified
1686 * trusted domain. */
1688 /* return WERR_OK; */
1689 return WERR_NO_SUCH_DOMAIN;
1693 return WERR_NO_SUCH_DOMAIN;
1698 netr_DatabaseRedo
1700 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1701 struct netr_DatabaseRedo *r)
1703 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1708 netr_NetrEnumerateTrustedDomains
1710 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1711 struct netr_NetrEnumerateTrustedDomains *r)
1713 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1718 netr_LogonGetCapabilities
1720 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1721 struct netr_LogonGetCapabilities *r)
1723 struct netlogon_creds_CredentialState *creds;
1724 NTSTATUS status;
1726 status = dcesrv_netr_creds_server_step_check(dce_call,
1727 mem_ctx,
1728 r->in.computer_name,
1729 r->in.credential,
1730 r->out.return_authenticator,
1731 &creds);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 DEBUG(0,(__location__ " Bad credentials - error\n"));
1735 NT_STATUS_NOT_OK_RETURN(status);
1737 if (r->in.query_level != 1) {
1738 return NT_STATUS_NOT_SUPPORTED;
1741 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1743 return NT_STATUS_OK;
1748 netr_NETRLOGONSETSERVICEBITS
1750 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1751 struct netr_NETRLOGONSETSERVICEBITS *r)
1753 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1758 netr_LogonGetTrustRid
1760 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1761 struct netr_LogonGetTrustRid *r)
1763 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1768 netr_NETRLOGONCOMPUTESERVERDIGEST
1770 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1771 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1778 netr_NETRLOGONCOMPUTECLIENTDIGEST
1780 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1781 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1783 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1789 netr_DsRGetSiteName
1791 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1792 struct netr_DsRGetSiteName *r)
1794 struct ldb_context *sam_ctx;
1795 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1797 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1798 dce_call->conn->auth_state.session_info, 0);
1799 if (sam_ctx == NULL) {
1800 return WERR_DS_UNAVAILABLE;
1804 * We assume to be a DC when we get called over NETLOGON. Hence we
1805 * get our site name always by using "samdb_server_site_name()"
1806 * and not "samdb_client_site_name()".
1808 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1809 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1811 return WERR_OK;
1816 fill in a netr_OneDomainInfo from a ldb search result
1818 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1819 struct loadparm_context *lp_ctx,
1820 struct ldb_context *sam_ctx,
1821 struct ldb_message *res,
1822 struct netr_OneDomainInfo *info,
1823 bool is_local, bool is_trust_list)
1825 ZERO_STRUCTP(info);
1827 if (is_trust_list) {
1828 /* w2k8 only fills this on trusted domains */
1829 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1830 info->trust_extension.length = 16;
1831 info->trust_extension.info->flags =
1832 NETR_TRUST_FLAG_TREEROOT |
1833 NETR_TRUST_FLAG_IN_FOREST |
1834 NETR_TRUST_FLAG_PRIMARY |
1835 NETR_TRUST_FLAG_NATIVE;
1837 info->trust_extension.info->parent_index = 0; /* should be index into array
1838 of parent */
1839 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1840 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1843 if (is_trust_list) {
1844 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1845 info->dns_forestname.string = NULL;
1846 } else {
1847 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1848 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1849 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1850 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1853 if (is_local) {
1854 info->domainname.string = lpcfg_workgroup(lp_ctx);
1855 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1856 info->domain_guid = samdb_result_guid(res, "objectGUID");
1857 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1858 } else {
1859 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1860 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1861 info->domain_guid = samdb_result_guid(res, "objectGUID");
1862 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1864 if (!is_trust_list) {
1865 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1868 return NT_STATUS_OK;
1872 netr_LogonGetDomainInfo
1873 this is called as part of the ADS domain logon procedure.
1875 It has an important role in convaying details about the client, such
1876 as Operating System, Version, Service Pack etc.
1878 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1879 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1881 struct netlogon_creds_CredentialState *creds;
1882 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1883 "securityIdentifier", "trustPartner", NULL };
1884 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1885 "msDS-SupportedEncryptionTypes", NULL };
1886 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1887 struct ldb_context *sam_ctx;
1888 struct ldb_message **res1, **res2, **res3, *new_msg;
1889 struct ldb_dn *workstation_dn;
1890 struct netr_DomainInformation *domain_info;
1891 struct netr_LsaPolicyInformation *lsa_policy_info;
1892 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1893 bool update_dns_hostname = true;
1894 int ret, ret3, i;
1895 NTSTATUS status;
1897 status = dcesrv_netr_creds_server_step_check(dce_call,
1898 mem_ctx,
1899 r->in.computer_name,
1900 r->in.credential,
1901 r->out.return_authenticator,
1902 &creds);
1903 if (!NT_STATUS_IS_OK(status)) {
1904 DEBUG(0,(__location__ " Bad credentials - error\n"));
1906 NT_STATUS_NOT_OK_RETURN(status);
1908 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1909 dce_call->conn->dce_ctx->lp_ctx,
1910 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1911 if (sam_ctx == NULL) {
1912 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1915 switch (r->in.level) {
1916 case 1: /* Domain information */
1918 if (r->in.query->workstation_info == NULL) {
1919 return NT_STATUS_INVALID_PARAMETER;
1922 /* Prepares the workstation DN */
1923 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1924 dom_sid_string(mem_ctx, creds->sid));
1925 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1927 /* Lookup for attributes in workstation object */
1928 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1929 attrs2);
1930 if (ret != 1) {
1931 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1934 /* Gets the sam account name which is checked against the DNS
1935 * hostname parameter. */
1936 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1937 "sAMAccountName",
1938 NULL);
1939 if (sam_account_name == NULL) {
1940 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1944 * Checks that the sam account name without a possible "$"
1945 * matches as prefix with the DNS hostname in the workstation
1946 * info structure.
1948 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1949 strcspn(sam_account_name, "$"));
1950 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1951 if (r->in.query->workstation_info->dns_hostname != NULL) {
1952 prefix2 = talloc_strndup(mem_ctx,
1953 r->in.query->workstation_info->dns_hostname,
1954 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1955 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1957 if (strcasecmp(prefix1, prefix2) != 0) {
1958 update_dns_hostname = false;
1960 } else {
1961 update_dns_hostname = false;
1964 /* Gets the old DNS hostname */
1965 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1966 "dNSHostName",
1967 NULL);
1970 * Updates the DNS hostname when the client wishes that the
1971 * server should handle this for him
1972 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1973 * obviously only checked when we do already have a
1974 * "dNSHostName".
1975 * See MS-NRPC section 3.5.4.3.9
1977 if ((old_dns_hostname != NULL) &&
1978 (r->in.query->workstation_info->workstation_flags
1979 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1980 update_dns_hostname = false;
1983 /* Gets host information and put them into our directory */
1985 new_msg = ldb_msg_new(mem_ctx);
1986 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1988 new_msg->dn = workstation_dn;
1990 /* Sets the OS name */
1992 if (r->in.query->workstation_info->os_name.string == NULL) {
1993 return NT_STATUS_INVALID_PARAMETER;
1996 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1997 r->in.query->workstation_info->os_name.string);
1998 if (ret != LDB_SUCCESS) {
1999 return NT_STATUS_NO_MEMORY;
2003 * Sets information from "os_version". On an empty structure
2004 * the values are cleared.
2006 if (r->in.query->workstation_info->os_version.os != NULL) {
2007 struct netr_OsVersionInfoEx *os_version;
2008 const char *os_version_str;
2010 os_version = &r->in.query->workstation_info->os_version.os->os;
2012 if (os_version->CSDVersion == NULL) {
2013 return NT_STATUS_INVALID_PARAMETER;
2016 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
2017 os_version->MajorVersion,
2018 os_version->MinorVersion,
2019 os_version->BuildNumber);
2020 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
2022 ret = ldb_msg_add_string(new_msg,
2023 "operatingSystemServicePack",
2024 os_version->CSDVersion);
2025 if (ret != LDB_SUCCESS) {
2026 return NT_STATUS_NO_MEMORY;
2029 ret = ldb_msg_add_string(new_msg,
2030 "operatingSystemVersion",
2031 os_version_str);
2032 if (ret != LDB_SUCCESS) {
2033 return NT_STATUS_NO_MEMORY;
2035 } else {
2036 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2037 "operatingSystemServicePack");
2038 if (ret != LDB_SUCCESS) {
2039 return NT_STATUS_NO_MEMORY;
2042 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
2043 "operatingSystemVersion");
2044 if (ret != LDB_SUCCESS) {
2045 return NT_STATUS_NO_MEMORY;
2050 * If the boolean "update_dns_hostname" remained true, then we
2051 * are fine to start the update.
2053 if (update_dns_hostname) {
2054 ret = ldb_msg_add_string(new_msg,
2055 "dNSHostname",
2056 r->in.query->workstation_info->dns_hostname);
2057 if (ret != LDB_SUCCESS) {
2058 return NT_STATUS_NO_MEMORY;
2061 /* This manual "servicePrincipalName" generation is
2062 * still needed! Since the update in the samldb LDB
2063 * module does only work if the entries already exist
2064 * which isn't always the case. */
2065 ret = ldb_msg_add_string(new_msg,
2066 "servicePrincipalName",
2067 talloc_asprintf(new_msg, "HOST/%s",
2068 r->in.computer_name));
2069 if (ret != LDB_SUCCESS) {
2070 return NT_STATUS_NO_MEMORY;
2073 ret = ldb_msg_add_string(new_msg,
2074 "servicePrincipalName",
2075 talloc_asprintf(new_msg, "HOST/%s",
2076 r->in.query->workstation_info->dns_hostname));
2077 if (ret != LDB_SUCCESS) {
2078 return NT_STATUS_NO_MEMORY;
2082 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
2083 DEBUG(3,("Impossible to update samdb: %s\n",
2084 ldb_errstring(sam_ctx)));
2087 talloc_free(new_msg);
2089 /* Writes back the domain information */
2091 /* We need to do two searches. The first will pull our primary
2092 domain and the second will pull any trusted domains. Our
2093 primary domain is also a "trusted" domain, so we need to
2094 put the primary domain into the lists of returned trusts as
2095 well. */
2096 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
2097 &res2, attrs);
2098 if (ret != 1) {
2099 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2102 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
2103 "(objectClass=trustedDomain)");
2104 if (ret3 == -1) {
2105 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2108 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
2109 NT_STATUS_HAVE_NO_MEMORY(domain_info);
2111 ZERO_STRUCTP(domain_info);
2113 /* Informations about the local and trusted domains */
2115 status = fill_one_domain_info(mem_ctx,
2116 dce_call->conn->dce_ctx->lp_ctx,
2117 sam_ctx, res2[0], &domain_info->primary_domain,
2118 true, false);
2119 NT_STATUS_NOT_OK_RETURN(status);
2121 domain_info->trusted_domain_count = ret3 + 1;
2122 domain_info->trusted_domains = talloc_array(mem_ctx,
2123 struct netr_OneDomainInfo,
2124 domain_info->trusted_domain_count);
2125 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
2127 for (i=0;i<ret3;i++) {
2128 status = fill_one_domain_info(mem_ctx,
2129 dce_call->conn->dce_ctx->lp_ctx,
2130 sam_ctx, res3[i],
2131 &domain_info->trusted_domains[i],
2132 false, true);
2133 NT_STATUS_NOT_OK_RETURN(status);
2136 status = fill_one_domain_info(mem_ctx,
2137 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
2138 &domain_info->trusted_domains[i], true, true);
2139 NT_STATUS_NOT_OK_RETURN(status);
2141 /* Sets the supported encryption types */
2142 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
2143 "msDS-SupportedEncryptionTypes",
2144 default_supported_enc_types);
2146 /* Other host domain information */
2148 lsa_policy_info = talloc(mem_ctx,
2149 struct netr_LsaPolicyInformation);
2150 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2151 ZERO_STRUCTP(lsa_policy_info);
2153 domain_info->lsa_policy = *lsa_policy_info;
2155 /* The DNS hostname is only returned back when there is a chance
2156 * for a change. */
2157 if ((r->in.query->workstation_info->workstation_flags
2158 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
2159 domain_info->dns_hostname.string = old_dns_hostname;
2160 } else {
2161 domain_info->dns_hostname.string = NULL;
2164 domain_info->workstation_flags =
2165 r->in.query->workstation_info->workstation_flags & (
2166 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
2168 r->out.info->domain_info = domain_info;
2169 break;
2170 case 2: /* LSA policy information - not used at the moment */
2171 lsa_policy_info = talloc(mem_ctx,
2172 struct netr_LsaPolicyInformation);
2173 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
2174 ZERO_STRUCTP(lsa_policy_info);
2176 r->out.info->lsa_policy_info = lsa_policy_info;
2177 break;
2178 default:
2179 return NT_STATUS_INVALID_LEVEL;
2180 break;
2183 return NT_STATUS_OK;
2188 netr_ServerPasswordGet
2190 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2191 struct netr_ServerPasswordGet *r)
2193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2198 netr_NETRLOGONSENDTOSAM
2200 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201 struct netr_NETRLOGONSENDTOSAM *r)
2203 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2208 netr_DsRGetDCNameEx2
2210 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
2211 TALLOC_CTX *mem_ctx,
2212 struct netr_DsRGetDCNameEx2 *r)
2214 struct ldb_context *sam_ctx;
2215 struct netr_DsRGetDCNameInfo *info;
2216 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2217 const struct tsocket_address *local_address;
2218 char *local_addr = NULL;
2219 const struct tsocket_address *remote_address;
2220 char *remote_addr = NULL;
2221 const char *server_site_name;
2222 char *guid_str;
2223 struct netlogon_samlogon_response response;
2224 NTSTATUS status;
2225 const char *dc_name = NULL;
2226 const char *domain_name = NULL;
2227 const char *pdc_ip;
2229 ZERO_STRUCTP(r->out.info);
2231 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2232 dce_call->conn->auth_state.session_info, 0);
2233 if (sam_ctx == NULL) {
2234 return WERR_DS_UNAVAILABLE;
2237 local_address = dcesrv_connection_get_local_address(dce_call->conn);
2238 if (tsocket_address_is_inet(local_address, "ip")) {
2239 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
2240 W_ERROR_HAVE_NO_MEMORY(local_addr);
2243 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
2244 if (tsocket_address_is_inet(remote_address, "ip")) {
2245 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
2246 W_ERROR_HAVE_NO_MEMORY(remote_addr);
2249 /* "server_unc" is ignored by w2k3 */
2251 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
2252 return WERR_INVALID_FLAGS;
2255 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
2256 r->in.flags & DS_PDC_REQUIRED &&
2257 r->in.flags & DS_KDC_REQUIRED) {
2258 return WERR_INVALID_FLAGS;
2260 if (r->in.flags & DS_IS_FLAT_NAME &&
2261 r->in.flags & DS_IS_DNS_NAME) {
2262 return WERR_INVALID_FLAGS;
2264 if (r->in.flags & DS_RETURN_DNS_NAME &&
2265 r->in.flags & DS_RETURN_FLAT_NAME) {
2266 return WERR_INVALID_FLAGS;
2268 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
2269 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
2270 return WERR_INVALID_FLAGS;
2273 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
2274 r->in.flags &
2275 (DS_DIRECTORY_SERVICE_REQUIRED |
2276 DS_DIRECTORY_SERVICE_PREFERRED |
2277 DS_GC_SERVER_REQUIRED |
2278 DS_PDC_REQUIRED |
2279 DS_KDC_REQUIRED)) {
2280 return WERR_INVALID_FLAGS;
2283 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
2284 r->in.site_name) {
2285 return WERR_INVALID_FLAGS;
2288 /* Proof server site parameter "site_name" if it was specified */
2289 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
2290 W_ERROR_HAVE_NO_MEMORY(server_site_name);
2291 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
2292 server_site_name) != 0)) {
2293 return WERR_NO_SUCH_DOMAIN;
2296 guid_str = r->in.domain_guid != NULL ?
2297 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2299 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2300 r->in.domain_name,
2301 r->in.domain_name,
2302 NULL, guid_str,
2303 r->in.client_account,
2304 r->in.mask, remote_addr,
2305 NETLOGON_NT_VERSION_5EX_WITH_IP,
2306 lp_ctx, &response, true);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 return ntstatus_to_werror(status);
2312 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2313 * (O) flag when the returned forest name is in DNS format. This is here
2314 * always the case (see below).
2316 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2318 if (r->in.flags & DS_RETURN_DNS_NAME) {
2319 dc_name = response.data.nt5_ex.pdc_dns_name;
2320 domain_name = response.data.nt5_ex.dns_domain;
2322 * According to MS-NRPC 2.2.1.2.1 we should set the
2323 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2324 * the returned information is in DNS form.
2326 response.data.nt5_ex.server_type |=
2327 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2328 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2329 dc_name = response.data.nt5_ex.pdc_name;
2330 domain_name = response.data.nt5_ex.domain_name;
2331 } else {
2334 * TODO: autodetect what we need to return
2335 * based on the given arguments
2337 dc_name = response.data.nt5_ex.pdc_name;
2338 domain_name = response.data.nt5_ex.domain_name;
2341 if (!dc_name || !dc_name[0]) {
2342 return WERR_NO_SUCH_DOMAIN;
2345 if (!domain_name || !domain_name[0]) {
2346 return WERR_NO_SUCH_DOMAIN;
2349 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2350 W_ERROR_HAVE_NO_MEMORY(info);
2351 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2352 dc_name[0] != '\\'? "\\\\":"",
2353 talloc_strdup(mem_ctx, dc_name));
2354 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2356 pdc_ip = local_addr;
2357 if (pdc_ip == NULL) {
2358 pdc_ip = "127.0.0.1";
2360 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2361 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2362 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2363 info->domain_guid = response.data.nt5_ex.domain_uuid;
2364 info->domain_name = domain_name;
2365 info->forest_name = response.data.nt5_ex.forest;
2366 info->dc_flags = response.data.nt5_ex.server_type;
2367 if (r->in.flags & DS_RETURN_DNS_NAME) {
2368 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2369 * returned if we are returning info->dc_unc containing a FQDN.
2370 * This attribute is called DomainControllerName in the specs,
2371 * it seems that we decide to return FQDN or netbios depending on
2372 * DS_RETURN_DNS_NAME.
2374 info->dc_flags |= DS_DNS_CONTROLLER;
2376 info->dc_site_name = response.data.nt5_ex.server_site;
2377 info->client_site_name = response.data.nt5_ex.client_site;
2379 *r->out.info = info;
2381 return WERR_OK;
2385 netr_DsRGetDCNameEx
2387 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2388 struct netr_DsRGetDCNameEx *r)
2390 struct netr_DsRGetDCNameEx2 r2;
2391 WERROR werr;
2393 ZERO_STRUCT(r2);
2395 r2.in.server_unc = r->in.server_unc;
2396 r2.in.client_account = NULL;
2397 r2.in.mask = 0;
2398 r2.in.domain_guid = r->in.domain_guid;
2399 r2.in.domain_name = r->in.domain_name;
2400 r2.in.site_name = r->in.site_name;
2401 r2.in.flags = r->in.flags;
2402 r2.out.info = r->out.info;
2404 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2406 return werr;
2410 netr_DsRGetDCName
2412 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2413 struct netr_DsRGetDCName *r)
2415 struct netr_DsRGetDCNameEx2 r2;
2416 WERROR werr;
2418 ZERO_STRUCT(r2);
2420 r2.in.server_unc = r->in.server_unc;
2421 r2.in.client_account = NULL;
2422 r2.in.mask = 0;
2423 r2.in.domain_name = r->in.domain_name;
2424 r2.in.domain_guid = r->in.domain_guid;
2426 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2427 r2.in.flags = r->in.flags;
2428 r2.out.info = r->out.info;
2430 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2432 return werr;
2435 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2437 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2438 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2440 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2445 netr_NetrEnumerateTrustedDomainsEx
2447 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2448 struct netr_NetrEnumerateTrustedDomainsEx *r)
2450 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2455 netr_DsRAddressToSitenamesExW
2457 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2458 struct netr_DsRAddressToSitenamesExW *r)
2460 struct ldb_context *sam_ctx;
2461 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2462 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2463 sa_family_t sin_family;
2464 struct sockaddr_in *addr;
2465 #ifdef HAVE_IPV6
2466 struct sockaddr_in6 *addr6;
2467 char addr_str[INET6_ADDRSTRLEN];
2468 #else
2469 char addr_str[INET_ADDRSTRLEN];
2470 #endif
2471 char *subnet_name;
2472 const char *res;
2473 uint32_t i;
2475 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2476 dce_call->conn->auth_state.session_info, 0);
2477 if (sam_ctx == NULL) {
2478 return WERR_DS_UNAVAILABLE;
2481 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2482 W_ERROR_HAVE_NO_MEMORY(ctr);
2484 *r->out.ctr = ctr;
2486 ctr->count = r->in.count;
2487 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2488 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2489 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2490 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2492 for (i=0; i<ctr->count; i++) {
2493 ctr->sitename[i].string = NULL;
2494 ctr->subnetname[i].string = NULL;
2496 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2497 continue;
2499 /* The first two byte of the buffer are reserved for the
2500 * "sin_family" but for now only the first one is used. */
2501 sin_family = r->in.addresses[i].buffer[0];
2503 switch (sin_family) {
2504 case AF_INET:
2505 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2506 continue;
2508 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2509 res = inet_ntop(AF_INET, &addr->sin_addr,
2510 addr_str, sizeof(addr_str));
2511 break;
2512 #ifdef HAVE_IPV6
2513 case AF_INET6:
2514 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2515 continue;
2517 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2518 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2519 addr_str, sizeof(addr_str));
2520 break;
2521 #endif
2522 default:
2523 continue;
2526 if (res == NULL) {
2527 continue;
2530 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2531 mem_ctx,
2532 addr_str,
2533 &subnet_name);
2534 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2535 ctr->subnetname[i].string = subnet_name;
2538 return WERR_OK;
2543 netr_DsRAddressToSitenamesW
2545 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2546 struct netr_DsRAddressToSitenamesW *r)
2548 struct netr_DsRAddressToSitenamesExW r2;
2549 struct netr_DsRAddressToSitenamesWCtr *ctr;
2550 uint32_t i;
2551 WERROR werr;
2553 ZERO_STRUCT(r2);
2555 r2.in.server_name = r->in.server_name;
2556 r2.in.count = r->in.count;
2557 r2.in.addresses = r->in.addresses;
2559 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2560 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2562 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2563 W_ERROR_HAVE_NO_MEMORY(ctr);
2565 *r->out.ctr = ctr;
2567 ctr->count = r->in.count;
2568 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2569 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2571 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2573 for (i=0; i<ctr->count; i++) {
2574 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2577 return werr;
2582 netr_DsrGetDcSiteCoverageW
2584 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2585 struct netr_DsrGetDcSiteCoverageW *r)
2587 struct ldb_context *sam_ctx;
2588 struct DcSitesCtr *ctr;
2589 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2591 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2592 dce_call->conn->auth_state.session_info, 0);
2593 if (sam_ctx == NULL) {
2594 return WERR_DS_UNAVAILABLE;
2597 ctr = talloc(mem_ctx, struct DcSitesCtr);
2598 W_ERROR_HAVE_NO_MEMORY(ctr);
2600 *r->out.ctr = ctr;
2602 /* For now only return our default site */
2603 ctr->num_sites = 1;
2604 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2605 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2606 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2607 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2609 return WERR_OK;
2613 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2614 struct ldb_context *sam_ctx,
2615 struct netr_DomainTrustList *trusts,
2616 uint32_t trust_flags)
2618 struct ldb_dn *system_dn;
2619 struct ldb_message **dom_res = NULL;
2620 const char *trust_attrs[] = { "flatname", "trustPartner",
2621 "securityIdentifier", "trustDirection",
2622 "trustType", "trustAttributes", NULL };
2623 uint32_t n;
2624 int i;
2625 int ret;
2627 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2628 NETR_TRUST_FLAG_OUTBOUND))) {
2629 return WERR_INVALID_FLAGS;
2632 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2633 ldb_get_default_basedn(sam_ctx),
2634 "(&(objectClass=container)(cn=System))");
2635 if (!system_dn) {
2636 return WERR_GENERAL_FAILURE;
2639 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2640 &dom_res, trust_attrs,
2641 "(objectclass=trustedDomain)");
2643 for (i = 0; i < ret; i++) {
2644 unsigned int trust_dir;
2645 uint32_t flags = 0;
2647 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2648 "trustDirection", 0);
2650 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2651 flags |= NETR_TRUST_FLAG_INBOUND;
2653 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2654 flags |= NETR_TRUST_FLAG_OUTBOUND;
2657 if (!(flags & trust_flags)) {
2658 /* this trust direction was not requested */
2659 continue;
2662 n = trusts->count;
2663 trusts->array = talloc_realloc(trusts, trusts->array,
2664 struct netr_DomainTrust,
2665 n + 1);
2666 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2668 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2669 if (!trusts->array[n].netbios_name) {
2670 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2671 "without flatname\n",
2672 ldb_dn_get_linearized(dom_res[i]->dn)));
2675 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2677 trusts->array[n].trust_flags = flags;
2678 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2679 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2680 /* TODO: find if we have parent in the list */
2681 trusts->array[n].parent_index = 0;
2684 trusts->array[n].trust_type =
2685 ldb_msg_find_attr_as_uint(dom_res[i],
2686 "trustType", 0);
2687 trusts->array[n].trust_attributes =
2688 ldb_msg_find_attr_as_uint(dom_res[i],
2689 "trustAttributes", 0);
2691 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2692 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2693 struct dom_sid zero_sid;
2694 ZERO_STRUCT(zero_sid);
2695 trusts->array[n].sid =
2696 dom_sid_dup(trusts, &zero_sid);
2697 } else {
2698 trusts->array[n].sid =
2699 samdb_result_dom_sid(trusts, dom_res[i],
2700 "securityIdentifier");
2702 trusts->array[n].guid = GUID_zero();
2704 trusts->count = n + 1;
2707 talloc_free(dom_res);
2708 return WERR_OK;
2712 netr_DsrEnumerateDomainTrusts
2714 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2715 TALLOC_CTX *mem_ctx,
2716 struct netr_DsrEnumerateDomainTrusts *r)
2718 struct netr_DomainTrustList *trusts;
2719 struct ldb_context *sam_ctx;
2720 int ret;
2721 struct ldb_message **dom_res;
2722 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2723 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2724 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2725 const char *p;
2726 WERROR werr;
2728 if (r->in.trust_flags & 0xFFFFFE00) {
2729 return WERR_INVALID_FLAGS;
2732 /* TODO: turn to hard check once we are sure this is 100% correct */
2733 if (!r->in.server_name) {
2734 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2735 "But received NULL!\n", dnsdomain));
2736 } else {
2737 p = strchr(r->in.server_name, '.');
2738 if (!p) {
2739 DEBUG(3, ("Invalid domain! Expected name in domain "
2740 "[%s]. But received [%s]!\n",
2741 dnsdomain, r->in.server_name));
2742 p = r->in.server_name;
2743 } else {
2744 p++;
2746 if (strcasecmp(p, dnsdomain)) {
2747 DEBUG(3, ("Invalid domain! Expected name in domain "
2748 "[%s]. But received [%s]!\n",
2749 dnsdomain, r->in.server_name));
2753 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2754 W_ERROR_HAVE_NO_MEMORY(trusts);
2756 trusts->count = 0;
2757 r->out.trusts = trusts;
2759 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2760 dce_call->conn->auth_state.session_info, 0);
2761 if (sam_ctx == NULL) {
2762 return WERR_GENERAL_FAILURE;
2765 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2766 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2768 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2769 trusts, r->in.trust_flags);
2770 W_ERROR_NOT_OK_RETURN(werr);
2773 /* NOTE: we currently are always the root of the forest */
2774 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2775 uint32_t n = trusts->count;
2777 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2778 &dom_res, dom_attrs);
2779 if (ret != 1) {
2780 return WERR_GENERAL_FAILURE;
2783 trusts->count = n + 1;
2784 trusts->array = talloc_realloc(trusts, trusts->array,
2785 struct netr_DomainTrust,
2786 trusts->count);
2787 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2789 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2790 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2791 trusts->array[n].trust_flags =
2792 NETR_TRUST_FLAG_NATIVE |
2793 NETR_TRUST_FLAG_TREEROOT |
2794 NETR_TRUST_FLAG_IN_FOREST |
2795 NETR_TRUST_FLAG_PRIMARY;
2796 /* we are always the root domain for now */
2797 trusts->array[n].parent_index = 0;
2798 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2799 trusts->array[n].trust_attributes = 0;
2800 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2801 dom_res[0],
2802 "objectSid");
2803 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2804 "objectGUID");
2805 talloc_free(dom_res);
2808 return WERR_OK;
2813 netr_DsrDeregisterDNSHostRecords
2815 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2816 struct netr_DsrDeregisterDNSHostRecords *r)
2818 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2822 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2823 struct netr_ServerGetTrustInfo *r);
2826 netr_ServerTrustPasswordsGet
2828 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2829 struct netr_ServerTrustPasswordsGet *r)
2831 struct netr_ServerGetTrustInfo r2 = {};
2832 struct netr_TrustInfo *_ti = NULL;
2833 NTSTATUS status;
2835 r2.in.server_name = r->in.server_name;
2836 r2.in.account_name = r->in.account_name;
2837 r2.in.secure_channel_type = r->in.secure_channel_type;
2838 r2.in.computer_name = r->in.computer_name;
2839 r2.in.credential = r->in.credential;
2841 r2.out.return_authenticator = r->out.return_authenticator;
2842 r2.out.new_owf_password = r->out.new_owf_password;
2843 r2.out.old_owf_password = r->out.old_owf_password;
2844 r2.out.trust_info = &_ti;
2846 status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
2848 r->out.return_authenticator = r2.out.return_authenticator;
2849 r->out.new_owf_password = r2.out.new_owf_password;
2850 r->out.old_owf_password = r2.out.old_owf_password;
2852 return status;
2856 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2857 struct ldb_context *sam_ctx,
2858 struct loadparm_context *lp_ctx,
2859 struct lsa_ForestTrustInformation *info)
2861 struct lsa_ForestTrustDomainInfo *domain_info;
2862 struct lsa_ForestTrustRecord *e;
2863 struct ldb_message **dom_res;
2864 const char * const dom_attrs[] = { "objectSid", NULL };
2865 int ret;
2867 /* we need to provide 2 entries:
2868 * 1. the Root Forest name
2869 * 2. the Domain Information
2872 info->count = 2;
2873 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2874 W_ERROR_HAVE_NO_MEMORY(info->entries);
2876 /* Forest root info */
2877 e = talloc(info, struct lsa_ForestTrustRecord);
2878 W_ERROR_HAVE_NO_MEMORY(e);
2880 e->flags = 0;
2881 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2882 e->time = 0; /* so far always 0 in trces. */
2883 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2884 mem_ctx);
2885 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2887 info->entries[0] = e;
2889 /* Domain info */
2890 e = talloc(info, struct lsa_ForestTrustRecord);
2891 W_ERROR_HAVE_NO_MEMORY(e);
2893 /* get our own domain info */
2894 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2895 if (ret != 1) {
2896 return WERR_GENERAL_FAILURE;
2899 /* TODO: check if disabled and set flags accordingly */
2900 e->flags = 0;
2901 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2902 e->time = 0; /* so far always 0 in traces. */
2904 domain_info = &e->forest_trust_data.domain_info;
2905 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2906 "objectSid");
2907 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2908 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2910 info->entries[1] = e;
2912 talloc_free(dom_res);
2914 return WERR_OK;
2918 netr_DsRGetForestTrustInformation
2920 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2921 TALLOC_CTX *mem_ctx,
2922 struct netr_DsRGetForestTrustInformation *r)
2924 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2925 struct lsa_ForestTrustInformation *info, **info_ptr;
2926 struct ldb_context *sam_ctx;
2927 WERROR werr;
2929 if (r->in.flags & 0xFFFFFFFE) {
2930 return WERR_INVALID_FLAGS;
2933 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2934 dce_call->conn->auth_state.session_info, 0);
2935 if (sam_ctx == NULL) {
2936 return WERR_GENERAL_FAILURE;
2939 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2940 if (!samdb_is_pdc(sam_ctx)) {
2941 return WERR_NERR_NOTPRIMARY;
2944 if (r->in.trusted_domain_name == NULL) {
2945 return WERR_INVALID_FLAGS;
2948 /* TODO: establish an schannel connection with
2949 * r->in.trusted_domain_name and perform a
2950 * netr_GetForestTrustInformation call against it */
2952 /* for now return not implementd */
2953 return WERR_CALL_NOT_IMPLEMENTED;
2956 /* TODO: check r->in.server_name is our name */
2958 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2959 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2961 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2962 W_ERROR_HAVE_NO_MEMORY(info);
2964 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2965 W_ERROR_NOT_OK_RETURN(werr);
2967 *info_ptr = info;
2968 r->out.forest_trust_info = info_ptr;
2970 return WERR_OK;
2975 netr_GetForestTrustInformation
2977 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2978 TALLOC_CTX *mem_ctx,
2979 struct netr_GetForestTrustInformation *r)
2981 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2982 struct netlogon_creds_CredentialState *creds;
2983 struct lsa_ForestTrustInformation *info, **info_ptr;
2984 struct ldb_context *sam_ctx;
2985 NTSTATUS status;
2986 WERROR werr;
2988 status = dcesrv_netr_creds_server_step_check(dce_call,
2989 mem_ctx,
2990 r->in.computer_name,
2991 r->in.credential,
2992 r->out.return_authenticator,
2993 &creds);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 return status;
2998 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2999 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
3000 return NT_STATUS_NOT_IMPLEMENTED;
3003 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
3004 dce_call->conn->auth_state.session_info, 0);
3005 if (sam_ctx == NULL) {
3006 return NT_STATUS_INTERNAL_ERROR;
3009 /* TODO: check r->in.server_name is our name */
3011 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
3012 if (!info_ptr) {
3013 return NT_STATUS_NO_MEMORY;
3015 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
3016 if (!info) {
3017 return NT_STATUS_NO_MEMORY;
3020 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
3021 if (!W_ERROR_IS_OK(werr)) {
3022 return werror_to_ntstatus(werr);
3025 *info_ptr = info;
3026 r->out.forest_trust_info = info_ptr;
3028 return NT_STATUS_OK;
3033 netr_ServerGetTrustInfo
3035 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3036 struct netr_ServerGetTrustInfo *r)
3038 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
3039 struct netlogon_creds_CredentialState *creds = NULL;
3040 struct ldb_context *sam_ctx = NULL;
3041 const char * const attrs[] = {
3042 "unicodePwd",
3043 "sAMAccountName",
3044 "userAccountControl",
3045 NULL
3047 struct ldb_message **res = NULL;
3048 struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
3049 NTSTATUS nt_status;
3050 int ret;
3051 const char *asid = NULL;
3052 uint32_t uac = 0;
3053 const char *aname = NULL;
3054 struct ldb_message *tdo_msg = NULL;
3055 const char * const tdo_attrs[] = {
3056 "trustAuthIncoming",
3057 "trustAttributes",
3058 NULL
3060 struct netr_TrustInfo *trust_info = NULL;
3062 ZERO_STRUCTP(r->out.new_owf_password);
3063 ZERO_STRUCTP(r->out.old_owf_password);
3065 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3066 mem_ctx,
3067 r->in.computer_name,
3068 r->in.credential,
3069 r->out.return_authenticator,
3070 &creds);
3071 if (!NT_STATUS_IS_OK(nt_status)) {
3072 return nt_status;
3075 /* TODO: check r->in.server_name is our name */
3077 if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
3078 return NT_STATUS_INVALID_PARAMETER;
3081 if (r->in.secure_channel_type != creds->secure_channel_type) {
3082 return NT_STATUS_INVALID_PARAMETER;
3085 if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
3086 return NT_STATUS_INVALID_PARAMETER;
3089 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
3090 lp_ctx, system_session(lp_ctx), 0);
3091 if (sam_ctx == NULL) {
3092 return NT_STATUS_INVALID_SYSTEM_SERVICE;
3095 asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
3096 if (asid == NULL) {
3097 return NT_STATUS_NO_MEMORY;
3100 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
3101 "(&(objectClass=user)(objectSid=%s))",
3102 asid);
3103 if (ret != 1) {
3104 return NT_STATUS_ACCOUNT_DISABLED;
3107 switch (creds->secure_channel_type) {
3108 case SEC_CHAN_DNS_DOMAIN:
3109 case SEC_CHAN_DOMAIN:
3110 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
3112 if (uac & UF_ACCOUNTDISABLE) {
3113 return NT_STATUS_ACCOUNT_DISABLED;
3116 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3117 return NT_STATUS_ACCOUNT_DISABLED;
3120 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
3121 if (aname == NULL) {
3122 return NT_STATUS_ACCOUNT_DISABLED;
3125 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
3126 SEC_CHAN_DOMAIN, aname,
3127 tdo_attrs, mem_ctx, &tdo_msg);
3128 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3129 return NT_STATUS_ACCOUNT_DISABLED;
3131 if (!NT_STATUS_IS_OK(nt_status)) {
3132 return nt_status;
3135 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
3136 &curNtHash,
3137 &prevNtHash);
3138 if (!NT_STATUS_IS_OK(nt_status)) {
3139 return nt_status;
3142 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
3143 if (trust_info == NULL) {
3144 return NT_STATUS_NO_MEMORY;
3147 trust_info->count = 1;
3148 trust_info->data = talloc_array(trust_info, uint32_t,
3149 trust_info->count);
3150 if (trust_info->data == NULL) {
3151 return NT_STATUS_NO_MEMORY;
3154 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
3155 "trustAttributes",
3157 break;
3159 default:
3160 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
3161 res[0],
3162 NULL, &curNtHash);
3163 if (!NT_STATUS_IS_OK(nt_status)) {
3164 return nt_status;
3167 prevNtHash = talloc(mem_ctx, struct samr_Password);
3168 if (prevNtHash == NULL) {
3169 return NT_STATUS_NO_MEMORY;
3172 E_md4hash("", prevNtHash->hash);
3173 break;
3176 if (curNtHash != NULL) {
3177 *r->out.new_owf_password = *curNtHash;
3178 netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
3180 if (prevNtHash != NULL) {
3181 *r->out.old_owf_password = *prevNtHash;
3182 netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
3185 if (trust_info != NULL) {
3186 *r->out.trust_info = trust_info;
3189 return NT_STATUS_OK;
3193 netr_Unused47
3195 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3196 struct netr_Unused47 *r)
3198 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3202 struct netr_dnsupdate_RODC_state {
3203 struct dcesrv_call_state *dce_call;
3204 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
3205 struct dnsupdate_RODC *r2;
3209 called when the forwarded RODC dns update request is finished
3211 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
3213 struct netr_dnsupdate_RODC_state *st =
3214 tevent_req_callback_data(subreq,
3215 struct netr_dnsupdate_RODC_state);
3216 NTSTATUS status;
3218 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
3219 TALLOC_FREE(subreq);
3220 if (!NT_STATUS_IS_OK(status)) {
3221 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
3222 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3225 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
3227 status = dcesrv_reply(st->dce_call);
3228 if (!NT_STATUS_IS_OK(status)) {
3229 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
3234 netr_DsrUpdateReadOnlyServerDnsRecords
3236 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
3237 TALLOC_CTX *mem_ctx,
3238 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
3240 struct netlogon_creds_CredentialState *creds;
3241 NTSTATUS nt_status;
3242 struct dcerpc_binding_handle *binding_handle;
3243 struct netr_dnsupdate_RODC_state *st;
3244 struct tevent_req *subreq;
3246 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
3247 mem_ctx,
3248 r->in.computer_name,
3249 r->in.credential,
3250 r->out.return_authenticator,
3251 &creds);
3252 NT_STATUS_NOT_OK_RETURN(nt_status);
3254 if (creds->secure_channel_type != SEC_CHAN_RODC) {
3255 return NT_STATUS_ACCESS_DENIED;
3258 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
3259 NT_STATUS_HAVE_NO_MEMORY(st);
3261 st->dce_call = dce_call;
3262 st->r = r;
3263 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
3264 NT_STATUS_HAVE_NO_MEMORY(st->r2);
3266 st->r2->in.dom_sid = creds->sid;
3267 st->r2->in.site_name = r->in.site_name;
3268 st->r2->in.dns_ttl = r->in.dns_ttl;
3269 st->r2->in.dns_names = r->in.dns_names;
3270 st->r2->out.dns_names = r->out.dns_names;
3272 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
3273 "dnsupdate", &ndr_table_irpc);
3274 if (binding_handle == NULL) {
3275 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
3276 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
3277 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3280 /* forward the call */
3281 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
3282 binding_handle, st->r2);
3283 NT_STATUS_HAVE_NO_MEMORY(subreq);
3285 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
3287 /* setup the callback */
3288 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
3290 return NT_STATUS_OK;
3294 /* include the generated boilerplate */
3295 #include "librpc/gen_ndr/ndr_netlogon_s.c"