s4:rpc_server/netlogon: handle DC_RETURN_NETBIOS and DC_RETURN_DNS in netr_DsRGetDCNa...
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob8ac5c613a317fb7d75f64a5c0b6262bf51f61bc5
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
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 "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
41 struct netlogon_server_pipe_state {
42 struct netr_Credential client_challenge;
43 struct netr_Credential server_challenge;
46 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
47 struct netr_ServerReqChallenge *r)
49 struct netlogon_server_pipe_state *pipe_state =
50 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52 ZERO_STRUCTP(r->out.return_credentials);
54 /* destroyed on pipe shutdown */
56 if (pipe_state) {
57 talloc_free(pipe_state);
58 dce_call->context->private_data = NULL;
61 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
62 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64 pipe_state->client_challenge = *r->in.credentials;
66 generate_random_buffer(pipe_state->server_challenge.data,
67 sizeof(pipe_state->server_challenge.data));
69 *r->out.return_credentials = pipe_state->server_challenge;
71 dce_call->context->private_data = pipe_state;
73 return NT_STATUS_OK;
76 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
77 struct netr_ServerAuthenticate3 *r)
79 struct netlogon_server_pipe_state *pipe_state =
80 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
81 struct netlogon_creds_CredentialState *creds;
82 struct ldb_context *sam_ctx;
83 struct samr_Password *mach_pwd;
84 uint32_t user_account_control;
85 int num_records;
86 struct ldb_message **msgs;
87 NTSTATUS nt_status;
88 const char *attrs[] = {"unicodePwd", "userAccountControl",
89 "objectSid", NULL};
91 const char *trust_dom_attrs[] = {"flatname", NULL};
92 const char *account_name;
94 ZERO_STRUCTP(r->out.return_credentials);
95 *r->out.rid = 0;
98 * According to Microsoft (see bugid #6099)
99 * Windows 7 looks at the negotiate_flags
100 * returned in this structure *even if the
101 * call fails with access denied!
103 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
104 NETLOGON_NEG_PERSISTENT_SAMREPL |
105 NETLOGON_NEG_ARCFOUR |
106 NETLOGON_NEG_PROMOTION_COUNT |
107 NETLOGON_NEG_CHANGELOG_BDC |
108 NETLOGON_NEG_FULL_SYNC_REPL |
109 NETLOGON_NEG_MULTIPLE_SIDS |
110 NETLOGON_NEG_REDO |
111 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
112 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
113 NETLOGON_NEG_GENERIC_PASSTHROUGH |
114 NETLOGON_NEG_CONCURRENT_RPC |
115 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
116 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
117 NETLOGON_NEG_STRONG_KEYS |
118 NETLOGON_NEG_TRANSITIVE_TRUSTS |
119 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
120 NETLOGON_NEG_PASSWORD_SET2 |
121 NETLOGON_NEG_GETDOMAININFO |
122 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
123 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
124 NETLOGON_NEG_RODC_PASSTHROUGH |
125 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
126 NETLOGON_NEG_AUTHENTICATED_RPC;
128 if (!pipe_state) {
129 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
130 return NT_STATUS_ACCESS_DENIED;
133 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
134 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
135 if (sam_ctx == NULL) {
136 return NT_STATUS_INVALID_SYSTEM_SERVICE;
139 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
140 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
141 const char *flatname;
142 if (!encoded_account) {
143 return NT_STATUS_NO_MEMORY;
146 /* Kill the trailing dot */
147 if (encoded_account[strlen(encoded_account)-1] == '.') {
148 encoded_account[strlen(encoded_account)-1] = '\0';
151 /* pull the user attributes */
152 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
153 trust_dom_attrs,
154 "(&(trustPartner=%s)(objectclass=trustedDomain))",
155 encoded_account);
157 if (num_records == 0) {
158 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
159 encoded_account));
160 return NT_STATUS_ACCESS_DENIED;
163 if (num_records > 1) {
164 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
165 return NT_STATUS_INTERNAL_DB_CORRUPTION;
168 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
169 if (!flatname) {
170 /* No flatname for this trust - we can't proceed */
171 return NT_STATUS_ACCESS_DENIED;
173 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
175 if (!account_name) {
176 return NT_STATUS_NO_MEMORY;
179 } else {
180 account_name = r->in.account_name;
183 /* pull the user attributes */
184 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
185 "(&(sAMAccountName=%s)(objectclass=user))",
186 ldb_binary_encode_string(mem_ctx, account_name));
188 if (num_records == 0) {
189 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
190 r->in.account_name));
191 return NT_STATUS_ACCESS_DENIED;
194 if (num_records > 1) {
195 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
196 return NT_STATUS_INTERNAL_DB_CORRUPTION;
199 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
201 if (user_account_control & UF_ACCOUNTDISABLE) {
202 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
203 return NT_STATUS_ACCESS_DENIED;
206 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
207 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
208 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
209 return NT_STATUS_ACCESS_DENIED;
211 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
212 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
213 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
214 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
216 return NT_STATUS_ACCESS_DENIED;
218 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
219 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
220 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
221 return NT_STATUS_ACCESS_DENIED;
223 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
224 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
225 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
226 return NT_STATUS_ACCESS_DENIED;
228 } else {
229 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
230 r->in.secure_channel_type));
231 return NT_STATUS_ACCESS_DENIED;
234 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
235 "objectSid", 0);
237 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
238 if (mach_pwd == NULL) {
239 return NT_STATUS_ACCESS_DENIED;
242 creds = netlogon_creds_server_init(mem_ctx,
243 r->in.account_name,
244 r->in.computer_name,
245 r->in.secure_channel_type,
246 &pipe_state->client_challenge,
247 &pipe_state->server_challenge,
248 mach_pwd,
249 r->in.credentials,
250 r->out.return_credentials,
251 *r->in.negotiate_flags);
253 if (!creds) {
254 return NT_STATUS_ACCESS_DENIED;
257 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
259 nt_status = schannel_save_creds_state(mem_ctx,
260 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
261 creds);
263 return nt_status;
266 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
267 struct netr_ServerAuthenticate *r)
269 struct netr_ServerAuthenticate3 a;
270 uint32_t rid;
271 /* TODO:
272 * negotiate_flags is used as an [in] parameter
273 * so it need to be initialised.
275 * (I think ... = 0; seems wrong here --metze)
277 uint32_t negotiate_flags_in = 0;
278 uint32_t negotiate_flags_out = 0;
280 a.in.server_name = r->in.server_name;
281 a.in.account_name = r->in.account_name;
282 a.in.secure_channel_type = r->in.secure_channel_type;
283 a.in.computer_name = r->in.computer_name;
284 a.in.credentials = r->in.credentials;
285 a.in.negotiate_flags = &negotiate_flags_in;
287 a.out.return_credentials = r->out.return_credentials;
288 a.out.rid = &rid;
289 a.out.negotiate_flags = &negotiate_flags_out;
291 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
294 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
295 struct netr_ServerAuthenticate2 *r)
297 struct netr_ServerAuthenticate3 r3;
298 uint32_t rid = 0;
300 r3.in.server_name = r->in.server_name;
301 r3.in.account_name = r->in.account_name;
302 r3.in.secure_channel_type = r->in.secure_channel_type;
303 r3.in.computer_name = r->in.computer_name;
304 r3.in.credentials = r->in.credentials;
305 r3.out.return_credentials = r->out.return_credentials;
306 r3.in.negotiate_flags = r->in.negotiate_flags;
307 r3.out.negotiate_flags = r->out.negotiate_flags;
308 r3.out.rid = &rid;
310 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
314 * NOTE: The following functions are nearly identical to the ones available in
315 * source3/rpc_server/srv_nelog_nt.c
316 * The reason we keep 2 copies is that they use different structures to
317 * represent the auth_info and the decrpc pipes.
321 * If schannel is required for this call test that it actually is available.
323 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
324 const char *computer_name,
325 bool integrity, bool privacy)
328 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
329 if (!privacy && !integrity) {
330 return NT_STATUS_OK;
333 if ((!privacy && integrity) &&
334 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
335 return NT_STATUS_OK;
338 if ((privacy || integrity) &&
339 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
340 return NT_STATUS_OK;
344 /* test didn't pass */
345 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
346 computer_name));
348 return NT_STATUS_ACCESS_DENIED;
351 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
352 TALLOC_CTX *mem_ctx,
353 const char *computer_name,
354 struct netr_Authenticator *received_authenticator,
355 struct netr_Authenticator *return_authenticator,
356 struct netlogon_creds_CredentialState **creds_out)
358 NTSTATUS nt_status;
359 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
360 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
362 if (schannel_global_required) {
363 nt_status = schannel_check_required(auth_info,
364 computer_name,
365 true, false);
366 if (!NT_STATUS_IS_OK(nt_status)) {
367 return nt_status;
371 nt_status = schannel_check_creds_state(mem_ctx,
372 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
373 computer_name,
374 received_authenticator,
375 return_authenticator,
376 creds_out);
377 return nt_status;
381 Change the machine account password for the currently connected
382 client. Supplies only the NT#.
385 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
386 struct netr_ServerPasswordSet *r)
388 struct netlogon_creds_CredentialState *creds;
389 struct ldb_context *sam_ctx;
390 const char * const attrs[] = { "unicodePwd", NULL };
391 struct ldb_message **res;
392 struct samr_Password *oldNtHash;
393 NTSTATUS nt_status;
394 int ret;
396 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
397 mem_ctx,
398 r->in.computer_name,
399 r->in.credential, r->out.return_authenticator,
400 &creds);
401 NT_STATUS_NOT_OK_RETURN(nt_status);
403 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);
404 if (sam_ctx == NULL) {
405 return NT_STATUS_INVALID_SYSTEM_SERVICE;
408 netlogon_creds_des_decrypt(creds, r->in.new_password);
410 /* fetch the old password hashes (the NT hash has to exist) */
412 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
413 "(&(objectClass=user)(objectSid=%s))",
414 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
415 if (ret != 1) {
416 return NT_STATUS_WRONG_PASSWORD;
419 nt_status = samdb_result_passwords(mem_ctx,
420 dce_call->conn->dce_ctx->lp_ctx,
421 res[0], NULL, &oldNtHash);
422 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
423 return NT_STATUS_WRONG_PASSWORD;
426 /* Using the sid for the account as the key, set the password */
427 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
428 creds->sid,
429 NULL, /* Don't have plaintext */
430 NULL, r->in.new_password,
431 NULL, oldNtHash, /* Password change */
432 NULL, NULL);
433 return nt_status;
437 Change the machine account password for the currently connected
438 client. Supplies new plaintext.
440 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
441 struct netr_ServerPasswordSet2 *r)
443 struct netlogon_creds_CredentialState *creds;
444 struct ldb_context *sam_ctx;
445 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
446 struct ldb_message **res;
447 struct samr_Password *oldLmHash, *oldNtHash;
448 NTSTATUS nt_status;
449 DATA_BLOB new_password;
450 int ret;
452 struct samr_CryptPassword password_buf;
454 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
455 mem_ctx,
456 r->in.computer_name,
457 r->in.credential, r->out.return_authenticator,
458 &creds);
459 NT_STATUS_NOT_OK_RETURN(nt_status);
461 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);
462 if (sam_ctx == NULL) {
463 return NT_STATUS_INVALID_SYSTEM_SERVICE;
466 memcpy(password_buf.data, r->in.new_password->data, 512);
467 SIVAL(password_buf.data, 512, r->in.new_password->length);
468 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
470 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
471 DEBUG(3,("samr: failed to decode password buffer\n"));
472 return NT_STATUS_WRONG_PASSWORD;
475 /* fetch the old password hashes (at least one of both has to exist) */
477 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
478 "(&(objectClass=user)(objectSid=%s))",
479 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
480 if (ret != 1) {
481 return NT_STATUS_WRONG_PASSWORD;
484 nt_status = samdb_result_passwords(mem_ctx,
485 dce_call->conn->dce_ctx->lp_ctx,
486 res[0], &oldLmHash, &oldNtHash);
487 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
488 return NT_STATUS_WRONG_PASSWORD;
491 /* Using the sid for the account as the key, set the password */
492 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
493 creds->sid,
494 &new_password, /* we have plaintext */
495 NULL, NULL,
496 oldLmHash, oldNtHash, /* Password change */
497 NULL, NULL);
498 return nt_status;
503 netr_LogonUasLogon
505 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
506 struct netr_LogonUasLogon *r)
508 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
513 netr_LogonUasLogoff
515 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
516 struct netr_LogonUasLogoff *r)
518 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
523 netr_LogonSamLogon_base
525 This version of the function allows other wrappers to say 'do not check the credentials'
527 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
529 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
530 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
532 struct auth_context *auth_context;
533 struct auth_usersupplied_info *user_info;
534 struct auth_serversupplied_info *server_info;
535 NTSTATUS nt_status;
536 static const char zeros[16];
537 struct netr_SamBaseInfo *sam;
538 struct netr_SamInfo2 *sam2;
539 struct netr_SamInfo3 *sam3;
540 struct netr_SamInfo6 *sam6;
542 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
543 NT_STATUS_HAVE_NO_MEMORY(user_info);
545 switch (r->in.logon_level) {
546 case NetlogonInteractiveInformation:
547 case NetlogonServiceInformation:
548 case NetlogonInteractiveTransitiveInformation:
549 case NetlogonServiceTransitiveInformation:
550 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
551 netlogon_creds_arcfour_crypt(creds,
552 r->in.logon->password->lmpassword.hash,
553 sizeof(r->in.logon->password->lmpassword.hash));
554 netlogon_creds_arcfour_crypt(creds,
555 r->in.logon->password->ntpassword.hash,
556 sizeof(r->in.logon->password->ntpassword.hash));
557 } else {
558 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
559 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
562 /* TODO: we need to deny anonymous access here */
563 nt_status = auth_context_create(mem_ctx,
564 dce_call->event_ctx, dce_call->msg_ctx,
565 dce_call->conn->dce_ctx->lp_ctx,
566 &auth_context);
567 NT_STATUS_NOT_OK_RETURN(nt_status);
569 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
570 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
571 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
572 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
574 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
575 user_info->password_state = AUTH_PASSWORD_HASH;
577 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
578 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
579 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
581 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
582 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
583 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
585 break;
586 case NetlogonNetworkInformation:
587 case NetlogonNetworkTransitiveInformation:
589 /* TODO: we need to deny anonymous access here */
590 nt_status = auth_context_create(mem_ctx,
591 dce_call->event_ctx, dce_call->msg_ctx,
592 dce_call->conn->dce_ctx->lp_ctx,
593 &auth_context);
594 NT_STATUS_NOT_OK_RETURN(nt_status);
596 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
597 NT_STATUS_NOT_OK_RETURN(nt_status);
599 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
600 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
601 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
602 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
604 user_info->password_state = AUTH_PASSWORD_RESPONSE;
605 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
606 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
608 break;
611 case NetlogonGenericInformation:
613 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
614 netlogon_creds_arcfour_crypt(creds,
615 r->in.logon->generic->data, r->in.logon->generic->length);
616 } else {
617 /* Using DES to verify kerberos tickets makes no sense */
618 return NT_STATUS_INVALID_PARAMETER;
621 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
622 NTSTATUS status;
623 struct dcerpc_binding_handle *irpc_handle;
624 struct kdc_check_generic_kerberos check;
625 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
626 NT_STATUS_HAVE_NO_MEMORY(generic);
627 *r->out.authoritative = 1;
629 /* TODO: Describe and deal with these flags */
630 *r->out.flags = 0;
632 r->out.validation->generic = generic;
634 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
635 dce_call->msg_ctx,
636 "kdc_server",
637 &ndr_table_irpc);
638 if (irpc_handle == NULL) {
639 return NT_STATUS_NO_LOGON_SERVERS;
642 check.in.generic_request =
643 data_blob_const(r->in.logon->generic->data,
644 r->in.logon->generic->length);
646 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
647 mem_ctx,
648 &check);
649 if (!NT_STATUS_IS_OK(status)) {
650 return status;
652 generic->length = check.out.generic_reply.length;
653 generic->data = check.out.generic_reply.data;
654 return NT_STATUS_OK;
657 /* Until we get an implemetnation of these other packages */
658 return NT_STATUS_INVALID_PARAMETER;
660 default:
661 return NT_STATUS_INVALID_PARAMETER;
664 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
665 NT_STATUS_NOT_OK_RETURN(nt_status);
667 switch (r->in.validation_level) {
668 case 2:
669 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
670 NT_STATUS_NOT_OK_RETURN(nt_status);
672 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
673 NT_STATUS_HAVE_NO_MEMORY(sam2);
674 sam2->base = *sam;
676 /* And put into the talloc tree */
677 talloc_steal(sam2, sam);
678 r->out.validation->sam2 = sam2;
680 sam = &sam2->base;
681 break;
683 case 3:
684 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
685 server_info,
686 &sam3);
687 NT_STATUS_NOT_OK_RETURN(nt_status);
689 r->out.validation->sam3 = sam3;
691 sam = &sam3->base;
692 break;
694 case 6:
695 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
696 server_info,
697 &sam3);
698 NT_STATUS_NOT_OK_RETURN(nt_status);
700 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
701 NT_STATUS_HAVE_NO_MEMORY(sam6);
702 sam6->base = sam3->base;
703 sam = &sam6->base;
704 sam6->sidcount = sam3->sidcount;
705 sam6->sids = sam3->sids;
707 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
708 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
709 sam->account_name.string, sam6->dns_domainname.string);
710 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
711 /* And put into the talloc tree */
712 talloc_steal(sam6, sam3);
714 r->out.validation->sam6 = sam6;
715 break;
717 default:
718 break;
721 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
722 /* It appears that level 6 is not individually encrypted */
723 if ((r->in.validation_level != 6) &&
724 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
725 /* This key is sent unencrypted without the ARCFOUR flag set */
726 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
727 netlogon_creds_arcfour_crypt(creds,
728 sam->key.key,
729 sizeof(sam->key.key));
733 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
734 /* It appears that level 6 is not individually encrypted */
735 if ((r->in.validation_level != 6) &&
736 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
737 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
738 netlogon_creds_arcfour_crypt(creds,
739 sam->LMSessKey.key,
740 sizeof(sam->LMSessKey.key));
741 } else {
742 netlogon_creds_des_encrypt_LMKey(creds,
743 &sam->LMSessKey);
747 *r->out.authoritative = 1;
749 /* TODO: Describe and deal with these flags */
750 *r->out.flags = 0;
752 return NT_STATUS_OK;
755 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
756 struct netr_LogonSamLogonEx *r)
758 NTSTATUS nt_status;
759 struct netlogon_creds_CredentialState *creds;
761 nt_status = schannel_get_creds_state(mem_ctx,
762 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
763 r->in.computer_name, &creds);
764 if (!NT_STATUS_IS_OK(nt_status)) {
765 return nt_status;
768 if (!dce_call->conn->auth_state.auth_info ||
769 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
770 return NT_STATUS_ACCESS_DENIED;
772 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
776 netr_LogonSamLogonWithFlags
779 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
780 struct netr_LogonSamLogonWithFlags *r)
782 NTSTATUS nt_status;
783 struct netlogon_creds_CredentialState *creds;
784 struct netr_LogonSamLogonEx r2;
786 struct netr_Authenticator *return_authenticator;
788 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
789 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
791 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
792 mem_ctx,
793 r->in.computer_name,
794 r->in.credential, return_authenticator,
795 &creds);
796 NT_STATUS_NOT_OK_RETURN(nt_status);
798 ZERO_STRUCT(r2);
800 r2.in.server_name = r->in.server_name;
801 r2.in.computer_name = r->in.computer_name;
802 r2.in.logon_level = r->in.logon_level;
803 r2.in.logon = r->in.logon;
804 r2.in.validation_level = r->in.validation_level;
805 r2.in.flags = r->in.flags;
806 r2.out.validation = r->out.validation;
807 r2.out.authoritative = r->out.authoritative;
808 r2.out.flags = r->out.flags;
810 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
812 r->out.return_authenticator = return_authenticator;
814 return nt_status;
818 netr_LogonSamLogon
820 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
821 struct netr_LogonSamLogon *r)
823 struct netr_LogonSamLogonWithFlags r2;
824 uint32_t flags = 0;
825 NTSTATUS status;
827 ZERO_STRUCT(r2);
829 r2.in.server_name = r->in.server_name;
830 r2.in.computer_name = r->in.computer_name;
831 r2.in.credential = r->in.credential;
832 r2.in.return_authenticator = r->in.return_authenticator;
833 r2.in.logon_level = r->in.logon_level;
834 r2.in.logon = r->in.logon;
835 r2.in.validation_level = r->in.validation_level;
836 r2.in.flags = &flags;
837 r2.out.validation = r->out.validation;
838 r2.out.authoritative = r->out.authoritative;
839 r2.out.flags = &flags;
841 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
843 r->out.return_authenticator = r2.out.return_authenticator;
845 return status;
850 netr_LogonSamLogoff
852 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
853 struct netr_LogonSamLogoff *r)
855 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
861 netr_DatabaseDeltas
863 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
864 struct netr_DatabaseDeltas *r)
866 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
871 netr_DatabaseSync2
873 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
874 struct netr_DatabaseSync2 *r)
876 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
877 return NT_STATUS_NOT_IMPLEMENTED;
882 netr_DatabaseSync
884 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
885 struct netr_DatabaseSync *r)
887 struct netr_DatabaseSync2 r2;
888 NTSTATUS status;
890 ZERO_STRUCT(r2);
892 r2.in.logon_server = r->in.logon_server;
893 r2.in.computername = r->in.computername;
894 r2.in.credential = r->in.credential;
895 r2.in.database_id = r->in.database_id;
896 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
897 r2.in.sync_context = r->in.sync_context;
898 r2.out.sync_context = r->out.sync_context;
899 r2.out.delta_enum_array = r->out.delta_enum_array;
900 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
902 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
904 return status;
909 netr_AccountDeltas
911 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
912 struct netr_AccountDeltas *r)
914 /* w2k3 returns "NOT IMPLEMENTED" for this call */
915 return NT_STATUS_NOT_IMPLEMENTED;
920 netr_AccountSync
922 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
923 struct netr_AccountSync *r)
925 /* w2k3 returns "NOT IMPLEMENTED" for this call */
926 return NT_STATUS_NOT_IMPLEMENTED;
931 netr_GetDcName
933 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934 struct netr_GetDcName *r)
936 const char * const attrs[] = { NULL };
937 struct ldb_context *sam_ctx;
938 struct ldb_message **res;
939 struct ldb_dn *domain_dn;
940 int ret;
941 const char *dcname;
944 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
945 * that the domainname needs to be a valid netbios domain
946 * name, if it is not NULL.
948 if (r->in.domainname) {
949 const char *dot = strchr(r->in.domainname, '.');
950 size_t len = strlen(r->in.domainname);
952 if (dot || len > 15) {
953 return WERR_DCNOTFOUND;
957 * TODO: Should we also varify that only valid
958 * netbios name characters are used?
962 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
963 dce_call->conn->dce_ctx->lp_ctx,
964 dce_call->conn->auth_state.session_info, 0);
965 if (sam_ctx == NULL) {
966 return WERR_DS_UNAVAILABLE;
969 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
970 r->in.domainname);
971 if (domain_dn == NULL) {
972 return WERR_DS_UNAVAILABLE;
975 ret = gendb_search_dn(sam_ctx, mem_ctx,
976 domain_dn, &res, attrs);
977 if (ret != 1) {
978 return WERR_NO_SUCH_DOMAIN;
981 /* TODO: - return real IP address
982 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
984 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
985 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
986 W_ERROR_HAVE_NO_MEMORY(dcname);
988 *r->out.dcname = dcname;
989 return WERR_OK;
994 netr_LogonControl2Ex
996 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
997 struct netr_LogonControl2Ex *r)
999 return WERR_NOT_SUPPORTED;
1004 netr_LogonControl
1006 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007 struct netr_LogonControl *r)
1009 struct netr_LogonControl2Ex r2;
1010 WERROR werr;
1012 if (r->in.level == 0x00000001) {
1013 ZERO_STRUCT(r2);
1015 r2.in.logon_server = r->in.logon_server;
1016 r2.in.function_code = r->in.function_code;
1017 r2.in.level = r->in.level;
1018 r2.in.data = NULL;
1019 r2.out.query = r->out.query;
1021 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1022 } else if (r->in.level == 0x00000002) {
1023 werr = WERR_NOT_SUPPORTED;
1024 } else {
1025 werr = WERR_UNKNOWN_LEVEL;
1028 return werr;
1033 netr_LogonControl2
1035 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1036 struct netr_LogonControl2 *r)
1038 struct netr_LogonControl2Ex r2;
1039 WERROR werr;
1041 ZERO_STRUCT(r2);
1043 r2.in.logon_server = r->in.logon_server;
1044 r2.in.function_code = r->in.function_code;
1045 r2.in.level = r->in.level;
1046 r2.in.data = r->in.data;
1047 r2.out.query = r->out.query;
1049 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1051 return werr;
1054 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1055 struct ldb_context *sam_ctx,
1056 struct netr_DomainTrustList *trusts,
1057 uint32_t trust_flags);
1060 netr_GetAnyDCName
1062 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1063 struct netr_GetAnyDCName *r)
1065 struct netr_DomainTrustList *trusts;
1066 struct ldb_context *sam_ctx;
1067 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1068 uint32_t i;
1069 WERROR werr;
1071 *r->out.dcname = NULL;
1073 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1074 /* if the domainname parameter wasn't set assume our domain */
1075 r->in.domainname = lpcfg_workgroup(lp_ctx);
1078 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1079 dce_call->conn->auth_state.session_info, 0);
1080 if (sam_ctx == NULL) {
1081 return WERR_DS_UNAVAILABLE;
1084 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1085 /* well we asked for a DC of our own domain */
1086 if (samdb_is_pdc(sam_ctx)) {
1087 /* we are the PDC of the specified domain */
1088 return WERR_NO_SUCH_DOMAIN;
1091 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1092 lpcfg_netbios_name(lp_ctx));
1093 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1095 return WERR_OK;
1098 /* Okay, now we have to consider the trusted domains */
1100 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1101 W_ERROR_HAVE_NO_MEMORY(trusts);
1103 trusts->count = 0;
1105 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1106 NETR_TRUST_FLAG_INBOUND
1107 | NETR_TRUST_FLAG_OUTBOUND);
1108 W_ERROR_NOT_OK_RETURN(werr);
1110 for (i = 0; i < trusts->count; i++) {
1111 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1112 /* FIXME: Here we need to find a DC for the specified
1113 * trusted domain. */
1115 /* return WERR_OK; */
1116 return WERR_NO_SUCH_DOMAIN;
1120 return WERR_NO_SUCH_DOMAIN;
1125 netr_DatabaseRedo
1127 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1128 struct netr_DatabaseRedo *r)
1130 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1135 netr_NetrEnumerateTrustedDomains
1137 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1138 struct netr_NetrEnumerateTrustedDomains *r)
1140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1145 netr_LogonGetCapabilities
1147 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_LogonGetCapabilities *r)
1150 /* we don't support AES yet */
1151 return NT_STATUS_NOT_IMPLEMENTED;
1156 netr_NETRLOGONSETSERVICEBITS
1158 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_NETRLOGONSETSERVICEBITS *r)
1161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1166 netr_LogonGetTrustRid
1168 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1169 struct netr_LogonGetTrustRid *r)
1171 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1176 netr_NETRLOGONCOMPUTESERVERDIGEST
1178 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1181 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1186 netr_NETRLOGONCOMPUTECLIENTDIGEST
1188 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1189 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1191 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1197 netr_DsRGetSiteName
1199 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1200 struct netr_DsRGetSiteName *r)
1202 struct ldb_context *sam_ctx;
1203 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1205 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1206 dce_call->conn->auth_state.session_info, 0);
1207 if (sam_ctx == NULL) {
1208 return WERR_DS_UNAVAILABLE;
1211 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1212 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1214 return WERR_OK;
1219 fill in a netr_OneDomainInfo from a ldb search result
1221 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1222 struct loadparm_context *lp_ctx,
1223 struct ldb_context *sam_ctx,
1224 struct ldb_message *res,
1225 struct netr_OneDomainInfo *info,
1226 bool is_local, bool is_trust_list)
1228 ZERO_STRUCTP(info);
1230 if (is_trust_list) {
1231 /* w2k8 only fills this on trusted domains */
1232 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1233 info->trust_extension.length = 16;
1234 info->trust_extension.info->flags =
1235 NETR_TRUST_FLAG_TREEROOT |
1236 NETR_TRUST_FLAG_IN_FOREST |
1237 NETR_TRUST_FLAG_PRIMARY |
1238 NETR_TRUST_FLAG_NATIVE;
1240 info->trust_extension.info->parent_index = 0; /* should be index into array
1241 of parent */
1242 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1243 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1246 if (is_trust_list) {
1247 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1248 info->dns_forestname.string = NULL;
1249 } else {
1250 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1251 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1252 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1253 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1256 if (is_local) {
1257 info->domainname.string = lpcfg_workgroup(lp_ctx);
1258 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1259 info->domain_guid = samdb_result_guid(res, "objectGUID");
1260 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1261 } else {
1262 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1263 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1264 info->domain_guid = samdb_result_guid(res, "objectGUID");
1265 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1267 if (!is_trust_list) {
1268 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1271 return NT_STATUS_OK;
1275 netr_LogonGetDomainInfo
1276 this is called as part of the ADS domain logon procedure.
1278 It has an important role in convaying details about the client, such
1279 as Operating System, Version, Service Pack etc.
1281 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1282 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1284 struct netlogon_creds_CredentialState *creds;
1285 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1286 "securityIdentifier", "trustPartner", NULL };
1287 const char * const attrs2[] = { "dNSHostName",
1288 "msDS-SupportedEncryptionTypes", NULL };
1289 const char *temp_str, *temp_str2;
1290 const char *old_dns_hostname;
1291 struct ldb_context *sam_ctx;
1292 struct ldb_message **res1, **res2, **res3, *new_msg;
1293 struct ldb_dn *workstation_dn;
1294 struct netr_DomainInformation *domain_info;
1295 struct netr_LsaPolicyInformation *lsa_policy_info;
1296 struct netr_OsVersionInfoEx *os_version;
1297 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1298 bool update_dns_hostname = true;
1299 int ret, ret3, i;
1300 NTSTATUS status;
1302 status = dcesrv_netr_creds_server_step_check(dce_call,
1303 mem_ctx,
1304 r->in.computer_name,
1305 r->in.credential,
1306 r->out.return_authenticator,
1307 &creds);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 DEBUG(0,(__location__ " Bad credentials - error\n"));
1311 NT_STATUS_NOT_OK_RETURN(status);
1313 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1314 dce_call->conn->dce_ctx->lp_ctx,
1315 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1316 if (sam_ctx == NULL) {
1317 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1320 switch (r->in.level) {
1321 case 1: /* Domain information */
1323 if (r->in.query->workstation_info == NULL) {
1324 return NT_STATUS_INVALID_PARAMETER;
1328 * Checks that the computer name parameter without possible "$"
1329 * matches as prefix with the DNS hostname in the workstation
1330 * info structure.
1332 temp_str = talloc_strndup(mem_ctx,
1333 r->in.computer_name,
1334 strcspn(r->in.computer_name, "$"));
1335 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1336 temp_str2 = talloc_strndup(mem_ctx,
1337 r->in.query->workstation_info->dns_hostname,
1338 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1339 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1340 if (strcasecmp(temp_str, temp_str2) != 0) {
1341 update_dns_hostname = false;
1344 /* Prepare the workstation DN */
1345 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1346 dom_sid_string(mem_ctx, creds->sid));
1347 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1349 /* Lookup for attributes in workstation object */
1350 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1351 &res1, attrs2);
1352 if (ret != 1) {
1353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1356 /* Gets the old DNS hostname */
1357 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0], "dNSHostName",
1358 NULL);
1361 * Updates the DNS hostname when the client wishes that the
1362 * server should handle this for him
1363 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1364 * obviously only checked when we do already have a
1365 * "dNSHostName".
1366 * See MS-NRPC section 3.5.4.3.9
1368 if ((old_dns_hostname != NULL) &&
1369 (r->in.query->workstation_info->workstation_flags
1370 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1371 update_dns_hostname = false;
1374 /* Gets host informations and put them into our directory */
1376 new_msg = ldb_msg_new(mem_ctx);
1377 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1379 new_msg->dn = workstation_dn;
1381 /* Sets the OS name */
1382 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1383 "operatingSystem",
1384 r->in.query->workstation_info->os_name.string);
1387 * Sets informations from "os_version". On an empty structure
1388 * the values are cleared.
1390 if (r->in.query->workstation_info->os_version.os != NULL) {
1391 os_version = &r->in.query->workstation_info->os_version.os->os;
1393 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1394 "operatingSystemServicePack",
1395 os_version->CSDVersion);
1397 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1398 "operatingSystemVersion",
1399 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1400 os_version->MajorVersion,
1401 os_version->MinorVersion,
1402 os_version->BuildNumber
1405 } else {
1406 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1407 "operatingSystemServicePack");
1409 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1410 "operatingSystemVersion");
1414 * If the boolean "update_dns_hostname" remained true, then we
1415 * are fine to start the update.
1417 if (update_dns_hostname) {
1418 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1419 "dNSHostname",
1420 r->in.query->workstation_info->dns_hostname);
1422 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1423 "servicePrincipalName",
1424 talloc_asprintf(mem_ctx, "HOST/%s",
1425 r->in.computer_name)
1427 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1428 "servicePrincipalName",
1429 talloc_asprintf(mem_ctx, "HOST/%s",
1430 r->in.query->workstation_info->dns_hostname)
1434 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1435 DEBUG(3,("Impossible to update samdb: %s\n",
1436 ldb_errstring(sam_ctx)));
1439 talloc_free(new_msg);
1441 /* Writes back the domain information */
1443 /* We need to do two searches. The first will pull our primary
1444 domain and the second will pull any trusted domains. Our
1445 primary domain is also a "trusted" domain, so we need to
1446 put the primary domain into the lists of returned trusts as
1447 well. */
1448 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1449 &res2, attrs);
1450 if (ret != 1) {
1451 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1454 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1455 "(objectClass=trustedDomain)");
1456 if (ret3 == -1) {
1457 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1460 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1461 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1463 ZERO_STRUCTP(domain_info);
1465 /* Informations about the local and trusted domains */
1467 status = fill_one_domain_info(mem_ctx,
1468 dce_call->conn->dce_ctx->lp_ctx,
1469 sam_ctx, res2[0], &domain_info->primary_domain,
1470 true, false);
1471 NT_STATUS_NOT_OK_RETURN(status);
1473 domain_info->trusted_domain_count = ret3 + 1;
1474 domain_info->trusted_domains = talloc_array(mem_ctx,
1475 struct netr_OneDomainInfo,
1476 domain_info->trusted_domain_count);
1477 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1479 for (i=0;i<ret3;i++) {
1480 status = fill_one_domain_info(mem_ctx,
1481 dce_call->conn->dce_ctx->lp_ctx,
1482 sam_ctx, res3[i],
1483 &domain_info->trusted_domains[i],
1484 false, true);
1485 NT_STATUS_NOT_OK_RETURN(status);
1488 status = fill_one_domain_info(mem_ctx,
1489 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1490 &domain_info->trusted_domains[i], true, true);
1491 NT_STATUS_NOT_OK_RETURN(status);
1493 /* Sets the supported encryption types */
1494 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1495 "msDS-SupportedEncryptionTypes",
1496 default_supported_enc_types);
1498 /* Other host domain informations */
1500 lsa_policy_info = talloc(mem_ctx,
1501 struct netr_LsaPolicyInformation);
1502 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1503 ZERO_STRUCTP(lsa_policy_info);
1505 domain_info->lsa_policy = *lsa_policy_info;
1507 /* The DNS hostname is only returned back when there is a chance
1508 * for a change. */
1509 if ((r->in.query->workstation_info->workstation_flags
1510 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1511 domain_info->dns_hostname.string = old_dns_hostname;
1512 } else {
1513 domain_info->dns_hostname.string = NULL;
1516 domain_info->workstation_flags =
1517 r->in.query->workstation_info->workstation_flags;
1519 r->out.info->domain_info = domain_info;
1520 break;
1521 case 2: /* LSA policy information - not used at the moment */
1522 lsa_policy_info = talloc(mem_ctx,
1523 struct netr_LsaPolicyInformation);
1524 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1525 ZERO_STRUCTP(lsa_policy_info);
1527 r->out.info->lsa_policy_info = lsa_policy_info;
1528 break;
1529 default:
1530 return NT_STATUS_INVALID_LEVEL;
1531 break;
1534 return NT_STATUS_OK;
1540 netr_ServerPasswordGet
1542 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1543 struct netr_ServerPasswordGet *r)
1545 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1550 netr_NETRLOGONSENDTOSAM
1552 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1553 struct netr_NETRLOGONSENDTOSAM *r)
1555 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1560 netr_DsRGetDCNameEx2
1562 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1563 TALLOC_CTX *mem_ctx,
1564 struct netr_DsRGetDCNameEx2 *r)
1566 struct ldb_context *sam_ctx;
1567 struct netr_DsRGetDCNameInfo *info;
1568 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1569 const struct tsocket_address *remote_address;
1570 char *addr = NULL;
1571 const char *server_site_name;
1572 char *guid_str;
1573 struct netlogon_samlogon_response response;
1574 NTSTATUS status;
1575 const char *dc_name = NULL;
1576 const char *domain_name = NULL;
1578 ZERO_STRUCTP(r->out.info);
1580 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1581 dce_call->conn->auth_state.session_info, 0);
1582 if (sam_ctx == NULL) {
1583 return WERR_DS_UNAVAILABLE;
1586 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1587 if (tsocket_address_is_inet(remote_address, "ip")) {
1588 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1589 W_ERROR_HAVE_NO_MEMORY(addr);
1592 /* "server_unc" is ignored by w2k3 */
1594 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1595 return WERR_INVALID_FLAGS;
1598 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1599 r->in.flags & DS_PDC_REQUIRED &&
1600 r->in.flags & DS_KDC_REQUIRED) {
1601 return WERR_INVALID_FLAGS;
1603 if (r->in.flags & DS_IS_FLAT_NAME &&
1604 r->in.flags & DS_IS_DNS_NAME) {
1605 return WERR_INVALID_FLAGS;
1607 if (r->in.flags & DS_RETURN_DNS_NAME &&
1608 r->in.flags & DS_RETURN_FLAT_NAME) {
1609 return WERR_INVALID_FLAGS;
1611 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1612 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1613 return WERR_INVALID_FLAGS;
1616 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1617 r->in.flags &
1618 (DS_DIRECTORY_SERVICE_REQUIRED |
1619 DS_DIRECTORY_SERVICE_PREFERRED |
1620 DS_GC_SERVER_REQUIRED |
1621 DS_PDC_REQUIRED |
1622 DS_KDC_REQUIRED)) {
1623 return WERR_INVALID_FLAGS;
1626 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1627 r->in.site_name) {
1628 return WERR_INVALID_FLAGS;
1631 /* Proof server site parameter "site_name" if it was specified */
1632 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1633 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1634 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1635 server_site_name) != 0)) {
1636 return WERR_NO_SUCH_DOMAIN;
1639 guid_str = r->in.domain_guid != NULL ?
1640 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1642 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1643 r->in.domain_name,
1644 r->in.domain_name,
1645 NULL, guid_str,
1646 r->in.client_account,
1647 r->in.mask, addr,
1648 NETLOGON_NT_VERSION_5EX_WITH_IP,
1649 lp_ctx, &response, true);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 return ntstatus_to_werror(status);
1654 if (r->in.flags & DS_RETURN_DNS_NAME) {
1655 dc_name = response.data.nt5_ex.pdc_dns_name;
1656 domain_name = response.data.nt5_ex.dns_domain;
1657 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1658 dc_name = response.data.nt5_ex.pdc_name;
1659 domain_name = response.data.nt5_ex.domain_name;
1660 } else {
1663 * TODO: autodetect what we need to return
1664 * based on the given arguments
1666 dc_name = response.data.nt5_ex.pdc_name;
1667 domain_name = response.data.nt5_ex.domain_name;
1670 if (!dc_name || !dc_name[0]) {
1671 return WERR_NO_SUCH_DOMAIN;
1674 if (!domain_name || !domain_name[0]) {
1675 return WERR_NO_SUCH_DOMAIN;
1678 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1679 W_ERROR_HAVE_NO_MEMORY(info);
1680 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1681 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1682 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1683 response.data.nt5_ex.sockaddr.pdc_ip);
1684 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1685 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1686 info->domain_guid = response.data.nt5_ex.domain_uuid;
1687 info->domain_name = domain_name;
1688 info->forest_name = response.data.nt5_ex.forest;
1689 info->dc_flags = response.data.nt5_ex.server_type;
1690 info->dc_site_name = response.data.nt5_ex.server_site;
1691 info->client_site_name = response.data.nt5_ex.client_site;
1693 *r->out.info = info;
1695 return WERR_OK;
1699 netr_DsRGetDCNameEx
1701 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1702 struct netr_DsRGetDCNameEx *r)
1704 struct netr_DsRGetDCNameEx2 r2;
1705 WERROR werr;
1707 ZERO_STRUCT(r2);
1709 r2.in.server_unc = r->in.server_unc;
1710 r2.in.client_account = NULL;
1711 r2.in.mask = 0;
1712 r2.in.domain_guid = r->in.domain_guid;
1713 r2.in.domain_name = r->in.domain_name;
1714 r2.in.site_name = r->in.site_name;
1715 r2.in.flags = r->in.flags;
1716 r2.out.info = r->out.info;
1718 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1720 return werr;
1724 netr_DsRGetDCName
1726 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1727 struct netr_DsRGetDCName *r)
1729 struct netr_DsRGetDCNameEx2 r2;
1730 WERROR werr;
1732 ZERO_STRUCT(r2);
1734 r2.in.server_unc = r->in.server_unc;
1735 r2.in.client_account = NULL;
1736 r2.in.mask = 0;
1737 r2.in.domain_name = r->in.domain_name;
1738 r2.in.domain_guid = r->in.domain_guid;
1740 r2.in.site_name = NULL; /* should fill in from site GUID */
1741 r2.in.flags = r->in.flags;
1742 r2.out.info = r->out.info;
1744 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1746 return werr;
1749 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1751 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1752 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1754 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1759 netr_NetrEnumerateTrustedDomainsEx
1761 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1762 struct netr_NetrEnumerateTrustedDomainsEx *r)
1764 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1769 netr_DsRAddressToSitenamesExW
1771 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1772 struct netr_DsRAddressToSitenamesExW *r)
1774 struct ldb_context *sam_ctx;
1775 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1776 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1777 sa_family_t sin_family;
1778 struct sockaddr_in *addr;
1779 #ifdef HAVE_IPV6
1780 struct sockaddr_in6 *addr6;
1781 char addr_str[INET6_ADDRSTRLEN];
1782 #else
1783 char addr_str[INET_ADDRSTRLEN];
1784 #endif
1785 char *subnet_name;
1786 const char *res;
1787 uint32_t i;
1789 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1790 dce_call->conn->auth_state.session_info, 0);
1791 if (sam_ctx == NULL) {
1792 return WERR_DS_UNAVAILABLE;
1795 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1796 W_ERROR_HAVE_NO_MEMORY(ctr);
1798 *r->out.ctr = ctr;
1800 ctr->count = r->in.count;
1801 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1802 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1803 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1804 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1806 for (i=0; i<ctr->count; i++) {
1807 ctr->sitename[i].string = NULL;
1808 ctr->subnetname[i].string = NULL;
1810 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1811 continue;
1813 /* The first two byte of the buffer are reserved for the
1814 * "sin_family" but for now only the first one is used. */
1815 sin_family = r->in.addresses[i].buffer[0];
1817 switch (sin_family) {
1818 case AF_INET:
1819 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1820 continue;
1822 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1823 res = inet_ntop(AF_INET, &addr->sin_addr,
1824 addr_str, sizeof(addr_str));
1825 break;
1826 #ifdef HAVE_IPV6
1827 case AF_INET6:
1828 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1829 continue;
1831 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1832 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1833 addr_str, sizeof(addr_str));
1834 break;
1835 #endif
1836 default:
1837 continue;
1840 if (res == NULL) {
1841 continue;
1844 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1845 mem_ctx,
1846 addr_str,
1847 &subnet_name);
1848 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1849 ctr->subnetname[i].string = subnet_name;
1852 return WERR_OK;
1857 netr_DsRAddressToSitenamesW
1859 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1860 struct netr_DsRAddressToSitenamesW *r)
1862 struct netr_DsRAddressToSitenamesExW r2;
1863 struct netr_DsRAddressToSitenamesWCtr *ctr;
1864 uint32_t i;
1865 WERROR werr;
1867 ZERO_STRUCT(r2);
1869 r2.in.server_name = r->in.server_name;
1870 r2.in.count = r->in.count;
1871 r2.in.addresses = r->in.addresses;
1873 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1874 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1876 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1877 W_ERROR_HAVE_NO_MEMORY(ctr);
1879 *r->out.ctr = ctr;
1881 ctr->count = r->in.count;
1882 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1883 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1885 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1887 for (i=0; i<ctr->count; i++) {
1888 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1891 return werr;
1896 netr_DsrGetDcSiteCoverageW
1898 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1899 struct netr_DsrGetDcSiteCoverageW *r)
1901 struct ldb_context *sam_ctx;
1902 struct DcSitesCtr *ctr;
1903 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1905 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1906 dce_call->conn->auth_state.session_info, 0);
1907 if (sam_ctx == NULL) {
1908 return WERR_DS_UNAVAILABLE;
1911 ctr = talloc(mem_ctx, struct DcSitesCtr);
1912 W_ERROR_HAVE_NO_MEMORY(ctr);
1914 *r->out.ctr = ctr;
1916 /* For now only return our default site */
1917 ctr->num_sites = 1;
1918 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1919 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1920 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1921 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1923 return WERR_OK;
1927 #define GET_CHECK_STR(dest, mem, msg, attr) \
1928 do {\
1929 const char *s; \
1930 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1931 if (!s) { \
1932 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1933 "without flatname\n", \
1934 ldb_dn_get_linearized(msg->dn))); \
1935 continue; \
1937 dest = talloc_strdup(mem, s); \
1938 W_ERROR_HAVE_NO_MEMORY(dest); \
1939 } while(0)
1942 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1943 struct ldb_context *sam_ctx,
1944 struct netr_DomainTrustList *trusts,
1945 uint32_t trust_flags)
1947 struct ldb_dn *system_dn;
1948 struct ldb_message **dom_res = NULL;
1949 const char *trust_attrs[] = { "flatname", "trustPartner",
1950 "securityIdentifier", "trustDirection",
1951 "trustType", "trustAttributes", NULL };
1952 uint32_t n;
1953 int i;
1954 int ret;
1956 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1957 NETR_TRUST_FLAG_OUTBOUND))) {
1958 return WERR_INVALID_FLAGS;
1961 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1962 ldb_get_default_basedn(sam_ctx),
1963 "(&(objectClass=container)(cn=System))");
1964 if (!system_dn) {
1965 return WERR_GENERAL_FAILURE;
1968 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1969 &dom_res, trust_attrs,
1970 "(objectclass=trustedDomain)");
1972 for (i = 0; i < ret; i++) {
1973 unsigned int trust_dir;
1974 uint32_t flags = 0;
1976 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1977 "trustDirection", 0);
1979 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1980 flags |= NETR_TRUST_FLAG_INBOUND;
1982 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1983 flags |= NETR_TRUST_FLAG_OUTBOUND;
1986 if (!(flags & trust_flags)) {
1987 /* this trust direction was not requested */
1988 continue;
1991 n = trusts->count;
1992 trusts->array = talloc_realloc(trusts, trusts->array,
1993 struct netr_DomainTrust,
1994 n + 1);
1995 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1997 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1998 dom_res[i], "flatname");
1999 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2000 dom_res[i], "trustPartner");
2002 trusts->array[n].trust_flags = flags;
2003 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2004 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2005 /* TODO: find if we have parent in the list */
2006 trusts->array[n].parent_index = 0;
2009 trusts->array[n].trust_type =
2010 ldb_msg_find_attr_as_uint(dom_res[i],
2011 "trustType", 0);
2012 trusts->array[n].trust_attributes =
2013 ldb_msg_find_attr_as_uint(dom_res[i],
2014 "trustAttributes", 0);
2016 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2017 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2018 struct dom_sid zero_sid;
2019 ZERO_STRUCT(zero_sid);
2020 trusts->array[n].sid =
2021 dom_sid_dup(trusts, &zero_sid);
2022 } else {
2023 trusts->array[n].sid =
2024 samdb_result_dom_sid(trusts, dom_res[i],
2025 "securityIdentifier");
2027 trusts->array[n].guid = GUID_zero();
2029 trusts->count = n + 1;
2032 talloc_free(dom_res);
2033 return WERR_OK;
2037 netr_DsrEnumerateDomainTrusts
2039 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2040 TALLOC_CTX *mem_ctx,
2041 struct netr_DsrEnumerateDomainTrusts *r)
2043 struct netr_DomainTrustList *trusts;
2044 struct ldb_context *sam_ctx;
2045 int ret;
2046 struct ldb_message **dom_res;
2047 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2048 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2049 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2050 const char *p;
2051 WERROR werr;
2053 if (r->in.trust_flags & 0xFFFFFE00) {
2054 return WERR_INVALID_FLAGS;
2057 /* TODO: turn to hard check once we are sure this is 100% correct */
2058 if (!r->in.server_name) {
2059 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2060 "But received NULL!\n", dnsdomain));
2061 } else {
2062 p = strchr(r->in.server_name, '.');
2063 if (!p) {
2064 DEBUG(3, ("Invalid domain! Expected name in domain "
2065 "[%s]. But received [%s]!\n",
2066 dnsdomain, r->in.server_name));
2067 p = r->in.server_name;
2068 } else {
2069 p++;
2071 if (strcasecmp(p, dnsdomain)) {
2072 DEBUG(3, ("Invalid domain! Expected name in domain "
2073 "[%s]. But received [%s]!\n",
2074 dnsdomain, r->in.server_name));
2078 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2079 W_ERROR_HAVE_NO_MEMORY(trusts);
2081 trusts->count = 0;
2082 r->out.trusts = trusts;
2084 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2085 dce_call->conn->auth_state.session_info, 0);
2086 if (sam_ctx == NULL) {
2087 return WERR_GENERAL_FAILURE;
2090 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2091 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2093 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2094 trusts, r->in.trust_flags);
2095 W_ERROR_NOT_OK_RETURN(werr);
2098 /* NOTE: we currently are always the root of the forest */
2099 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2100 uint32_t n = trusts->count;
2102 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2103 &dom_res, dom_attrs);
2104 if (ret != 1) {
2105 return WERR_GENERAL_FAILURE;
2108 trusts->count = n + 1;
2109 trusts->array = talloc_realloc(trusts, trusts->array,
2110 struct netr_DomainTrust,
2111 trusts->count);
2112 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2114 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2115 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2116 trusts->array[n].trust_flags =
2117 NETR_TRUST_FLAG_NATIVE |
2118 NETR_TRUST_FLAG_TREEROOT |
2119 NETR_TRUST_FLAG_IN_FOREST |
2120 NETR_TRUST_FLAG_PRIMARY;
2121 /* we are always the root domain for now */
2122 trusts->array[n].parent_index = 0;
2123 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2124 trusts->array[n].trust_attributes = 0;
2125 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2126 dom_res[0],
2127 "objectSid");
2128 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2129 "objectGUID");
2130 talloc_free(dom_res);
2133 return WERR_OK;
2138 netr_DsrDeregisterDNSHostRecords
2140 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2141 struct netr_DsrDeregisterDNSHostRecords *r)
2143 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2148 netr_ServerTrustPasswordsGet
2150 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2151 struct netr_ServerTrustPasswordsGet *r)
2153 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2157 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2158 struct ldb_context *sam_ctx,
2159 struct loadparm_context *lp_ctx,
2160 struct lsa_ForestTrustInformation *info)
2162 struct lsa_ForestTrustDomainInfo *domain_info;
2163 struct lsa_ForestTrustRecord *e;
2164 struct ldb_message **dom_res;
2165 const char * const dom_attrs[] = { "objectSid", NULL };
2166 int ret;
2168 /* we need to provide 2 entries:
2169 * 1. the Root Forest name
2170 * 2. the Domain Information
2173 info->count = 2;
2174 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2175 W_ERROR_HAVE_NO_MEMORY(info->entries);
2177 /* Forest root info */
2178 e = talloc(info, struct lsa_ForestTrustRecord);
2179 W_ERROR_HAVE_NO_MEMORY(e);
2181 e->flags = 0;
2182 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2183 e->time = 0; /* so far always 0 in trces. */
2184 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2185 mem_ctx);
2186 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2188 info->entries[0] = e;
2190 /* Domain info */
2191 e = talloc(info, struct lsa_ForestTrustRecord);
2192 W_ERROR_HAVE_NO_MEMORY(e);
2194 /* get our own domain info */
2195 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2196 if (ret != 1) {
2197 return WERR_GENERAL_FAILURE;
2200 /* TODO: check if disabled and set flags accordingly */
2201 e->flags = 0;
2202 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2203 e->time = 0; /* so far always 0 in traces. */
2205 domain_info = &e->forest_trust_data.domain_info;
2206 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2207 "objectSid");
2208 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2209 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2211 info->entries[1] = e;
2213 talloc_free(dom_res);
2215 return WERR_OK;
2219 netr_DsRGetForestTrustInformation
2221 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2222 TALLOC_CTX *mem_ctx,
2223 struct netr_DsRGetForestTrustInformation *r)
2225 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2226 struct lsa_ForestTrustInformation *info, **info_ptr;
2227 struct ldb_context *sam_ctx;
2228 WERROR werr;
2230 if (r->in.flags & 0xFFFFFFFE) {
2231 return WERR_INVALID_FLAGS;
2234 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2235 dce_call->conn->auth_state.session_info, 0);
2236 if (sam_ctx == NULL) {
2237 return WERR_GENERAL_FAILURE;
2240 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2241 if (!samdb_is_pdc(sam_ctx)) {
2242 return WERR_NERR_NOTPRIMARY;
2245 if (r->in.trusted_domain_name == NULL) {
2246 return WERR_INVALID_FLAGS;
2249 /* TODO: establish an schannel connection with
2250 * r->in.trusted_domain_name and perform a
2251 * netr_GetForestTrustInformation call against it */
2253 /* for now return not implementd */
2254 return WERR_CALL_NOT_IMPLEMENTED;
2257 /* TODO: check r->in.server_name is our name */
2259 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2260 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2262 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2263 W_ERROR_HAVE_NO_MEMORY(info);
2265 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2266 W_ERROR_NOT_OK_RETURN(werr);
2268 *info_ptr = info;
2269 r->out.forest_trust_info = info_ptr;
2271 return WERR_OK;
2276 netr_GetForestTrustInformation
2278 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2279 TALLOC_CTX *mem_ctx,
2280 struct netr_GetForestTrustInformation *r)
2282 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2283 struct netlogon_creds_CredentialState *creds;
2284 struct lsa_ForestTrustInformation *info, **info_ptr;
2285 struct ldb_context *sam_ctx;
2286 NTSTATUS status;
2287 WERROR werr;
2289 status = dcesrv_netr_creds_server_step_check(dce_call,
2290 mem_ctx,
2291 r->in.computer_name,
2292 r->in.credential,
2293 r->out.return_authenticator,
2294 &creds);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 return status;
2299 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2300 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2301 return NT_STATUS_NOT_IMPLEMENTED;
2304 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2305 dce_call->conn->auth_state.session_info, 0);
2306 if (sam_ctx == NULL) {
2307 return NT_STATUS_UNSUCCESSFUL;
2310 /* TODO: check r->in.server_name is our name */
2312 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2313 if (!info_ptr) {
2314 return NT_STATUS_NO_MEMORY;
2316 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2317 if (!info) {
2318 return NT_STATUS_NO_MEMORY;
2321 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2322 if (!W_ERROR_IS_OK(werr)) {
2323 return werror_to_ntstatus(werr);
2326 *info_ptr = info;
2327 r->out.forest_trust_info = info_ptr;
2329 return NT_STATUS_OK;
2334 netr_ServerGetTrustInfo
2336 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2337 struct netr_ServerGetTrustInfo *r)
2339 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2343 netr_Unused47
2345 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2346 struct netr_Unused47 *r)
2348 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2352 struct netr_dnsupdate_RODC_state {
2353 struct dcesrv_call_state *dce_call;
2354 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2355 struct dnsupdate_RODC *r2;
2359 called when the forwarded RODC dns update request is finished
2361 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2363 struct netr_dnsupdate_RODC_state *st =
2364 tevent_req_callback_data(subreq,
2365 struct netr_dnsupdate_RODC_state);
2366 NTSTATUS status;
2368 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2369 TALLOC_FREE(subreq);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2372 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2375 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2377 status = dcesrv_reply(st->dce_call);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2384 netr_DsrUpdateReadOnlyServerDnsRecords
2386 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2387 TALLOC_CTX *mem_ctx,
2388 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2390 struct netlogon_creds_CredentialState *creds;
2391 NTSTATUS nt_status;
2392 struct dcerpc_binding_handle *binding_handle;
2393 struct netr_dnsupdate_RODC_state *st;
2394 struct tevent_req *subreq;
2396 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2397 mem_ctx,
2398 r->in.computer_name,
2399 r->in.credential,
2400 r->out.return_authenticator,
2401 &creds);
2402 NT_STATUS_NOT_OK_RETURN(nt_status);
2404 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2405 return NT_STATUS_ACCESS_DENIED;
2408 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2409 NT_STATUS_HAVE_NO_MEMORY(st);
2411 st->dce_call = dce_call;
2412 st->r = r;
2413 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2414 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2416 st->r2->in.dom_sid = creds->sid;
2417 st->r2->in.site_name = r->in.site_name;
2418 st->r2->in.dns_ttl = r->in.dns_ttl;
2419 st->r2->in.dns_names = r->in.dns_names;
2420 st->r2->out.dns_names = r->out.dns_names;
2422 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2423 "dnsupdate", &ndr_table_irpc);
2424 if (binding_handle == NULL) {
2425 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2426 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2427 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2430 /* forward the call */
2431 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2432 binding_handle, st->r2);
2433 NT_STATUS_HAVE_NO_MEMORY(subreq);
2435 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2437 /* setup the callback */
2438 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2440 return NT_STATUS_OK;
2444 /* include the generated boilerplate */
2445 #include "librpc/gen_ndr/ndr_netlogon_s.c"