s4:rpc_server/netlogon: let dcesrv_netr_ServerAuthenticate3() fallback to the previou...
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob9ed287f01c57d71e0b47d6618c432aa2af382b01
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 *curNtHash = NULL;
116 struct samr_Password *prevNtHash = NULL;
117 uint32_t user_account_control;
118 int num_records;
119 struct ldb_message **msgs;
120 NTSTATUS nt_status;
121 const char *attrs[] = {"unicodePwd", "userAccountControl",
122 "objectSid", 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_DOMAIN ||
259 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
261 struct ldb_message *tdo_msg = NULL;
262 const char * const tdo_attrs[] = {
263 "trustAuthIncoming",
264 "trustAttributes",
265 "flatName",
266 NULL
268 char *encoded_name = NULL;
269 size_t len;
270 const char *flatname = NULL;
271 char trailer = '$';
272 bool require_trailer = true;
273 const char *netbios = NULL;
274 const char *dns = NULL;
276 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
277 trailer = '.';
278 require_trailer = false;
281 encoded_name = ldb_binary_encode_string(mem_ctx,
282 r->in.account_name);
283 if (encoded_name == NULL) {
284 return NT_STATUS_NO_MEMORY;
287 len = strlen(encoded_name);
288 if (len < 2) {
289 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
292 if (require_trailer && encoded_name[len - 1] != trailer) {
293 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
295 encoded_name[len - 1] = '\0';
297 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
298 dns = encoded_name;
299 } else {
300 netbios = encoded_name;
303 nt_status = dsdb_trust_search_tdo(sam_ctx,
304 netbios, dns,
305 tdo_attrs, mem_ctx, &tdo_msg);
306 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
307 DEBUG(2, ("Client asked for a trusted domain secure channel, "
308 "but there's no tdo for [%s] => [%s] \n",
309 r->in.account_name, encoded_name));
310 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
312 if (!NT_STATUS_IS_OK(nt_status)) {
313 return nt_status;
316 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
317 &curNtHash,
318 &prevNtHash);
319 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
320 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
322 if (!NT_STATUS_IS_OK(nt_status)) {
323 return nt_status;
326 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
327 if (flatname == NULL) {
328 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
331 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
332 if (account_name == NULL) {
333 return NT_STATUS_NO_MEMORY;
335 } else {
336 account_name = r->in.account_name;
339 /* pull the user attributes */
340 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
341 "(&(sAMAccountName=%s)(objectclass=user))",
342 ldb_binary_encode_string(mem_ctx, account_name));
344 if (num_records == 0) {
345 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
346 r->in.account_name));
347 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
350 if (num_records > 1) {
351 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
355 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
357 if (user_account_control & UF_ACCOUNTDISABLE) {
358 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
359 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
362 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
363 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
364 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
365 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
367 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
368 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
369 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
370 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
372 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
374 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
375 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
376 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
377 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
379 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
380 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
381 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
382 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
384 } else {
385 /* we should never reach this */
386 return NT_STATUS_INTERNAL_ERROR;
389 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
390 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
391 dce_call->conn->dce_ctx->lp_ctx,
392 msgs[0], NULL, &curNtHash);
393 if (!NT_STATUS_IS_OK(nt_status)) {
394 return NT_STATUS_ACCESS_DENIED;
398 if (curNtHash == NULL) {
399 return NT_STATUS_ACCESS_DENIED;
402 if (!challenge_valid) {
403 DEBUG(1, ("No challenge requested by client [%s/%s], "
404 "cannot authenticate\n",
405 r->in.computer_name,
406 r->in.account_name));
407 return NT_STATUS_ACCESS_DENIED;
410 creds = netlogon_creds_server_init(mem_ctx,
411 r->in.account_name,
412 r->in.computer_name,
413 r->in.secure_channel_type,
414 &challenge.client_challenge,
415 &challenge.server_challenge,
416 curNtHash,
417 r->in.credentials,
418 r->out.return_credentials,
419 negotiate_flags);
420 if (creds == NULL && prevNtHash != NULL) {
422 * We fallback to the previous password for domain trusts.
424 * Note that lpcfg_old_password_allowed_period() doesn't
425 * apply here.
427 creds = netlogon_creds_server_init(mem_ctx,
428 r->in.account_name,
429 r->in.computer_name,
430 r->in.secure_channel_type,
431 &challenge.client_challenge,
432 &challenge.server_challenge,
433 prevNtHash,
434 r->in.credentials,
435 r->out.return_credentials,
436 negotiate_flags);
438 if (creds == NULL) {
439 return NT_STATUS_ACCESS_DENIED;
442 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
444 nt_status = schannel_save_creds_state(mem_ctx,
445 dce_call->conn->dce_ctx->lp_ctx,
446 creds);
447 if (!NT_STATUS_IS_OK(nt_status)) {
448 ZERO_STRUCTP(r->out.return_credentials);
449 return nt_status;
452 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
453 "objectSid", 0);
455 return NT_STATUS_OK;
458 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
459 struct netr_ServerAuthenticate *r)
461 struct netr_ServerAuthenticate3 a;
462 uint32_t rid;
463 /* TODO:
464 * negotiate_flags is used as an [in] parameter
465 * so it need to be initialised.
467 * (I think ... = 0; seems wrong here --metze)
469 uint32_t negotiate_flags_in = 0;
470 uint32_t negotiate_flags_out = 0;
472 a.in.server_name = r->in.server_name;
473 a.in.account_name = r->in.account_name;
474 a.in.secure_channel_type = r->in.secure_channel_type;
475 a.in.computer_name = r->in.computer_name;
476 a.in.credentials = r->in.credentials;
477 a.in.negotiate_flags = &negotiate_flags_in;
479 a.out.return_credentials = r->out.return_credentials;
480 a.out.rid = &rid;
481 a.out.negotiate_flags = &negotiate_flags_out;
483 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
486 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
487 struct netr_ServerAuthenticate2 *r)
489 struct netr_ServerAuthenticate3 r3;
490 uint32_t rid = 0;
492 r3.in.server_name = r->in.server_name;
493 r3.in.account_name = r->in.account_name;
494 r3.in.secure_channel_type = r->in.secure_channel_type;
495 r3.in.computer_name = r->in.computer_name;
496 r3.in.credentials = r->in.credentials;
497 r3.out.return_credentials = r->out.return_credentials;
498 r3.in.negotiate_flags = r->in.negotiate_flags;
499 r3.out.negotiate_flags = r->out.negotiate_flags;
500 r3.out.rid = &rid;
502 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
506 * NOTE: The following functions are nearly identical to the ones available in
507 * source3/rpc_server/srv_nelog_nt.c
508 * The reason we keep 2 copies is that they use different structures to
509 * represent the auth_info and the decrpc pipes.
513 * If schannel is required for this call test that it actually is available.
515 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
516 const char *computer_name,
517 bool integrity, bool privacy)
520 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
521 if (!privacy && !integrity) {
522 return NT_STATUS_OK;
525 if ((!privacy && integrity) &&
526 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
527 return NT_STATUS_OK;
530 if ((privacy || integrity) &&
531 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
532 return NT_STATUS_OK;
536 /* test didn't pass */
537 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
538 computer_name));
540 return NT_STATUS_ACCESS_DENIED;
543 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
544 TALLOC_CTX *mem_ctx,
545 const char *computer_name,
546 struct netr_Authenticator *received_authenticator,
547 struct netr_Authenticator *return_authenticator,
548 struct netlogon_creds_CredentialState **creds_out)
550 NTSTATUS nt_status;
551 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
552 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
554 if (schannel_global_required) {
555 nt_status = schannel_check_required(auth_info,
556 computer_name,
557 true, false);
558 if (!NT_STATUS_IS_OK(nt_status)) {
559 return nt_status;
563 nt_status = schannel_check_creds_state(mem_ctx,
564 dce_call->conn->dce_ctx->lp_ctx,
565 computer_name,
566 received_authenticator,
567 return_authenticator,
568 creds_out);
569 return nt_status;
573 Change the machine account password for the currently connected
574 client. Supplies only the NT#.
577 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
578 struct netr_ServerPasswordSet *r)
580 struct netlogon_creds_CredentialState *creds;
581 struct ldb_context *sam_ctx;
582 const char * const attrs[] = { "unicodePwd", NULL };
583 struct ldb_message **res;
584 struct samr_Password *oldNtHash;
585 NTSTATUS nt_status;
586 int ret;
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 netlogon_creds_des_decrypt(creds, r->in.new_password);
602 /* fetch the old password hashes (the NT hash has to exist) */
604 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
605 "(&(objectClass=user)(objectSid=%s))",
606 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
607 if (ret != 1) {
608 return NT_STATUS_WRONG_PASSWORD;
611 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
612 dce_call->conn->dce_ctx->lp_ctx,
613 res[0], NULL, &oldNtHash);
614 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
615 return NT_STATUS_WRONG_PASSWORD;
618 /* Using the sid for the account as the key, set the password */
619 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
620 creds->sid,
621 NULL, /* Don't have version */
622 NULL, /* Don't have plaintext */
623 NULL, r->in.new_password,
624 NULL, oldNtHash, /* Password change */
625 NULL, NULL);
626 return nt_status;
630 Change the machine account password for the currently connected
631 client. Supplies new plaintext.
633 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
634 struct netr_ServerPasswordSet2 *r)
636 struct netlogon_creds_CredentialState *creds;
637 struct ldb_context *sam_ctx;
638 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
639 struct ldb_message **res;
640 struct samr_Password *oldLmHash, *oldNtHash;
641 struct NL_PASSWORD_VERSION version = {};
642 const uint32_t *new_version = NULL;
643 NTSTATUS nt_status;
644 DATA_BLOB new_password;
645 int ret;
646 struct samr_CryptPassword password_buf;
648 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
649 mem_ctx,
650 r->in.computer_name,
651 r->in.credential, r->out.return_authenticator,
652 &creds);
653 NT_STATUS_NOT_OK_RETURN(nt_status);
655 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);
656 if (sam_ctx == NULL) {
657 return NT_STATUS_INVALID_SYSTEM_SERVICE;
660 memcpy(password_buf.data, r->in.new_password->data, 512);
661 SIVAL(password_buf.data, 512, r->in.new_password->length);
663 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
664 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
665 } else {
666 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
669 switch (creds->secure_channel_type) {
670 case SEC_CHAN_DOMAIN:
671 case SEC_CHAN_DNS_DOMAIN: {
672 uint32_t len = IVAL(password_buf.data, 512);
673 if (len <= 500) {
674 uint32_t ofs = 500 - len;
675 uint8_t *p;
677 p = password_buf.data + ofs;
679 version.ReservedField = IVAL(p, 0);
680 version.PasswordVersionNumber = IVAL(p, 4);
681 version.PasswordVersionPresent = IVAL(p, 8);
683 if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
684 new_version = &version.PasswordVersionNumber;
687 break;
688 default:
689 break;
692 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
693 DEBUG(3,("samr: failed to decode password buffer\n"));
694 return NT_STATUS_WRONG_PASSWORD;
697 /* fetch the old password hashes (at least one of both has to exist) */
699 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
700 "(&(objectClass=user)(objectSid=%s))",
701 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
702 if (ret != 1) {
703 return NT_STATUS_WRONG_PASSWORD;
706 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
707 dce_call->conn->dce_ctx->lp_ctx,
708 res[0], &oldLmHash, &oldNtHash);
709 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
710 return NT_STATUS_WRONG_PASSWORD;
713 /* Using the sid for the account as the key, set the password */
714 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
715 creds->sid,
716 new_version,
717 &new_password, /* we have plaintext */
718 NULL, NULL,
719 oldLmHash, oldNtHash, /* Password change */
720 NULL, NULL);
721 return nt_status;
726 netr_LogonUasLogon
728 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
729 struct netr_LogonUasLogon *r)
731 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
736 netr_LogonUasLogoff
738 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739 struct netr_LogonUasLogoff *r)
741 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
745 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
747 switch (r->in.logon_level) {
748 case NetlogonInteractiveInformation:
749 case NetlogonServiceInformation:
750 case NetlogonInteractiveTransitiveInformation:
751 case NetlogonServiceTransitiveInformation:
752 if (r->in.logon->password == NULL) {
753 return NT_STATUS_INVALID_PARAMETER;
756 switch (r->in.validation_level) {
757 case NetlogonValidationSamInfo: /* 2 */
758 case NetlogonValidationSamInfo2: /* 3 */
759 case NetlogonValidationSamInfo4: /* 6 */
760 break;
761 default:
762 return NT_STATUS_INVALID_INFO_CLASS;
765 break;
766 case NetlogonNetworkInformation:
767 case NetlogonNetworkTransitiveInformation:
768 if (r->in.logon->network == NULL) {
769 return NT_STATUS_INVALID_PARAMETER;
772 switch (r->in.validation_level) {
773 case NetlogonValidationSamInfo: /* 2 */
774 case NetlogonValidationSamInfo2: /* 3 */
775 case NetlogonValidationSamInfo4: /* 6 */
776 break;
777 default:
778 return NT_STATUS_INVALID_INFO_CLASS;
781 break;
783 case NetlogonGenericInformation:
784 if (r->in.logon->generic == NULL) {
785 return NT_STATUS_INVALID_PARAMETER;
788 switch (r->in.validation_level) {
789 /* TODO: case NetlogonValidationGenericInfo: 4 */
790 case NetlogonValidationGenericInfo2: /* 5 */
791 break;
792 default:
793 return NT_STATUS_INVALID_INFO_CLASS;
796 break;
797 default:
798 return NT_STATUS_INVALID_PARAMETER;
801 return NT_STATUS_OK;
805 netr_LogonSamLogon_base
807 This version of the function allows other wrappers to say 'do not check the credentials'
809 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
811 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
812 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
814 struct auth4_context *auth_context;
815 struct auth_usersupplied_info *user_info;
816 struct auth_user_info_dc *user_info_dc;
817 NTSTATUS nt_status;
818 struct netr_SamBaseInfo *sam;
819 struct netr_SamInfo2 *sam2;
820 struct netr_SamInfo3 *sam3;
821 struct netr_SamInfo6 *sam6;
823 *r->out.authoritative = 1;
825 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
826 NT_STATUS_HAVE_NO_MEMORY(user_info);
828 netlogon_creds_decrypt_samlogon_logon(creds,
829 r->in.logon_level,
830 r->in.logon);
832 switch (r->in.logon_level) {
833 case NetlogonInteractiveInformation:
834 case NetlogonServiceInformation:
835 case NetlogonInteractiveTransitiveInformation:
836 case NetlogonServiceTransitiveInformation:
838 /* TODO: we need to deny anonymous access here */
839 nt_status = auth_context_create(mem_ctx,
840 dce_call->event_ctx, dce_call->msg_ctx,
841 dce_call->conn->dce_ctx->lp_ctx,
842 &auth_context);
843 NT_STATUS_NOT_OK_RETURN(nt_status);
845 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
846 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
847 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
848 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
850 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
851 user_info->password_state = AUTH_PASSWORD_HASH;
853 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
854 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
855 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
857 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
858 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
859 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
861 break;
862 case NetlogonNetworkInformation:
863 case NetlogonNetworkTransitiveInformation:
865 /* TODO: we need to deny anonymous access here */
866 nt_status = auth_context_create(mem_ctx,
867 dce_call->event_ctx, dce_call->msg_ctx,
868 dce_call->conn->dce_ctx->lp_ctx,
869 &auth_context);
870 NT_STATUS_NOT_OK_RETURN(nt_status);
872 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
873 NT_STATUS_NOT_OK_RETURN(nt_status);
875 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
876 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
877 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
878 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
880 user_info->password_state = AUTH_PASSWORD_RESPONSE;
881 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
882 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
884 break;
887 case NetlogonGenericInformation:
889 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
890 /* OK */
891 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
892 /* OK */
893 } else {
894 /* Using DES to verify kerberos tickets makes no sense */
895 return NT_STATUS_INVALID_PARAMETER;
898 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
899 NTSTATUS status;
900 struct dcerpc_binding_handle *irpc_handle;
901 struct kdc_check_generic_kerberos check;
902 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
903 NT_STATUS_HAVE_NO_MEMORY(generic);
904 *r->out.authoritative = 1;
906 /* TODO: Describe and deal with these flags */
907 *r->out.flags = 0;
909 r->out.validation->generic = generic;
911 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
912 dce_call->msg_ctx,
913 "kdc_server",
914 &ndr_table_irpc);
915 if (irpc_handle == NULL) {
916 return NT_STATUS_NO_LOGON_SERVERS;
919 check.in.generic_request =
920 data_blob_const(r->in.logon->generic->data,
921 r->in.logon->generic->length);
924 * TODO: make this async and avoid
925 * dcerpc_binding_handle_set_sync_ev()
927 dcerpc_binding_handle_set_sync_ev(irpc_handle,
928 dce_call->event_ctx);
929 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
930 mem_ctx,
931 &check);
932 if (!NT_STATUS_IS_OK(status)) {
933 return status;
935 generic->length = check.out.generic_reply.length;
936 generic->data = check.out.generic_reply.data;
937 return NT_STATUS_OK;
940 /* Until we get an implemetnation of these other packages */
941 return NT_STATUS_INVALID_PARAMETER;
943 default:
944 return NT_STATUS_INVALID_PARAMETER;
947 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
948 /* TODO: set *r->out.authoritative = 0 on specific errors */
949 NT_STATUS_NOT_OK_RETURN(nt_status);
951 switch (r->in.validation_level) {
952 case 2:
953 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
954 NT_STATUS_NOT_OK_RETURN(nt_status);
956 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
957 NT_STATUS_HAVE_NO_MEMORY(sam2);
958 sam2->base = *sam;
960 /* And put into the talloc tree */
961 talloc_steal(sam2, sam);
962 r->out.validation->sam2 = sam2;
964 sam = &sam2->base;
965 break;
967 case 3:
968 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
969 user_info_dc,
970 &sam3);
971 NT_STATUS_NOT_OK_RETURN(nt_status);
973 r->out.validation->sam3 = sam3;
975 sam = &sam3->base;
976 break;
978 case 6:
979 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
980 user_info_dc,
981 &sam3);
982 NT_STATUS_NOT_OK_RETURN(nt_status);
984 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
985 NT_STATUS_HAVE_NO_MEMORY(sam6);
986 sam6->base = sam3->base;
987 sam = &sam6->base;
988 sam6->sidcount = sam3->sidcount;
989 sam6->sids = sam3->sids;
991 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
992 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
993 sam->account_name.string, sam6->dns_domainname.string);
994 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
995 /* And put into the talloc tree */
996 talloc_steal(sam6, sam3);
998 r->out.validation->sam6 = sam6;
999 break;
1001 default:
1002 return NT_STATUS_INVALID_INFO_CLASS;
1005 netlogon_creds_encrypt_samlogon_validation(creds,
1006 r->in.validation_level,
1007 r->out.validation);
1009 /* TODO: Describe and deal with these flags */
1010 *r->out.flags = 0;
1012 return NT_STATUS_OK;
1015 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1016 struct netr_LogonSamLogonEx *r)
1018 NTSTATUS nt_status;
1019 struct netlogon_creds_CredentialState *creds;
1021 *r->out.authoritative = 1;
1023 nt_status = dcesrv_netr_LogonSamLogon_check(r);
1024 if (!NT_STATUS_IS_OK(nt_status)) {
1025 return nt_status;
1028 nt_status = schannel_get_creds_state(mem_ctx,
1029 dce_call->conn->dce_ctx->lp_ctx,
1030 r->in.computer_name, &creds);
1031 if (!NT_STATUS_IS_OK(nt_status)) {
1032 return nt_status;
1035 if (!dce_call->conn->auth_state.auth_info ||
1036 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
1037 return NT_STATUS_ACCESS_DENIED;
1039 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
1043 netr_LogonSamLogonWithFlags
1046 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1047 struct netr_LogonSamLogonWithFlags *r)
1049 NTSTATUS nt_status;
1050 struct netlogon_creds_CredentialState *creds;
1051 struct netr_LogonSamLogonEx r2;
1053 struct netr_Authenticator *return_authenticator;
1055 ZERO_STRUCT(r2);
1057 r2.in.server_name = r->in.server_name;
1058 r2.in.computer_name = r->in.computer_name;
1059 r2.in.logon_level = r->in.logon_level;
1060 r2.in.logon = r->in.logon;
1061 r2.in.validation_level = r->in.validation_level;
1062 r2.in.flags = r->in.flags;
1063 r2.out.validation = r->out.validation;
1064 r2.out.authoritative = r->out.authoritative;
1065 r2.out.flags = r->out.flags;
1067 *r->out.authoritative = 1;
1069 nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
1070 if (!NT_STATUS_IS_OK(nt_status)) {
1071 return nt_status;
1074 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
1075 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
1077 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
1078 mem_ctx,
1079 r->in.computer_name,
1080 r->in.credential, return_authenticator,
1081 &creds);
1082 NT_STATUS_NOT_OK_RETURN(nt_status);
1084 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
1086 r->out.return_authenticator = return_authenticator;
1088 return nt_status;
1092 netr_LogonSamLogon
1094 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1095 struct netr_LogonSamLogon *r)
1097 struct netr_LogonSamLogonWithFlags r2;
1098 uint32_t flags = 0;
1099 NTSTATUS status;
1101 ZERO_STRUCT(r2);
1103 r2.in.server_name = r->in.server_name;
1104 r2.in.computer_name = r->in.computer_name;
1105 r2.in.credential = r->in.credential;
1106 r2.in.return_authenticator = r->in.return_authenticator;
1107 r2.in.logon_level = r->in.logon_level;
1108 r2.in.logon = r->in.logon;
1109 r2.in.validation_level = r->in.validation_level;
1110 r2.in.flags = &flags;
1111 r2.out.validation = r->out.validation;
1112 r2.out.authoritative = r->out.authoritative;
1113 r2.out.flags = &flags;
1115 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
1117 r->out.return_authenticator = r2.out.return_authenticator;
1119 return status;
1124 netr_LogonSamLogoff
1126 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1127 struct netr_LogonSamLogoff *r)
1129 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1135 netr_DatabaseDeltas
1137 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1138 struct netr_DatabaseDeltas *r)
1140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1145 netr_DatabaseSync2
1147 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_DatabaseSync2 *r)
1150 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
1151 return NT_STATUS_NOT_IMPLEMENTED;
1156 netr_DatabaseSync
1158 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_DatabaseSync *r)
1161 struct netr_DatabaseSync2 r2;
1162 NTSTATUS status;
1164 ZERO_STRUCT(r2);
1166 r2.in.logon_server = r->in.logon_server;
1167 r2.in.computername = r->in.computername;
1168 r2.in.credential = r->in.credential;
1169 r2.in.database_id = r->in.database_id;
1170 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
1171 r2.in.sync_context = r->in.sync_context;
1172 r2.out.sync_context = r->out.sync_context;
1173 r2.out.delta_enum_array = r->out.delta_enum_array;
1174 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
1176 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
1178 return status;
1183 netr_AccountDeltas
1185 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1186 struct netr_AccountDeltas *r)
1188 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1189 return NT_STATUS_NOT_IMPLEMENTED;
1194 netr_AccountSync
1196 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1197 struct netr_AccountSync *r)
1199 /* w2k3 returns "NOT IMPLEMENTED" for this call */
1200 return NT_STATUS_NOT_IMPLEMENTED;
1205 netr_GetDcName
1207 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1208 struct netr_GetDcName *r)
1210 const char * const attrs[] = { NULL };
1211 struct ldb_context *sam_ctx;
1212 struct ldb_message **res;
1213 struct ldb_dn *domain_dn;
1214 int ret;
1215 const char *dcname;
1218 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1219 * that the domainname needs to be a valid netbios domain
1220 * name, if it is not NULL.
1222 if (r->in.domainname) {
1223 const char *dot = strchr(r->in.domainname, '.');
1224 size_t len = strlen(r->in.domainname);
1226 if (dot || len > 15) {
1227 return WERR_DCNOTFOUND;
1231 * TODO: Should we also varify that only valid
1232 * netbios name characters are used?
1236 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1237 dce_call->conn->dce_ctx->lp_ctx,
1238 dce_call->conn->auth_state.session_info, 0);
1239 if (sam_ctx == NULL) {
1240 return WERR_DS_UNAVAILABLE;
1243 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1244 r->in.domainname);
1245 if (domain_dn == NULL) {
1246 return WERR_NO_SUCH_DOMAIN;
1249 ret = gendb_search_dn(sam_ctx, mem_ctx,
1250 domain_dn, &res, attrs);
1251 if (ret != 1) {
1252 return WERR_NO_SUCH_DOMAIN;
1255 /* TODO: - return real IP address
1256 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1258 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1259 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1260 W_ERROR_HAVE_NO_MEMORY(dcname);
1262 *r->out.dcname = dcname;
1263 return WERR_OK;
1268 netr_LogonControl2Ex
1270 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1271 struct netr_LogonControl2Ex *r)
1273 return WERR_NOT_SUPPORTED;
1278 netr_LogonControl
1280 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1281 struct netr_LogonControl *r)
1283 struct netr_LogonControl2Ex r2;
1284 WERROR werr;
1286 if (r->in.level == 0x00000001) {
1287 ZERO_STRUCT(r2);
1289 r2.in.logon_server = r->in.logon_server;
1290 r2.in.function_code = r->in.function_code;
1291 r2.in.level = r->in.level;
1292 r2.in.data = NULL;
1293 r2.out.query = r->out.query;
1295 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1296 } else if (r->in.level == 0x00000002) {
1297 werr = WERR_NOT_SUPPORTED;
1298 } else {
1299 werr = WERR_UNKNOWN_LEVEL;
1302 return werr;
1307 netr_LogonControl2
1309 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1310 struct netr_LogonControl2 *r)
1312 struct netr_LogonControl2Ex r2;
1313 WERROR werr;
1315 ZERO_STRUCT(r2);
1317 r2.in.logon_server = r->in.logon_server;
1318 r2.in.function_code = r->in.function_code;
1319 r2.in.level = r->in.level;
1320 r2.in.data = r->in.data;
1321 r2.out.query = r->out.query;
1323 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1325 return werr;
1328 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1329 struct ldb_context *sam_ctx,
1330 struct netr_DomainTrustList *trusts,
1331 uint32_t trust_flags);
1334 netr_GetAnyDCName
1336 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1337 struct netr_GetAnyDCName *r)
1339 struct netr_DomainTrustList *trusts;
1340 struct ldb_context *sam_ctx;
1341 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1342 uint32_t i;
1343 WERROR werr;
1345 *r->out.dcname = NULL;
1347 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1348 /* if the domainname parameter wasn't set assume our domain */
1349 r->in.domainname = lpcfg_workgroup(lp_ctx);
1352 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1353 dce_call->conn->auth_state.session_info, 0);
1354 if (sam_ctx == NULL) {
1355 return WERR_DS_UNAVAILABLE;
1358 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1359 /* well we asked for a DC of our own domain */
1360 if (samdb_is_pdc(sam_ctx)) {
1361 /* we are the PDC of the specified domain */
1362 return WERR_NO_SUCH_DOMAIN;
1365 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1366 lpcfg_netbios_name(lp_ctx));
1367 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1369 return WERR_OK;
1372 /* Okay, now we have to consider the trusted domains */
1374 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1375 W_ERROR_HAVE_NO_MEMORY(trusts);
1377 trusts->count = 0;
1379 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1380 NETR_TRUST_FLAG_INBOUND
1381 | NETR_TRUST_FLAG_OUTBOUND);
1382 W_ERROR_NOT_OK_RETURN(werr);
1384 for (i = 0; i < trusts->count; i++) {
1385 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1386 /* FIXME: Here we need to find a DC for the specified
1387 * trusted domain. */
1389 /* return WERR_OK; */
1390 return WERR_NO_SUCH_DOMAIN;
1394 return WERR_NO_SUCH_DOMAIN;
1399 netr_DatabaseRedo
1401 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1402 struct netr_DatabaseRedo *r)
1404 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1409 netr_NetrEnumerateTrustedDomains
1411 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1412 struct netr_NetrEnumerateTrustedDomains *r)
1414 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1419 netr_LogonGetCapabilities
1421 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1422 struct netr_LogonGetCapabilities *r)
1424 struct netlogon_creds_CredentialState *creds;
1425 NTSTATUS status;
1427 status = dcesrv_netr_creds_server_step_check(dce_call,
1428 mem_ctx,
1429 r->in.computer_name,
1430 r->in.credential,
1431 r->out.return_authenticator,
1432 &creds);
1433 if (!NT_STATUS_IS_OK(status)) {
1434 DEBUG(0,(__location__ " Bad credentials - error\n"));
1436 NT_STATUS_NOT_OK_RETURN(status);
1438 if (r->in.query_level != 1) {
1439 return NT_STATUS_NOT_SUPPORTED;
1442 r->out.capabilities->server_capabilities = creds->negotiate_flags;
1444 return NT_STATUS_OK;
1449 netr_NETRLOGONSETSERVICEBITS
1451 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1452 struct netr_NETRLOGONSETSERVICEBITS *r)
1454 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1459 netr_LogonGetTrustRid
1461 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1462 struct netr_LogonGetTrustRid *r)
1464 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1469 netr_NETRLOGONCOMPUTESERVERDIGEST
1471 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1472 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1474 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1479 netr_NETRLOGONCOMPUTECLIENTDIGEST
1481 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1482 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1484 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1490 netr_DsRGetSiteName
1492 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1493 struct netr_DsRGetSiteName *r)
1495 struct ldb_context *sam_ctx;
1496 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1498 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1499 dce_call->conn->auth_state.session_info, 0);
1500 if (sam_ctx == NULL) {
1501 return WERR_DS_UNAVAILABLE;
1505 * We assume to be a DC when we get called over NETLOGON. Hence we
1506 * get our site name always by using "samdb_server_site_name()"
1507 * and not "samdb_client_site_name()".
1509 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1510 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1512 return WERR_OK;
1517 fill in a netr_OneDomainInfo from a ldb search result
1519 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1520 struct loadparm_context *lp_ctx,
1521 struct ldb_context *sam_ctx,
1522 struct ldb_message *res,
1523 struct netr_OneDomainInfo *info,
1524 bool is_local, bool is_trust_list)
1526 ZERO_STRUCTP(info);
1528 if (is_trust_list) {
1529 /* w2k8 only fills this on trusted domains */
1530 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1531 info->trust_extension.length = 16;
1532 info->trust_extension.info->flags =
1533 NETR_TRUST_FLAG_TREEROOT |
1534 NETR_TRUST_FLAG_IN_FOREST |
1535 NETR_TRUST_FLAG_PRIMARY |
1536 NETR_TRUST_FLAG_NATIVE;
1538 info->trust_extension.info->parent_index = 0; /* should be index into array
1539 of parent */
1540 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1541 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1544 if (is_trust_list) {
1545 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1546 info->dns_forestname.string = NULL;
1547 } else {
1548 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1549 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1550 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1551 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1554 if (is_local) {
1555 info->domainname.string = lpcfg_workgroup(lp_ctx);
1556 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1557 info->domain_guid = samdb_result_guid(res, "objectGUID");
1558 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1559 } else {
1560 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1561 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1562 info->domain_guid = samdb_result_guid(res, "objectGUID");
1563 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1565 if (!is_trust_list) {
1566 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1569 return NT_STATUS_OK;
1573 netr_LogonGetDomainInfo
1574 this is called as part of the ADS domain logon procedure.
1576 It has an important role in convaying details about the client, such
1577 as Operating System, Version, Service Pack etc.
1579 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1580 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1582 struct netlogon_creds_CredentialState *creds;
1583 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1584 "securityIdentifier", "trustPartner", NULL };
1585 const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1586 "msDS-SupportedEncryptionTypes", NULL };
1587 const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1588 struct ldb_context *sam_ctx;
1589 struct ldb_message **res1, **res2, **res3, *new_msg;
1590 struct ldb_dn *workstation_dn;
1591 struct netr_DomainInformation *domain_info;
1592 struct netr_LsaPolicyInformation *lsa_policy_info;
1593 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1594 bool update_dns_hostname = true;
1595 int ret, ret3, i;
1596 NTSTATUS status;
1598 status = dcesrv_netr_creds_server_step_check(dce_call,
1599 mem_ctx,
1600 r->in.computer_name,
1601 r->in.credential,
1602 r->out.return_authenticator,
1603 &creds);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 DEBUG(0,(__location__ " Bad credentials - error\n"));
1607 NT_STATUS_NOT_OK_RETURN(status);
1609 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1610 dce_call->conn->dce_ctx->lp_ctx,
1611 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1612 if (sam_ctx == NULL) {
1613 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1616 switch (r->in.level) {
1617 case 1: /* Domain information */
1619 if (r->in.query->workstation_info == NULL) {
1620 return NT_STATUS_INVALID_PARAMETER;
1623 /* Prepares the workstation DN */
1624 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1625 dom_sid_string(mem_ctx, creds->sid));
1626 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1628 /* Lookup for attributes in workstation object */
1629 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1630 attrs2);
1631 if (ret != 1) {
1632 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1635 /* Gets the sam account name which is checked against the DNS
1636 * hostname parameter. */
1637 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1638 "sAMAccountName",
1639 NULL);
1640 if (sam_account_name == NULL) {
1641 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1645 * Checks that the sam account name without a possible "$"
1646 * matches as prefix with the DNS hostname in the workstation
1647 * info structure.
1649 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1650 strcspn(sam_account_name, "$"));
1651 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1652 if (r->in.query->workstation_info->dns_hostname != NULL) {
1653 prefix2 = talloc_strndup(mem_ctx,
1654 r->in.query->workstation_info->dns_hostname,
1655 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1656 NT_STATUS_HAVE_NO_MEMORY(prefix2);
1658 if (strcasecmp(prefix1, prefix2) != 0) {
1659 update_dns_hostname = false;
1661 } else {
1662 update_dns_hostname = false;
1665 /* Gets the old DNS hostname */
1666 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1667 "dNSHostName",
1668 NULL);
1671 * Updates the DNS hostname when the client wishes that the
1672 * server should handle this for him
1673 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1674 * obviously only checked when we do already have a
1675 * "dNSHostName".
1676 * See MS-NRPC section 3.5.4.3.9
1678 if ((old_dns_hostname != NULL) &&
1679 (r->in.query->workstation_info->workstation_flags
1680 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1681 update_dns_hostname = false;
1684 /* Gets host information and put them into our directory */
1686 new_msg = ldb_msg_new(mem_ctx);
1687 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1689 new_msg->dn = workstation_dn;
1691 /* Sets the OS name */
1693 if (r->in.query->workstation_info->os_name.string == NULL) {
1694 return NT_STATUS_INVALID_PARAMETER;
1697 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1698 r->in.query->workstation_info->os_name.string);
1699 if (ret != LDB_SUCCESS) {
1700 return NT_STATUS_NO_MEMORY;
1704 * Sets information from "os_version". On an empty structure
1705 * the values are cleared.
1707 if (r->in.query->workstation_info->os_version.os != NULL) {
1708 struct netr_OsVersionInfoEx *os_version;
1709 const char *os_version_str;
1711 os_version = &r->in.query->workstation_info->os_version.os->os;
1713 if (os_version->CSDVersion == NULL) {
1714 return NT_STATUS_INVALID_PARAMETER;
1717 os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1718 os_version->MajorVersion,
1719 os_version->MinorVersion,
1720 os_version->BuildNumber);
1721 NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1723 ret = ldb_msg_add_string(new_msg,
1724 "operatingSystemServicePack",
1725 os_version->CSDVersion);
1726 if (ret != LDB_SUCCESS) {
1727 return NT_STATUS_NO_MEMORY;
1730 ret = ldb_msg_add_string(new_msg,
1731 "operatingSystemVersion",
1732 os_version_str);
1733 if (ret != LDB_SUCCESS) {
1734 return NT_STATUS_NO_MEMORY;
1736 } else {
1737 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1738 "operatingSystemServicePack");
1739 if (ret != LDB_SUCCESS) {
1740 return NT_STATUS_NO_MEMORY;
1743 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1744 "operatingSystemVersion");
1745 if (ret != LDB_SUCCESS) {
1746 return NT_STATUS_NO_MEMORY;
1751 * If the boolean "update_dns_hostname" remained true, then we
1752 * are fine to start the update.
1754 if (update_dns_hostname) {
1755 ret = ldb_msg_add_string(new_msg,
1756 "dNSHostname",
1757 r->in.query->workstation_info->dns_hostname);
1758 if (ret != LDB_SUCCESS) {
1759 return NT_STATUS_NO_MEMORY;
1762 /* This manual "servicePrincipalName" generation is
1763 * still needed! Since the update in the samldb LDB
1764 * module does only work if the entries already exist
1765 * which isn't always the case. */
1766 ret = ldb_msg_add_string(new_msg,
1767 "servicePrincipalName",
1768 talloc_asprintf(new_msg, "HOST/%s",
1769 r->in.computer_name));
1770 if (ret != LDB_SUCCESS) {
1771 return NT_STATUS_NO_MEMORY;
1774 ret = ldb_msg_add_string(new_msg,
1775 "servicePrincipalName",
1776 talloc_asprintf(new_msg, "HOST/%s",
1777 r->in.query->workstation_info->dns_hostname));
1778 if (ret != LDB_SUCCESS) {
1779 return NT_STATUS_NO_MEMORY;
1783 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1784 DEBUG(3,("Impossible to update samdb: %s\n",
1785 ldb_errstring(sam_ctx)));
1788 talloc_free(new_msg);
1790 /* Writes back the domain information */
1792 /* We need to do two searches. The first will pull our primary
1793 domain and the second will pull any trusted domains. Our
1794 primary domain is also a "trusted" domain, so we need to
1795 put the primary domain into the lists of returned trusts as
1796 well. */
1797 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1798 &res2, attrs);
1799 if (ret != 1) {
1800 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1803 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1804 "(objectClass=trustedDomain)");
1805 if (ret3 == -1) {
1806 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1809 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1810 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1812 ZERO_STRUCTP(domain_info);
1814 /* Informations about the local and trusted domains */
1816 status = fill_one_domain_info(mem_ctx,
1817 dce_call->conn->dce_ctx->lp_ctx,
1818 sam_ctx, res2[0], &domain_info->primary_domain,
1819 true, false);
1820 NT_STATUS_NOT_OK_RETURN(status);
1822 domain_info->trusted_domain_count = ret3 + 1;
1823 domain_info->trusted_domains = talloc_array(mem_ctx,
1824 struct netr_OneDomainInfo,
1825 domain_info->trusted_domain_count);
1826 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1828 for (i=0;i<ret3;i++) {
1829 status = fill_one_domain_info(mem_ctx,
1830 dce_call->conn->dce_ctx->lp_ctx,
1831 sam_ctx, res3[i],
1832 &domain_info->trusted_domains[i],
1833 false, true);
1834 NT_STATUS_NOT_OK_RETURN(status);
1837 status = fill_one_domain_info(mem_ctx,
1838 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1839 &domain_info->trusted_domains[i], true, true);
1840 NT_STATUS_NOT_OK_RETURN(status);
1842 /* Sets the supported encryption types */
1843 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1844 "msDS-SupportedEncryptionTypes",
1845 default_supported_enc_types);
1847 /* Other host domain information */
1849 lsa_policy_info = talloc(mem_ctx,
1850 struct netr_LsaPolicyInformation);
1851 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1852 ZERO_STRUCTP(lsa_policy_info);
1854 domain_info->lsa_policy = *lsa_policy_info;
1856 /* The DNS hostname is only returned back when there is a chance
1857 * for a change. */
1858 if ((r->in.query->workstation_info->workstation_flags
1859 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1860 domain_info->dns_hostname.string = old_dns_hostname;
1861 } else {
1862 domain_info->dns_hostname.string = NULL;
1865 domain_info->workstation_flags =
1866 r->in.query->workstation_info->workstation_flags & (
1867 NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1869 r->out.info->domain_info = domain_info;
1870 break;
1871 case 2: /* LSA policy information - not used at the moment */
1872 lsa_policy_info = talloc(mem_ctx,
1873 struct netr_LsaPolicyInformation);
1874 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1875 ZERO_STRUCTP(lsa_policy_info);
1877 r->out.info->lsa_policy_info = lsa_policy_info;
1878 break;
1879 default:
1880 return NT_STATUS_INVALID_LEVEL;
1881 break;
1884 return NT_STATUS_OK;
1889 netr_ServerPasswordGet
1891 static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1892 struct netr_ServerPasswordGet *r)
1894 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1899 netr_NETRLOGONSENDTOSAM
1901 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1902 struct netr_NETRLOGONSENDTOSAM *r)
1904 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1909 netr_DsRGetDCNameEx2
1911 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1912 TALLOC_CTX *mem_ctx,
1913 struct netr_DsRGetDCNameEx2 *r)
1915 struct ldb_context *sam_ctx;
1916 struct netr_DsRGetDCNameInfo *info;
1917 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1918 const struct tsocket_address *local_address;
1919 char *local_addr = NULL;
1920 const struct tsocket_address *remote_address;
1921 char *remote_addr = NULL;
1922 const char *server_site_name;
1923 char *guid_str;
1924 struct netlogon_samlogon_response response;
1925 NTSTATUS status;
1926 const char *dc_name = NULL;
1927 const char *domain_name = NULL;
1928 const char *pdc_ip;
1930 ZERO_STRUCTP(r->out.info);
1932 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1933 dce_call->conn->auth_state.session_info, 0);
1934 if (sam_ctx == NULL) {
1935 return WERR_DS_UNAVAILABLE;
1938 local_address = dcesrv_connection_get_local_address(dce_call->conn);
1939 if (tsocket_address_is_inet(local_address, "ip")) {
1940 local_addr = tsocket_address_inet_addr_string(local_address, mem_ctx);
1941 W_ERROR_HAVE_NO_MEMORY(local_addr);
1944 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1945 if (tsocket_address_is_inet(remote_address, "ip")) {
1946 remote_addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1947 W_ERROR_HAVE_NO_MEMORY(remote_addr);
1950 /* "server_unc" is ignored by w2k3 */
1952 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1953 return WERR_INVALID_FLAGS;
1956 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1957 r->in.flags & DS_PDC_REQUIRED &&
1958 r->in.flags & DS_KDC_REQUIRED) {
1959 return WERR_INVALID_FLAGS;
1961 if (r->in.flags & DS_IS_FLAT_NAME &&
1962 r->in.flags & DS_IS_DNS_NAME) {
1963 return WERR_INVALID_FLAGS;
1965 if (r->in.flags & DS_RETURN_DNS_NAME &&
1966 r->in.flags & DS_RETURN_FLAT_NAME) {
1967 return WERR_INVALID_FLAGS;
1969 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1970 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1971 return WERR_INVALID_FLAGS;
1974 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1975 r->in.flags &
1976 (DS_DIRECTORY_SERVICE_REQUIRED |
1977 DS_DIRECTORY_SERVICE_PREFERRED |
1978 DS_GC_SERVER_REQUIRED |
1979 DS_PDC_REQUIRED |
1980 DS_KDC_REQUIRED)) {
1981 return WERR_INVALID_FLAGS;
1984 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1985 r->in.site_name) {
1986 return WERR_INVALID_FLAGS;
1989 /* Proof server site parameter "site_name" if it was specified */
1990 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1991 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1992 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1993 server_site_name) != 0)) {
1994 return WERR_NO_SUCH_DOMAIN;
1997 guid_str = r->in.domain_guid != NULL ?
1998 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
2000 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
2001 r->in.domain_name,
2002 r->in.domain_name,
2003 NULL, guid_str,
2004 r->in.client_account,
2005 r->in.mask, remote_addr,
2006 NETLOGON_NT_VERSION_5EX_WITH_IP,
2007 lp_ctx, &response, true);
2008 if (!NT_STATUS_IS_OK(status)) {
2009 return ntstatus_to_werror(status);
2013 * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
2014 * (O) flag when the returned forest name is in DNS format. This is here
2015 * always the case (see below).
2017 response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
2019 if (r->in.flags & DS_RETURN_DNS_NAME) {
2020 dc_name = response.data.nt5_ex.pdc_dns_name;
2021 domain_name = response.data.nt5_ex.dns_domain;
2023 * According to MS-NRPC 2.2.1.2.1 we should set the
2024 * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
2025 * the returned information is in DNS form.
2027 response.data.nt5_ex.server_type |=
2028 DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
2029 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
2030 dc_name = response.data.nt5_ex.pdc_name;
2031 domain_name = response.data.nt5_ex.domain_name;
2032 } else {
2035 * TODO: autodetect what we need to return
2036 * based on the given arguments
2038 dc_name = response.data.nt5_ex.pdc_name;
2039 domain_name = response.data.nt5_ex.domain_name;
2042 if (!dc_name || !dc_name[0]) {
2043 return WERR_NO_SUCH_DOMAIN;
2046 if (!domain_name || !domain_name[0]) {
2047 return WERR_NO_SUCH_DOMAIN;
2050 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
2051 W_ERROR_HAVE_NO_MEMORY(info);
2052 info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
2053 dc_name[0] != '\\'? "\\\\":"",
2054 talloc_strdup(mem_ctx, dc_name));
2055 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
2057 pdc_ip = local_addr;
2058 if (pdc_ip == NULL) {
2059 pdc_ip = "127.0.0.1";
2061 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
2062 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
2063 info->dc_address_type = DS_ADDRESS_TYPE_INET;
2064 info->domain_guid = response.data.nt5_ex.domain_uuid;
2065 info->domain_name = domain_name;
2066 info->forest_name = response.data.nt5_ex.forest;
2067 info->dc_flags = response.data.nt5_ex.server_type;
2068 if (r->in.flags & DS_RETURN_DNS_NAME) {
2069 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
2070 * returned if we are returning info->dc_unc containing a FQDN.
2071 * This attribute is called DomainControllerName in the specs,
2072 * it seems that we decide to return FQDN or netbios depending on
2073 * DS_RETURN_DNS_NAME.
2075 info->dc_flags |= DS_DNS_CONTROLLER;
2077 info->dc_site_name = response.data.nt5_ex.server_site;
2078 info->client_site_name = response.data.nt5_ex.client_site;
2080 *r->out.info = info;
2082 return WERR_OK;
2086 netr_DsRGetDCNameEx
2088 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2089 struct netr_DsRGetDCNameEx *r)
2091 struct netr_DsRGetDCNameEx2 r2;
2092 WERROR werr;
2094 ZERO_STRUCT(r2);
2096 r2.in.server_unc = r->in.server_unc;
2097 r2.in.client_account = NULL;
2098 r2.in.mask = 0;
2099 r2.in.domain_guid = r->in.domain_guid;
2100 r2.in.domain_name = r->in.domain_name;
2101 r2.in.site_name = r->in.site_name;
2102 r2.in.flags = r->in.flags;
2103 r2.out.info = r->out.info;
2105 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2107 return werr;
2111 netr_DsRGetDCName
2113 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2114 struct netr_DsRGetDCName *r)
2116 struct netr_DsRGetDCNameEx2 r2;
2117 WERROR werr;
2119 ZERO_STRUCT(r2);
2121 r2.in.server_unc = r->in.server_unc;
2122 r2.in.client_account = NULL;
2123 r2.in.mask = 0;
2124 r2.in.domain_name = r->in.domain_name;
2125 r2.in.domain_guid = r->in.domain_guid;
2127 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
2128 r2.in.flags = r->in.flags;
2129 r2.out.info = r->out.info;
2131 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
2133 return werr;
2136 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
2138 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2139 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
2141 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2146 netr_NetrEnumerateTrustedDomainsEx
2148 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2149 struct netr_NetrEnumerateTrustedDomainsEx *r)
2151 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2156 netr_DsRAddressToSitenamesExW
2158 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2159 struct netr_DsRAddressToSitenamesExW *r)
2161 struct ldb_context *sam_ctx;
2162 struct netr_DsRAddressToSitenamesExWCtr *ctr;
2163 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2164 sa_family_t sin_family;
2165 struct sockaddr_in *addr;
2166 #ifdef HAVE_IPV6
2167 struct sockaddr_in6 *addr6;
2168 char addr_str[INET6_ADDRSTRLEN];
2169 #else
2170 char addr_str[INET_ADDRSTRLEN];
2171 #endif
2172 char *subnet_name;
2173 const char *res;
2174 uint32_t i;
2176 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2177 dce_call->conn->auth_state.session_info, 0);
2178 if (sam_ctx == NULL) {
2179 return WERR_DS_UNAVAILABLE;
2182 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
2183 W_ERROR_HAVE_NO_MEMORY(ctr);
2185 *r->out.ctr = ctr;
2187 ctr->count = r->in.count;
2188 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2189 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2190 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
2191 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
2193 for (i=0; i<ctr->count; i++) {
2194 ctr->sitename[i].string = NULL;
2195 ctr->subnetname[i].string = NULL;
2197 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
2198 continue;
2200 /* The first two byte of the buffer are reserved for the
2201 * "sin_family" but for now only the first one is used. */
2202 sin_family = r->in.addresses[i].buffer[0];
2204 switch (sin_family) {
2205 case AF_INET:
2206 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2207 continue;
2209 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2210 res = inet_ntop(AF_INET, &addr->sin_addr,
2211 addr_str, sizeof(addr_str));
2212 break;
2213 #ifdef HAVE_IPV6
2214 case AF_INET6:
2215 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2216 continue;
2218 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2219 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2220 addr_str, sizeof(addr_str));
2221 break;
2222 #endif
2223 default:
2224 continue;
2227 if (res == NULL) {
2228 continue;
2231 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
2232 mem_ctx,
2233 addr_str,
2234 &subnet_name);
2235 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2236 ctr->subnetname[i].string = subnet_name;
2239 return WERR_OK;
2244 netr_DsRAddressToSitenamesW
2246 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2247 struct netr_DsRAddressToSitenamesW *r)
2249 struct netr_DsRAddressToSitenamesExW r2;
2250 struct netr_DsRAddressToSitenamesWCtr *ctr;
2251 uint32_t i;
2252 WERROR werr;
2254 ZERO_STRUCT(r2);
2256 r2.in.server_name = r->in.server_name;
2257 r2.in.count = r->in.count;
2258 r2.in.addresses = r->in.addresses;
2260 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2261 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2263 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2264 W_ERROR_HAVE_NO_MEMORY(ctr);
2266 *r->out.ctr = ctr;
2268 ctr->count = r->in.count;
2269 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2270 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2272 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2274 for (i=0; i<ctr->count; i++) {
2275 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
2278 return werr;
2283 netr_DsrGetDcSiteCoverageW
2285 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2286 struct netr_DsrGetDcSiteCoverageW *r)
2288 struct ldb_context *sam_ctx;
2289 struct DcSitesCtr *ctr;
2290 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2292 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2293 dce_call->conn->auth_state.session_info, 0);
2294 if (sam_ctx == NULL) {
2295 return WERR_DS_UNAVAILABLE;
2298 ctr = talloc(mem_ctx, struct DcSitesCtr);
2299 W_ERROR_HAVE_NO_MEMORY(ctr);
2301 *r->out.ctr = ctr;
2303 /* For now only return our default site */
2304 ctr->num_sites = 1;
2305 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2306 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2307 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2308 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2310 return WERR_OK;
2314 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2315 struct ldb_context *sam_ctx,
2316 struct netr_DomainTrustList *trusts,
2317 uint32_t trust_flags)
2319 struct ldb_dn *system_dn;
2320 struct ldb_message **dom_res = NULL;
2321 const char *trust_attrs[] = { "flatname", "trustPartner",
2322 "securityIdentifier", "trustDirection",
2323 "trustType", "trustAttributes", NULL };
2324 uint32_t n;
2325 int i;
2326 int ret;
2328 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2329 NETR_TRUST_FLAG_OUTBOUND))) {
2330 return WERR_INVALID_FLAGS;
2333 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2334 ldb_get_default_basedn(sam_ctx),
2335 "(&(objectClass=container)(cn=System))");
2336 if (!system_dn) {
2337 return WERR_GENERAL_FAILURE;
2340 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2341 &dom_res, trust_attrs,
2342 "(objectclass=trustedDomain)");
2344 for (i = 0; i < ret; i++) {
2345 unsigned int trust_dir;
2346 uint32_t flags = 0;
2348 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2349 "trustDirection", 0);
2351 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2352 flags |= NETR_TRUST_FLAG_INBOUND;
2354 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2355 flags |= NETR_TRUST_FLAG_OUTBOUND;
2358 if (!(flags & trust_flags)) {
2359 /* this trust direction was not requested */
2360 continue;
2363 n = trusts->count;
2364 trusts->array = talloc_realloc(trusts, trusts->array,
2365 struct netr_DomainTrust,
2366 n + 1);
2367 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2369 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2370 if (!trusts->array[n].netbios_name) {
2371 DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2372 "without flatname\n",
2373 ldb_dn_get_linearized(dom_res[i]->dn)));
2376 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2378 trusts->array[n].trust_flags = flags;
2379 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2380 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2381 /* TODO: find if we have parent in the list */
2382 trusts->array[n].parent_index = 0;
2385 trusts->array[n].trust_type =
2386 ldb_msg_find_attr_as_uint(dom_res[i],
2387 "trustType", 0);
2388 trusts->array[n].trust_attributes =
2389 ldb_msg_find_attr_as_uint(dom_res[i],
2390 "trustAttributes", 0);
2392 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
2393 (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
2394 struct dom_sid zero_sid;
2395 ZERO_STRUCT(zero_sid);
2396 trusts->array[n].sid =
2397 dom_sid_dup(trusts, &zero_sid);
2398 } else {
2399 trusts->array[n].sid =
2400 samdb_result_dom_sid(trusts, dom_res[i],
2401 "securityIdentifier");
2403 trusts->array[n].guid = GUID_zero();
2405 trusts->count = n + 1;
2408 talloc_free(dom_res);
2409 return WERR_OK;
2413 netr_DsrEnumerateDomainTrusts
2415 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2416 TALLOC_CTX *mem_ctx,
2417 struct netr_DsrEnumerateDomainTrusts *r)
2419 struct netr_DomainTrustList *trusts;
2420 struct ldb_context *sam_ctx;
2421 int ret;
2422 struct ldb_message **dom_res;
2423 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2424 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2425 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2426 const char *p;
2427 WERROR werr;
2429 if (r->in.trust_flags & 0xFFFFFE00) {
2430 return WERR_INVALID_FLAGS;
2433 /* TODO: turn to hard check once we are sure this is 100% correct */
2434 if (!r->in.server_name) {
2435 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2436 "But received NULL!\n", dnsdomain));
2437 } else {
2438 p = strchr(r->in.server_name, '.');
2439 if (!p) {
2440 DEBUG(3, ("Invalid domain! Expected name in domain "
2441 "[%s]. But received [%s]!\n",
2442 dnsdomain, r->in.server_name));
2443 p = r->in.server_name;
2444 } else {
2445 p++;
2447 if (strcasecmp(p, dnsdomain)) {
2448 DEBUG(3, ("Invalid domain! Expected name in domain "
2449 "[%s]. But received [%s]!\n",
2450 dnsdomain, r->in.server_name));
2454 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2455 W_ERROR_HAVE_NO_MEMORY(trusts);
2457 trusts->count = 0;
2458 r->out.trusts = trusts;
2460 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2461 dce_call->conn->auth_state.session_info, 0);
2462 if (sam_ctx == NULL) {
2463 return WERR_GENERAL_FAILURE;
2466 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2467 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2469 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2470 trusts, r->in.trust_flags);
2471 W_ERROR_NOT_OK_RETURN(werr);
2474 /* NOTE: we currently are always the root of the forest */
2475 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2476 uint32_t n = trusts->count;
2478 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2479 &dom_res, dom_attrs);
2480 if (ret != 1) {
2481 return WERR_GENERAL_FAILURE;
2484 trusts->count = n + 1;
2485 trusts->array = talloc_realloc(trusts, trusts->array,
2486 struct netr_DomainTrust,
2487 trusts->count);
2488 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2490 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2491 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2492 trusts->array[n].trust_flags =
2493 NETR_TRUST_FLAG_NATIVE |
2494 NETR_TRUST_FLAG_TREEROOT |
2495 NETR_TRUST_FLAG_IN_FOREST |
2496 NETR_TRUST_FLAG_PRIMARY;
2497 /* we are always the root domain for now */
2498 trusts->array[n].parent_index = 0;
2499 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
2500 trusts->array[n].trust_attributes = 0;
2501 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2502 dom_res[0],
2503 "objectSid");
2504 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2505 "objectGUID");
2506 talloc_free(dom_res);
2509 return WERR_OK;
2514 netr_DsrDeregisterDNSHostRecords
2516 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2517 struct netr_DsrDeregisterDNSHostRecords *r)
2519 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2524 netr_ServerTrustPasswordsGet
2526 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2527 struct netr_ServerTrustPasswordsGet *r)
2529 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2533 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2534 struct ldb_context *sam_ctx,
2535 struct loadparm_context *lp_ctx,
2536 struct lsa_ForestTrustInformation *info)
2538 struct lsa_ForestTrustDomainInfo *domain_info;
2539 struct lsa_ForestTrustRecord *e;
2540 struct ldb_message **dom_res;
2541 const char * const dom_attrs[] = { "objectSid", NULL };
2542 int ret;
2544 /* we need to provide 2 entries:
2545 * 1. the Root Forest name
2546 * 2. the Domain Information
2549 info->count = 2;
2550 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2551 W_ERROR_HAVE_NO_MEMORY(info->entries);
2553 /* Forest root info */
2554 e = talloc(info, struct lsa_ForestTrustRecord);
2555 W_ERROR_HAVE_NO_MEMORY(e);
2557 e->flags = 0;
2558 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2559 e->time = 0; /* so far always 0 in trces. */
2560 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2561 mem_ctx);
2562 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2564 info->entries[0] = e;
2566 /* Domain info */
2567 e = talloc(info, struct lsa_ForestTrustRecord);
2568 W_ERROR_HAVE_NO_MEMORY(e);
2570 /* get our own domain info */
2571 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2572 if (ret != 1) {
2573 return WERR_GENERAL_FAILURE;
2576 /* TODO: check if disabled and set flags accordingly */
2577 e->flags = 0;
2578 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2579 e->time = 0; /* so far always 0 in traces. */
2581 domain_info = &e->forest_trust_data.domain_info;
2582 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2583 "objectSid");
2584 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2585 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2587 info->entries[1] = e;
2589 talloc_free(dom_res);
2591 return WERR_OK;
2595 netr_DsRGetForestTrustInformation
2597 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2598 TALLOC_CTX *mem_ctx,
2599 struct netr_DsRGetForestTrustInformation *r)
2601 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2602 struct lsa_ForestTrustInformation *info, **info_ptr;
2603 struct ldb_context *sam_ctx;
2604 WERROR werr;
2606 if (r->in.flags & 0xFFFFFFFE) {
2607 return WERR_INVALID_FLAGS;
2610 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2611 dce_call->conn->auth_state.session_info, 0);
2612 if (sam_ctx == NULL) {
2613 return WERR_GENERAL_FAILURE;
2616 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2617 if (!samdb_is_pdc(sam_ctx)) {
2618 return WERR_NERR_NOTPRIMARY;
2621 if (r->in.trusted_domain_name == NULL) {
2622 return WERR_INVALID_FLAGS;
2625 /* TODO: establish an schannel connection with
2626 * r->in.trusted_domain_name and perform a
2627 * netr_GetForestTrustInformation call against it */
2629 /* for now return not implementd */
2630 return WERR_CALL_NOT_IMPLEMENTED;
2633 /* TODO: check r->in.server_name is our name */
2635 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2636 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2638 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2639 W_ERROR_HAVE_NO_MEMORY(info);
2641 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2642 W_ERROR_NOT_OK_RETURN(werr);
2644 *info_ptr = info;
2645 r->out.forest_trust_info = info_ptr;
2647 return WERR_OK;
2652 netr_GetForestTrustInformation
2654 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2655 TALLOC_CTX *mem_ctx,
2656 struct netr_GetForestTrustInformation *r)
2658 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2659 struct netlogon_creds_CredentialState *creds;
2660 struct lsa_ForestTrustInformation *info, **info_ptr;
2661 struct ldb_context *sam_ctx;
2662 NTSTATUS status;
2663 WERROR werr;
2665 status = dcesrv_netr_creds_server_step_check(dce_call,
2666 mem_ctx,
2667 r->in.computer_name,
2668 r->in.credential,
2669 r->out.return_authenticator,
2670 &creds);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 return status;
2675 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2676 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2677 return NT_STATUS_NOT_IMPLEMENTED;
2680 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2681 dce_call->conn->auth_state.session_info, 0);
2682 if (sam_ctx == NULL) {
2683 return NT_STATUS_INTERNAL_ERROR;
2686 /* TODO: check r->in.server_name is our name */
2688 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2689 if (!info_ptr) {
2690 return NT_STATUS_NO_MEMORY;
2692 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2693 if (!info) {
2694 return NT_STATUS_NO_MEMORY;
2697 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2698 if (!W_ERROR_IS_OK(werr)) {
2699 return werror_to_ntstatus(werr);
2702 *info_ptr = info;
2703 r->out.forest_trust_info = info_ptr;
2705 return NT_STATUS_OK;
2710 netr_ServerGetTrustInfo
2712 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2713 struct netr_ServerGetTrustInfo *r)
2715 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2719 netr_Unused47
2721 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2722 struct netr_Unused47 *r)
2724 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2728 struct netr_dnsupdate_RODC_state {
2729 struct dcesrv_call_state *dce_call;
2730 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2731 struct dnsupdate_RODC *r2;
2735 called when the forwarded RODC dns update request is finished
2737 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2739 struct netr_dnsupdate_RODC_state *st =
2740 tevent_req_callback_data(subreq,
2741 struct netr_dnsupdate_RODC_state);
2742 NTSTATUS status;
2744 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2745 TALLOC_FREE(subreq);
2746 if (!NT_STATUS_IS_OK(status)) {
2747 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2748 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2751 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2753 status = dcesrv_reply(st->dce_call);
2754 if (!NT_STATUS_IS_OK(status)) {
2755 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2760 netr_DsrUpdateReadOnlyServerDnsRecords
2762 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2763 TALLOC_CTX *mem_ctx,
2764 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2766 struct netlogon_creds_CredentialState *creds;
2767 NTSTATUS nt_status;
2768 struct dcerpc_binding_handle *binding_handle;
2769 struct netr_dnsupdate_RODC_state *st;
2770 struct tevent_req *subreq;
2772 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2773 mem_ctx,
2774 r->in.computer_name,
2775 r->in.credential,
2776 r->out.return_authenticator,
2777 &creds);
2778 NT_STATUS_NOT_OK_RETURN(nt_status);
2780 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2781 return NT_STATUS_ACCESS_DENIED;
2784 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2785 NT_STATUS_HAVE_NO_MEMORY(st);
2787 st->dce_call = dce_call;
2788 st->r = r;
2789 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2790 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2792 st->r2->in.dom_sid = creds->sid;
2793 st->r2->in.site_name = r->in.site_name;
2794 st->r2->in.dns_ttl = r->in.dns_ttl;
2795 st->r2->in.dns_names = r->in.dns_names;
2796 st->r2->out.dns_names = r->out.dns_names;
2798 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2799 "dnsupdate", &ndr_table_irpc);
2800 if (binding_handle == NULL) {
2801 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2802 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2803 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2806 /* forward the call */
2807 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2808 binding_handle, st->r2);
2809 NT_STATUS_HAVE_NO_MEMORY(subreq);
2811 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2813 /* setup the callback */
2814 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2816 return NT_STATUS_OK;
2820 /* include the generated boilerplate */
2821 #include "librpc/gen_ndr/ndr_netlogon_s.c"