s4:rpc_server/netlogon: extract and pass down the password version in dcesrv_netr_Ser...
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobe9f07f84fc228c1a213c0ab3fd10d44bfb69807d
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 "lib/socket/netif.h"
45 static struct memcache *global_challenge_table;
47 struct netlogon_server_pipe_state {
48 struct netr_Credential client_challenge;
49 struct netr_Credential server_challenge;
52 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
53 struct netr_ServerReqChallenge *r)
55 struct netlogon_server_pipe_state *pipe_state =
56 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
57 DATA_BLOB key, val;
59 ZERO_STRUCTP(r->out.return_credentials);
61 if (global_challenge_table == NULL) {
63 * We maintain a global challenge table
64 * with a fixed size (8k)
66 * This is required for the strange clients
67 * which use different connections for
68 * netr_ServerReqChallenge() and netr_ServerAuthenticate3()
71 global_challenge_table = memcache_init(talloc_autofree_context(),
72 8192);
73 if (global_challenge_table == NULL) {
74 return NT_STATUS_NO_MEMORY;
78 /* destroyed on pipe shutdown */
80 if (pipe_state) {
81 talloc_free(pipe_state);
82 dce_call->context->private_data = NULL;
85 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
86 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
88 pipe_state->client_challenge = *r->in.credentials;
90 generate_random_buffer(pipe_state->server_challenge.data,
91 sizeof(pipe_state->server_challenge.data));
93 *r->out.return_credentials = pipe_state->server_challenge;
95 dce_call->context->private_data = pipe_state;
97 key = data_blob_string_const(r->in.computer_name);
98 val = data_blob_const(pipe_state, sizeof(*pipe_state));
100 memcache_add(global_challenge_table, SINGLETON_CACHE, key, val);
102 return NT_STATUS_OK;
105 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
106 struct netr_ServerAuthenticate3 *r)
108 struct netlogon_server_pipe_state *pipe_state =
109 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
110 DATA_BLOB challenge_key;
111 bool challenge_valid = false;
112 struct netlogon_server_pipe_state challenge;
113 struct netlogon_creds_CredentialState *creds;
114 struct ldb_context *sam_ctx;
115 struct samr_Password *mach_pwd;
116 uint32_t user_account_control;
117 int num_records;
118 struct ldb_message **msgs;
119 NTSTATUS nt_status;
120 const char *attrs[] = {"unicodePwd", "userAccountControl",
121 "objectSid", NULL};
123 const char *trust_dom_attrs[] = {"flatname", NULL};
124 const char *account_name;
125 uint32_t server_flags = 0;
126 uint32_t negotiate_flags = 0;
127 bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
128 bool reject_des_client = !allow_nt4_crypto;
129 bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
131 ZERO_STRUCTP(r->out.return_credentials);
132 *r->out.rid = 0;
134 challenge_key = data_blob_string_const(r->in.computer_name);
135 if (pipe_state != NULL) {
136 dce_call->context->private_data = NULL;
139 * If we had a challenge remembered on the connection
140 * consider this for usage. This can't be cleanup
141 * by other clients.
143 * This is the default code path for typical clients
144 * which call netr_ServerReqChallenge() and
145 * netr_ServerAuthenticate3() on the same dcerpc connection.
147 challenge = *pipe_state;
148 TALLOC_FREE(pipe_state);
149 challenge_valid = true;
150 } else {
151 DATA_BLOB val;
152 bool ok;
155 * Fallback and try to get the challenge from
156 * the global cache.
158 * If too many clients are using this code path,
159 * they may destroy their cache entries as the
160 * global_challenge_table memcache has a fixed size.
162 * Note: this handles global_challenge_table == NULL fine
164 ok = memcache_lookup(global_challenge_table, SINGLETON_CACHE,
165 challenge_key, &val);
166 if (ok && val.length == sizeof(challenge)) {
167 memcpy(&challenge, val.data, sizeof(challenge));
168 challenge_valid = true;
169 } else {
170 ZERO_STRUCT(challenge);
175 * At this point we can cleanup the cache entry,
176 * if we fail the client needs to call netr_ServerReqChallenge
177 * again.
179 * Note: this handles global_challenge_table == NULL
180 * and also a non existing record just fine.
182 memcache_delete(global_challenge_table,
183 SINGLETON_CACHE, challenge_key);
185 server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
186 NETLOGON_NEG_PERSISTENT_SAMREPL |
187 NETLOGON_NEG_ARCFOUR |
188 NETLOGON_NEG_PROMOTION_COUNT |
189 NETLOGON_NEG_CHANGELOG_BDC |
190 NETLOGON_NEG_FULL_SYNC_REPL |
191 NETLOGON_NEG_MULTIPLE_SIDS |
192 NETLOGON_NEG_REDO |
193 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
194 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
195 NETLOGON_NEG_GENERIC_PASSTHROUGH |
196 NETLOGON_NEG_CONCURRENT_RPC |
197 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
198 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
199 NETLOGON_NEG_STRONG_KEYS |
200 NETLOGON_NEG_TRANSITIVE_TRUSTS |
201 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
202 NETLOGON_NEG_PASSWORD_SET2 |
203 NETLOGON_NEG_GETDOMAININFO |
204 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
205 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
206 NETLOGON_NEG_RODC_PASSTHROUGH |
207 NETLOGON_NEG_SUPPORTS_AES |
208 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
209 NETLOGON_NEG_AUTHENTICATED_RPC;
211 negotiate_flags = *r->in.negotiate_flags & server_flags;
213 if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
214 reject_des_client = false;
217 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
218 reject_des_client = false;
219 reject_md5_client = false;
222 if (reject_des_client || reject_md5_client) {
224 * Here we match Windows 2012 and return no flags.
226 *r->out.negotiate_flags = 0;
227 return NT_STATUS_DOWNGRADE_DETECTED;
231 * According to Microsoft (see bugid #6099)
232 * Windows 7 looks at the negotiate_flags
233 * returned in this structure *even if the
234 * call fails with access denied!
236 *r->out.negotiate_flags = negotiate_flags;
238 switch (r->in.secure_channel_type) {
239 case SEC_CHAN_WKSTA:
240 case SEC_CHAN_DNS_DOMAIN:
241 case SEC_CHAN_DOMAIN:
242 case SEC_CHAN_BDC:
243 case SEC_CHAN_RODC:
244 break;
245 case SEC_CHAN_NULL:
246 return NT_STATUS_INVALID_PARAMETER;
247 default:
248 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
249 r->in.secure_channel_type));
250 return NT_STATUS_INVALID_PARAMETER;
253 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
254 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
255 if (sam_ctx == NULL) {
256 return NT_STATUS_INVALID_SYSTEM_SERVICE;
259 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
260 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
261 const char *flatname;
262 if (!encoded_account) {
263 return NT_STATUS_NO_MEMORY;
266 /* Kill the trailing dot */
267 if (encoded_account[strlen(encoded_account)-1] == '.') {
268 encoded_account[strlen(encoded_account)-1] = '\0';
271 /* pull the user attributes */
272 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
273 trust_dom_attrs,
274 "(&(trustPartner=%s)(objectclass=trustedDomain))",
275 encoded_account);
277 if (num_records == 0) {
278 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
279 encoded_account));
280 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
283 if (num_records > 1) {
284 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
285 return NT_STATUS_INTERNAL_DB_CORRUPTION;
288 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
289 if (!flatname) {
290 /* No flatname for this trust - we can't proceed */
291 DEBUG(3,("Couldn't find flatname for trust [%s] in samdb.\n",
292 encoded_account));
293 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
295 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
297 if (!account_name) {
298 return NT_STATUS_NO_MEMORY;
301 } else {
302 account_name = r->in.account_name;
305 /* pull the user attributes */
306 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
307 "(&(sAMAccountName=%s)(objectclass=user))",
308 ldb_binary_encode_string(mem_ctx, account_name));
310 if (num_records == 0) {
311 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
312 r->in.account_name));
313 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
316 if (num_records > 1) {
317 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
318 return NT_STATUS_INTERNAL_DB_CORRUPTION;
321 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
323 if (user_account_control & UF_ACCOUNTDISABLE) {
324 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
325 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
328 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
329 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
330 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
331 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
333 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
334 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
335 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
336 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
338 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
340 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
341 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
342 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
343 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
345 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
346 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
347 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
348 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
350 } else {
351 /* we should never reach this */
352 return NT_STATUS_INTERNAL_ERROR;
355 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
356 if (mach_pwd == NULL) {
357 return NT_STATUS_ACCESS_DENIED;
360 if (!challenge_valid) {
361 DEBUG(1, ("No challenge requested by client [%s/%s], "
362 "cannot authenticate\n",
363 r->in.computer_name,
364 r->in.account_name));
365 return NT_STATUS_ACCESS_DENIED;
368 creds = netlogon_creds_server_init(mem_ctx,
369 r->in.account_name,
370 r->in.computer_name,
371 r->in.secure_channel_type,
372 &challenge.client_challenge,
373 &challenge.server_challenge,
374 mach_pwd,
375 r->in.credentials,
376 r->out.return_credentials,
377 negotiate_flags);
378 if (!creds) {
379 return NT_STATUS_ACCESS_DENIED;
382 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
384 nt_status = schannel_save_creds_state(mem_ctx,
385 dce_call->conn->dce_ctx->lp_ctx,
386 creds);
387 if (!NT_STATUS_IS_OK(nt_status)) {
388 ZERO_STRUCTP(r->out.return_credentials);
389 return nt_status;
392 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
393 "objectSid", 0);
395 return NT_STATUS_OK;
398 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
399 struct netr_ServerAuthenticate *r)
401 struct netr_ServerAuthenticate3 a;
402 uint32_t rid;
403 /* TODO:
404 * negotiate_flags is used as an [in] parameter
405 * so it need to be initialised.
407 * (I think ... = 0; seems wrong here --metze)
409 uint32_t negotiate_flags_in = 0;
410 uint32_t negotiate_flags_out = 0;
412 a.in.server_name = r->in.server_name;
413 a.in.account_name = r->in.account_name;
414 a.in.secure_channel_type = r->in.secure_channel_type;
415 a.in.computer_name = r->in.computer_name;
416 a.in.credentials = r->in.credentials;
417 a.in.negotiate_flags = &negotiate_flags_in;
419 a.out.return_credentials = r->out.return_credentials;
420 a.out.rid = &rid;
421 a.out.negotiate_flags = &negotiate_flags_out;
423 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
426 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
427 struct netr_ServerAuthenticate2 *r)
429 struct netr_ServerAuthenticate3 r3;
430 uint32_t rid = 0;
432 r3.in.server_name = r->in.server_name;
433 r3.in.account_name = r->in.account_name;
434 r3.in.secure_channel_type = r->in.secure_channel_type;
435 r3.in.computer_name = r->in.computer_name;
436 r3.in.credentials = r->in.credentials;
437 r3.out.return_credentials = r->out.return_credentials;
438 r3.in.negotiate_flags = r->in.negotiate_flags;
439 r3.out.negotiate_flags = r->out.negotiate_flags;
440 r3.out.rid = &rid;
442 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
446 * NOTE: The following functions are nearly identical to the ones available in
447 * source3/rpc_server/srv_nelog_nt.c
448 * The reason we keep 2 copies is that they use different structures to
449 * represent the auth_info and the decrpc pipes.
453 * If schannel is required for this call test that it actually is available.
455 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
456 const char *computer_name,
457 bool integrity, bool privacy)
460 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
461 if (!privacy && !integrity) {
462 return NT_STATUS_OK;
465 if ((!privacy && integrity) &&
466 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
467 return NT_STATUS_OK;
470 if ((privacy || integrity) &&
471 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
472 return NT_STATUS_OK;
476 /* test didn't pass */
477 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
478 computer_name));
480 return NT_STATUS_ACCESS_DENIED;
483 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
484 TALLOC_CTX *mem_ctx,
485 const char *computer_name,
486 struct netr_Authenticator *received_authenticator,
487 struct netr_Authenticator *return_authenticator,
488 struct netlogon_creds_CredentialState **creds_out)
490 NTSTATUS nt_status;
491 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
492 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
494 if (schannel_global_required) {
495 nt_status = schannel_check_required(auth_info,
496 computer_name,
497 true, false);
498 if (!NT_STATUS_IS_OK(nt_status)) {
499 return nt_status;
503 nt_status = schannel_check_creds_state(mem_ctx,
504 dce_call->conn->dce_ctx->lp_ctx,
505 computer_name,
506 received_authenticator,
507 return_authenticator,
508 creds_out);
509 return nt_status;
513 Change the machine account password for the currently connected
514 client. Supplies only the NT#.
517 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct netr_ServerPasswordSet *r)
520 struct netlogon_creds_CredentialState *creds;
521 struct ldb_context *sam_ctx;
522 const char * const attrs[] = { "unicodePwd", NULL };
523 struct ldb_message **res;
524 struct samr_Password *oldNtHash;
525 NTSTATUS nt_status;
526 int ret;
528 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
529 mem_ctx,
530 r->in.computer_name,
531 r->in.credential, r->out.return_authenticator,
532 &creds);
533 NT_STATUS_NOT_OK_RETURN(nt_status);
535 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);
536 if (sam_ctx == NULL) {
537 return NT_STATUS_INVALID_SYSTEM_SERVICE;
540 netlogon_creds_des_decrypt(creds, r->in.new_password);
542 /* fetch the old password hashes (the NT hash has to exist) */
544 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
545 "(&(objectClass=user)(objectSid=%s))",
546 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
547 if (ret != 1) {
548 return NT_STATUS_WRONG_PASSWORD;
551 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
552 dce_call->conn->dce_ctx->lp_ctx,
553 res[0], NULL, &oldNtHash);
554 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
555 return NT_STATUS_WRONG_PASSWORD;
558 /* Using the sid for the account as the key, set the password */
559 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
560 creds->sid,
561 NULL, /* Don't have version */
562 NULL, /* Don't have plaintext */
563 NULL, r->in.new_password,
564 NULL, oldNtHash, /* Password change */
565 NULL, NULL);
566 return nt_status;
570 Change the machine account password for the currently connected
571 client. Supplies new plaintext.
573 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
574 struct netr_ServerPasswordSet2 *r)
576 struct netlogon_creds_CredentialState *creds;
577 struct ldb_context *sam_ctx;
578 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
579 struct ldb_message **res;
580 struct samr_Password *oldLmHash, *oldNtHash;
581 struct NL_PASSWORD_VERSION version = {};
582 const uint32_t *new_version = NULL;
583 NTSTATUS nt_status;
584 DATA_BLOB new_password;
585 int ret;
586 struct samr_CryptPassword password_buf;
588 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
589 mem_ctx,
590 r->in.computer_name,
591 r->in.credential, r->out.return_authenticator,
592 &creds);
593 NT_STATUS_NOT_OK_RETURN(nt_status);
595 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);
596 if (sam_ctx == NULL) {
597 return NT_STATUS_INVALID_SYSTEM_SERVICE;
600 memcpy(password_buf.data, r->in.new_password->data, 512);
601 SIVAL(password_buf.data, 512, r->in.new_password->length);
603 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
604 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
605 } else {
606 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
609 switch (creds->secure_channel_type) {
610 case SEC_CHAN_DOMAIN:
611 case SEC_CHAN_DNS_DOMAIN: {
612 uint32_t len = IVAL(password_buf.data, 512);
613 if (len <= 500) {
614 uint32_t ofs = 500 - len;
615 uint8_t *p;
617 p = password_buf.data + ofs;
619 version.ReservedField = IVAL(p, 0);
620 version.PasswordVersionNumber = IVAL(p, 4);
621 version.PasswordVersionPresent = IVAL(p, 8);
623 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
624 new_version = &version.PasswordVersionNumber;
627 break;
628 default:
629 break;
632 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
633 DEBUG(3,("samr: failed to decode password buffer\n"));
634 return NT_STATUS_WRONG_PASSWORD;
637 /* fetch the old password hashes (at least one of both has to exist) */
639 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
640 "(&(objectClass=user)(objectSid=%s))",
641 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
642 if (ret != 1) {
643 return NT_STATUS_WRONG_PASSWORD;
646 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
647 dce_call->conn->dce_ctx->lp_ctx,
648 res[0], &oldLmHash, &oldNtHash);
649 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
650 return NT_STATUS_WRONG_PASSWORD;
653 /* Using the sid for the account as the key, set the password */
654 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
655 creds->sid,
656 new_version,
657 &new_password, /* we have plaintext */
658 NULL, NULL,
659 oldLmHash, oldNtHash, /* Password change */
660 NULL, NULL);
661 return nt_status;
666 netr_LogonUasLogon
668 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
669 struct netr_LogonUasLogon *r)
671 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
676 netr_LogonUasLogoff
678 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
679 struct netr_LogonUasLogoff *r)
681 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
685 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
687 switch (r->in.logon_level) {
688 case NetlogonInteractiveInformation:
689 case NetlogonServiceInformation:
690 case NetlogonInteractiveTransitiveInformation:
691 case NetlogonServiceTransitiveInformation:
692 if (r->in.logon->password == NULL) {
693 return NT_STATUS_INVALID_PARAMETER;
696 switch (r->in.validation_level) {
697 case NetlogonValidationSamInfo: /* 2 */
698 case NetlogonValidationSamInfo2: /* 3 */
699 case NetlogonValidationSamInfo4: /* 6 */
700 break;
701 default:
702 return NT_STATUS_INVALID_INFO_CLASS;
705 break;
706 case NetlogonNetworkInformation:
707 case NetlogonNetworkTransitiveInformation:
708 if (r->in.logon->network == NULL) {
709 return NT_STATUS_INVALID_PARAMETER;
712 switch (r->in.validation_level) {
713 case NetlogonValidationSamInfo: /* 2 */
714 case NetlogonValidationSamInfo2: /* 3 */
715 case NetlogonValidationSamInfo4: /* 6 */
716 break;
717 default:
718 return NT_STATUS_INVALID_INFO_CLASS;
721 break;
723 case NetlogonGenericInformation:
724 if (r->in.logon->generic == NULL) {
725 return NT_STATUS_INVALID_PARAMETER;
728 switch (r->in.validation_level) {
729 /* TODO: case NetlogonValidationGenericInfo: 4 */
730 case NetlogonValidationGenericInfo2: /* 5 */
731 break;
732 default:
733 return NT_STATUS_INVALID_INFO_CLASS;
736 break;
737 default:
738 return NT_STATUS_INVALID_PARAMETER;
741 return NT_STATUS_OK;
745 netr_LogonSamLogon_base
747 This version of the function allows other wrappers to say 'do not check the credentials'
749 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
751 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
752 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
754 struct auth4_context *auth_context;
755 struct auth_usersupplied_info *user_info;
756 struct auth_user_info_dc *user_info_dc;
757 NTSTATUS nt_status;
758 struct netr_SamBaseInfo *sam;
759 struct netr_SamInfo2 *sam2;
760 struct netr_SamInfo3 *sam3;
761 struct netr_SamInfo6 *sam6;
763 *r->out.authoritative = 1;
765 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
766 NT_STATUS_HAVE_NO_MEMORY(user_info);
768 netlogon_creds_decrypt_samlogon_logon(creds,
769 r->in.logon_level,
770 r->in.logon);
772 switch (r->in.logon_level) {
773 case NetlogonInteractiveInformation:
774 case NetlogonServiceInformation:
775 case NetlogonInteractiveTransitiveInformation:
776 case NetlogonServiceTransitiveInformation:
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 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
786 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
787 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
788 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
790 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
791 user_info->password_state = AUTH_PASSWORD_HASH;
793 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
794 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
795 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
797 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
798 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
799 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
801 break;
802 case NetlogonNetworkInformation:
803 case NetlogonNetworkTransitiveInformation:
805 /* TODO: we need to deny anonymous access here */
806 nt_status = auth_context_create(mem_ctx,
807 dce_call->event_ctx, dce_call->msg_ctx,
808 dce_call->conn->dce_ctx->lp_ctx,
809 &auth_context);
810 NT_STATUS_NOT_OK_RETURN(nt_status);
812 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
813 NT_STATUS_NOT_OK_RETURN(nt_status);
815 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
816 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
817 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
818 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
820 user_info->password_state = AUTH_PASSWORD_RESPONSE;
821 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
822 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
824 break;
827 case NetlogonGenericInformation:
829 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
830 /* OK */
831 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
832 /* OK */
833 } else {
834 /* Using DES to verify kerberos tickets makes no sense */
835 return NT_STATUS_INVALID_PARAMETER;
838 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
839 NTSTATUS status;
840 struct dcerpc_binding_handle *irpc_handle;
841 struct kdc_check_generic_kerberos check;
842 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
843 NT_STATUS_HAVE_NO_MEMORY(generic);
844 *r->out.authoritative = 1;
846 /* TODO: Describe and deal with these flags */
847 *r->out.flags = 0;
849 r->out.validation->generic = generic;
851 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
852 dce_call->msg_ctx,
853 "kdc_server",
854 &ndr_table_irpc);
855 if (irpc_handle == NULL) {
856 return NT_STATUS_NO_LOGON_SERVERS;
859 check.in.generic_request =
860 data_blob_const(r->in.logon->generic->data,
861 r->in.logon->generic->length);
864 * TODO: make this async and avoid
865 * dcerpc_binding_handle_set_sync_ev()
867 dcerpc_binding_handle_set_sync_ev(irpc_handle,
868 dce_call->event_ctx);
869 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
870 mem_ctx,
871 &check);
872 if (!NT_STATUS_IS_OK(status)) {
873 return status;
875 generic->length = check.out.generic_reply.length;
876 generic->data = check.out.generic_reply.data;
877 return NT_STATUS_OK;
880 /* Until we get an implemetnation of these other packages */
881 return NT_STATUS_INVALID_PARAMETER;
883 default:
884 return NT_STATUS_INVALID_PARAMETER;
887 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
888 /* TODO: set *r->out.authoritative = 0 on specific errors */
889 NT_STATUS_NOT_OK_RETURN(nt_status);
891 switch (r->in.validation_level) {
892 case 2:
893 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
894 NT_STATUS_NOT_OK_RETURN(nt_status);
896 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
897 NT_STATUS_HAVE_NO_MEMORY(sam2);
898 sam2->base = *sam;
900 /* And put into the talloc tree */
901 talloc_steal(sam2, sam);
902 r->out.validation->sam2 = sam2;
904 sam = &sam2->base;
905 break;
907 case 3:
908 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
909 user_info_dc,
910 &sam3);
911 NT_STATUS_NOT_OK_RETURN(nt_status);
913 r->out.validation->sam3 = sam3;
915 sam = &sam3->base;
916 break;
918 case 6:
919 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
920 user_info_dc,
921 &sam3);
922 NT_STATUS_NOT_OK_RETURN(nt_status);
924 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
925 NT_STATUS_HAVE_NO_MEMORY(sam6);
926 sam6->base = sam3->base;
927 sam = &sam6->base;
928 sam6->sidcount = sam3->sidcount;
929 sam6->sids = sam3->sids;
931 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
932 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
933 sam->account_name.string, sam6->dns_domainname.string);
934 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
935 /* And put into the talloc tree */
936 talloc_steal(sam6, sam3);
938 r->out.validation->sam6 = sam6;
939 break;
941 default:
942 return NT_STATUS_INVALID_INFO_CLASS;
945 netlogon_creds_encrypt_samlogon_validation(creds,
946 r->in.validation_level,
947 r->out.validation);
949 /* TODO: Describe and deal with these flags */
950 *r->out.flags = 0;
952 return NT_STATUS_OK;
955 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
956 struct netr_LogonSamLogonEx *r)
958 NTSTATUS nt_status;
959 struct netlogon_creds_CredentialState *creds;
961 *r->out.authoritative = 1;
963 nt_status = dcesrv_netr_LogonSamLogon_check(r);
964 if (!NT_STATUS_IS_OK(nt_status)) {
965 return nt_status;
968 nt_status = schannel_get_creds_state(mem_ctx,
969 dce_call->conn->dce_ctx->lp_ctx,
970 r->in.computer_name, &creds);
971 if (!NT_STATUS_IS_OK(nt_status)) {
972 return nt_status;
975 if (!dce_call->conn->auth_state.auth_info ||
976 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
977 return NT_STATUS_ACCESS_DENIED;
979 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
983 netr_LogonSamLogonWithFlags
986 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
987 struct netr_LogonSamLogonWithFlags *r)
989 NTSTATUS nt_status;
990 struct netlogon_creds_CredentialState *creds;
991 struct netr_LogonSamLogonEx r2;
993 struct netr_Authenticator *return_authenticator;
995 ZERO_STRUCT(r2);
997 r2.in.server_name = r->in.server_name;
998 r2.in.computer_name = r->in.computer_name;
999 r2.in.logon_level = r->in.logon_level;
1000 r2.in.logon = r->in.logon;
1001 r2.in.validation_level = r->in.validation_level;
1002 r2.in.flags = r->in.flags;
1003 r2.out.validation = r->out.validation;
1004 r2.out.authoritative = r->out.authoritative;
1005 r2.out.flags = r->out.flags;
1007 *r->out.authoritative = 1;
1009 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1010 if (!NT_STATUS_IS_OK(nt_status)) {
1011 return nt_status;
1014 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1015 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1017 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1018 mem_ctx,
1019 r->in.computer_name,
1020 r->in.credential, return_authenticator,
1021 &creds);
1022 NT_STATUS_NOT_OK_RETURN(nt_status);
1024 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1026 r->out.return_authenticator = return_authenticator;
1028 return nt_status;
1032 netr_LogonSamLogon
1034 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1035 struct netr_LogonSamLogon *r)
1037 struct netr_LogonSamLogonWithFlags r2;
1038 uint32_t flags = 0;
1039 NTSTATUS status;
1041 ZERO_STRUCT(r2);
1043 r2.in.server_name = r->in.server_name;
1044 r2.in.computer_name = r->in.computer_name;
1045 r2.in.credential = r->in.credential;
1046 r2.in.return_authenticator = r->in.return_authenticator;
1047 r2.in.logon_level = r->in.logon_level;
1048 r2.in.logon = r->in.logon;
1049 r2.in.validation_level = r->in.validation_level;
1050 r2.in.flags = &flags;
1051 r2.out.validation = r->out.validation;
1052 r2.out.authoritative = r->out.authoritative;
1053 r2.out.flags = &flags;
1055 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1057 r->out.return_authenticator = r2.out.return_authenticator;
1059 return status;
1064 netr_LogonSamLogoff
1066 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1067 struct netr_LogonSamLogoff *r)
1069 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1075 netr_DatabaseDeltas
1077 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1078 struct netr_DatabaseDeltas *r)
1080 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1085 netr_DatabaseSync2
1087 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1088 struct netr_DatabaseSync2 *r)
1090 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1091 return NT_STATUS_NOT_IMPLEMENTED;
1096 netr_DatabaseSync
1098 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1099 struct netr_DatabaseSync *r)
1101 struct netr_DatabaseSync2 r2;
1102 NTSTATUS status;
1104 ZERO_STRUCT(r2);
1106 r2.in.logon_server = r->in.logon_server;
1107 r2.in.computername = r->in.computername;
1108 r2.in.credential = r->in.credential;
1109 r2.in.database_id = r->in.database_id;
1110 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1111 r2.in.sync_context = r->in.sync_context;
1112 r2.out.sync_context = r->out.sync_context;
1113 r2.out.delta_enum_array = r->out.delta_enum_array;
1114 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1116 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1118 return status;
1123 netr_AccountDeltas
1125 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126 struct netr_AccountDeltas *r)
1128 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1129 return NT_STATUS_NOT_IMPLEMENTED;
1134 netr_AccountSync
1136 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137 struct netr_AccountSync *r)
1139 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1140 return NT_STATUS_NOT_IMPLEMENTED;
1145 netr_GetDcName
1147 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_GetDcName *r)
1150 const char * const attrs[] = { NULL };
1151 struct ldb_context *sam_ctx;
1152 struct ldb_message **res;
1153 struct ldb_dn *domain_dn;
1154 int ret;
1155 const char *dcname;
1158 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1159 * that the domainname needs to be a valid netbios domain
1160 * name, if it is not NULL.
1162 if (r->in.domainname) {
1163 const char *dot = strchr(r->in.domainname, '.');
1164 size_t len = strlen(r->in.domainname);
1166 if (dot || len > 15) {
1167 return WERR_DCNOTFOUND;
1171 * TODO: Should we also varify that only valid
1172 * netbios name characters are used?
1176 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1177 dce_call->conn->dce_ctx->lp_ctx,
1178 dce_call->conn->auth_state.session_info, 0);
1179 if (sam_ctx == NULL) {
1180 return WERR_DS_UNAVAILABLE;
1183 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1184 r->in.domainname);
1185 if (domain_dn == NULL) {
1186 return WERR_NO_SUCH_DOMAIN;
1189 ret = gendb_search_dn(sam_ctx, mem_ctx,
1190 domain_dn, &res, attrs);
1191 if (ret != 1) {
1192 return WERR_NO_SUCH_DOMAIN;
1195 /* TODO: - return real IP address
1196 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1198 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1199 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1200 W_ERROR_HAVE_NO_MEMORY(dcname);
1202 *r->out.dcname = dcname;
1203 return WERR_OK;
1208 netr_LogonControl2Ex
1210 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1211 struct netr_LogonControl2Ex *r)
1213 return WERR_NOT_SUPPORTED;
1218 netr_LogonControl
1220 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1221 struct netr_LogonControl *r)
1223 struct netr_LogonControl2Ex r2;
1224 WERROR werr;
1226 if (r->in.level == 0x00000001) {
1227 ZERO_STRUCT(r2);
1229 r2.in.logon_server = r->in.logon_server;
1230 r2.in.function_code = r->in.function_code;
1231 r2.in.level = r->in.level;
1232 r2.in.data = NULL;
1233 r2.out.query = r->out.query;
1235 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1236 } else if (r->in.level == 0x00000002) {
1237 werr = WERR_NOT_SUPPORTED;
1238 } else {
1239 werr = WERR_UNKNOWN_LEVEL;
1242 return werr;
1247 netr_LogonControl2
1249 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250 struct netr_LogonControl2 *r)
1252 struct netr_LogonControl2Ex r2;
1253 WERROR werr;
1255 ZERO_STRUCT(r2);
1257 r2.in.logon_server = r->in.logon_server;
1258 r2.in.function_code = r->in.function_code;
1259 r2.in.level = r->in.level;
1260 r2.in.data = r->in.data;
1261 r2.out.query = r->out.query;
1263 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1265 return werr;
1268 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1269 struct ldb_context *sam_ctx,
1270 struct netr_DomainTrustList *trusts,
1271 uint32_t trust_flags);
1274 netr_GetAnyDCName
1276 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1277 struct netr_GetAnyDCName *r)
1279 struct netr_DomainTrustList *trusts;
1280 struct ldb_context *sam_ctx;
1281 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1282 uint32_t i;
1283 WERROR werr;
1285 *r->out.dcname = NULL;
1287 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1288 /* if the domainname parameter wasn't set assume our domain */
1289 r->in.domainname = lpcfg_workgroup(lp_ctx);
1292 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1293 dce_call->conn->auth_state.session_info, 0);
1294 if (sam_ctx == NULL) {
1295 return WERR_DS_UNAVAILABLE;
1298 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1299 /* well we asked for a DC of our own domain */
1300 if (samdb_is_pdc(sam_ctx)) {
1301 /* we are the PDC of the specified domain */
1302 return WERR_NO_SUCH_DOMAIN;
1305 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1306 lpcfg_netbios_name(lp_ctx));
1307 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1309 return WERR_OK;
1312 /* Okay, now we have to consider the trusted domains */
1314 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1315 W_ERROR_HAVE_NO_MEMORY(trusts);
1317 trusts->count = 0;
1319 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1320 NETR_TRUST_FLAG_INBOUND
1321 | NETR_TRUST_FLAG_OUTBOUND);
1322 W_ERROR_NOT_OK_RETURN(werr);
1324 for (i = 0; i < trusts->count; i++) {
1325 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1326 /* FIXME: Here we need to find a DC for the specified
1327 * trusted domain. */
1329 /* return WERR_OK; */
1330 return WERR_NO_SUCH_DOMAIN;
1334 return WERR_NO_SUCH_DOMAIN;
1339 netr_DatabaseRedo
1341 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1342 struct netr_DatabaseRedo *r)
1344 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1349 netr_NetrEnumerateTrustedDomains
1351 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1352 struct netr_NetrEnumerateTrustedDomains *r)
1354 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1359 netr_LogonGetCapabilities
1361 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1362 struct netr_LogonGetCapabilities *r)
1364 struct netlogon_creds_CredentialState *creds;
1365 NTSTATUS status;
1367 status = dcesrv_netr_creds_server_step_check(dce_call,
1368 mem_ctx,
1369 r->in.computer_name,
1370 r->in.credential,
1371 r->out.return_authenticator,
1372 &creds);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 DEBUG(0,(__location__ " Bad credentials - error\n"));
1376 NT_STATUS_NOT_OK_RETURN(status);
1378 if (r->in.query_level != 1) {
1379 return NT_STATUS_NOT_SUPPORTED;
1382 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1384 return NT_STATUS_OK;
1389 netr_NETRLOGONSETSERVICEBITS
1391 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1392 struct netr_NETRLOGONSETSERVICEBITS *r)
1394 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1399 netr_LogonGetTrustRid
1401 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1402 struct netr_LogonGetTrustRid *r)
1404 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1409 netr_NETRLOGONCOMPUTESERVERDIGEST
1411 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1412 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1414 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1419 netr_NETRLOGONCOMPUTECLIENTDIGEST
1421 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1422 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1424 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1430 netr_DsRGetSiteName
1432 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1433 struct netr_DsRGetSiteName *r)
1435 struct ldb_context *sam_ctx;
1436 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1438 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1439 dce_call->conn->auth_state.session_info, 0);
1440 if (sam_ctx == NULL) {
1441 return WERR_DS_UNAVAILABLE;
1445 * We assume to be a DC when we get called over NETLOGON. Hence we
1446 * get our site name always by using "samdb_server_site_name()"
1447 * and not "samdb_client_site_name()".
1449 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1450 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1452 return WERR_OK;
1457 fill in a netr_OneDomainInfo from a ldb search result
1459 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1460 struct loadparm_context *lp_ctx,
1461 struct ldb_context *sam_ctx,
1462 struct ldb_message *res,
1463 struct netr_OneDomainInfo *info,
1464 bool is_local, bool is_trust_list)
1466 ZERO_STRUCTP(info);
1468 if (is_trust_list) {
1469 /* w2k8 only fills this on trusted domains */
1470 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1471 info->trust_extension.length = 16;
1472 info->trust_extension.info->flags =
1473 NETR_TRUST_FLAG_TREEROOT |
1474 NETR_TRUST_FLAG_IN_FOREST |
1475 NETR_TRUST_FLAG_PRIMARY |
1476 NETR_TRUST_FLAG_NATIVE;
1478 info->trust_extension.info->parent_index = 0; /* should be index into array
1479 of parent */
1480 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1481 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1484 if (is_trust_list) {
1485 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1486 info->dns_forestname.string = NULL;
1487 } else {
1488 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1489 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1490 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1491 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1494 if (is_local) {
1495 info->domainname.string = lpcfg_workgroup(lp_ctx);
1496 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1497 info->domain_guid = samdb_result_guid(res, "objectGUID");
1498 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1499 } else {
1500 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1501 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1502 info->domain_guid = samdb_result_guid(res, "objectGUID");
1503 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1505 if (!is_trust_list) {
1506 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1509 return NT_STATUS_OK;
1513 netr_LogonGetDomainInfo
1514 this is called as part of the ADS domain logon procedure.
1516 It has an important role in convaying details about the client, such
1517 as Operating System, Version, Service Pack etc.
1519 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1520 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1522 struct netlogon_creds_CredentialState *creds;
1523 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1524 "securityIdentifier", "trustPartner", NULL };
1525 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1526 "msDS-SupportedEncryptionTypes", NULL };
1527 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1528 struct ldb_context *sam_ctx;
1529 struct ldb_message **res1, **res2, **res3, *new_msg;
1530 struct ldb_dn *workstation_dn;
1531 struct netr_DomainInformation *domain_info;
1532 struct netr_LsaPolicyInformation *lsa_policy_info;
1533 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1534 bool update_dns_hostname = true;
1535 int ret, ret3, i;
1536 NTSTATUS status;
1538 status = dcesrv_netr_creds_server_step_check(dce_call,
1539 mem_ctx,
1540 r->in.computer_name,
1541 r->in.credential,
1542 r->out.return_authenticator,
1543 &creds);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0,(__location__ " Bad credentials - error\n"));
1547 NT_STATUS_NOT_OK_RETURN(status);
1549 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1550 dce_call->conn->dce_ctx->lp_ctx,
1551 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1552 if (sam_ctx == NULL) {
1553 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1556 switch (r->in.level) {
1557 case 1: /* Domain information */
1559 if (r->in.query->workstation_info == NULL) {
1560 return NT_STATUS_INVALID_PARAMETER;
1563 /* Prepares the workstation DN */
1564 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1565 dom_sid_string(mem_ctx, creds->sid));
1566 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1568 /* Lookup for attributes in workstation object */
1569 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1570 attrs2);
1571 if (ret != 1) {
1572 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1575 /* Gets the sam account name which is checked against the DNS
1576 * hostname parameter. */
1577 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1578 "sAMAccountName",
1579 NULL);
1580 if (sam_account_name == NULL) {
1581 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1585 * Checks that the sam account name without a possible "$"
1586 * matches as prefix with the DNS hostname in the workstation
1587 * info structure.
1589 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1590 strcspn(sam_account_name, "$"));
1591 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1592 if (r->in.query->workstation_info->dns_hostname != NULL) {
1593 prefix2 = talloc_strndup(mem_ctx,
1594 r->in.query->workstation_info->dns_hostname,
1595 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1596 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1598 if (strcasecmp(prefix1, prefix2) != 0) {
1599 update_dns_hostname = false;
1601 } else {
1602 update_dns_hostname = false;
1605 /* Gets the old DNS hostname */
1606 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1607 "dNSHostName",
1608 NULL);
1611 * Updates the DNS hostname when the client wishes that the
1612 * server should handle this for him
1613 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1614 * obviously only checked when we do already have a
1615 * "dNSHostName".
1616 * See MS-NRPC section 3.5.4.3.9
1618 if ((old_dns_hostname != NULL) &&
1619 (r->in.query->workstation_info->workstation_flags
1620 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1621 update_dns_hostname = false;
1624 /* Gets host information and put them into our directory */
1626 new_msg = ldb_msg_new(mem_ctx);
1627 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1629 new_msg->dn = workstation_dn;
1631 /* Sets the OS name */
1633 if (r->in.query->workstation_info->os_name.string == NULL) {
1634 return NT_STATUS_INVALID_PARAMETER;
1637 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1638 r->in.query->workstation_info->os_name.string);
1639 if (ret != LDB_SUCCESS) {
1640 return NT_STATUS_NO_MEMORY;
1644 * Sets information from "os_version". On an empty structure
1645 * the values are cleared.
1647 if (r->in.query->workstation_info->os_version.os != NULL) {
1648 struct netr_OsVersionInfoEx *os_version;
1649 const char *os_version_str;
1651 os_version = &r->in.query->workstation_info->os_version.os->os;
1653 if (os_version->CSDVersion == NULL) {
1654 return NT_STATUS_INVALID_PARAMETER;
1657 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1658 os_version->MajorVersion,
1659 os_version->MinorVersion,
1660 os_version->BuildNumber);
1661 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1663 ret = ldb_msg_add_string(new_msg,
1664 "operatingSystemServicePack",
1665 os_version->CSDVersion);
1666 if (ret != LDB_SUCCESS) {
1667 return NT_STATUS_NO_MEMORY;
1670 ret = ldb_msg_add_string(new_msg,
1671 "operatingSystemVersion",
1672 os_version_str);
1673 if (ret != LDB_SUCCESS) {
1674 return NT_STATUS_NO_MEMORY;
1676 } else {
1677 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1678 "operatingSystemServicePack");
1679 if (ret != LDB_SUCCESS) {
1680 return NT_STATUS_NO_MEMORY;
1683 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1684 "operatingSystemVersion");
1685 if (ret != LDB_SUCCESS) {
1686 return NT_STATUS_NO_MEMORY;
1691 * If the boolean "update_dns_hostname" remained true, then we
1692 * are fine to start the update.
1694 if (update_dns_hostname) {
1695 ret = ldb_msg_add_string(new_msg,
1696 "dNSHostname",
1697 r->in.query->workstation_info->dns_hostname);
1698 if (ret != LDB_SUCCESS) {
1699 return NT_STATUS_NO_MEMORY;
1702 /* This manual "servicePrincipalName" generation is
1703 * still needed! Since the update in the samldb LDB
1704 * module does only work if the entries already exist
1705 * which isn't always the case. */
1706 ret = ldb_msg_add_string(new_msg,
1707 "servicePrincipalName",
1708 talloc_asprintf(new_msg, "HOST/%s",
1709 r->in.computer_name));
1710 if (ret != LDB_SUCCESS) {
1711 return NT_STATUS_NO_MEMORY;
1714 ret = ldb_msg_add_string(new_msg,
1715 "servicePrincipalName",
1716 talloc_asprintf(new_msg, "HOST/%s",
1717 r->in.query->workstation_info->dns_hostname));
1718 if (ret != LDB_SUCCESS) {
1719 return NT_STATUS_NO_MEMORY;
1723 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1724 DEBUG(3,("Impossible to update samdb: %s\n",
1725 ldb_errstring(sam_ctx)));
1728 talloc_free(new_msg);
1730 /* Writes back the domain information */
1732 /* We need to do two searches. The first will pull our primary
1733 domain and the second will pull any trusted domains. Our
1734 primary domain is also a "trusted" domain, so we need to
1735 put the primary domain into the lists of returned trusts as
1736 well. */
1737 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1738 &res2, attrs);
1739 if (ret != 1) {
1740 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1743 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1744 "(objectClass=trustedDomain)");
1745 if (ret3 == -1) {
1746 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1749 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1750 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1752 ZERO_STRUCTP(domain_info);
1754 /* Informations about the local and trusted domains */
1756 status = fill_one_domain_info(mem_ctx,
1757 dce_call->conn->dce_ctx->lp_ctx,
1758 sam_ctx, res2[0], &domain_info->primary_domain,
1759 true, false);
1760 NT_STATUS_NOT_OK_RETURN(status);
1762 domain_info->trusted_domain_count = ret3 + 1;
1763 domain_info->trusted_domains = talloc_array(mem_ctx,
1764 struct netr_OneDomainInfo,
1765 domain_info->trusted_domain_count);
1766 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1768 for (i=0;i<ret3;i++) {
1769 status = fill_one_domain_info(mem_ctx,
1770 dce_call->conn->dce_ctx->lp_ctx,
1771 sam_ctx, res3[i],
1772 &domain_info->trusted_domains[i],
1773 false, true);
1774 NT_STATUS_NOT_OK_RETURN(status);
1777 status = fill_one_domain_info(mem_ctx,
1778 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1779 &domain_info->trusted_domains[i], true, true);
1780 NT_STATUS_NOT_OK_RETURN(status);
1782 /* Sets the supported encryption types */
1783 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1784 "msDS-SupportedEncryptionTypes",
1785 default_supported_enc_types);
1787 /* Other host domain information */
1789 lsa_policy_info = talloc(mem_ctx,
1790 struct netr_LsaPolicyInformation);
1791 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1792 ZERO_STRUCTP(lsa_policy_info);
1794 domain_info->lsa_policy = *lsa_policy_info;
1796 /* The DNS hostname is only returned back when there is a chance
1797 * for a change. */
1798 if ((r->in.query->workstation_info->workstation_flags
1799 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1800 domain_info->dns_hostname.string = old_dns_hostname;
1801 } else {
1802 domain_info->dns_hostname.string = NULL;
1805 domain_info->workstation_flags =
1806 r->in.query->workstation_info->workstation_flags & (
1807 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1809 r->out.info->domain_info = domain_info;
1810 break;
1811 case 2: /* LSA policy information - not used at the moment */
1812 lsa_policy_info = talloc(mem_ctx,
1813 struct netr_LsaPolicyInformation);
1814 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1815 ZERO_STRUCTP(lsa_policy_info);
1817 r->out.info->lsa_policy_info = lsa_policy_info;
1818 break;
1819 default:
1820 return NT_STATUS_INVALID_LEVEL;
1821 break;
1824 return NT_STATUS_OK;
1829 netr_ServerPasswordGet
1831 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1832 struct netr_ServerPasswordGet *r)
1834 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1839 netr_NETRLOGONSENDTOSAM
1841 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1842 struct netr_NETRLOGONSENDTOSAM *r)
1844 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1849 netr_DsRGetDCNameEx2
1851 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1852 TALLOC_CTX *mem_ctx,
1853 struct netr_DsRGetDCNameEx2 *r)
1855 struct ldb_context *sam_ctx;
1856 struct netr_DsRGetDCNameInfo *info;
1857 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1858 const struct tsocket_address *local_address;
1859 char *local_addr = NULL;
1860 const struct tsocket_address *remote_address;
1861 char *remote_addr = NULL;
1862 const char *server_site_name;
1863 char *guid_str;
1864 struct netlogon_samlogon_response response;
1865 NTSTATUS status;
1866 const char *dc_name = NULL;
1867 const char *domain_name = NULL;
1868 const char *pdc_ip;
1870 ZERO_STRUCTP(r->out.info);
1872 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1873 dce_call->conn->auth_state.session_info, 0);
1874 if (sam_ctx == NULL) {
1875 return WERR_DS_UNAVAILABLE;
1878 local_address = dcesrv_connection_get_local_address(dce_call->conn);
1879 if (tsocket_address_is_inet(local_address, "ip")) {
1880 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
1881 W_ERROR_HAVE_NO_MEMORY(local_addr);
1884 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1885 if (tsocket_address_is_inet(remote_address, "ip")) {
1886 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1887 W_ERROR_HAVE_NO_MEMORY(remote_addr);
1890 /* "server_unc" is ignored by w2k3 */
1892 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1893 return WERR_INVALID_FLAGS;
1896 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1897 r->in.flags & DS_PDC_REQUIRED &&
1898 r->in.flags & DS_KDC_REQUIRED) {
1899 return WERR_INVALID_FLAGS;
1901 if (r->in.flags & DS_IS_FLAT_NAME &&
1902 r->in.flags & DS_IS_DNS_NAME) {
1903 return WERR_INVALID_FLAGS;
1905 if (r->in.flags & DS_RETURN_DNS_NAME &&
1906 r->in.flags & DS_RETURN_FLAT_NAME) {
1907 return WERR_INVALID_FLAGS;
1909 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1910 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1911 return WERR_INVALID_FLAGS;
1914 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1915 r->in.flags &
1916 (DS_DIRECTORY_SERVICE_REQUIRED |
1917 DS_DIRECTORY_SERVICE_PREFERRED |
1918 DS_GC_SERVER_REQUIRED |
1919 DS_PDC_REQUIRED |
1920 DS_KDC_REQUIRED)) {
1921 return WERR_INVALID_FLAGS;
1924 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1925 r->in.site_name) {
1926 return WERR_INVALID_FLAGS;
1929 /* Proof server site parameter "site_name" if it was specified */
1930 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1931 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1932 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1933 server_site_name) != 0)) {
1934 return WERR_NO_SUCH_DOMAIN;
1937 guid_str = r->in.domain_guid != NULL ?
1938 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1940 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1941 r->in.domain_name,
1942 r->in.domain_name,
1943 NULL, guid_str,
1944 r->in.client_account,
1945 r->in.mask, remote_addr,
1946 NETLOGON_NT_VERSION_5EX_WITH_IP,
1947 lp_ctx, &response, true);
1948 if (!NT_STATUS_IS_OK(status)) {
1949 return ntstatus_to_werror(status);
1953 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1954 * (O) flag when the returned forest name is in DNS format. This is here
1955 * always the case (see below).
1957 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1959 if (r->in.flags & DS_RETURN_DNS_NAME) {
1960 dc_name = response.data.nt5_ex.pdc_dns_name;
1961 domain_name = response.data.nt5_ex.dns_domain;
1963 * According to MS-NRPC 2.2.1.2.1 we should set the
1964 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1965 * the returned information is in DNS form.
1967 response.data.nt5_ex.server_type |=
1968 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1969 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1970 dc_name = response.data.nt5_ex.pdc_name;
1971 domain_name = response.data.nt5_ex.domain_name;
1972 } else {
1975 * TODO: autodetect what we need to return
1976 * based on the given arguments
1978 dc_name = response.data.nt5_ex.pdc_name;
1979 domain_name = response.data.nt5_ex.domain_name;
1982 if (!dc_name || !dc_name[0]) {
1983 return WERR_NO_SUCH_DOMAIN;
1986 if (!domain_name || !domain_name[0]) {
1987 return WERR_NO_SUCH_DOMAIN;
1990 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1991 W_ERROR_HAVE_NO_MEMORY(info);
1992 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
1993 dc_name[0] != '\\'? "\\\\":"",
1994 talloc_strdup(mem_ctx, dc_name));
1995 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1997 pdc_ip = local_addr;
1998 if (pdc_ip == NULL) {
1999 pdc_ip = "127.0.0.1";
2001 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2002 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2003 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2004 info->domain_guid = response.data.nt5_ex.domain_uuid;
2005 info->domain_name = domain_name;
2006 info->forest_name = response.data.nt5_ex.forest;
2007 info->dc_flags = response.data.nt5_ex.server_type;
2008 if (r->in.flags & DS_RETURN_DNS_NAME) {
2009 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2010 * returned if we are returning info->dc_unc containing a FQDN.
2011 * This attribute is called DomainControllerName in the specs,
2012 * it seems that we decide to return FQDN or netbios depending on
2013 * DS_RETURN_DNS_NAME.
2015 info->dc_flags |= DS_DNS_CONTROLLER;
2017 info->dc_site_name = response.data.nt5_ex.server_site;
2018 info->client_site_name = response.data.nt5_ex.client_site;
2020 *r->out.info = info;
2022 return WERR_OK;
2026 netr_DsRGetDCNameEx
2028 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2029 struct netr_DsRGetDCNameEx *r)
2031 struct netr_DsRGetDCNameEx2 r2;
2032 WERROR werr;
2034 ZERO_STRUCT(r2);
2036 r2.in.server_unc = r->in.server_unc;
2037 r2.in.client_account = NULL;
2038 r2.in.mask = 0;
2039 r2.in.domain_guid = r->in.domain_guid;
2040 r2.in.domain_name = r->in.domain_name;
2041 r2.in.site_name = r->in.site_name;
2042 r2.in.flags = r->in.flags;
2043 r2.out.info = r->out.info;
2045 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2047 return werr;
2051 netr_DsRGetDCName
2053 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2054 struct netr_DsRGetDCName *r)
2056 struct netr_DsRGetDCNameEx2 r2;
2057 WERROR werr;
2059 ZERO_STRUCT(r2);
2061 r2.in.server_unc = r->in.server_unc;
2062 r2.in.client_account = NULL;
2063 r2.in.mask = 0;
2064 r2.in.domain_name = r->in.domain_name;
2065 r2.in.domain_guid = r->in.domain_guid;
2067 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2068 r2.in.flags = r->in.flags;
2069 r2.out.info = r->out.info;
2071 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2073 return werr;
2076 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2078 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2079 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2081 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2086 netr_NetrEnumerateTrustedDomainsEx
2088 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2089 struct netr_NetrEnumerateTrustedDomainsEx *r)
2091 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2096 netr_DsRAddressToSitenamesExW
2098 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2099 struct netr_DsRAddressToSitenamesExW *r)
2101 struct ldb_context *sam_ctx;
2102 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2103 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2104 sa_family_t sin_family;
2105 struct sockaddr_in *addr;
2106 #ifdef HAVE_IPV6
2107 struct sockaddr_in6 *addr6;
2108 char addr_str[INET6_ADDRSTRLEN];
2109 #else
2110 char addr_str[INET_ADDRSTRLEN];
2111 #endif
2112 char *subnet_name;
2113 const char *res;
2114 uint32_t i;
2116 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2117 dce_call->conn->auth_state.session_info, 0);
2118 if (sam_ctx == NULL) {
2119 return WERR_DS_UNAVAILABLE;
2122 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2123 W_ERROR_HAVE_NO_MEMORY(ctr);
2125 *r->out.ctr = ctr;
2127 ctr->count = r->in.count;
2128 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2129 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2130 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2131 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2133 for (i=0; i<ctr->count; i++) {
2134 ctr->sitename[i].string = NULL;
2135 ctr->subnetname[i].string = NULL;
2137 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2138 continue;
2140 /* The first two byte of the buffer are reserved for the
2141 * "sin_family" but for now only the first one is used. */
2142 sin_family = r->in.addresses[i].buffer[0];
2144 switch (sin_family) {
2145 case AF_INET:
2146 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2147 continue;
2149 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2150 res = inet_ntop(AF_INET, &addr->sin_addr,
2151 addr_str, sizeof(addr_str));
2152 break;
2153 #ifdef HAVE_IPV6
2154 case AF_INET6:
2155 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2156 continue;
2158 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2159 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2160 addr_str, sizeof(addr_str));
2161 break;
2162 #endif
2163 default:
2164 continue;
2167 if (res == NULL) {
2168 continue;
2171 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2172 mem_ctx,
2173 addr_str,
2174 &subnet_name);
2175 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2176 ctr->subnetname[i].string = subnet_name;
2179 return WERR_OK;
2184 netr_DsRAddressToSitenamesW
2186 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2187 struct netr_DsRAddressToSitenamesW *r)
2189 struct netr_DsRAddressToSitenamesExW r2;
2190 struct netr_DsRAddressToSitenamesWCtr *ctr;
2191 uint32_t i;
2192 WERROR werr;
2194 ZERO_STRUCT(r2);
2196 r2.in.server_name = r->in.server_name;
2197 r2.in.count = r->in.count;
2198 r2.in.addresses = r->in.addresses;
2200 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2201 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2203 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2204 W_ERROR_HAVE_NO_MEMORY(ctr);
2206 *r->out.ctr = ctr;
2208 ctr->count = r->in.count;
2209 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2210 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2212 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2214 for (i=0; i<ctr->count; i++) {
2215 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2218 return werr;
2223 netr_DsrGetDcSiteCoverageW
2225 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2226 struct netr_DsrGetDcSiteCoverageW *r)
2228 struct ldb_context *sam_ctx;
2229 struct DcSitesCtr *ctr;
2230 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2232 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2233 dce_call->conn->auth_state.session_info, 0);
2234 if (sam_ctx == NULL) {
2235 return WERR_DS_UNAVAILABLE;
2238 ctr = talloc(mem_ctx, struct DcSitesCtr);
2239 W_ERROR_HAVE_NO_MEMORY(ctr);
2241 *r->out.ctr = ctr;
2243 /* For now only return our default site */
2244 ctr->num_sites = 1;
2245 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2246 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2247 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2248 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2250 return WERR_OK;
2254 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2255 struct ldb_context *sam_ctx,
2256 struct netr_DomainTrustList *trusts,
2257 uint32_t trust_flags)
2259 struct ldb_dn *system_dn;
2260 struct ldb_message **dom_res = NULL;
2261 const char *trust_attrs[] = { "flatname", "trustPartner",
2262 "securityIdentifier", "trustDirection",
2263 "trustType", "trustAttributes", NULL };
2264 uint32_t n;
2265 int i;
2266 int ret;
2268 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2269 NETR_TRUST_FLAG_OUTBOUND))) {
2270 return WERR_INVALID_FLAGS;
2273 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2274 ldb_get_default_basedn(sam_ctx),
2275 "(&(objectClass=container)(cn=System))");
2276 if (!system_dn) {
2277 return WERR_GENERAL_FAILURE;
2280 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2281 &dom_res, trust_attrs,
2282 "(objectclass=trustedDomain)");
2284 for (i = 0; i < ret; i++) {
2285 unsigned int trust_dir;
2286 uint32_t flags = 0;
2288 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2289 "trustDirection", 0);
2291 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2292 flags |= NETR_TRUST_FLAG_INBOUND;
2294 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2295 flags |= NETR_TRUST_FLAG_OUTBOUND;
2298 if (!(flags & trust_flags)) {
2299 /* this trust direction was not requested */
2300 continue;
2303 n = trusts->count;
2304 trusts->array = talloc_realloc(trusts, trusts->array,
2305 struct netr_DomainTrust,
2306 n + 1);
2307 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2309 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2310 if (!trusts->array[n].netbios_name) {
2311 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2312 "without flatname\n",
2313 ldb_dn_get_linearized(dom_res[i]->dn)));
2316 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2318 trusts->array[n].trust_flags = flags;
2319 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2320 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2321 /* TODO: find if we have parent in the list */
2322 trusts->array[n].parent_index = 0;
2325 trusts->array[n].trust_type =
2326 ldb_msg_find_attr_as_uint(dom_res[i],
2327 "trustType", 0);
2328 trusts->array[n].trust_attributes =
2329 ldb_msg_find_attr_as_uint(dom_res[i],
2330 "trustAttributes", 0);
2332 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2333 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2334 struct dom_sid zero_sid;
2335 ZERO_STRUCT(zero_sid);
2336 trusts->array[n].sid =
2337 dom_sid_dup(trusts, &zero_sid);
2338 } else {
2339 trusts->array[n].sid =
2340 samdb_result_dom_sid(trusts, dom_res[i],
2341 "securityIdentifier");
2343 trusts->array[n].guid = GUID_zero();
2345 trusts->count = n + 1;
2348 talloc_free(dom_res);
2349 return WERR_OK;
2353 netr_DsrEnumerateDomainTrusts
2355 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2356 TALLOC_CTX *mem_ctx,
2357 struct netr_DsrEnumerateDomainTrusts *r)
2359 struct netr_DomainTrustList *trusts;
2360 struct ldb_context *sam_ctx;
2361 int ret;
2362 struct ldb_message **dom_res;
2363 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2364 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2365 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2366 const char *p;
2367 WERROR werr;
2369 if (r->in.trust_flags & 0xFFFFFE00) {
2370 return WERR_INVALID_FLAGS;
2373 /* TODO: turn to hard check once we are sure this is 100% correct */
2374 if (!r->in.server_name) {
2375 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2376 "But received NULL!\n", dnsdomain));
2377 } else {
2378 p = strchr(r->in.server_name, '.');
2379 if (!p) {
2380 DEBUG(3, ("Invalid domain! Expected name in domain "
2381 "[%s]. But received [%s]!\n",
2382 dnsdomain, r->in.server_name));
2383 p = r->in.server_name;
2384 } else {
2385 p++;
2387 if (strcasecmp(p, dnsdomain)) {
2388 DEBUG(3, ("Invalid domain! Expected name in domain "
2389 "[%s]. But received [%s]!\n",
2390 dnsdomain, r->in.server_name));
2394 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2395 W_ERROR_HAVE_NO_MEMORY(trusts);
2397 trusts->count = 0;
2398 r->out.trusts = trusts;
2400 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2401 dce_call->conn->auth_state.session_info, 0);
2402 if (sam_ctx == NULL) {
2403 return WERR_GENERAL_FAILURE;
2406 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2407 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2409 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2410 trusts, r->in.trust_flags);
2411 W_ERROR_NOT_OK_RETURN(werr);
2414 /* NOTE: we currently are always the root of the forest */
2415 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2416 uint32_t n = trusts->count;
2418 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2419 &dom_res, dom_attrs);
2420 if (ret != 1) {
2421 return WERR_GENERAL_FAILURE;
2424 trusts->count = n + 1;
2425 trusts->array = talloc_realloc(trusts, trusts->array,
2426 struct netr_DomainTrust,
2427 trusts->count);
2428 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2430 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2431 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2432 trusts->array[n].trust_flags =
2433 NETR_TRUST_FLAG_NATIVE |
2434 NETR_TRUST_FLAG_TREEROOT |
2435 NETR_TRUST_FLAG_IN_FOREST |
2436 NETR_TRUST_FLAG_PRIMARY;
2437 /* we are always the root domain for now */
2438 trusts->array[n].parent_index = 0;
2439 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2440 trusts->array[n].trust_attributes = 0;
2441 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2442 dom_res[0],
2443 "objectSid");
2444 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2445 "objectGUID");
2446 talloc_free(dom_res);
2449 return WERR_OK;
2454 netr_DsrDeregisterDNSHostRecords
2456 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2457 struct netr_DsrDeregisterDNSHostRecords *r)
2459 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2464 netr_ServerTrustPasswordsGet
2466 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2467 struct netr_ServerTrustPasswordsGet *r)
2469 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2473 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2474 struct ldb_context *sam_ctx,
2475 struct loadparm_context *lp_ctx,
2476 struct lsa_ForestTrustInformation *info)
2478 struct lsa_ForestTrustDomainInfo *domain_info;
2479 struct lsa_ForestTrustRecord *e;
2480 struct ldb_message **dom_res;
2481 const char * const dom_attrs[] = { "objectSid", NULL };
2482 int ret;
2484 /* we need to provide 2 entries:
2485 * 1. the Root Forest name
2486 * 2. the Domain Information
2489 info->count = 2;
2490 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2491 W_ERROR_HAVE_NO_MEMORY(info->entries);
2493 /* Forest root info */
2494 e = talloc(info, struct lsa_ForestTrustRecord);
2495 W_ERROR_HAVE_NO_MEMORY(e);
2497 e->flags = 0;
2498 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2499 e->time = 0; /* so far always 0 in trces. */
2500 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2501 mem_ctx);
2502 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2504 info->entries[0] = e;
2506 /* Domain info */
2507 e = talloc(info, struct lsa_ForestTrustRecord);
2508 W_ERROR_HAVE_NO_MEMORY(e);
2510 /* get our own domain info */
2511 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2512 if (ret != 1) {
2513 return WERR_GENERAL_FAILURE;
2516 /* TODO: check if disabled and set flags accordingly */
2517 e->flags = 0;
2518 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2519 e->time = 0; /* so far always 0 in traces. */
2521 domain_info = &e->forest_trust_data.domain_info;
2522 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2523 "objectSid");
2524 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2525 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2527 info->entries[1] = e;
2529 talloc_free(dom_res);
2531 return WERR_OK;
2535 netr_DsRGetForestTrustInformation
2537 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2538 TALLOC_CTX *mem_ctx,
2539 struct netr_DsRGetForestTrustInformation *r)
2541 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2542 struct lsa_ForestTrustInformation *info, **info_ptr;
2543 struct ldb_context *sam_ctx;
2544 WERROR werr;
2546 if (r->in.flags & 0xFFFFFFFE) {
2547 return WERR_INVALID_FLAGS;
2550 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2551 dce_call->conn->auth_state.session_info, 0);
2552 if (sam_ctx == NULL) {
2553 return WERR_GENERAL_FAILURE;
2556 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2557 if (!samdb_is_pdc(sam_ctx)) {
2558 return WERR_NERR_NOTPRIMARY;
2561 if (r->in.trusted_domain_name == NULL) {
2562 return WERR_INVALID_FLAGS;
2565 /* TODO: establish an schannel connection with
2566 * r->in.trusted_domain_name and perform a
2567 * netr_GetForestTrustInformation call against it */
2569 /* for now return not implementd */
2570 return WERR_CALL_NOT_IMPLEMENTED;
2573 /* TODO: check r->in.server_name is our name */
2575 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2576 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2578 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2579 W_ERROR_HAVE_NO_MEMORY(info);
2581 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2582 W_ERROR_NOT_OK_RETURN(werr);
2584 *info_ptr = info;
2585 r->out.forest_trust_info = info_ptr;
2587 return WERR_OK;
2592 netr_GetForestTrustInformation
2594 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2595 TALLOC_CTX *mem_ctx,
2596 struct netr_GetForestTrustInformation *r)
2598 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2599 struct netlogon_creds_CredentialState *creds;
2600 struct lsa_ForestTrustInformation *info, **info_ptr;
2601 struct ldb_context *sam_ctx;
2602 NTSTATUS status;
2603 WERROR werr;
2605 status = dcesrv_netr_creds_server_step_check(dce_call,
2606 mem_ctx,
2607 r->in.computer_name,
2608 r->in.credential,
2609 r->out.return_authenticator,
2610 &creds);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 return status;
2615 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2616 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2617 return NT_STATUS_NOT_IMPLEMENTED;
2620 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2621 dce_call->conn->auth_state.session_info, 0);
2622 if (sam_ctx == NULL) {
2623 return NT_STATUS_INTERNAL_ERROR;
2626 /* TODO: check r->in.server_name is our name */
2628 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2629 if (!info_ptr) {
2630 return NT_STATUS_NO_MEMORY;
2632 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2633 if (!info) {
2634 return NT_STATUS_NO_MEMORY;
2637 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2638 if (!W_ERROR_IS_OK(werr)) {
2639 return werror_to_ntstatus(werr);
2642 *info_ptr = info;
2643 r->out.forest_trust_info = info_ptr;
2645 return NT_STATUS_OK;
2650 netr_ServerGetTrustInfo
2652 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2653 struct netr_ServerGetTrustInfo *r)
2655 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2659 netr_Unused47
2661 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2662 struct netr_Unused47 *r)
2664 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2668 struct netr_dnsupdate_RODC_state {
2669 struct dcesrv_call_state *dce_call;
2670 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2671 struct dnsupdate_RODC *r2;
2675 called when the forwarded RODC dns update request is finished
2677 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2679 struct netr_dnsupdate_RODC_state *st =
2680 tevent_req_callback_data(subreq,
2681 struct netr_dnsupdate_RODC_state);
2682 NTSTATUS status;
2684 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2685 TALLOC_FREE(subreq);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2688 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2691 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2693 status = dcesrv_reply(st->dce_call);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2700 netr_DsrUpdateReadOnlyServerDnsRecords
2702 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2703 TALLOC_CTX *mem_ctx,
2704 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2706 struct netlogon_creds_CredentialState *creds;
2707 NTSTATUS nt_status;
2708 struct dcerpc_binding_handle *binding_handle;
2709 struct netr_dnsupdate_RODC_state *st;
2710 struct tevent_req *subreq;
2712 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2713 mem_ctx,
2714 r->in.computer_name,
2715 r->in.credential,
2716 r->out.return_authenticator,
2717 &creds);
2718 NT_STATUS_NOT_OK_RETURN(nt_status);
2720 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2721 return NT_STATUS_ACCESS_DENIED;
2724 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2725 NT_STATUS_HAVE_NO_MEMORY(st);
2727 st->dce_call = dce_call;
2728 st->r = r;
2729 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2730 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2732 st->r2->in.dom_sid = creds->sid;
2733 st->r2->in.site_name = r->in.site_name;
2734 st->r2->in.dns_ttl = r->in.dns_ttl;
2735 st->r2->in.dns_names = r->in.dns_names;
2736 st->r2->out.dns_names = r->out.dns_names;
2738 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2739 "dnsupdate", &ndr_table_irpc);
2740 if (binding_handle == NULL) {
2741 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2742 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2743 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2746 /* forward the call */
2747 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2748 binding_handle, st->r2);
2749 NT_STATUS_HAVE_NO_MEMORY(subreq);
2751 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2753 /* setup the callback */
2754 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2756 return NT_STATUS_OK;
2760 /* include the generated boilerplate */
2761 #include "librpc/gen_ndr/ndr_netlogon_s.c"