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/>.
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"
39 struct netlogon_server_pipe_state {
40 struct netr_Credential client_challenge;
41 struct netr_Credential server_challenge;
44 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
45 struct netr_ServerReqChallenge *r)
47 struct netlogon_server_pipe_state *pipe_state =
48 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
50 ZERO_STRUCTP(r->out.return_credentials);
52 /* destroyed on pipe shutdown */
55 talloc_free(pipe_state);
56 dce_call->context->private_data = NULL;
59 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
60 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
62 pipe_state->client_challenge = *r->in.credentials;
64 generate_random_buffer(pipe_state->server_challenge.data,
65 sizeof(pipe_state->server_challenge.data));
67 *r->out.return_credentials = pipe_state->server_challenge;
69 dce_call->context->private_data = pipe_state;
74 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
75 struct netr_ServerAuthenticate3 *r)
77 struct netlogon_server_pipe_state *pipe_state =
78 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
79 struct netlogon_creds_CredentialState *creds;
80 struct ldb_context *sam_ctx;
81 struct samr_Password *mach_pwd;
82 uint32_t user_account_control;
84 struct ldb_message **msgs;
86 const char *attrs[] = {"unicodePwd", "userAccountControl",
89 const char *trust_dom_attrs[] = {"flatname", NULL};
90 const char *account_name;
92 ZERO_STRUCTP(r->out.return_credentials);
96 * According to Microsoft (see bugid #6099)
97 * Windows 7 looks at the negotiate_flags
98 * returned in this structure *even if the
99 * call fails with access denied!
101 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
102 NETLOGON_NEG_PERSISTENT_SAMREPL |
103 NETLOGON_NEG_ARCFOUR |
104 NETLOGON_NEG_PROMOTION_COUNT |
105 NETLOGON_NEG_CHANGELOG_BDC |
106 NETLOGON_NEG_FULL_SYNC_REPL |
107 NETLOGON_NEG_MULTIPLE_SIDS |
109 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
110 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
111 NETLOGON_NEG_GENERIC_PASSTHROUGH |
112 NETLOGON_NEG_CONCURRENT_RPC |
113 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
114 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
115 NETLOGON_NEG_STRONG_KEYS |
116 NETLOGON_NEG_TRANSITIVE_TRUSTS |
117 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
118 NETLOGON_NEG_PASSWORD_SET2 |
119 NETLOGON_NEG_GETDOMAININFO |
120 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
121 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
122 NETLOGON_NEG_RODC_PASSTHROUGH |
123 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
124 NETLOGON_NEG_AUTHENTICATED_RPC;
127 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
128 return NT_STATUS_ACCESS_DENIED;
131 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
132 system_session(dce_call->conn->dce_ctx->lp_ctx));
133 if (sam_ctx == NULL) {
134 return NT_STATUS_INVALID_SYSTEM_SERVICE;
137 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
138 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
139 const char *flatname;
140 if (!encoded_account) {
141 return NT_STATUS_NO_MEMORY;
144 /* Kill the trailing dot */
145 if (encoded_account[strlen(encoded_account)-1] == '.') {
146 encoded_account[strlen(encoded_account)-1] = '\0';
149 /* pull the user attributes */
150 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
152 "(&(trustPartner=%s)(objectclass=trustedDomain))",
155 if (num_records == 0) {
156 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
158 return NT_STATUS_ACCESS_DENIED;
161 if (num_records > 1) {
162 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
163 return NT_STATUS_INTERNAL_DB_CORRUPTION;
166 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
168 /* No flatname for this trust - we can't proceed */
169 return NT_STATUS_ACCESS_DENIED;
171 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
174 return NT_STATUS_NO_MEMORY;
178 account_name = r->in.account_name;
181 /* pull the user attributes */
182 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
183 "(&(sAMAccountName=%s)(objectclass=user))",
184 ldb_binary_encode_string(mem_ctx, account_name));
186 if (num_records == 0) {
187 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
188 r->in.account_name));
189 return NT_STATUS_ACCESS_DENIED;
192 if (num_records > 1) {
193 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
194 return NT_STATUS_INTERNAL_DB_CORRUPTION;
197 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
199 if (user_account_control & UF_ACCOUNTDISABLE) {
200 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
201 return NT_STATUS_ACCESS_DENIED;
204 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
205 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
206 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
207 return NT_STATUS_ACCESS_DENIED;
209 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
210 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
211 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
212 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
214 return NT_STATUS_ACCESS_DENIED;
216 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
217 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
218 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
219 return NT_STATUS_ACCESS_DENIED;
221 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
222 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
223 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
224 return NT_STATUS_ACCESS_DENIED;
227 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
228 r->in.secure_channel_type));
229 return NT_STATUS_ACCESS_DENIED;
232 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
235 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
236 if (mach_pwd == NULL) {
237 return NT_STATUS_ACCESS_DENIED;
240 creds = netlogon_creds_server_init(mem_ctx,
243 r->in.secure_channel_type,
244 &pipe_state->client_challenge,
245 &pipe_state->server_challenge,
248 r->out.return_credentials,
249 *r->in.negotiate_flags);
252 return NT_STATUS_ACCESS_DENIED;
255 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
257 nt_status = schannel_save_creds_state(mem_ctx,
258 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
264 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
265 struct netr_ServerAuthenticate *r)
267 struct netr_ServerAuthenticate3 a;
270 * negotiate_flags is used as an [in] parameter
271 * so it need to be initialised.
273 * (I think ... = 0; seems wrong here --metze)
275 uint32_t negotiate_flags_in = 0;
276 uint32_t negotiate_flags_out = 0;
278 a.in.server_name = r->in.server_name;
279 a.in.account_name = r->in.account_name;
280 a.in.secure_channel_type = r->in.secure_channel_type;
281 a.in.computer_name = r->in.computer_name;
282 a.in.credentials = r->in.credentials;
283 a.in.negotiate_flags = &negotiate_flags_in;
285 a.out.return_credentials = r->out.return_credentials;
287 a.out.negotiate_flags = &negotiate_flags_out;
289 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
292 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
293 struct netr_ServerAuthenticate2 *r)
295 struct netr_ServerAuthenticate3 r3;
298 r3.in.server_name = r->in.server_name;
299 r3.in.account_name = r->in.account_name;
300 r3.in.secure_channel_type = r->in.secure_channel_type;
301 r3.in.computer_name = r->in.computer_name;
302 r3.in.credentials = r->in.credentials;
303 r3.out.return_credentials = r->out.return_credentials;
304 r3.in.negotiate_flags = r->in.negotiate_flags;
305 r3.out.negotiate_flags = r->out.negotiate_flags;
308 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
312 * NOTE: The following functions are nearly identical to the ones available in
313 * source3/rpc_server/srv_nelog_nt.c
314 * The reason we keep 2 copies is that they use different structures to
315 * represent the auth_info and the decrpc pipes.
319 * If schannel is required for this call test that it actually is available.
321 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
322 const char *computer_name,
323 bool integrity, bool privacy)
326 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
327 if (!privacy && !integrity) {
331 if ((!privacy && integrity) &&
332 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
336 if ((privacy || integrity) &&
337 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
342 /* test didn't pass */
343 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
346 return NT_STATUS_ACCESS_DENIED;
349 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
351 const char *computer_name,
352 struct netr_Authenticator *received_authenticator,
353 struct netr_Authenticator *return_authenticator,
354 struct netlogon_creds_CredentialState **creds_out)
357 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
358 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
360 if (schannel_global_required) {
361 nt_status = schannel_check_required(auth_info,
364 if (!NT_STATUS_IS_OK(nt_status)) {
369 nt_status = schannel_check_creds_state(mem_ctx,
370 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
372 received_authenticator,
373 return_authenticator,
379 Change the machine account password for the currently connected
380 client. Supplies only the NT#.
383 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
384 struct netr_ServerPasswordSet *r)
386 struct netlogon_creds_CredentialState *creds;
387 struct ldb_context *sam_ctx;
388 const char * const attrs[] = { "unicodePwd", NULL };
389 struct ldb_message **res;
390 struct samr_Password *oldNtHash;
394 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
397 r->in.credential, r->out.return_authenticator,
399 NT_STATUS_NOT_OK_RETURN(nt_status);
401 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));
402 if (sam_ctx == NULL) {
403 return NT_STATUS_INVALID_SYSTEM_SERVICE;
406 netlogon_creds_des_decrypt(creds, r->in.new_password);
408 /* fetch the old password hashes (the NT hash has to exist) */
410 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
411 "(&(objectClass=user)(objectSid=%s))",
412 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
414 return NT_STATUS_WRONG_PASSWORD;
417 nt_status = samdb_result_passwords(mem_ctx,
418 dce_call->conn->dce_ctx->lp_ctx,
419 res[0], NULL, &oldNtHash);
420 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
421 return NT_STATUS_WRONG_PASSWORD;
424 /* Using the sid for the account as the key, set the password */
425 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
427 NULL, /* Don't have plaintext */
428 NULL, r->in.new_password,
429 NULL, oldNtHash, /* Password change */
435 Change the machine account password for the currently connected
436 client. Supplies new plaintext.
438 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
439 struct netr_ServerPasswordSet2 *r)
441 struct netlogon_creds_CredentialState *creds;
442 struct ldb_context *sam_ctx;
443 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
444 struct ldb_message **res;
445 struct samr_Password *oldLmHash, *oldNtHash;
447 DATA_BLOB new_password;
450 struct samr_CryptPassword password_buf;
452 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
455 r->in.credential, r->out.return_authenticator,
457 NT_STATUS_NOT_OK_RETURN(nt_status);
459 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));
460 if (sam_ctx == NULL) {
461 return NT_STATUS_INVALID_SYSTEM_SERVICE;
464 memcpy(password_buf.data, r->in.new_password->data, 512);
465 SIVAL(password_buf.data, 512, r->in.new_password->length);
466 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
468 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
469 DEBUG(3,("samr: failed to decode password buffer\n"));
470 return NT_STATUS_WRONG_PASSWORD;
473 /* fetch the old password hashes (at least one of both has to exist) */
475 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
476 "(&(objectClass=user)(objectSid=%s))",
477 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
479 return NT_STATUS_WRONG_PASSWORD;
482 nt_status = samdb_result_passwords(mem_ctx,
483 dce_call->conn->dce_ctx->lp_ctx,
484 res[0], &oldLmHash, &oldNtHash);
485 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
486 return NT_STATUS_WRONG_PASSWORD;
489 /* Using the sid for the account as the key, set the password */
490 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
492 &new_password, /* we have plaintext */
494 oldLmHash, oldNtHash, /* Password change */
503 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
504 struct netr_LogonUasLogon *r)
506 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
513 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
514 struct netr_LogonUasLogoff *r)
516 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
521 netr_LogonSamLogon_base
523 This version of the function allows other wrappers to say 'do not check the credentials'
525 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
527 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
530 struct auth_context *auth_context;
531 struct auth_usersupplied_info *user_info;
532 struct auth_serversupplied_info *server_info;
534 static const char zeros[16];
535 struct netr_SamBaseInfo *sam;
536 struct netr_SamInfo2 *sam2;
537 struct netr_SamInfo3 *sam3;
538 struct netr_SamInfo6 *sam6;
540 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
541 NT_STATUS_HAVE_NO_MEMORY(user_info);
543 switch (r->in.logon_level) {
544 case NetlogonInteractiveInformation:
545 case NetlogonServiceInformation:
546 case NetlogonInteractiveTransitiveInformation:
547 case NetlogonServiceTransitiveInformation:
548 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
549 netlogon_creds_arcfour_crypt(creds,
550 r->in.logon->password->lmpassword.hash,
551 sizeof(r->in.logon->password->lmpassword.hash));
552 netlogon_creds_arcfour_crypt(creds,
553 r->in.logon->password->ntpassword.hash,
554 sizeof(r->in.logon->password->ntpassword.hash));
556 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
557 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
560 /* TODO: we need to deny anonymous access here */
561 nt_status = auth_context_create(mem_ctx,
562 dce_call->event_ctx, dce_call->msg_ctx,
563 dce_call->conn->dce_ctx->lp_ctx,
565 NT_STATUS_NOT_OK_RETURN(nt_status);
567 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
568 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
569 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
570 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
572 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
573 user_info->password_state = AUTH_PASSWORD_HASH;
575 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
576 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
577 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
579 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
580 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
581 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
584 case NetlogonNetworkInformation:
585 case NetlogonNetworkTransitiveInformation:
587 /* TODO: we need to deny anonymous access here */
588 nt_status = auth_context_create(mem_ctx,
589 dce_call->event_ctx, dce_call->msg_ctx,
590 dce_call->conn->dce_ctx->lp_ctx,
592 NT_STATUS_NOT_OK_RETURN(nt_status);
594 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
595 NT_STATUS_NOT_OK_RETURN(nt_status);
597 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
598 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
599 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
600 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
602 user_info->password_state = AUTH_PASSWORD_RESPONSE;
603 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
604 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
609 case NetlogonGenericInformation:
611 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
612 netlogon_creds_arcfour_crypt(creds,
613 r->in.logon->generic->data, r->in.logon->generic->length);
615 /* Using DES to verify kerberos tickets makes no sense */
616 return NT_STATUS_INVALID_PARAMETER;
619 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
621 struct dcerpc_binding_handle *irpc_handle;
622 struct kdc_check_generic_kerberos check;
623 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
624 NT_STATUS_HAVE_NO_MEMORY(generic);
625 *r->out.authoritative = 1;
627 /* TODO: Describe and deal with these flags */
630 r->out.validation->generic = generic;
632 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
636 if (irpc_handle == NULL) {
637 return NT_STATUS_NO_LOGON_SERVERS;
640 check.in.generic_request =
641 data_blob_const(r->in.logon->generic->data,
642 r->in.logon->generic->length);
644 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
647 if (!NT_STATUS_IS_OK(status)) {
650 generic->length = check.out.generic_reply.length;
651 generic->data = check.out.generic_reply.data;
655 /* Until we get an implemetnation of these other packages */
656 return NT_STATUS_INVALID_PARAMETER;
659 return NT_STATUS_INVALID_PARAMETER;
662 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
663 NT_STATUS_NOT_OK_RETURN(nt_status);
665 switch (r->in.validation_level) {
667 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
668 NT_STATUS_NOT_OK_RETURN(nt_status);
670 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
671 NT_STATUS_HAVE_NO_MEMORY(sam2);
674 /* And put into the talloc tree */
675 talloc_steal(sam2, sam);
676 r->out.validation->sam2 = sam2;
682 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
685 NT_STATUS_NOT_OK_RETURN(nt_status);
687 r->out.validation->sam3 = sam3;
693 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
696 NT_STATUS_NOT_OK_RETURN(nt_status);
698 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
699 NT_STATUS_HAVE_NO_MEMORY(sam6);
700 sam6->base = sam3->base;
702 sam6->sidcount = sam3->sidcount;
703 sam6->sids = sam3->sids;
705 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
706 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
707 sam->account_name.string, sam6->dns_domainname.string);
708 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
709 /* And put into the talloc tree */
710 talloc_steal(sam6, sam3);
712 r->out.validation->sam6 = sam6;
719 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
720 /* It appears that level 6 is not individually encrypted */
721 if ((r->in.validation_level != 6) &&
722 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
723 /* This key is sent unencrypted without the ARCFOUR flag set */
724 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
725 netlogon_creds_arcfour_crypt(creds,
727 sizeof(sam->key.key));
731 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
732 /* It appears that level 6 is not individually encrypted */
733 if ((r->in.validation_level != 6) &&
734 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
735 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
736 netlogon_creds_arcfour_crypt(creds,
738 sizeof(sam->LMSessKey.key));
740 netlogon_creds_des_encrypt_LMKey(creds,
745 *r->out.authoritative = 1;
747 /* TODO: Describe and deal with these flags */
753 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
754 struct netr_LogonSamLogonEx *r)
757 struct netlogon_creds_CredentialState *creds;
759 nt_status = schannel_get_creds_state(mem_ctx,
760 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
761 r->in.computer_name, &creds);
762 if (!NT_STATUS_IS_OK(nt_status)) {
766 if (!dce_call->conn->auth_state.auth_info ||
767 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
768 return NT_STATUS_ACCESS_DENIED;
770 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
774 netr_LogonSamLogonWithFlags
777 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
778 struct netr_LogonSamLogonWithFlags *r)
781 struct netlogon_creds_CredentialState *creds;
782 struct netr_LogonSamLogonEx r2;
784 struct netr_Authenticator *return_authenticator;
786 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
787 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
789 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
792 r->in.credential, return_authenticator,
794 NT_STATUS_NOT_OK_RETURN(nt_status);
798 r2.in.server_name = r->in.server_name;
799 r2.in.computer_name = r->in.computer_name;
800 r2.in.logon_level = r->in.logon_level;
801 r2.in.logon = r->in.logon;
802 r2.in.validation_level = r->in.validation_level;
803 r2.in.flags = r->in.flags;
804 r2.out.validation = r->out.validation;
805 r2.out.authoritative = r->out.authoritative;
806 r2.out.flags = r->out.flags;
808 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
810 r->out.return_authenticator = return_authenticator;
818 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
819 struct netr_LogonSamLogon *r)
821 struct netr_LogonSamLogonWithFlags r2;
827 r2.in.server_name = r->in.server_name;
828 r2.in.computer_name = r->in.computer_name;
829 r2.in.credential = r->in.credential;
830 r2.in.return_authenticator = r->in.return_authenticator;
831 r2.in.logon_level = r->in.logon_level;
832 r2.in.logon = r->in.logon;
833 r2.in.validation_level = r->in.validation_level;
834 r2.in.flags = &flags;
835 r2.out.validation = r->out.validation;
836 r2.out.authoritative = r->out.authoritative;
837 r2.out.flags = &flags;
839 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
841 r->out.return_authenticator = r2.out.return_authenticator;
850 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
851 struct netr_LogonSamLogoff *r)
853 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
861 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
862 struct netr_DatabaseDeltas *r)
864 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
871 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
872 struct netr_DatabaseSync2 *r)
874 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
875 return NT_STATUS_NOT_IMPLEMENTED;
882 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
883 struct netr_DatabaseSync *r)
885 struct netr_DatabaseSync2 r2;
890 r2.in.logon_server = r->in.logon_server;
891 r2.in.computername = r->in.computername;
892 r2.in.credential = r->in.credential;
893 r2.in.database_id = r->in.database_id;
894 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
895 r2.in.sync_context = r->in.sync_context;
896 r2.out.sync_context = r->out.sync_context;
897 r2.out.delta_enum_array = r->out.delta_enum_array;
898 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
900 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
909 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
910 struct netr_AccountDeltas *r)
912 /* w2k3 returns "NOT IMPLEMENTED" for this call */
913 return NT_STATUS_NOT_IMPLEMENTED;
920 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
921 struct netr_AccountSync *r)
923 /* w2k3 returns "NOT IMPLEMENTED" for this call */
924 return NT_STATUS_NOT_IMPLEMENTED;
931 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
932 struct netr_GetDcName *r)
934 const char * const attrs[] = { NULL };
935 struct ldb_context *sam_ctx;
936 struct ldb_message **res;
937 struct ldb_dn *domain_dn;
941 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
942 dce_call->conn->dce_ctx->lp_ctx,
943 dce_call->conn->auth_state.session_info);
944 if (sam_ctx == NULL) {
945 return WERR_DS_UNAVAILABLE;
948 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
950 if (domain_dn == NULL) {
951 return WERR_DS_UNAVAILABLE;
954 ret = gendb_search_dn(sam_ctx, mem_ctx,
955 domain_dn, &res, attrs);
957 return WERR_NO_SUCH_DOMAIN;
960 /* TODO: - return real IP address
961 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
963 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
964 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
965 W_ERROR_HAVE_NO_MEMORY(dcname);
967 *r->out.dcname = dcname;
975 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
976 struct netr_LogonControl2Ex *r)
978 return WERR_NOT_SUPPORTED;
985 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
986 struct netr_LogonControl *r)
988 struct netr_LogonControl2Ex r2;
991 if (r->in.level == 0x00000001) {
994 r2.in.logon_server = r->in.logon_server;
995 r2.in.function_code = r->in.function_code;
996 r2.in.level = r->in.level;
998 r2.out.query = r->out.query;
1000 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1001 } else if (r->in.level == 0x00000002) {
1002 werr = WERR_NOT_SUPPORTED;
1004 werr = WERR_UNKNOWN_LEVEL;
1014 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1015 struct netr_LogonControl2 *r)
1017 struct netr_LogonControl2Ex r2;
1022 r2.in.logon_server = r->in.logon_server;
1023 r2.in.function_code = r->in.function_code;
1024 r2.in.level = r->in.level;
1025 r2.in.data = r->in.data;
1026 r2.out.query = r->out.query;
1028 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1033 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1034 struct ldb_context *sam_ctx,
1035 struct netr_DomainTrustList *trusts,
1036 uint32_t trust_flags);
1041 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1042 struct netr_GetAnyDCName *r)
1044 struct netr_DomainTrustList *trusts;
1045 struct ldb_context *sam_ctx;
1046 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1050 *r->out.dcname = NULL;
1052 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1053 /* if the domainname parameter wasn't set assume our domain */
1054 r->in.domainname = lpcfg_workgroup(lp_ctx);
1057 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1058 dce_call->conn->auth_state.session_info);
1059 if (sam_ctx == NULL) {
1060 return WERR_DS_UNAVAILABLE;
1063 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1064 /* well we asked for a DC of our own domain */
1065 if (samdb_is_pdc(sam_ctx)) {
1066 /* we are the PDC of the specified domain */
1067 return WERR_NO_SUCH_DOMAIN;
1070 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1071 lpcfg_netbios_name(lp_ctx));
1072 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1077 /* Okay, now we have to consider the trusted domains */
1079 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1080 W_ERROR_HAVE_NO_MEMORY(trusts);
1084 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1085 NETR_TRUST_FLAG_INBOUND
1086 | NETR_TRUST_FLAG_OUTBOUND);
1087 W_ERROR_NOT_OK_RETURN(werr);
1089 for (i = 0; i < trusts->count; i++) {
1090 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1091 /* FIXME: Here we need to find a DC for the specified
1092 * trusted domain. */
1094 /* return WERR_OK; */
1095 return WERR_NO_SUCH_DOMAIN;
1099 return WERR_NO_SUCH_DOMAIN;
1106 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1107 struct netr_DatabaseRedo *r)
1109 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1114 netr_NetrEnumerateTrustedDomains
1116 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1117 struct netr_NetrEnumerateTrustedDomains *r)
1119 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1124 netr_LogonGetCapabilities
1126 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1127 struct netr_LogonGetCapabilities *r)
1129 /* we don't support AES yet */
1130 return NT_STATUS_NOT_IMPLEMENTED;
1135 netr_NETRLOGONSETSERVICEBITS
1137 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1138 struct netr_NETRLOGONSETSERVICEBITS *r)
1140 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1145 netr_LogonGetTrustRid
1147 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1148 struct netr_LogonGetTrustRid *r)
1150 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1155 netr_NETRLOGONCOMPUTESERVERDIGEST
1157 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1158 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1160 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1165 netr_NETRLOGONCOMPUTECLIENTDIGEST
1167 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1168 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1170 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1178 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179 struct netr_DsRGetSiteName *r)
1181 struct ldb_context *sam_ctx;
1182 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1184 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1185 dce_call->conn->auth_state.session_info);
1186 if (sam_ctx == NULL) {
1187 return WERR_DS_UNAVAILABLE;
1190 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1191 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1198 fill in a netr_OneDomainInfo from a ldb search result
1200 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1201 struct loadparm_context *lp_ctx,
1202 struct ldb_context *sam_ctx,
1203 struct ldb_message *res,
1204 struct netr_OneDomainInfo *info,
1205 bool is_local, bool is_trust_list)
1209 if (is_trust_list) {
1210 /* w2k8 only fills this on trusted domains */
1211 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1212 info->trust_extension.length = 16;
1213 info->trust_extension.info->flags =
1214 NETR_TRUST_FLAG_TREEROOT |
1215 NETR_TRUST_FLAG_IN_FOREST |
1216 NETR_TRUST_FLAG_PRIMARY |
1217 NETR_TRUST_FLAG_NATIVE;
1219 info->trust_extension.info->parent_index = 0; /* should be index into array
1221 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1222 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1225 if (is_trust_list) {
1226 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1227 info->dns_forestname.string = NULL;
1229 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1230 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1231 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1232 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1236 info->domainname.string = lpcfg_workgroup(lp_ctx);
1237 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1238 info->domain_guid = samdb_result_guid(res, "objectGUID");
1239 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1241 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1242 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1243 info->domain_guid = samdb_result_guid(res, "objectGUID");
1244 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1246 if (!is_trust_list) {
1247 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1250 return NT_STATUS_OK;
1254 netr_LogonGetDomainInfo
1255 this is called as part of the ADS domain logon procedure.
1257 It has an important role in convaying details about the client, such
1258 as Operating System, Version, Service Pack etc.
1260 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1261 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1263 struct netlogon_creds_CredentialState *creds;
1264 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1265 "securityIdentifier", "trustPartner", NULL };
1266 const char * const attrs2[] = { "dNSHostName",
1267 "msDS-SupportedEncryptionTypes", NULL };
1268 const char *temp_str, *temp_str2;
1269 const char *old_dns_hostname;
1270 struct ldb_context *sam_ctx;
1271 struct ldb_message **res1, **res2, **res3, *new_msg;
1272 struct ldb_dn *workstation_dn;
1273 struct netr_DomainInformation *domain_info;
1274 struct netr_LsaPolicyInformation *lsa_policy_info;
1275 struct netr_OsVersionInfoEx *os_version;
1276 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1277 bool update_dns_hostname = true;
1281 status = dcesrv_netr_creds_server_step_check(dce_call,
1283 r->in.computer_name,
1285 r->out.return_authenticator,
1287 if (!NT_STATUS_IS_OK(status)) {
1288 DEBUG(0,(__location__ " Bad credentials - error\n"));
1290 NT_STATUS_NOT_OK_RETURN(status);
1292 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1293 dce_call->conn->dce_ctx->lp_ctx,
1294 system_session(dce_call->conn->dce_ctx->lp_ctx));
1295 if (sam_ctx == NULL) {
1296 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1299 switch (r->in.level) {
1300 case 1: /* Domain information */
1302 if (r->in.query->workstation_info == NULL) {
1303 return NT_STATUS_INVALID_PARAMETER;
1307 * Checks that the computer name parameter without possible "$"
1308 * matches as prefix with the DNS hostname in the workstation
1311 temp_str = talloc_strndup(mem_ctx,
1312 r->in.computer_name,
1313 strcspn(r->in.computer_name, "$"));
1314 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1315 temp_str2 = talloc_strndup(mem_ctx,
1316 r->in.query->workstation_info->dns_hostname,
1317 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1318 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1319 if (strcasecmp(temp_str, temp_str2) != 0) {
1320 update_dns_hostname = false;
1323 /* Prepare the workstation DN */
1324 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1325 dom_sid_string(mem_ctx, creds->sid));
1326 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1328 /* Lookup for attributes in workstation object */
1329 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1332 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1335 /* Gets the old DNS hostname */
1336 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1340 * Updates the DNS hostname when the client wishes that the
1341 * server should handle this for him
1342 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1343 * obviously only checked when we do already have a
1345 * See MS-NRPC section 3.5.4.3.9
1347 if ((old_dns_hostname != NULL) &&
1348 (r->in.query->workstation_info->workstation_flags
1349 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1350 update_dns_hostname = false;
1353 /* Gets host informations and put them into our directory */
1355 new_msg = ldb_msg_new(mem_ctx);
1356 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1358 new_msg->dn = workstation_dn;
1360 /* Sets the OS name */
1361 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1363 r->in.query->workstation_info->os_name.string);
1366 * Sets informations from "os_version". On an empty structure
1367 * the values are cleared.
1369 if (r->in.query->workstation_info->os_version.os != NULL) {
1370 os_version = &r->in.query->workstation_info->os_version.os->os;
1372 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1373 "operatingSystemServicePack",
1374 os_version->CSDVersion);
1376 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1377 "operatingSystemVersion",
1378 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1379 os_version->MajorVersion,
1380 os_version->MinorVersion,
1381 os_version->BuildNumber
1385 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1386 "operatingSystemServicePack");
1388 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1389 "operatingSystemVersion");
1393 * If the boolean "update_dns_hostname" remained true, then we
1394 * are fine to start the update.
1396 if (update_dns_hostname) {
1397 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1399 r->in.query->workstation_info->dns_hostname);
1401 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1402 "servicePrincipalName",
1403 talloc_asprintf(mem_ctx, "HOST/%s",
1404 r->in.computer_name)
1406 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1407 "servicePrincipalName",
1408 talloc_asprintf(mem_ctx, "HOST/%s",
1409 r->in.query->workstation_info->dns_hostname)
1413 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1414 DEBUG(3,("Impossible to update samdb: %s\n",
1415 ldb_errstring(sam_ctx)));
1418 talloc_free(new_msg);
1420 /* Writes back the domain information */
1422 /* We need to do two searches. The first will pull our primary
1423 domain and the second will pull any trusted domains. Our
1424 primary domain is also a "trusted" domain, so we need to
1425 put the primary domain into the lists of returned trusts as
1427 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1430 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1433 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1434 "(objectClass=trustedDomain)");
1436 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1439 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1440 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1442 ZERO_STRUCTP(domain_info);
1444 /* Informations about the local and trusted domains */
1446 status = fill_one_domain_info(mem_ctx,
1447 dce_call->conn->dce_ctx->lp_ctx,
1448 sam_ctx, res2[0], &domain_info->primary_domain,
1450 NT_STATUS_NOT_OK_RETURN(status);
1452 domain_info->trusted_domain_count = ret3 + 1;
1453 domain_info->trusted_domains = talloc_array(mem_ctx,
1454 struct netr_OneDomainInfo,
1455 domain_info->trusted_domain_count);
1456 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1458 for (i=0;i<ret3;i++) {
1459 status = fill_one_domain_info(mem_ctx,
1460 dce_call->conn->dce_ctx->lp_ctx,
1462 &domain_info->trusted_domains[i],
1464 NT_STATUS_NOT_OK_RETURN(status);
1467 status = fill_one_domain_info(mem_ctx,
1468 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1469 &domain_info->trusted_domains[i], true, true);
1470 NT_STATUS_NOT_OK_RETURN(status);
1472 /* Sets the supported encryption types */
1473 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1474 "msDS-SupportedEncryptionTypes",
1475 default_supported_enc_types);
1477 /* Other host domain informations */
1479 lsa_policy_info = talloc(mem_ctx,
1480 struct netr_LsaPolicyInformation);
1481 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1482 ZERO_STRUCTP(lsa_policy_info);
1484 domain_info->lsa_policy = *lsa_policy_info;
1486 /* The DNS hostname is only returned back when there is a chance
1488 if ((r->in.query->workstation_info->workstation_flags
1489 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1490 domain_info->dns_hostname.string = old_dns_hostname;
1492 domain_info->dns_hostname.string = NULL;
1495 domain_info->workstation_flags =
1496 r->in.query->workstation_info->workstation_flags;
1498 r->out.info->domain_info = domain_info;
1500 case 2: /* LSA policy information - not used at the moment */
1501 lsa_policy_info = talloc(mem_ctx,
1502 struct netr_LsaPolicyInformation);
1503 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1504 ZERO_STRUCTP(lsa_policy_info);
1506 r->out.info->lsa_policy_info = lsa_policy_info;
1509 return NT_STATUS_INVALID_LEVEL;
1513 return NT_STATUS_OK;
1519 netr_ServerPasswordGet
1521 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1522 struct netr_ServerPasswordGet *r)
1524 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1529 netr_NETRLOGONSENDTOSAM
1531 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1532 struct netr_NETRLOGONSENDTOSAM *r)
1534 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1539 netr_DsRGetDCNameEx2
1541 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1542 TALLOC_CTX *mem_ctx,
1543 struct netr_DsRGetDCNameEx2 *r)
1545 struct ldb_context *sam_ctx;
1546 struct netr_DsRGetDCNameInfo *info;
1547 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1548 const struct tsocket_address *remote_address;
1550 const char *server_site_name;
1552 struct netlogon_samlogon_response response;
1555 ZERO_STRUCTP(r->out.info);
1557 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1558 dce_call->conn->auth_state.session_info);
1559 if (sam_ctx == NULL) {
1560 return WERR_DS_UNAVAILABLE;
1563 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1564 if (tsocket_address_is_inet(remote_address, "ip")) {
1565 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1566 W_ERROR_HAVE_NO_MEMORY(addr);
1569 /* "server_unc" is ignored by w2k3 */
1571 /* Proof server site parameter "site_name" if it was specified */
1572 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1573 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1574 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1575 server_site_name) != 0)) {
1576 return WERR_NO_SUCH_DOMAIN;
1579 /* TODO: the flags are ignored for now */
1581 guid_str = r->in.domain_guid != NULL ?
1582 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1584 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1588 r->in.client_account,
1590 NETLOGON_NT_VERSION_5EX_WITH_IP,
1591 lp_ctx, &response, true);
1592 if (!NT_STATUS_IS_OK(status)) {
1593 return ntstatus_to_werror(status);
1596 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1597 W_ERROR_HAVE_NO_MEMORY(info);
1598 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1599 response.data.nt5_ex.pdc_dns_name);
1600 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1601 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1602 response.data.nt5_ex.sockaddr.pdc_ip);
1603 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1604 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1605 info->domain_guid = response.data.nt5_ex.domain_uuid;
1606 info->domain_name = response.data.nt5_ex.dns_domain;
1607 info->forest_name = response.data.nt5_ex.forest;
1608 info->dc_flags = response.data.nt5_ex.server_type;
1609 info->dc_site_name = response.data.nt5_ex.server_site;
1610 info->client_site_name = response.data.nt5_ex.client_site;
1612 *r->out.info = info;
1620 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1621 struct netr_DsRGetDCNameEx *r)
1623 struct netr_DsRGetDCNameEx2 r2;
1628 r2.in.server_unc = r->in.server_unc;
1629 r2.in.client_account = NULL;
1631 r2.in.domain_guid = r->in.domain_guid;
1632 r2.in.domain_name = r->in.domain_name;
1633 r2.in.site_name = r->in.site_name;
1634 r2.in.flags = r->in.flags;
1635 r2.out.info = r->out.info;
1637 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1645 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1646 struct netr_DsRGetDCName *r)
1648 struct netr_DsRGetDCNameEx2 r2;
1653 r2.in.server_unc = r->in.server_unc;
1654 r2.in.client_account = NULL;
1656 r2.in.domain_name = r->in.domain_name;
1657 r2.in.domain_guid = r->in.domain_guid;
1659 r2.in.site_name = NULL; /* should fill in from site GUID */
1660 r2.in.flags = r->in.flags;
1661 r2.out.info = r->out.info;
1663 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1668 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1670 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1671 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1673 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1678 netr_NetrEnumerateTrustedDomainsEx
1680 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1681 struct netr_NetrEnumerateTrustedDomainsEx *r)
1683 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1688 netr_DsRAddressToSitenamesExW
1690 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1691 struct netr_DsRAddressToSitenamesExW *r)
1693 struct ldb_context *sam_ctx;
1694 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1695 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1696 sa_family_t sin_family;
1697 struct sockaddr_in *addr;
1699 struct sockaddr_in6 *addr6;
1700 char addr_str[INET6_ADDRSTRLEN];
1702 char addr_str[INET_ADDRSTRLEN];
1708 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1709 dce_call->conn->auth_state.session_info);
1710 if (sam_ctx == NULL) {
1711 return WERR_DS_UNAVAILABLE;
1714 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1715 W_ERROR_HAVE_NO_MEMORY(ctr);
1719 ctr->count = r->in.count;
1720 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1721 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1722 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1723 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1725 for (i=0; i<ctr->count; i++) {
1726 ctr->sitename[i].string = NULL;
1727 ctr->subnetname[i].string = NULL;
1729 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1732 /* The first two byte of the buffer are reserved for the
1733 * "sin_family" but for now only the first one is used. */
1734 sin_family = r->in.addresses[i].buffer[0];
1736 switch (sin_family) {
1738 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1741 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1742 res = inet_ntop(AF_INET, &addr->sin_addr,
1743 addr_str, sizeof(addr_str));
1747 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1750 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1751 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1752 addr_str, sizeof(addr_str));
1763 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1767 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1768 ctr->subnetname[i].string = subnet_name;
1776 netr_DsRAddressToSitenamesW
1778 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1779 struct netr_DsRAddressToSitenamesW *r)
1781 struct netr_DsRAddressToSitenamesExW r2;
1782 struct netr_DsRAddressToSitenamesWCtr *ctr;
1788 r2.in.server_name = r->in.server_name;
1789 r2.in.count = r->in.count;
1790 r2.in.addresses = r->in.addresses;
1792 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1793 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1795 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1796 W_ERROR_HAVE_NO_MEMORY(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);
1804 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1806 for (i=0; i<ctr->count; i++) {
1807 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1815 netr_DsrGetDcSiteCoverageW
1817 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1818 struct netr_DsrGetDcSiteCoverageW *r)
1820 struct ldb_context *sam_ctx;
1821 struct DcSitesCtr *ctr;
1822 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1824 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1825 dce_call->conn->auth_state.session_info);
1826 if (sam_ctx == NULL) {
1827 return WERR_DS_UNAVAILABLE;
1830 ctr = talloc(mem_ctx, struct DcSitesCtr);
1831 W_ERROR_HAVE_NO_MEMORY(ctr);
1835 /* For now only return our default site */
1837 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1838 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1839 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1840 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1846 #define GET_CHECK_STR(dest, mem, msg, attr) \
1849 s = samdb_result_string(msg, attr, NULL); \
1851 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1852 "without flatname\n", \
1853 ldb_dn_get_linearized(msg->dn))); \
1856 dest = talloc_strdup(mem, s); \
1857 W_ERROR_HAVE_NO_MEMORY(dest); \
1861 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1862 struct ldb_context *sam_ctx,
1863 struct netr_DomainTrustList *trusts,
1864 uint32_t trust_flags)
1866 struct ldb_dn *system_dn;
1867 struct ldb_message **dom_res = NULL;
1868 const char *trust_attrs[] = { "flatname", "trustPartner",
1869 "securityIdentifier", "trustDirection",
1870 "trustType", "trustAttributes", NULL };
1875 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1876 NETR_TRUST_FLAG_OUTBOUND))) {
1877 return WERR_INVALID_FLAGS;
1880 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1881 ldb_get_default_basedn(sam_ctx),
1882 "(&(objectClass=container)(cn=System))");
1884 return WERR_GENERAL_FAILURE;
1887 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1888 &dom_res, trust_attrs,
1889 "(objectclass=trustedDomain)");
1891 for (i = 0; i < ret; i++) {
1892 unsigned int trust_dir;
1895 trust_dir = samdb_result_uint(dom_res[i],
1896 "trustDirection", 0);
1898 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1899 flags |= NETR_TRUST_FLAG_INBOUND;
1901 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1902 flags |= NETR_TRUST_FLAG_OUTBOUND;
1905 if (!(flags & trust_flags)) {
1906 /* this trust direction was not requested */
1911 trusts->array = talloc_realloc(trusts, trusts->array,
1912 struct netr_DomainTrust,
1914 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1916 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1917 dom_res[i], "flatname");
1918 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1919 dom_res[i], "trustPartner");
1921 trusts->array[n].trust_flags = flags;
1922 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1923 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1924 /* TODO: find if we have parent in the list */
1925 trusts->array[n].parent_index = 0;
1928 trusts->array[n].trust_type =
1929 samdb_result_uint(dom_res[i],
1931 trusts->array[n].trust_attributes =
1932 samdb_result_uint(dom_res[i],
1933 "trustAttributes", 0);
1935 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1936 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1937 struct dom_sid zero_sid;
1938 ZERO_STRUCT(zero_sid);
1939 trusts->array[n].sid =
1940 dom_sid_dup(trusts, &zero_sid);
1942 trusts->array[n].sid =
1943 samdb_result_dom_sid(trusts, dom_res[i],
1944 "securityIdentifier");
1946 trusts->array[n].guid = GUID_zero();
1948 trusts->count = n + 1;
1951 talloc_free(dom_res);
1956 netr_DsrEnumerateDomainTrusts
1958 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1959 TALLOC_CTX *mem_ctx,
1960 struct netr_DsrEnumerateDomainTrusts *r)
1962 struct netr_DomainTrustList *trusts;
1963 struct ldb_context *sam_ctx;
1965 struct ldb_message **dom_res;
1966 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1967 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1968 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1972 if (r->in.trust_flags & 0xFFFFFE00) {
1973 return WERR_INVALID_FLAGS;
1976 /* TODO: turn to hard check once we are sure this is 100% correct */
1977 if (!r->in.server_name) {
1978 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1979 "But received NULL!\n", dnsdomain));
1981 p = strchr(r->in.server_name, '.');
1983 DEBUG(3, ("Invalid domain! Expected name in domain "
1984 "[%s]. But received [%s]!\n",
1985 dnsdomain, r->in.server_name));
1986 p = r->in.server_name;
1990 if (strcasecmp(p, dnsdomain)) {
1991 DEBUG(3, ("Invalid domain! Expected name in domain "
1992 "[%s]. But received [%s]!\n",
1993 dnsdomain, r->in.server_name));
1997 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1998 W_ERROR_HAVE_NO_MEMORY(trusts);
2001 r->out.trusts = trusts;
2003 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2004 dce_call->conn->auth_state.session_info);
2005 if (sam_ctx == NULL) {
2006 return WERR_GENERAL_FAILURE;
2009 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2010 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2012 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2013 trusts, r->in.trust_flags);
2014 W_ERROR_NOT_OK_RETURN(werr);
2017 /* NOTE: we currently are always the root of the forest */
2018 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2019 uint32_t n = trusts->count;
2021 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2022 &dom_res, dom_attrs);
2024 return WERR_GENERAL_FAILURE;
2027 trusts->count = n + 1;
2028 trusts->array = talloc_realloc(trusts, trusts->array,
2029 struct netr_DomainTrust,
2031 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2033 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2034 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2035 trusts->array[n].trust_flags =
2036 NETR_TRUST_FLAG_NATIVE |
2037 NETR_TRUST_FLAG_TREEROOT |
2038 NETR_TRUST_FLAG_IN_FOREST |
2039 NETR_TRUST_FLAG_PRIMARY;
2040 /* we are always the root domain for now */
2041 trusts->array[n].parent_index = 0;
2042 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2043 trusts->array[n].trust_attributes = 0;
2044 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2047 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2049 talloc_free(dom_res);
2057 netr_DsrDeregisterDNSHostRecords
2059 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2060 struct netr_DsrDeregisterDNSHostRecords *r)
2062 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2067 netr_ServerTrustPasswordsGet
2069 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2070 struct netr_ServerTrustPasswordsGet *r)
2072 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2076 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2077 struct ldb_context *sam_ctx,
2078 struct loadparm_context *lp_ctx,
2079 struct lsa_ForestTrustInformation *info)
2081 struct lsa_ForestTrustDomainInfo *domain_info;
2082 struct lsa_ForestTrustRecord *e;
2083 struct ldb_message **dom_res;
2084 const char * const dom_attrs[] = { "objectSid", NULL };
2087 /* we need to provide 2 entries:
2088 * 1. the Root Forest name
2089 * 2. the Domain Information
2093 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2094 W_ERROR_HAVE_NO_MEMORY(info->entries);
2096 /* Forest root info */
2097 e = talloc(info, struct lsa_ForestTrustRecord);
2098 W_ERROR_HAVE_NO_MEMORY(e);
2101 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2102 e->time = 0; /* so far always 0 in trces. */
2103 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2105 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2107 info->entries[0] = e;
2110 e = talloc(info, struct lsa_ForestTrustRecord);
2111 W_ERROR_HAVE_NO_MEMORY(e);
2113 /* get our own domain info */
2114 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2116 return WERR_GENERAL_FAILURE;
2119 /* TODO: check if disabled and set flags accordingly */
2121 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2122 e->time = 0; /* so far always 0 in traces. */
2124 domain_info = &e->forest_trust_data.domain_info;
2125 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2127 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2128 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2130 info->entries[1] = e;
2132 talloc_free(dom_res);
2138 netr_DsRGetForestTrustInformation
2140 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2141 TALLOC_CTX *mem_ctx,
2142 struct netr_DsRGetForestTrustInformation *r)
2144 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2145 struct lsa_ForestTrustInformation *info, **info_ptr;
2146 struct ldb_context *sam_ctx;
2149 if (r->in.flags & 0xFFFFFFFE) {
2150 return WERR_INVALID_FLAGS;
2153 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2154 dce_call->conn->auth_state.session_info);
2155 if (sam_ctx == NULL) {
2156 return WERR_GENERAL_FAILURE;
2159 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2160 if (!samdb_is_pdc(sam_ctx)) {
2161 return WERR_NERR_NOTPRIMARY;
2164 if (r->in.trusted_domain_name == NULL) {
2165 return WERR_INVALID_FLAGS;
2168 /* TODO: establish an schannel connection with
2169 * r->in.trusted_domain_name and perform a
2170 * netr_GetForestTrustInformation call against it */
2172 /* for now return not implementd */
2173 return WERR_CALL_NOT_IMPLEMENTED;
2176 /* TODO: check r->in.server_name is our name */
2178 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2179 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2181 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2182 W_ERROR_HAVE_NO_MEMORY(info);
2184 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2185 W_ERROR_NOT_OK_RETURN(werr);
2188 r->out.forest_trust_info = info_ptr;
2195 netr_GetForestTrustInformation
2197 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2198 TALLOC_CTX *mem_ctx,
2199 struct netr_GetForestTrustInformation *r)
2201 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2202 struct netlogon_creds_CredentialState *creds;
2203 struct lsa_ForestTrustInformation *info, **info_ptr;
2204 struct ldb_context *sam_ctx;
2208 status = dcesrv_netr_creds_server_step_check(dce_call,
2210 r->in.computer_name,
2212 r->out.return_authenticator,
2214 if (!NT_STATUS_IS_OK(status)) {
2218 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2219 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2220 return NT_STATUS_NOT_IMPLEMENTED;
2223 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2224 dce_call->conn->auth_state.session_info);
2225 if (sam_ctx == NULL) {
2226 return NT_STATUS_UNSUCCESSFUL;
2229 /* TODO: check r->in.server_name is our name */
2231 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2233 return NT_STATUS_NO_MEMORY;
2235 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2237 return NT_STATUS_NO_MEMORY;
2240 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2241 if (!W_ERROR_IS_OK(werr)) {
2242 return werror_to_ntstatus(werr);
2246 r->out.forest_trust_info = info_ptr;
2248 return NT_STATUS_OK;
2253 netr_ServerGetTrustInfo
2255 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2256 struct netr_ServerGetTrustInfo *r)
2258 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2262 /* include the generated boilerplate */
2263 #include "librpc/gen_ndr/ndr_netlogon_s.c"