swrap: Wrap fopen to detect stale file descriptors.
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobc5740f65c8c3b59094b64d32666ae4639805b851
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_irpc.h"
42 #include "lib/socket/netif.h"
44 static struct memcache *global_challenge_table;
46 struct netlogon_server_pipe_state {
47 struct netr_Credential client_challenge;
48 struct netr_Credential server_challenge;
51 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
52 struct netr_ServerReqChallenge *r)
54 struct netlogon_server_pipe_state *pipe_state =
55 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
56 DATA_BLOB key, val;
58 ZERO_STRUCTP(r->out.return_credentials);
60 if (global_challenge_table == NULL) {
62 * We maintain a global challenge table
63 * with a fixed size (8k)
65 * This is required for the strange clients
66 * which use different connections for
67 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
70 global_challenge_table = memcache_init(talloc_autofree_context(),
71 8192);
72 if (global_challenge_table == NULL) {
73 return NT_STATUS_NO_MEMORY;
77 /* destroyed on pipe shutdown */
79 if (pipe_state) {
80 talloc_free(pipe_state);
81 dce_call->context->private_data = NULL;
84 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
85 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
87 pipe_state->client_challenge = *r->in.credentials;
89 generate_random_buffer(pipe_state->server_challenge.data,
90 sizeof(pipe_state->server_challenge.data));
92 *r->out.return_credentials = pipe_state->server_challenge;
94 dce_call->context->private_data = pipe_state;
96 key = data_blob_string_const(r->in.computer_name);
97 val = data_blob_const(pipe_state, sizeof(*pipe_state));
99 memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
101 return NT_STATUS_OK;
104 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
105 struct netr_ServerAuthenticate3 *r)
107 struct netlogon_server_pipe_state *pipe_state =
108 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
109 DATA_BLOB challenge_key;
110 bool challenge_valid = false;
111 struct netlogon_server_pipe_state challenge;
112 struct netlogon_creds_CredentialState *creds;
113 struct ldb_context *sam_ctx;
114 struct samr_Password *mach_pwd;
115 uint32_t user_account_control;
116 int num_records;
117 struct ldb_message **msgs;
118 NTSTATUS nt_status;
119 const char *attrs[] = {"unicodePwd", "userAccountControl",
120 "objectSid", NULL};
122 const char *trust_dom_attrs[] = {"flatname", NULL};
123 const char *account_name;
124 uint32_t server_flags = 0;
125 uint32_t negotiate_flags = 0;
126 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
127 bool reject_des_client = !allow_nt4_crypto;
128 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
130 ZERO_STRUCTP(r->out.return_credentials);
131 *r->out.rid = 0;
133 challenge_key = data_blob_string_const(r->in.computer_name);
134 if (pipe_state != NULL) {
135 dce_call->context->private_data = NULL;
138 * If we had a challenge remembered on the connection
139 * consider this for usage. This can't be cleanup
140 * by other clients.
142 * This is the default code path for typical clients
143 * which call netr_ServerReqChallenge() and
144 * netr_ServerAuthenticate3() on the same dcerpc connection.
146 challenge = *pipe_state;
147 TALLOC_FREE(pipe_state);
148 challenge_valid = true;
149 } else {
150 DATA_BLOB val;
151 bool ok;
154 * Fallback and try to get the challenge from
155 * the global cache.
157 * If too many clients are using this code path,
158 * they may destroy their cache entries as the
159 * global_challenge_table memcache has a fixed size.
161 * Note: this handles global_challenge_table == NULL fine
163 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
164 challenge_key, &val);
165 if (ok && val.length == sizeof(challenge)) {
166 memcpy(&challenge, val.data, sizeof(challenge));
167 challenge_valid = true;
168 } else {
169 ZERO_STRUCT(challenge);
174 * At this point we can cleanup the cache entry,
175 * if we fail the client needs to call netr_ServerReqChallenge
176 * again.
178 * Note: this handles global_challenge_table == NULL
179 * and also a non existing record just fine.
181 memcache_delete(global_challenge_table,
182 SINGLETON_CACHE, challenge_key);
184 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
185 NETLOGON_NEG_PERSISTENT_SAMREPL |
186 NETLOGON_NEG_ARCFOUR |
187 NETLOGON_NEG_PROMOTION_COUNT |
188 NETLOGON_NEG_CHANGELOG_BDC |
189 NETLOGON_NEG_FULL_SYNC_REPL |
190 NETLOGON_NEG_MULTIPLE_SIDS |
191 NETLOGON_NEG_REDO |
192 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
193 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
194 NETLOGON_NEG_GENERIC_PASSTHROUGH |
195 NETLOGON_NEG_CONCURRENT_RPC |
196 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
197 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
198 NETLOGON_NEG_STRONG_KEYS |
199 NETLOGON_NEG_TRANSITIVE_TRUSTS |
200 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
201 NETLOGON_NEG_PASSWORD_SET2 |
202 NETLOGON_NEG_GETDOMAININFO |
203 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
204 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
205 NETLOGON_NEG_RODC_PASSTHROUGH |
206 NETLOGON_NEG_SUPPORTS_AES |
207 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
208 NETLOGON_NEG_AUTHENTICATED_RPC;
210 negotiate_flags = *r->in.negotiate_flags & server_flags;
212 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
213 reject_des_client = false;
216 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
217 reject_des_client = false;
218 reject_md5_client = false;
221 if (reject_des_client || reject_md5_client) {
223 * Here we match Windows 2012 and return no flags.
225 *r->out.negotiate_flags = 0;
226 return NT_STATUS_DOWNGRADE_DETECTED;
230 * According to Microsoft (see bugid #6099)
231 * Windows 7 looks at the negotiate_flags
232 * returned in this structure *even if the
233 * call fails with access denied!
235 *r->out.negotiate_flags = negotiate_flags;
237 switch (r->in.secure_channel_type) {
238 case SEC_CHAN_WKSTA:
239 case SEC_CHAN_DNS_DOMAIN:
240 case SEC_CHAN_DOMAIN:
241 case SEC_CHAN_BDC:
242 case SEC_CHAN_RODC:
243 break;
244 case SEC_CHAN_NULL:
245 return NT_STATUS_INVALID_PARAMETER;
246 default:
247 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
248 r->in.secure_channel_type));
249 return NT_STATUS_INVALID_PARAMETER;
252 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
253 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
254 if (sam_ctx == NULL) {
255 return NT_STATUS_INVALID_SYSTEM_SERVICE;
258 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
259 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
260 const char *flatname;
261 if (!encoded_account) {
262 return NT_STATUS_NO_MEMORY;
265 /* Kill the trailing dot */
266 if (encoded_account[strlen(encoded_account)-1] == '.') {
267 encoded_account[strlen(encoded_account)-1] = '\0';
270 /* pull the user attributes */
271 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
272 trust_dom_attrs,
273 "(&(trustPartner=%s)(objectclass=trustedDomain))",
274 encoded_account);
276 if (num_records == 0) {
277 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
278 encoded_account));
279 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
282 if (num_records > 1) {
283 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
284 return NT_STATUS_INTERNAL_DB_CORRUPTION;
287 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
288 if (!flatname) {
289 /* No flatname for this trust - we can't proceed */
290 DEBUG(3,("Couldn't find flatname for trust [%s] in samdb.\n",
291 encoded_account));
292 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
294 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
296 if (!account_name) {
297 return NT_STATUS_NO_MEMORY;
300 } else {
301 account_name = r->in.account_name;
304 /* pull the user attributes */
305 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
306 "(&(sAMAccountName=%s)(objectclass=user))",
307 ldb_binary_encode_string(mem_ctx, account_name));
309 if (num_records == 0) {
310 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
311 r->in.account_name));
312 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
315 if (num_records > 1) {
316 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
317 return NT_STATUS_INTERNAL_DB_CORRUPTION;
320 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
322 if (user_account_control & UF_ACCOUNTDISABLE) {
323 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
324 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
327 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
328 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
329 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
330 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
332 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
333 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
334 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
335 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
337 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
339 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
340 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
341 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
342 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
344 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
345 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
346 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
347 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
349 } else {
350 /* we should never reach this */
351 return NT_STATUS_INTERNAL_ERROR;
354 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
355 if (mach_pwd == NULL) {
356 return NT_STATUS_ACCESS_DENIED;
359 if (!challenge_valid) {
360 DEBUG(1, ("No challenge requested by client [%s/%s], "
361 "cannot authenticate\n",
362 r->in.computer_name,
363 r->in.account_name));
364 return NT_STATUS_ACCESS_DENIED;
367 creds = netlogon_creds_server_init(mem_ctx,
368 r->in.account_name,
369 r->in.computer_name,
370 r->in.secure_channel_type,
371 &challenge.client_challenge,
372 &challenge.server_challenge,
373 mach_pwd,
374 r->in.credentials,
375 r->out.return_credentials,
376 negotiate_flags);
377 if (!creds) {
378 return NT_STATUS_ACCESS_DENIED;
381 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
383 nt_status = schannel_save_creds_state(mem_ctx,
384 dce_call->conn->dce_ctx->lp_ctx,
385 creds);
386 if (!NT_STATUS_IS_OK(nt_status)) {
387 ZERO_STRUCTP(r->out.return_credentials);
388 return nt_status;
391 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
392 "objectSid", 0);
394 return NT_STATUS_OK;
397 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398 struct netr_ServerAuthenticate *r)
400 struct netr_ServerAuthenticate3 a;
401 uint32_t rid;
402 /* TODO:
403 * negotiate_flags is used as an [in] parameter
404 * so it need to be initialised.
406 * (I think ... = 0; seems wrong here --metze)
408 uint32_t negotiate_flags_in = 0;
409 uint32_t negotiate_flags_out = 0;
411 a.in.server_name = r->in.server_name;
412 a.in.account_name = r->in.account_name;
413 a.in.secure_channel_type = r->in.secure_channel_type;
414 a.in.computer_name = r->in.computer_name;
415 a.in.credentials = r->in.credentials;
416 a.in.negotiate_flags = &negotiate_flags_in;
418 a.out.return_credentials = r->out.return_credentials;
419 a.out.rid = &rid;
420 a.out.negotiate_flags = &negotiate_flags_out;
422 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
425 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
426 struct netr_ServerAuthenticate2 *r)
428 struct netr_ServerAuthenticate3 r3;
429 uint32_t rid = 0;
431 r3.in.server_name = r->in.server_name;
432 r3.in.account_name = r->in.account_name;
433 r3.in.secure_channel_type = r->in.secure_channel_type;
434 r3.in.computer_name = r->in.computer_name;
435 r3.in.credentials = r->in.credentials;
436 r3.out.return_credentials = r->out.return_credentials;
437 r3.in.negotiate_flags = r->in.negotiate_flags;
438 r3.out.negotiate_flags = r->out.negotiate_flags;
439 r3.out.rid = &rid;
441 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
445 * NOTE: The following functions are nearly identical to the ones available in
446 * source3/rpc_server/srv_nelog_nt.c
447 * The reason we keep 2 copies is that they use different structures to
448 * represent the auth_info and the decrpc pipes.
452 * If schannel is required for this call test that it actually is available.
454 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
455 const char *computer_name,
456 bool integrity, bool privacy)
459 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
460 if (!privacy && !integrity) {
461 return NT_STATUS_OK;
464 if ((!privacy && integrity) &&
465 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
466 return NT_STATUS_OK;
469 if ((privacy || integrity) &&
470 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
471 return NT_STATUS_OK;
475 /* test didn't pass */
476 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
477 computer_name));
479 return NT_STATUS_ACCESS_DENIED;
482 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
483 TALLOC_CTX *mem_ctx,
484 const char *computer_name,
485 struct netr_Authenticator *received_authenticator,
486 struct netr_Authenticator *return_authenticator,
487 struct netlogon_creds_CredentialState **creds_out)
489 NTSTATUS nt_status;
490 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
491 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
493 if (schannel_global_required) {
494 nt_status = schannel_check_required(auth_info,
495 computer_name,
496 true, false);
497 if (!NT_STATUS_IS_OK(nt_status)) {
498 return nt_status;
502 nt_status = schannel_check_creds_state(mem_ctx,
503 dce_call->conn->dce_ctx->lp_ctx,
504 computer_name,
505 received_authenticator,
506 return_authenticator,
507 creds_out);
508 return nt_status;
512 Change the machine account password for the currently connected
513 client. Supplies only the NT#.
516 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
517 struct netr_ServerPasswordSet *r)
519 struct netlogon_creds_CredentialState *creds;
520 struct ldb_context *sam_ctx;
521 const char * const attrs[] = { "unicodePwd", NULL };
522 struct ldb_message **res;
523 struct samr_Password *oldNtHash;
524 NTSTATUS nt_status;
525 int ret;
527 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
528 mem_ctx,
529 r->in.computer_name,
530 r->in.credential, r->out.return_authenticator,
531 &creds);
532 NT_STATUS_NOT_OK_RETURN(nt_status);
534 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);
535 if (sam_ctx == NULL) {
536 return NT_STATUS_INVALID_SYSTEM_SERVICE;
539 netlogon_creds_des_decrypt(creds, r->in.new_password);
541 /* fetch the old password hashes (the NT hash has to exist) */
543 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
544 "(&(objectClass=user)(objectSid=%s))",
545 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
546 if (ret != 1) {
547 return NT_STATUS_WRONG_PASSWORD;
550 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
551 dce_call->conn->dce_ctx->lp_ctx,
552 res[0], NULL, &oldNtHash);
553 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
554 return NT_STATUS_WRONG_PASSWORD;
557 /* Using the sid for the account as the key, set the password */
558 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
559 creds->sid,
560 NULL, /* Don't have plaintext */
561 NULL, r->in.new_password,
562 NULL, oldNtHash, /* Password change */
563 NULL, NULL);
564 return nt_status;
568 Change the machine account password for the currently connected
569 client. Supplies new plaintext.
571 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
572 struct netr_ServerPasswordSet2 *r)
574 struct netlogon_creds_CredentialState *creds;
575 struct ldb_context *sam_ctx;
576 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
577 struct ldb_message **res;
578 struct samr_Password *oldLmHash, *oldNtHash;
579 NTSTATUS nt_status;
580 DATA_BLOB new_password;
581 int ret;
583 struct samr_CryptPassword password_buf;
585 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
586 mem_ctx,
587 r->in.computer_name,
588 r->in.credential, r->out.return_authenticator,
589 &creds);
590 NT_STATUS_NOT_OK_RETURN(nt_status);
592 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);
593 if (sam_ctx == NULL) {
594 return NT_STATUS_INVALID_SYSTEM_SERVICE;
597 memcpy(password_buf.data, r->in.new_password->data, 512);
598 SIVAL(password_buf.data, 512, r->in.new_password->length);
600 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
601 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
602 } else {
603 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
606 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
607 DEBUG(3,("samr: failed to decode password buffer\n"));
608 return NT_STATUS_WRONG_PASSWORD;
611 /* fetch the old password hashes (at least one of both has to exist) */
613 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
614 "(&(objectClass=user)(objectSid=%s))",
615 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
616 if (ret != 1) {
617 return NT_STATUS_WRONG_PASSWORD;
620 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
621 dce_call->conn->dce_ctx->lp_ctx,
622 res[0], &oldLmHash, &oldNtHash);
623 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
624 return NT_STATUS_WRONG_PASSWORD;
627 /* Using the sid for the account as the key, set the password */
628 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
629 creds->sid,
630 &new_password, /* we have plaintext */
631 NULL, NULL,
632 oldLmHash, oldNtHash, /* Password change */
633 NULL, NULL);
634 return nt_status;
639 netr_LogonUasLogon
641 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
642 struct netr_LogonUasLogon *r)
644 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
649 netr_LogonUasLogoff
651 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
652 struct netr_LogonUasLogoff *r)
654 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
658 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
660 switch (r->in.logon_level) {
661 case NetlogonInteractiveInformation:
662 case NetlogonServiceInformation:
663 case NetlogonInteractiveTransitiveInformation:
664 case NetlogonServiceTransitiveInformation:
665 if (r->in.logon->password == NULL) {
666 return NT_STATUS_INVALID_PARAMETER;
669 switch (r->in.validation_level) {
670 case NetlogonValidationSamInfo: /* 2 */
671 case NetlogonValidationSamInfo2: /* 3 */
672 case NetlogonValidationSamInfo4: /* 6 */
673 break;
674 default:
675 return NT_STATUS_INVALID_INFO_CLASS;
678 break;
679 case NetlogonNetworkInformation:
680 case NetlogonNetworkTransitiveInformation:
681 if (r->in.logon->network == NULL) {
682 return NT_STATUS_INVALID_PARAMETER;
685 switch (r->in.validation_level) {
686 case NetlogonValidationSamInfo: /* 2 */
687 case NetlogonValidationSamInfo2: /* 3 */
688 case NetlogonValidationSamInfo4: /* 6 */
689 break;
690 default:
691 return NT_STATUS_INVALID_INFO_CLASS;
694 break;
696 case NetlogonGenericInformation:
697 if (r->in.logon->generic == NULL) {
698 return NT_STATUS_INVALID_PARAMETER;
701 switch (r->in.validation_level) {
702 /* TODO: case NetlogonValidationGenericInfo: 4 */
703 case NetlogonValidationGenericInfo2: /* 5 */
704 break;
705 default:
706 return NT_STATUS_INVALID_INFO_CLASS;
709 break;
710 default:
711 return NT_STATUS_INVALID_PARAMETER;
714 return NT_STATUS_OK;
718 netr_LogonSamLogon_base
720 This version of the function allows other wrappers to say 'do not check the credentials'
722 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
724 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
725 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
727 struct auth4_context *auth_context;
728 struct auth_usersupplied_info *user_info;
729 struct auth_user_info_dc *user_info_dc;
730 NTSTATUS nt_status;
731 struct netr_SamBaseInfo *sam;
732 struct netr_SamInfo2 *sam2;
733 struct netr_SamInfo3 *sam3;
734 struct netr_SamInfo6 *sam6;
736 *r->out.authoritative = 1;
738 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
739 NT_STATUS_HAVE_NO_MEMORY(user_info);
741 netlogon_creds_decrypt_samlogon_logon(creds,
742 r->in.logon_level,
743 r->in.logon);
745 switch (r->in.logon_level) {
746 case NetlogonInteractiveInformation:
747 case NetlogonServiceInformation:
748 case NetlogonInteractiveTransitiveInformation:
749 case NetlogonServiceTransitiveInformation:
751 /* TODO: we need to deny anonymous access here */
752 nt_status = auth_context_create(mem_ctx,
753 dce_call->event_ctx, dce_call->msg_ctx,
754 dce_call->conn->dce_ctx->lp_ctx,
755 &auth_context);
756 NT_STATUS_NOT_OK_RETURN(nt_status);
758 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
759 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
760 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
761 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
763 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
764 user_info->password_state = AUTH_PASSWORD_HASH;
766 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
767 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
768 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
770 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
771 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
772 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
774 break;
775 case NetlogonNetworkInformation:
776 case NetlogonNetworkTransitiveInformation:
778 /* TODO: we need to deny anonymous access here */
779 nt_status = auth_context_create(mem_ctx,
780 dce_call->event_ctx, dce_call->msg_ctx,
781 dce_call->conn->dce_ctx->lp_ctx,
782 &auth_context);
783 NT_STATUS_NOT_OK_RETURN(nt_status);
785 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
786 NT_STATUS_NOT_OK_RETURN(nt_status);
788 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
789 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
790 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
791 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
793 user_info->password_state = AUTH_PASSWORD_RESPONSE;
794 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
795 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
797 break;
800 case NetlogonGenericInformation:
802 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
803 /* OK */
804 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
805 /* OK */
806 } else {
807 /* Using DES to verify kerberos tickets makes no sense */
808 return NT_STATUS_INVALID_PARAMETER;
811 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
812 NTSTATUS status;
813 struct dcerpc_binding_handle *irpc_handle;
814 struct kdc_check_generic_kerberos check;
815 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
816 NT_STATUS_HAVE_NO_MEMORY(generic);
817 *r->out.authoritative = 1;
819 /* TODO: Describe and deal with these flags */
820 *r->out.flags = 0;
822 r->out.validation->generic = generic;
824 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
825 dce_call->msg_ctx,
826 "kdc_server",
827 &ndr_table_irpc);
828 if (irpc_handle == NULL) {
829 return NT_STATUS_NO_LOGON_SERVERS;
832 check.in.generic_request =
833 data_blob_const(r->in.logon->generic->data,
834 r->in.logon->generic->length);
837 * TODO: make this async and avoid
838 * dcerpc_binding_handle_set_sync_ev()
840 dcerpc_binding_handle_set_sync_ev(irpc_handle,
841 dce_call->event_ctx);
842 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
843 mem_ctx,
844 &check);
845 if (!NT_STATUS_IS_OK(status)) {
846 return status;
848 generic->length = check.out.generic_reply.length;
849 generic->data = check.out.generic_reply.data;
850 return NT_STATUS_OK;
853 /* Until we get an implemetnation of these other packages */
854 return NT_STATUS_INVALID_PARAMETER;
856 default:
857 return NT_STATUS_INVALID_PARAMETER;
860 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
861 /* TODO: set *r->out.authoritative = 0 on specific errors */
862 NT_STATUS_NOT_OK_RETURN(nt_status);
864 switch (r->in.validation_level) {
865 case 2:
866 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
867 NT_STATUS_NOT_OK_RETURN(nt_status);
869 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
870 NT_STATUS_HAVE_NO_MEMORY(sam2);
871 sam2->base = *sam;
873 /* And put into the talloc tree */
874 talloc_steal(sam2, sam);
875 r->out.validation->sam2 = sam2;
877 sam = &sam2->base;
878 break;
880 case 3:
881 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
882 user_info_dc,
883 &sam3);
884 NT_STATUS_NOT_OK_RETURN(nt_status);
886 r->out.validation->sam3 = sam3;
888 sam = &sam3->base;
889 break;
891 case 6:
892 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
893 user_info_dc,
894 &sam3);
895 NT_STATUS_NOT_OK_RETURN(nt_status);
897 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
898 NT_STATUS_HAVE_NO_MEMORY(sam6);
899 sam6->base = sam3->base;
900 sam = &sam6->base;
901 sam6->sidcount = sam3->sidcount;
902 sam6->sids = sam3->sids;
904 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
905 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
906 sam->account_name.string, sam6->dns_domainname.string);
907 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
908 /* And put into the talloc tree */
909 talloc_steal(sam6, sam3);
911 r->out.validation->sam6 = sam6;
912 break;
914 default:
915 return NT_STATUS_INVALID_INFO_CLASS;
918 netlogon_creds_encrypt_samlogon_validation(creds,
919 r->in.validation_level,
920 r->out.validation);
922 /* TODO: Describe and deal with these flags */
923 *r->out.flags = 0;
925 return NT_STATUS_OK;
928 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
929 struct netr_LogonSamLogonEx *r)
931 NTSTATUS nt_status;
932 struct netlogon_creds_CredentialState *creds;
934 *r->out.authoritative = 1;
936 nt_status = dcesrv_netr_LogonSamLogon_check(r);
937 if (!NT_STATUS_IS_OK(nt_status)) {
938 return nt_status;
941 nt_status = schannel_get_creds_state(mem_ctx,
942 dce_call->conn->dce_ctx->lp_ctx,
943 r->in.computer_name, &creds);
944 if (!NT_STATUS_IS_OK(nt_status)) {
945 return nt_status;
948 if (!dce_call->conn->auth_state.auth_info ||
949 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
950 return NT_STATUS_ACCESS_DENIED;
952 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
956 netr_LogonSamLogonWithFlags
959 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
960 struct netr_LogonSamLogonWithFlags *r)
962 NTSTATUS nt_status;
963 struct netlogon_creds_CredentialState *creds;
964 struct netr_LogonSamLogonEx r2;
966 struct netr_Authenticator *return_authenticator;
968 ZERO_STRUCT(r2);
970 r2.in.server_name = r->in.server_name;
971 r2.in.computer_name = r->in.computer_name;
972 r2.in.logon_level = r->in.logon_level;
973 r2.in.logon = r->in.logon;
974 r2.in.validation_level = r->in.validation_level;
975 r2.in.flags = r->in.flags;
976 r2.out.validation = r->out.validation;
977 r2.out.authoritative = r->out.authoritative;
978 r2.out.flags = r->out.flags;
980 *r->out.authoritative = 1;
982 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
983 if (!NT_STATUS_IS_OK(nt_status)) {
984 return nt_status;
987 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
988 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
990 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
991 mem_ctx,
992 r->in.computer_name,
993 r->in.credential, return_authenticator,
994 &creds);
995 NT_STATUS_NOT_OK_RETURN(nt_status);
997 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
999 r->out.return_authenticator = return_authenticator;
1001 return nt_status;
1005 netr_LogonSamLogon
1007 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1008 struct netr_LogonSamLogon *r)
1010 struct netr_LogonSamLogonWithFlags r2;
1011 uint32_t flags = 0;
1012 NTSTATUS status;
1014 ZERO_STRUCT(r2);
1016 r2.in.server_name = r->in.server_name;
1017 r2.in.computer_name = r->in.computer_name;
1018 r2.in.credential = r->in.credential;
1019 r2.in.return_authenticator = r->in.return_authenticator;
1020 r2.in.logon_level = r->in.logon_level;
1021 r2.in.logon = r->in.logon;
1022 r2.in.validation_level = r->in.validation_level;
1023 r2.in.flags = &flags;
1024 r2.out.validation = r->out.validation;
1025 r2.out.authoritative = r->out.authoritative;
1026 r2.out.flags = &flags;
1028 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1030 r->out.return_authenticator = r2.out.return_authenticator;
1032 return status;
1037 netr_LogonSamLogoff
1039 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1040 struct netr_LogonSamLogoff *r)
1042 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1048 netr_DatabaseDeltas
1050 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1051 struct netr_DatabaseDeltas *r)
1053 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1058 netr_DatabaseSync2
1060 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1061 struct netr_DatabaseSync2 *r)
1063 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1064 return NT_STATUS_NOT_IMPLEMENTED;
1069 netr_DatabaseSync
1071 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1072 struct netr_DatabaseSync *r)
1074 struct netr_DatabaseSync2 r2;
1075 NTSTATUS status;
1077 ZERO_STRUCT(r2);
1079 r2.in.logon_server = r->in.logon_server;
1080 r2.in.computername = r->in.computername;
1081 r2.in.credential = r->in.credential;
1082 r2.in.database_id = r->in.database_id;
1083 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1084 r2.in.sync_context = r->in.sync_context;
1085 r2.out.sync_context = r->out.sync_context;
1086 r2.out.delta_enum_array = r->out.delta_enum_array;
1087 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1089 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1091 return status;
1096 netr_AccountDeltas
1098 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1099 struct netr_AccountDeltas *r)
1101 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1102 return NT_STATUS_NOT_IMPLEMENTED;
1107 netr_AccountSync
1109 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1110 struct netr_AccountSync *r)
1112 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1113 return NT_STATUS_NOT_IMPLEMENTED;
1118 netr_GetDcName
1120 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1121 struct netr_GetDcName *r)
1123 const char * const attrs[] = { NULL };
1124 struct ldb_context *sam_ctx;
1125 struct ldb_message **res;
1126 struct ldb_dn *domain_dn;
1127 int ret;
1128 const char *dcname;
1131 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1132 * that the domainname needs to be a valid netbios domain
1133 * name, if it is not NULL.
1135 if (r->in.domainname) {
1136 const char *dot = strchr(r->in.domainname, '.');
1137 size_t len = strlen(r->in.domainname);
1139 if (dot || len > 15) {
1140 return WERR_DCNOTFOUND;
1144 * TODO: Should we also varify that only valid
1145 * netbios name characters are used?
1149 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1150 dce_call->conn->dce_ctx->lp_ctx,
1151 dce_call->conn->auth_state.session_info, 0);
1152 if (sam_ctx == NULL) {
1153 return WERR_DS_UNAVAILABLE;
1156 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1157 r->in.domainname);
1158 if (domain_dn == NULL) {
1159 return WERR_NO_SUCH_DOMAIN;
1162 ret = gendb_search_dn(sam_ctx, mem_ctx,
1163 domain_dn, &res, attrs);
1164 if (ret != 1) {
1165 return WERR_NO_SUCH_DOMAIN;
1168 /* TODO: - return real IP address
1169 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1171 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1172 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1173 W_ERROR_HAVE_NO_MEMORY(dcname);
1175 *r->out.dcname = dcname;
1176 return WERR_OK;
1181 netr_LogonControl2Ex
1183 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1184 struct netr_LogonControl2Ex *r)
1186 return WERR_NOT_SUPPORTED;
1191 netr_LogonControl
1193 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1194 struct netr_LogonControl *r)
1196 struct netr_LogonControl2Ex r2;
1197 WERROR werr;
1199 if (r->in.level == 0x00000001) {
1200 ZERO_STRUCT(r2);
1202 r2.in.logon_server = r->in.logon_server;
1203 r2.in.function_code = r->in.function_code;
1204 r2.in.level = r->in.level;
1205 r2.in.data = NULL;
1206 r2.out.query = r->out.query;
1208 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1209 } else if (r->in.level == 0x00000002) {
1210 werr = WERR_NOT_SUPPORTED;
1211 } else {
1212 werr = WERR_UNKNOWN_LEVEL;
1215 return werr;
1220 netr_LogonControl2
1222 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1223 struct netr_LogonControl2 *r)
1225 struct netr_LogonControl2Ex r2;
1226 WERROR werr;
1228 ZERO_STRUCT(r2);
1230 r2.in.logon_server = r->in.logon_server;
1231 r2.in.function_code = r->in.function_code;
1232 r2.in.level = r->in.level;
1233 r2.in.data = r->in.data;
1234 r2.out.query = r->out.query;
1236 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1238 return werr;
1241 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1242 struct ldb_context *sam_ctx,
1243 struct netr_DomainTrustList *trusts,
1244 uint32_t trust_flags);
1247 netr_GetAnyDCName
1249 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250 struct netr_GetAnyDCName *r)
1252 struct netr_DomainTrustList *trusts;
1253 struct ldb_context *sam_ctx;
1254 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1255 uint32_t i;
1256 WERROR werr;
1258 *r->out.dcname = NULL;
1260 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1261 /* if the domainname parameter wasn't set assume our domain */
1262 r->in.domainname = lpcfg_workgroup(lp_ctx);
1265 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1266 dce_call->conn->auth_state.session_info, 0);
1267 if (sam_ctx == NULL) {
1268 return WERR_DS_UNAVAILABLE;
1271 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1272 /* well we asked for a DC of our own domain */
1273 if (samdb_is_pdc(sam_ctx)) {
1274 /* we are the PDC of the specified domain */
1275 return WERR_NO_SUCH_DOMAIN;
1278 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1279 lpcfg_netbios_name(lp_ctx));
1280 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1282 return WERR_OK;
1285 /* Okay, now we have to consider the trusted domains */
1287 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1288 W_ERROR_HAVE_NO_MEMORY(trusts);
1290 trusts->count = 0;
1292 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1293 NETR_TRUST_FLAG_INBOUND
1294 | NETR_TRUST_FLAG_OUTBOUND);
1295 W_ERROR_NOT_OK_RETURN(werr);
1297 for (i = 0; i < trusts->count; i++) {
1298 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1299 /* FIXME: Here we need to find a DC for the specified
1300 * trusted domain. */
1302 /* return WERR_OK; */
1303 return WERR_NO_SUCH_DOMAIN;
1307 return WERR_NO_SUCH_DOMAIN;
1312 netr_DatabaseRedo
1314 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1315 struct netr_DatabaseRedo *r)
1317 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1322 netr_NetrEnumerateTrustedDomains
1324 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1325 struct netr_NetrEnumerateTrustedDomains *r)
1327 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1332 netr_LogonGetCapabilities
1334 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1335 struct netr_LogonGetCapabilities *r)
1337 struct netlogon_creds_CredentialState *creds;
1338 NTSTATUS status;
1340 status = dcesrv_netr_creds_server_step_check(dce_call,
1341 mem_ctx,
1342 r->in.computer_name,
1343 r->in.credential,
1344 r->out.return_authenticator,
1345 &creds);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 DEBUG(0,(__location__ " Bad credentials - error\n"));
1349 NT_STATUS_NOT_OK_RETURN(status);
1351 if (r->in.query_level != 1) {
1352 return NT_STATUS_NOT_SUPPORTED;
1355 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1357 return NT_STATUS_OK;
1362 netr_NETRLOGONSETSERVICEBITS
1364 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1365 struct netr_NETRLOGONSETSERVICEBITS *r)
1367 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1372 netr_LogonGetTrustRid
1374 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1375 struct netr_LogonGetTrustRid *r)
1377 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1382 netr_NETRLOGONCOMPUTESERVERDIGEST
1384 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1385 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1387 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1392 netr_NETRLOGONCOMPUTECLIENTDIGEST
1394 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1395 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1397 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1403 netr_DsRGetSiteName
1405 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1406 struct netr_DsRGetSiteName *r)
1408 struct ldb_context *sam_ctx;
1409 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1411 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1412 dce_call->conn->auth_state.session_info, 0);
1413 if (sam_ctx == NULL) {
1414 return WERR_DS_UNAVAILABLE;
1418 * We assume to be a DC when we get called over NETLOGON. Hence we
1419 * get our site name always by using "samdb_server_site_name()"
1420 * and not "samdb_client_site_name()".
1422 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1423 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1425 return WERR_OK;
1430 fill in a netr_OneDomainInfo from a ldb search result
1432 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1433 struct loadparm_context *lp_ctx,
1434 struct ldb_context *sam_ctx,
1435 struct ldb_message *res,
1436 struct netr_OneDomainInfo *info,
1437 bool is_local, bool is_trust_list)
1439 ZERO_STRUCTP(info);
1441 if (is_trust_list) {
1442 /* w2k8 only fills this on trusted domains */
1443 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1444 info->trust_extension.length = 16;
1445 info->trust_extension.info->flags =
1446 NETR_TRUST_FLAG_TREEROOT |
1447 NETR_TRUST_FLAG_IN_FOREST |
1448 NETR_TRUST_FLAG_PRIMARY |
1449 NETR_TRUST_FLAG_NATIVE;
1451 info->trust_extension.info->parent_index = 0; /* should be index into array
1452 of parent */
1453 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1454 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1457 if (is_trust_list) {
1458 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1459 info->dns_forestname.string = NULL;
1460 } else {
1461 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1462 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1463 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1464 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1467 if (is_local) {
1468 info->domainname.string = lpcfg_workgroup(lp_ctx);
1469 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1470 info->domain_guid = samdb_result_guid(res, "objectGUID");
1471 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1472 } else {
1473 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1474 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1475 info->domain_guid = samdb_result_guid(res, "objectGUID");
1476 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1478 if (!is_trust_list) {
1479 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1482 return NT_STATUS_OK;
1486 netr_LogonGetDomainInfo
1487 this is called as part of the ADS domain logon procedure.
1489 It has an important role in convaying details about the client, such
1490 as Operating System, Version, Service Pack etc.
1492 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1493 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1495 struct netlogon_creds_CredentialState *creds;
1496 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1497 "securityIdentifier", "trustPartner", NULL };
1498 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1499 "msDS-SupportedEncryptionTypes", NULL };
1500 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1501 struct ldb_context *sam_ctx;
1502 struct ldb_message **res1, **res2, **res3, *new_msg;
1503 struct ldb_dn *workstation_dn;
1504 struct netr_DomainInformation *domain_info;
1505 struct netr_LsaPolicyInformation *lsa_policy_info;
1506 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1507 bool update_dns_hostname = true;
1508 int ret, ret3, i;
1509 NTSTATUS status;
1511 status = dcesrv_netr_creds_server_step_check(dce_call,
1512 mem_ctx,
1513 r->in.computer_name,
1514 r->in.credential,
1515 r->out.return_authenticator,
1516 &creds);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 DEBUG(0,(__location__ " Bad credentials - error\n"));
1520 NT_STATUS_NOT_OK_RETURN(status);
1522 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1523 dce_call->conn->dce_ctx->lp_ctx,
1524 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1525 if (sam_ctx == NULL) {
1526 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1529 switch (r->in.level) {
1530 case 1: /* Domain information */
1532 if (r->in.query->workstation_info == NULL) {
1533 return NT_STATUS_INVALID_PARAMETER;
1536 /* Prepares the workstation DN */
1537 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1538 dom_sid_string(mem_ctx, creds->sid));
1539 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1541 /* Lookup for attributes in workstation object */
1542 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1543 attrs2);
1544 if (ret != 1) {
1545 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1548 /* Gets the sam account name which is checked against the DNS
1549 * hostname parameter. */
1550 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1551 "sAMAccountName",
1552 NULL);
1553 if (sam_account_name == NULL) {
1554 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1558 * Checks that the sam account name without a possible "$"
1559 * matches as prefix with the DNS hostname in the workstation
1560 * info structure.
1562 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1563 strcspn(sam_account_name, "$"));
1564 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1565 if (r->in.query->workstation_info->dns_hostname != NULL) {
1566 prefix2 = talloc_strndup(mem_ctx,
1567 r->in.query->workstation_info->dns_hostname,
1568 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1569 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1571 if (strcasecmp(prefix1, prefix2) != 0) {
1572 update_dns_hostname = false;
1574 } else {
1575 update_dns_hostname = false;
1578 /* Gets the old DNS hostname */
1579 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1580 "dNSHostName",
1581 NULL);
1584 * Updates the DNS hostname when the client wishes that the
1585 * server should handle this for him
1586 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1587 * obviously only checked when we do already have a
1588 * "dNSHostName".
1589 * See MS-NRPC section 3.5.4.3.9
1591 if ((old_dns_hostname != NULL) &&
1592 (r->in.query->workstation_info->workstation_flags
1593 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1594 update_dns_hostname = false;
1597 /* Gets host information and put them into our directory */
1599 new_msg = ldb_msg_new(mem_ctx);
1600 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1602 new_msg->dn = workstation_dn;
1604 /* Sets the OS name */
1606 if (r->in.query->workstation_info->os_name.string == NULL) {
1607 return NT_STATUS_INVALID_PARAMETER;
1610 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1611 r->in.query->workstation_info->os_name.string);
1612 if (ret != LDB_SUCCESS) {
1613 return NT_STATUS_NO_MEMORY;
1617 * Sets information from "os_version". On an empty structure
1618 * the values are cleared.
1620 if (r->in.query->workstation_info->os_version.os != NULL) {
1621 struct netr_OsVersionInfoEx *os_version;
1622 const char *os_version_str;
1624 os_version = &r->in.query->workstation_info->os_version.os->os;
1626 if (os_version->CSDVersion == NULL) {
1627 return NT_STATUS_INVALID_PARAMETER;
1630 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1631 os_version->MajorVersion,
1632 os_version->MinorVersion,
1633 os_version->BuildNumber);
1634 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1636 ret = ldb_msg_add_string(new_msg,
1637 "operatingSystemServicePack",
1638 os_version->CSDVersion);
1639 if (ret != LDB_SUCCESS) {
1640 return NT_STATUS_NO_MEMORY;
1643 ret = ldb_msg_add_string(new_msg,
1644 "operatingSystemVersion",
1645 os_version_str);
1646 if (ret != LDB_SUCCESS) {
1647 return NT_STATUS_NO_MEMORY;
1649 } else {
1650 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1651 "operatingSystemServicePack");
1652 if (ret != LDB_SUCCESS) {
1653 return NT_STATUS_NO_MEMORY;
1656 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1657 "operatingSystemVersion");
1658 if (ret != LDB_SUCCESS) {
1659 return NT_STATUS_NO_MEMORY;
1664 * If the boolean "update_dns_hostname" remained true, then we
1665 * are fine to start the update.
1667 if (update_dns_hostname) {
1668 ret = ldb_msg_add_string(new_msg,
1669 "dNSHostname",
1670 r->in.query->workstation_info->dns_hostname);
1671 if (ret != LDB_SUCCESS) {
1672 return NT_STATUS_NO_MEMORY;
1675 /* This manual "servicePrincipalName" generation is
1676 * still needed! Since the update in the samldb LDB
1677 * module does only work if the entries already exist
1678 * which isn't always the case. */
1679 ret = ldb_msg_add_string(new_msg,
1680 "servicePrincipalName",
1681 talloc_asprintf(new_msg, "HOST/%s",
1682 r->in.computer_name));
1683 if (ret != LDB_SUCCESS) {
1684 return NT_STATUS_NO_MEMORY;
1687 ret = ldb_msg_add_string(new_msg,
1688 "servicePrincipalName",
1689 talloc_asprintf(new_msg, "HOST/%s",
1690 r->in.query->workstation_info->dns_hostname));
1691 if (ret != LDB_SUCCESS) {
1692 return NT_STATUS_NO_MEMORY;
1696 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1697 DEBUG(3,("Impossible to update samdb: %s\n",
1698 ldb_errstring(sam_ctx)));
1701 talloc_free(new_msg);
1703 /* Writes back the domain information */
1705 /* We need to do two searches. The first will pull our primary
1706 domain and the second will pull any trusted domains. Our
1707 primary domain is also a "trusted" domain, so we need to
1708 put the primary domain into the lists of returned trusts as
1709 well. */
1710 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1711 &res2, attrs);
1712 if (ret != 1) {
1713 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1716 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1717 "(objectClass=trustedDomain)");
1718 if (ret3 == -1) {
1719 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1722 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1723 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1725 ZERO_STRUCTP(domain_info);
1727 /* Informations about the local and trusted domains */
1729 status = fill_one_domain_info(mem_ctx,
1730 dce_call->conn->dce_ctx->lp_ctx,
1731 sam_ctx, res2[0], &domain_info->primary_domain,
1732 true, false);
1733 NT_STATUS_NOT_OK_RETURN(status);
1735 domain_info->trusted_domain_count = ret3 + 1;
1736 domain_info->trusted_domains = talloc_array(mem_ctx,
1737 struct netr_OneDomainInfo,
1738 domain_info->trusted_domain_count);
1739 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1741 for (i=0;i<ret3;i++) {
1742 status = fill_one_domain_info(mem_ctx,
1743 dce_call->conn->dce_ctx->lp_ctx,
1744 sam_ctx, res3[i],
1745 &domain_info->trusted_domains[i],
1746 false, true);
1747 NT_STATUS_NOT_OK_RETURN(status);
1750 status = fill_one_domain_info(mem_ctx,
1751 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1752 &domain_info->trusted_domains[i], true, true);
1753 NT_STATUS_NOT_OK_RETURN(status);
1755 /* Sets the supported encryption types */
1756 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1757 "msDS-SupportedEncryptionTypes",
1758 default_supported_enc_types);
1760 /* Other host domain information */
1762 lsa_policy_info = talloc(mem_ctx,
1763 struct netr_LsaPolicyInformation);
1764 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1765 ZERO_STRUCTP(lsa_policy_info);
1767 domain_info->lsa_policy = *lsa_policy_info;
1769 /* The DNS hostname is only returned back when there is a chance
1770 * for a change. */
1771 if ((r->in.query->workstation_info->workstation_flags
1772 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1773 domain_info->dns_hostname.string = old_dns_hostname;
1774 } else {
1775 domain_info->dns_hostname.string = NULL;
1778 domain_info->workstation_flags =
1779 r->in.query->workstation_info->workstation_flags & (
1780 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1782 r->out.info->domain_info = domain_info;
1783 break;
1784 case 2: /* LSA policy information - not used at the moment */
1785 lsa_policy_info = talloc(mem_ctx,
1786 struct netr_LsaPolicyInformation);
1787 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1788 ZERO_STRUCTP(lsa_policy_info);
1790 r->out.info->lsa_policy_info = lsa_policy_info;
1791 break;
1792 default:
1793 return NT_STATUS_INVALID_LEVEL;
1794 break;
1797 return NT_STATUS_OK;
1802 netr_ServerPasswordGet
1804 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1805 struct netr_ServerPasswordGet *r)
1807 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1812 netr_NETRLOGONSENDTOSAM
1814 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1815 struct netr_NETRLOGONSENDTOSAM *r)
1817 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1822 netr_DsRGetDCNameEx2
1824 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1825 TALLOC_CTX *mem_ctx,
1826 struct netr_DsRGetDCNameEx2 *r)
1828 struct ldb_context *sam_ctx;
1829 struct netr_DsRGetDCNameInfo *info;
1830 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1831 const struct tsocket_address *remote_address;
1832 char *addr = NULL;
1833 const char *server_site_name;
1834 char *guid_str;
1835 struct netlogon_samlogon_response response;
1836 NTSTATUS status;
1837 const char *dc_name = NULL;
1838 const char *domain_name = NULL;
1839 struct interface *ifaces;
1840 const char *pdc_ip;
1842 ZERO_STRUCTP(r->out.info);
1844 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1845 dce_call->conn->auth_state.session_info, 0);
1846 if (sam_ctx == NULL) {
1847 return WERR_DS_UNAVAILABLE;
1850 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1851 if (tsocket_address_is_inet(remote_address, "ip")) {
1852 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1853 W_ERROR_HAVE_NO_MEMORY(addr);
1856 /* "server_unc" is ignored by w2k3 */
1858 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1859 return WERR_INVALID_FLAGS;
1862 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1863 r->in.flags & DS_PDC_REQUIRED &&
1864 r->in.flags & DS_KDC_REQUIRED) {
1865 return WERR_INVALID_FLAGS;
1867 if (r->in.flags & DS_IS_FLAT_NAME &&
1868 r->in.flags & DS_IS_DNS_NAME) {
1869 return WERR_INVALID_FLAGS;
1871 if (r->in.flags & DS_RETURN_DNS_NAME &&
1872 r->in.flags & DS_RETURN_FLAT_NAME) {
1873 return WERR_INVALID_FLAGS;
1875 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1876 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1877 return WERR_INVALID_FLAGS;
1880 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1881 r->in.flags &
1882 (DS_DIRECTORY_SERVICE_REQUIRED |
1883 DS_DIRECTORY_SERVICE_PREFERRED |
1884 DS_GC_SERVER_REQUIRED |
1885 DS_PDC_REQUIRED |
1886 DS_KDC_REQUIRED)) {
1887 return WERR_INVALID_FLAGS;
1890 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1891 r->in.site_name) {
1892 return WERR_INVALID_FLAGS;
1895 /* Proof server site parameter "site_name" if it was specified */
1896 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1897 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1898 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1899 server_site_name) != 0)) {
1900 return WERR_NO_SUCH_DOMAIN;
1903 guid_str = r->in.domain_guid != NULL ?
1904 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1906 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1907 r->in.domain_name,
1908 r->in.domain_name,
1909 NULL, guid_str,
1910 r->in.client_account,
1911 r->in.mask, addr,
1912 NETLOGON_NT_VERSION_5EX_WITH_IP,
1913 lp_ctx, &response, true);
1914 if (!NT_STATUS_IS_OK(status)) {
1915 return ntstatus_to_werror(status);
1919 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1920 * (O) flag when the returned forest name is in DNS format. This is here
1921 * always the case (see below).
1923 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1925 if (r->in.flags & DS_RETURN_DNS_NAME) {
1926 dc_name = response.data.nt5_ex.pdc_dns_name;
1927 domain_name = response.data.nt5_ex.dns_domain;
1929 * According to MS-NRPC 2.2.1.2.1 we should set the
1930 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1931 * the returned information is in DNS form.
1933 response.data.nt5_ex.server_type |=
1934 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1935 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1936 dc_name = response.data.nt5_ex.pdc_name;
1937 domain_name = response.data.nt5_ex.domain_name;
1938 } else {
1941 * TODO: autodetect what we need to return
1942 * based on the given arguments
1944 dc_name = response.data.nt5_ex.pdc_name;
1945 domain_name = response.data.nt5_ex.domain_name;
1948 if (!dc_name || !dc_name[0]) {
1949 return WERR_NO_SUCH_DOMAIN;
1952 if (!domain_name || !domain_name[0]) {
1953 return WERR_NO_SUCH_DOMAIN;
1956 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1957 W_ERROR_HAVE_NO_MEMORY(info);
1958 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1959 dc_name[0] == '\\'? "\\\\":"",
1960 talloc_strdup(mem_ctx, dc_name));
1961 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1963 load_interface_list(mem_ctx, lp_ctx, &ifaces);
1964 pdc_ip = iface_list_best_ip(ifaces, addr);
1965 if (pdc_ip == NULL) {
1966 pdc_ip = "127.0.0.1";
1968 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1969 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1970 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1971 info->domain_guid = response.data.nt5_ex.domain_uuid;
1972 info->domain_name = domain_name;
1973 info->forest_name = response.data.nt5_ex.forest;
1974 info->dc_flags = response.data.nt5_ex.server_type;
1975 if (r->in.flags & DS_RETURN_DNS_NAME) {
1976 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
1977 * returned if we are returning info->dc_unc containing a FQDN.
1978 * This attribute is called DomainControllerName in the specs,
1979 * it seems that we decide to return FQDN or netbios depending on
1980 * DS_RETURN_DNS_NAME.
1982 info->dc_flags |= DS_DNS_CONTROLLER;
1984 info->dc_site_name = response.data.nt5_ex.server_site;
1985 info->client_site_name = response.data.nt5_ex.client_site;
1987 *r->out.info = info;
1989 return WERR_OK;
1993 netr_DsRGetDCNameEx
1995 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1996 struct netr_DsRGetDCNameEx *r)
1998 struct netr_DsRGetDCNameEx2 r2;
1999 WERROR werr;
2001 ZERO_STRUCT(r2);
2003 r2.in.server_unc = r->in.server_unc;
2004 r2.in.client_account = NULL;
2005 r2.in.mask = 0;
2006 r2.in.domain_guid = r->in.domain_guid;
2007 r2.in.domain_name = r->in.domain_name;
2008 r2.in.site_name = r->in.site_name;
2009 r2.in.flags = r->in.flags;
2010 r2.out.info = r->out.info;
2012 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2014 return werr;
2018 netr_DsRGetDCName
2020 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2021 struct netr_DsRGetDCName *r)
2023 struct netr_DsRGetDCNameEx2 r2;
2024 WERROR werr;
2026 ZERO_STRUCT(r2);
2028 r2.in.server_unc = r->in.server_unc;
2029 r2.in.client_account = NULL;
2030 r2.in.mask = 0;
2031 r2.in.domain_name = r->in.domain_name;
2032 r2.in.domain_guid = r->in.domain_guid;
2034 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2035 r2.in.flags = r->in.flags;
2036 r2.out.info = r->out.info;
2038 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2040 return werr;
2043 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2045 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2046 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2048 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2053 netr_NetrEnumerateTrustedDomainsEx
2055 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2056 struct netr_NetrEnumerateTrustedDomainsEx *r)
2058 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2063 netr_DsRAddressToSitenamesExW
2065 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2066 struct netr_DsRAddressToSitenamesExW *r)
2068 struct ldb_context *sam_ctx;
2069 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2070 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2071 sa_family_t sin_family;
2072 struct sockaddr_in *addr;
2073 #ifdef HAVE_IPV6
2074 struct sockaddr_in6 *addr6;
2075 char addr_str[INET6_ADDRSTRLEN];
2076 #else
2077 char addr_str[INET_ADDRSTRLEN];
2078 #endif
2079 char *subnet_name;
2080 const char *res;
2081 uint32_t i;
2083 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2084 dce_call->conn->auth_state.session_info, 0);
2085 if (sam_ctx == NULL) {
2086 return WERR_DS_UNAVAILABLE;
2089 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2090 W_ERROR_HAVE_NO_MEMORY(ctr);
2092 *r->out.ctr = ctr;
2094 ctr->count = r->in.count;
2095 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2096 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2097 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2098 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2100 for (i=0; i<ctr->count; i++) {
2101 ctr->sitename[i].string = NULL;
2102 ctr->subnetname[i].string = NULL;
2104 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2105 continue;
2107 /* The first two byte of the buffer are reserved for the
2108 * "sin_family" but for now only the first one is used. */
2109 sin_family = r->in.addresses[i].buffer[0];
2111 switch (sin_family) {
2112 case AF_INET:
2113 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2114 continue;
2116 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2117 res = inet_ntop(AF_INET, &addr->sin_addr,
2118 addr_str, sizeof(addr_str));
2119 break;
2120 #ifdef HAVE_IPV6
2121 case AF_INET6:
2122 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2123 continue;
2125 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2126 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2127 addr_str, sizeof(addr_str));
2128 break;
2129 #endif
2130 default:
2131 continue;
2134 if (res == NULL) {
2135 continue;
2138 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2139 mem_ctx,
2140 addr_str,
2141 &subnet_name);
2142 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2143 ctr->subnetname[i].string = subnet_name;
2146 return WERR_OK;
2151 netr_DsRAddressToSitenamesW
2153 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2154 struct netr_DsRAddressToSitenamesW *r)
2156 struct netr_DsRAddressToSitenamesExW r2;
2157 struct netr_DsRAddressToSitenamesWCtr *ctr;
2158 uint32_t i;
2159 WERROR werr;
2161 ZERO_STRUCT(r2);
2163 r2.in.server_name = r->in.server_name;
2164 r2.in.count = r->in.count;
2165 r2.in.addresses = r->in.addresses;
2167 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2168 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2170 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2171 W_ERROR_HAVE_NO_MEMORY(ctr);
2173 *r->out.ctr = ctr;
2175 ctr->count = r->in.count;
2176 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2177 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2179 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2181 for (i=0; i<ctr->count; i++) {
2182 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2185 return werr;
2190 netr_DsrGetDcSiteCoverageW
2192 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2193 struct netr_DsrGetDcSiteCoverageW *r)
2195 struct ldb_context *sam_ctx;
2196 struct DcSitesCtr *ctr;
2197 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2199 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2200 dce_call->conn->auth_state.session_info, 0);
2201 if (sam_ctx == NULL) {
2202 return WERR_DS_UNAVAILABLE;
2205 ctr = talloc(mem_ctx, struct DcSitesCtr);
2206 W_ERROR_HAVE_NO_MEMORY(ctr);
2208 *r->out.ctr = ctr;
2210 /* For now only return our default site */
2211 ctr->num_sites = 1;
2212 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2213 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2214 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2215 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2217 return WERR_OK;
2221 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2222 struct ldb_context *sam_ctx,
2223 struct netr_DomainTrustList *trusts,
2224 uint32_t trust_flags)
2226 struct ldb_dn *system_dn;
2227 struct ldb_message **dom_res = NULL;
2228 const char *trust_attrs[] = { "flatname", "trustPartner",
2229 "securityIdentifier", "trustDirection",
2230 "trustType", "trustAttributes", NULL };
2231 uint32_t n;
2232 int i;
2233 int ret;
2235 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2236 NETR_TRUST_FLAG_OUTBOUND))) {
2237 return WERR_INVALID_FLAGS;
2240 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2241 ldb_get_default_basedn(sam_ctx),
2242 "(&(objectClass=container)(cn=System))");
2243 if (!system_dn) {
2244 return WERR_GENERAL_FAILURE;
2247 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2248 &dom_res, trust_attrs,
2249 "(objectclass=trustedDomain)");
2251 for (i = 0; i < ret; i++) {
2252 unsigned int trust_dir;
2253 uint32_t flags = 0;
2255 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2256 "trustDirection", 0);
2258 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2259 flags |= NETR_TRUST_FLAG_INBOUND;
2261 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2262 flags |= NETR_TRUST_FLAG_OUTBOUND;
2265 if (!(flags & trust_flags)) {
2266 /* this trust direction was not requested */
2267 continue;
2270 n = trusts->count;
2271 trusts->array = talloc_realloc(trusts, trusts->array,
2272 struct netr_DomainTrust,
2273 n + 1);
2274 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2276 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2277 if (!trusts->array[n].netbios_name) {
2278 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2279 "without flatname\n",
2280 ldb_dn_get_linearized(dom_res[i]->dn)));
2283 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2285 trusts->array[n].trust_flags = flags;
2286 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2287 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2288 /* TODO: find if we have parent in the list */
2289 trusts->array[n].parent_index = 0;
2292 trusts->array[n].trust_type =
2293 ldb_msg_find_attr_as_uint(dom_res[i],
2294 "trustType", 0);
2295 trusts->array[n].trust_attributes =
2296 ldb_msg_find_attr_as_uint(dom_res[i],
2297 "trustAttributes", 0);
2299 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2300 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2301 struct dom_sid zero_sid;
2302 ZERO_STRUCT(zero_sid);
2303 trusts->array[n].sid =
2304 dom_sid_dup(trusts, &zero_sid);
2305 } else {
2306 trusts->array[n].sid =
2307 samdb_result_dom_sid(trusts, dom_res[i],
2308 "securityIdentifier");
2310 trusts->array[n].guid = GUID_zero();
2312 trusts->count = n + 1;
2315 talloc_free(dom_res);
2316 return WERR_OK;
2320 netr_DsrEnumerateDomainTrusts
2322 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2323 TALLOC_CTX *mem_ctx,
2324 struct netr_DsrEnumerateDomainTrusts *r)
2326 struct netr_DomainTrustList *trusts;
2327 struct ldb_context *sam_ctx;
2328 int ret;
2329 struct ldb_message **dom_res;
2330 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2331 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2332 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2333 const char *p;
2334 WERROR werr;
2336 if (r->in.trust_flags & 0xFFFFFE00) {
2337 return WERR_INVALID_FLAGS;
2340 /* TODO: turn to hard check once we are sure this is 100% correct */
2341 if (!r->in.server_name) {
2342 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2343 "But received NULL!\n", dnsdomain));
2344 } else {
2345 p = strchr(r->in.server_name, '.');
2346 if (!p) {
2347 DEBUG(3, ("Invalid domain! Expected name in domain "
2348 "[%s]. But received [%s]!\n",
2349 dnsdomain, r->in.server_name));
2350 p = r->in.server_name;
2351 } else {
2352 p++;
2354 if (strcasecmp(p, dnsdomain)) {
2355 DEBUG(3, ("Invalid domain! Expected name in domain "
2356 "[%s]. But received [%s]!\n",
2357 dnsdomain, r->in.server_name));
2361 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2362 W_ERROR_HAVE_NO_MEMORY(trusts);
2364 trusts->count = 0;
2365 r->out.trusts = trusts;
2367 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2368 dce_call->conn->auth_state.session_info, 0);
2369 if (sam_ctx == NULL) {
2370 return WERR_GENERAL_FAILURE;
2373 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2374 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2376 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2377 trusts, r->in.trust_flags);
2378 W_ERROR_NOT_OK_RETURN(werr);
2381 /* NOTE: we currently are always the root of the forest */
2382 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2383 uint32_t n = trusts->count;
2385 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2386 &dom_res, dom_attrs);
2387 if (ret != 1) {
2388 return WERR_GENERAL_FAILURE;
2391 trusts->count = n + 1;
2392 trusts->array = talloc_realloc(trusts, trusts->array,
2393 struct netr_DomainTrust,
2394 trusts->count);
2395 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2397 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2398 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2399 trusts->array[n].trust_flags =
2400 NETR_TRUST_FLAG_NATIVE |
2401 NETR_TRUST_FLAG_TREEROOT |
2402 NETR_TRUST_FLAG_IN_FOREST |
2403 NETR_TRUST_FLAG_PRIMARY;
2404 /* we are always the root domain for now */
2405 trusts->array[n].parent_index = 0;
2406 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2407 trusts->array[n].trust_attributes = 0;
2408 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2409 dom_res[0],
2410 "objectSid");
2411 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2412 "objectGUID");
2413 talloc_free(dom_res);
2416 return WERR_OK;
2421 netr_DsrDeregisterDNSHostRecords
2423 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2424 struct netr_DsrDeregisterDNSHostRecords *r)
2426 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2431 netr_ServerTrustPasswordsGet
2433 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2434 struct netr_ServerTrustPasswordsGet *r)
2436 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2440 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2441 struct ldb_context *sam_ctx,
2442 struct loadparm_context *lp_ctx,
2443 struct lsa_ForestTrustInformation *info)
2445 struct lsa_ForestTrustDomainInfo *domain_info;
2446 struct lsa_ForestTrustRecord *e;
2447 struct ldb_message **dom_res;
2448 const char * const dom_attrs[] = { "objectSid", NULL };
2449 int ret;
2451 /* we need to provide 2 entries:
2452 * 1. the Root Forest name
2453 * 2. the Domain Information
2456 info->count = 2;
2457 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2458 W_ERROR_HAVE_NO_MEMORY(info->entries);
2460 /* Forest root info */
2461 e = talloc(info, struct lsa_ForestTrustRecord);
2462 W_ERROR_HAVE_NO_MEMORY(e);
2464 e->flags = 0;
2465 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2466 e->time = 0; /* so far always 0 in trces. */
2467 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2468 mem_ctx);
2469 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2471 info->entries[0] = e;
2473 /* Domain info */
2474 e = talloc(info, struct lsa_ForestTrustRecord);
2475 W_ERROR_HAVE_NO_MEMORY(e);
2477 /* get our own domain info */
2478 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2479 if (ret != 1) {
2480 return WERR_GENERAL_FAILURE;
2483 /* TODO: check if disabled and set flags accordingly */
2484 e->flags = 0;
2485 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2486 e->time = 0; /* so far always 0 in traces. */
2488 domain_info = &e->forest_trust_data.domain_info;
2489 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2490 "objectSid");
2491 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2492 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2494 info->entries[1] = e;
2496 talloc_free(dom_res);
2498 return WERR_OK;
2502 netr_DsRGetForestTrustInformation
2504 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2505 TALLOC_CTX *mem_ctx,
2506 struct netr_DsRGetForestTrustInformation *r)
2508 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2509 struct lsa_ForestTrustInformation *info, **info_ptr;
2510 struct ldb_context *sam_ctx;
2511 WERROR werr;
2513 if (r->in.flags & 0xFFFFFFFE) {
2514 return WERR_INVALID_FLAGS;
2517 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2518 dce_call->conn->auth_state.session_info, 0);
2519 if (sam_ctx == NULL) {
2520 return WERR_GENERAL_FAILURE;
2523 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2524 if (!samdb_is_pdc(sam_ctx)) {
2525 return WERR_NERR_NOTPRIMARY;
2528 if (r->in.trusted_domain_name == NULL) {
2529 return WERR_INVALID_FLAGS;
2532 /* TODO: establish an schannel connection with
2533 * r->in.trusted_domain_name and perform a
2534 * netr_GetForestTrustInformation call against it */
2536 /* for now return not implementd */
2537 return WERR_CALL_NOT_IMPLEMENTED;
2540 /* TODO: check r->in.server_name is our name */
2542 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2543 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2545 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2546 W_ERROR_HAVE_NO_MEMORY(info);
2548 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2549 W_ERROR_NOT_OK_RETURN(werr);
2551 *info_ptr = info;
2552 r->out.forest_trust_info = info_ptr;
2554 return WERR_OK;
2559 netr_GetForestTrustInformation
2561 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2562 TALLOC_CTX *mem_ctx,
2563 struct netr_GetForestTrustInformation *r)
2565 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2566 struct netlogon_creds_CredentialState *creds;
2567 struct lsa_ForestTrustInformation *info, **info_ptr;
2568 struct ldb_context *sam_ctx;
2569 NTSTATUS status;
2570 WERROR werr;
2572 status = dcesrv_netr_creds_server_step_check(dce_call,
2573 mem_ctx,
2574 r->in.computer_name,
2575 r->in.credential,
2576 r->out.return_authenticator,
2577 &creds);
2578 if (!NT_STATUS_IS_OK(status)) {
2579 return status;
2582 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2583 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2584 return NT_STATUS_NOT_IMPLEMENTED;
2587 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2588 dce_call->conn->auth_state.session_info, 0);
2589 if (sam_ctx == NULL) {
2590 return NT_STATUS_INTERNAL_ERROR;
2593 /* TODO: check r->in.server_name is our name */
2595 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2596 if (!info_ptr) {
2597 return NT_STATUS_NO_MEMORY;
2599 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2600 if (!info) {
2601 return NT_STATUS_NO_MEMORY;
2604 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2605 if (!W_ERROR_IS_OK(werr)) {
2606 return werror_to_ntstatus(werr);
2609 *info_ptr = info;
2610 r->out.forest_trust_info = info_ptr;
2612 return NT_STATUS_OK;
2617 netr_ServerGetTrustInfo
2619 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2620 struct netr_ServerGetTrustInfo *r)
2622 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2626 netr_Unused47
2628 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2629 struct netr_Unused47 *r)
2631 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2635 struct netr_dnsupdate_RODC_state {
2636 struct dcesrv_call_state *dce_call;
2637 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2638 struct dnsupdate_RODC *r2;
2642 called when the forwarded RODC dns update request is finished
2644 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2646 struct netr_dnsupdate_RODC_state *st =
2647 tevent_req_callback_data(subreq,
2648 struct netr_dnsupdate_RODC_state);
2649 NTSTATUS status;
2651 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2652 TALLOC_FREE(subreq);
2653 if (!NT_STATUS_IS_OK(status)) {
2654 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2655 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2658 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2660 status = dcesrv_reply(st->dce_call);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2667 netr_DsrUpdateReadOnlyServerDnsRecords
2669 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2670 TALLOC_CTX *mem_ctx,
2671 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2673 struct netlogon_creds_CredentialState *creds;
2674 NTSTATUS nt_status;
2675 struct dcerpc_binding_handle *binding_handle;
2676 struct netr_dnsupdate_RODC_state *st;
2677 struct tevent_req *subreq;
2679 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2680 mem_ctx,
2681 r->in.computer_name,
2682 r->in.credential,
2683 r->out.return_authenticator,
2684 &creds);
2685 NT_STATUS_NOT_OK_RETURN(nt_status);
2687 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2688 return NT_STATUS_ACCESS_DENIED;
2691 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2692 NT_STATUS_HAVE_NO_MEMORY(st);
2694 st->dce_call = dce_call;
2695 st->r = r;
2696 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2697 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2699 st->r2->in.dom_sid = creds->sid;
2700 st->r2->in.site_name = r->in.site_name;
2701 st->r2->in.dns_ttl = r->in.dns_ttl;
2702 st->r2->in.dns_names = r->in.dns_names;
2703 st->r2->out.dns_names = r->out.dns_names;
2705 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2706 "dnsupdate", &ndr_table_irpc);
2707 if (binding_handle == NULL) {
2708 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2709 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2710 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2713 /* forward the call */
2714 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2715 binding_handle, st->r2);
2716 NT_STATUS_HAVE_NO_MEMORY(subreq);
2718 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2720 /* setup the callback */
2721 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2723 return NT_STATUS_OK;
2727 /* include the generated boilerplate */
2728 #include "librpc/gen_ndr/ndr_netlogon_s.c"