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"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
40 struct netlogon_server_pipe_state {
41 struct netr_Credential client_challenge;
42 struct netr_Credential server_challenge;
45 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
46 struct netr_ServerReqChallenge *r)
48 struct netlogon_server_pipe_state *pipe_state =
49 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
51 ZERO_STRUCTP(r->out.return_credentials);
53 /* destroyed on pipe shutdown */
56 talloc_free(pipe_state);
57 dce_call->context->private_data = NULL;
60 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
61 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
63 pipe_state->client_challenge = *r->in.credentials;
65 generate_random_buffer(pipe_state->server_challenge.data,
66 sizeof(pipe_state->server_challenge.data));
68 *r->out.return_credentials = pipe_state->server_challenge;
70 dce_call->context->private_data = pipe_state;
75 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
76 struct netr_ServerAuthenticate3 *r)
78 struct netlogon_server_pipe_state *pipe_state =
79 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
80 struct netlogon_creds_CredentialState *creds;
81 struct ldb_context *sam_ctx;
82 struct samr_Password *mach_pwd;
83 uint32_t user_account_control;
85 struct ldb_message **msgs;
87 const char *attrs[] = {"unicodePwd", "userAccountControl",
90 const char *trust_dom_attrs[] = {"flatname", NULL};
91 const char *account_name;
93 ZERO_STRUCTP(r->out.return_credentials);
97 * According to Microsoft (see bugid #6099)
98 * Windows 7 looks at the negotiate_flags
99 * returned in this structure *even if the
100 * call fails with access denied!
102 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
103 NETLOGON_NEG_PERSISTENT_SAMREPL |
104 NETLOGON_NEG_ARCFOUR |
105 NETLOGON_NEG_PROMOTION_COUNT |
106 NETLOGON_NEG_CHANGELOG_BDC |
107 NETLOGON_NEG_FULL_SYNC_REPL |
108 NETLOGON_NEG_MULTIPLE_SIDS |
110 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
111 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
112 NETLOGON_NEG_GENERIC_PASSTHROUGH |
113 NETLOGON_NEG_CONCURRENT_RPC |
114 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
115 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
116 NETLOGON_NEG_STRONG_KEYS |
117 NETLOGON_NEG_TRANSITIVE_TRUSTS |
118 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
119 NETLOGON_NEG_PASSWORD_SET2 |
120 NETLOGON_NEG_GETDOMAININFO |
121 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
122 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
123 NETLOGON_NEG_RODC_PASSTHROUGH |
124 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
125 NETLOGON_NEG_AUTHENTICATED_RPC;
128 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
129 return NT_STATUS_ACCESS_DENIED;
132 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
133 system_session(dce_call->conn->dce_ctx->lp_ctx));
134 if (sam_ctx == NULL) {
135 return NT_STATUS_INVALID_SYSTEM_SERVICE;
138 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
139 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
140 const char *flatname;
141 if (!encoded_account) {
142 return NT_STATUS_NO_MEMORY;
145 /* Kill the trailing dot */
146 if (encoded_account[strlen(encoded_account)-1] == '.') {
147 encoded_account[strlen(encoded_account)-1] = '\0';
150 /* pull the user attributes */
151 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
153 "(&(trustPartner=%s)(objectclass=trustedDomain))",
156 if (num_records == 0) {
157 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
159 return NT_STATUS_ACCESS_DENIED;
162 if (num_records > 1) {
163 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
164 return NT_STATUS_INTERNAL_DB_CORRUPTION;
167 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
169 /* No flatname for this trust - we can't proceed */
170 return NT_STATUS_ACCESS_DENIED;
172 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
175 return NT_STATUS_NO_MEMORY;
179 account_name = r->in.account_name;
182 /* pull the user attributes */
183 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
184 "(&(sAMAccountName=%s)(objectclass=user))",
185 ldb_binary_encode_string(mem_ctx, account_name));
187 if (num_records == 0) {
188 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
189 r->in.account_name));
190 return NT_STATUS_ACCESS_DENIED;
193 if (num_records > 1) {
194 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
195 return NT_STATUS_INTERNAL_DB_CORRUPTION;
198 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
200 if (user_account_control & UF_ACCOUNTDISABLE) {
201 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
202 return NT_STATUS_ACCESS_DENIED;
205 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
206 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
207 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
208 return NT_STATUS_ACCESS_DENIED;
210 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
211 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
212 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
213 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
215 return NT_STATUS_ACCESS_DENIED;
217 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
218 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
219 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
220 return NT_STATUS_ACCESS_DENIED;
222 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
223 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
224 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
225 return NT_STATUS_ACCESS_DENIED;
228 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
229 r->in.secure_channel_type));
230 return NT_STATUS_ACCESS_DENIED;
233 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
236 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
237 if (mach_pwd == NULL) {
238 return NT_STATUS_ACCESS_DENIED;
241 creds = netlogon_creds_server_init(mem_ctx,
244 r->in.secure_channel_type,
245 &pipe_state->client_challenge,
246 &pipe_state->server_challenge,
249 r->out.return_credentials,
250 *r->in.negotiate_flags);
253 return NT_STATUS_ACCESS_DENIED;
256 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
258 nt_status = schannel_save_creds_state(mem_ctx,
259 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
265 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
266 struct netr_ServerAuthenticate *r)
268 struct netr_ServerAuthenticate3 a;
271 * negotiate_flags is used as an [in] parameter
272 * so it need to be initialised.
274 * (I think ... = 0; seems wrong here --metze)
276 uint32_t negotiate_flags_in = 0;
277 uint32_t negotiate_flags_out = 0;
279 a.in.server_name = r->in.server_name;
280 a.in.account_name = r->in.account_name;
281 a.in.secure_channel_type = r->in.secure_channel_type;
282 a.in.computer_name = r->in.computer_name;
283 a.in.credentials = r->in.credentials;
284 a.in.negotiate_flags = &negotiate_flags_in;
286 a.out.return_credentials = r->out.return_credentials;
288 a.out.negotiate_flags = &negotiate_flags_out;
290 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
293 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
294 struct netr_ServerAuthenticate2 *r)
296 struct netr_ServerAuthenticate3 r3;
299 r3.in.server_name = r->in.server_name;
300 r3.in.account_name = r->in.account_name;
301 r3.in.secure_channel_type = r->in.secure_channel_type;
302 r3.in.computer_name = r->in.computer_name;
303 r3.in.credentials = r->in.credentials;
304 r3.out.return_credentials = r->out.return_credentials;
305 r3.in.negotiate_flags = r->in.negotiate_flags;
306 r3.out.negotiate_flags = r->out.negotiate_flags;
309 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
313 * NOTE: The following functions are nearly identical to the ones available in
314 * source3/rpc_server/srv_nelog_nt.c
315 * The reason we keep 2 copies is that they use different structures to
316 * represent the auth_info and the decrpc pipes.
320 * If schannel is required for this call test that it actually is available.
322 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
323 const char *computer_name,
324 bool integrity, bool privacy)
327 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
328 if (!privacy && !integrity) {
332 if ((!privacy && integrity) &&
333 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
337 if ((privacy || integrity) &&
338 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
343 /* test didn't pass */
344 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
347 return NT_STATUS_ACCESS_DENIED;
350 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
352 const char *computer_name,
353 struct netr_Authenticator *received_authenticator,
354 struct netr_Authenticator *return_authenticator,
355 struct netlogon_creds_CredentialState **creds_out)
358 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
359 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
361 if (schannel_global_required) {
362 nt_status = schannel_check_required(auth_info,
365 if (!NT_STATUS_IS_OK(nt_status)) {
370 nt_status = schannel_check_creds_state(mem_ctx,
371 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
373 received_authenticator,
374 return_authenticator,
380 Change the machine account password for the currently connected
381 client. Supplies only the NT#.
384 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
385 struct netr_ServerPasswordSet *r)
387 struct netlogon_creds_CredentialState *creds;
388 struct ldb_context *sam_ctx;
389 const char * const attrs[] = { "unicodePwd", NULL };
390 struct ldb_message **res;
391 struct samr_Password *oldNtHash;
395 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
398 r->in.credential, r->out.return_authenticator,
400 NT_STATUS_NOT_OK_RETURN(nt_status);
402 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));
403 if (sam_ctx == NULL) {
404 return NT_STATUS_INVALID_SYSTEM_SERVICE;
407 netlogon_creds_des_decrypt(creds, r->in.new_password);
409 /* fetch the old password hashes (the NT hash has to exist) */
411 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
412 "(&(objectClass=user)(objectSid=%s))",
413 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
415 return NT_STATUS_WRONG_PASSWORD;
418 nt_status = samdb_result_passwords(mem_ctx,
419 dce_call->conn->dce_ctx->lp_ctx,
420 res[0], NULL, &oldNtHash);
421 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
422 return NT_STATUS_WRONG_PASSWORD;
425 /* Using the sid for the account as the key, set the password */
426 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
428 NULL, /* Don't have plaintext */
429 NULL, r->in.new_password,
430 NULL, oldNtHash, /* Password change */
436 Change the machine account password for the currently connected
437 client. Supplies new plaintext.
439 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
440 struct netr_ServerPasswordSet2 *r)
442 struct netlogon_creds_CredentialState *creds;
443 struct ldb_context *sam_ctx;
444 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
445 struct ldb_message **res;
446 struct samr_Password *oldLmHash, *oldNtHash;
448 DATA_BLOB new_password;
451 struct samr_CryptPassword password_buf;
453 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
456 r->in.credential, r->out.return_authenticator,
458 NT_STATUS_NOT_OK_RETURN(nt_status);
460 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));
461 if (sam_ctx == NULL) {
462 return NT_STATUS_INVALID_SYSTEM_SERVICE;
465 memcpy(password_buf.data, r->in.new_password->data, 512);
466 SIVAL(password_buf.data, 512, r->in.new_password->length);
467 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
469 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
470 DEBUG(3,("samr: failed to decode password buffer\n"));
471 return NT_STATUS_WRONG_PASSWORD;
474 /* fetch the old password hashes (at least one of both has to exist) */
476 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
477 "(&(objectClass=user)(objectSid=%s))",
478 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
480 return NT_STATUS_WRONG_PASSWORD;
483 nt_status = samdb_result_passwords(mem_ctx,
484 dce_call->conn->dce_ctx->lp_ctx,
485 res[0], &oldLmHash, &oldNtHash);
486 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
487 return NT_STATUS_WRONG_PASSWORD;
490 /* Using the sid for the account as the key, set the password */
491 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
493 &new_password, /* we have plaintext */
495 oldLmHash, oldNtHash, /* Password change */
504 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
505 struct netr_LogonUasLogon *r)
507 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
514 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
515 struct netr_LogonUasLogoff *r)
517 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
522 netr_LogonSamLogon_base
524 This version of the function allows other wrappers to say 'do not check the credentials'
526 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
528 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
529 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
531 struct auth_context *auth_context;
532 struct auth_usersupplied_info *user_info;
533 struct auth_serversupplied_info *server_info;
535 static const char zeros[16];
536 struct netr_SamBaseInfo *sam;
537 struct netr_SamInfo2 *sam2;
538 struct netr_SamInfo3 *sam3;
539 struct netr_SamInfo6 *sam6;
541 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
542 NT_STATUS_HAVE_NO_MEMORY(user_info);
544 switch (r->in.logon_level) {
545 case NetlogonInteractiveInformation:
546 case NetlogonServiceInformation:
547 case NetlogonInteractiveTransitiveInformation:
548 case NetlogonServiceTransitiveInformation:
549 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
550 netlogon_creds_arcfour_crypt(creds,
551 r->in.logon->password->lmpassword.hash,
552 sizeof(r->in.logon->password->lmpassword.hash));
553 netlogon_creds_arcfour_crypt(creds,
554 r->in.logon->password->ntpassword.hash,
555 sizeof(r->in.logon->password->ntpassword.hash));
557 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
558 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
561 /* TODO: we need to deny anonymous access here */
562 nt_status = auth_context_create(mem_ctx,
563 dce_call->event_ctx, dce_call->msg_ctx,
564 dce_call->conn->dce_ctx->lp_ctx,
566 NT_STATUS_NOT_OK_RETURN(nt_status);
568 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
569 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
570 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
571 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
573 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
574 user_info->password_state = AUTH_PASSWORD_HASH;
576 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
577 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
578 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
580 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
581 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
582 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
585 case NetlogonNetworkInformation:
586 case NetlogonNetworkTransitiveInformation:
588 /* TODO: we need to deny anonymous access here */
589 nt_status = auth_context_create(mem_ctx,
590 dce_call->event_ctx, dce_call->msg_ctx,
591 dce_call->conn->dce_ctx->lp_ctx,
593 NT_STATUS_NOT_OK_RETURN(nt_status);
595 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
596 NT_STATUS_NOT_OK_RETURN(nt_status);
598 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
599 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
600 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
601 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
603 user_info->password_state = AUTH_PASSWORD_RESPONSE;
604 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
605 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
610 case NetlogonGenericInformation:
612 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
613 netlogon_creds_arcfour_crypt(creds,
614 r->in.logon->generic->data, r->in.logon->generic->length);
616 /* Using DES to verify kerberos tickets makes no sense */
617 return NT_STATUS_INVALID_PARAMETER;
620 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
622 struct dcerpc_binding_handle *irpc_handle;
623 struct kdc_check_generic_kerberos check;
624 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
625 NT_STATUS_HAVE_NO_MEMORY(generic);
626 *r->out.authoritative = 1;
628 /* TODO: Describe and deal with these flags */
631 r->out.validation->generic = generic;
633 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
637 if (irpc_handle == NULL) {
638 return NT_STATUS_NO_LOGON_SERVERS;
641 check.in.generic_request =
642 data_blob_const(r->in.logon->generic->data,
643 r->in.logon->generic->length);
645 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
648 if (!NT_STATUS_IS_OK(status)) {
651 generic->length = check.out.generic_reply.length;
652 generic->data = check.out.generic_reply.data;
656 /* Until we get an implemetnation of these other packages */
657 return NT_STATUS_INVALID_PARAMETER;
660 return NT_STATUS_INVALID_PARAMETER;
663 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
664 NT_STATUS_NOT_OK_RETURN(nt_status);
666 switch (r->in.validation_level) {
668 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
669 NT_STATUS_NOT_OK_RETURN(nt_status);
671 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
672 NT_STATUS_HAVE_NO_MEMORY(sam2);
675 /* And put into the talloc tree */
676 talloc_steal(sam2, sam);
677 r->out.validation->sam2 = sam2;
683 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
686 NT_STATUS_NOT_OK_RETURN(nt_status);
688 r->out.validation->sam3 = sam3;
694 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
697 NT_STATUS_NOT_OK_RETURN(nt_status);
699 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
700 NT_STATUS_HAVE_NO_MEMORY(sam6);
701 sam6->base = sam3->base;
703 sam6->sidcount = sam3->sidcount;
704 sam6->sids = sam3->sids;
706 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
707 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
708 sam->account_name.string, sam6->dns_domainname.string);
709 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
710 /* And put into the talloc tree */
711 talloc_steal(sam6, sam3);
713 r->out.validation->sam6 = sam6;
720 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
721 /* It appears that level 6 is not individually encrypted */
722 if ((r->in.validation_level != 6) &&
723 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
724 /* This key is sent unencrypted without the ARCFOUR flag set */
725 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
726 netlogon_creds_arcfour_crypt(creds,
728 sizeof(sam->key.key));
732 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
733 /* It appears that level 6 is not individually encrypted */
734 if ((r->in.validation_level != 6) &&
735 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
736 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
737 netlogon_creds_arcfour_crypt(creds,
739 sizeof(sam->LMSessKey.key));
741 netlogon_creds_des_encrypt_LMKey(creds,
746 *r->out.authoritative = 1;
748 /* TODO: Describe and deal with these flags */
754 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
755 struct netr_LogonSamLogonEx *r)
758 struct netlogon_creds_CredentialState *creds;
760 nt_status = schannel_get_creds_state(mem_ctx,
761 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
762 r->in.computer_name, &creds);
763 if (!NT_STATUS_IS_OK(nt_status)) {
767 if (!dce_call->conn->auth_state.auth_info ||
768 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
769 return NT_STATUS_ACCESS_DENIED;
771 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
775 netr_LogonSamLogonWithFlags
778 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
779 struct netr_LogonSamLogonWithFlags *r)
782 struct netlogon_creds_CredentialState *creds;
783 struct netr_LogonSamLogonEx r2;
785 struct netr_Authenticator *return_authenticator;
787 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
788 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
790 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
793 r->in.credential, return_authenticator,
795 NT_STATUS_NOT_OK_RETURN(nt_status);
799 r2.in.server_name = r->in.server_name;
800 r2.in.computer_name = r->in.computer_name;
801 r2.in.logon_level = r->in.logon_level;
802 r2.in.logon = r->in.logon;
803 r2.in.validation_level = r->in.validation_level;
804 r2.in.flags = r->in.flags;
805 r2.out.validation = r->out.validation;
806 r2.out.authoritative = r->out.authoritative;
807 r2.out.flags = r->out.flags;
809 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
811 r->out.return_authenticator = return_authenticator;
819 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
820 struct netr_LogonSamLogon *r)
822 struct netr_LogonSamLogonWithFlags r2;
828 r2.in.server_name = r->in.server_name;
829 r2.in.computer_name = r->in.computer_name;
830 r2.in.credential = r->in.credential;
831 r2.in.return_authenticator = r->in.return_authenticator;
832 r2.in.logon_level = r->in.logon_level;
833 r2.in.logon = r->in.logon;
834 r2.in.validation_level = r->in.validation_level;
835 r2.in.flags = &flags;
836 r2.out.validation = r->out.validation;
837 r2.out.authoritative = r->out.authoritative;
838 r2.out.flags = &flags;
840 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
842 r->out.return_authenticator = r2.out.return_authenticator;
851 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
852 struct netr_LogonSamLogoff *r)
854 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
862 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
863 struct netr_DatabaseDeltas *r)
865 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
872 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
873 struct netr_DatabaseSync2 *r)
875 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
876 return NT_STATUS_NOT_IMPLEMENTED;
883 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
884 struct netr_DatabaseSync *r)
886 struct netr_DatabaseSync2 r2;
891 r2.in.logon_server = r->in.logon_server;
892 r2.in.computername = r->in.computername;
893 r2.in.credential = r->in.credential;
894 r2.in.database_id = r->in.database_id;
895 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
896 r2.in.sync_context = r->in.sync_context;
897 r2.out.sync_context = r->out.sync_context;
898 r2.out.delta_enum_array = r->out.delta_enum_array;
899 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
901 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
910 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
911 struct netr_AccountDeltas *r)
913 /* w2k3 returns "NOT IMPLEMENTED" for this call */
914 return NT_STATUS_NOT_IMPLEMENTED;
921 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
922 struct netr_AccountSync *r)
924 /* w2k3 returns "NOT IMPLEMENTED" for this call */
925 return NT_STATUS_NOT_IMPLEMENTED;
932 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
933 struct netr_GetDcName *r)
935 const char * const attrs[] = { NULL };
936 struct ldb_context *sam_ctx;
937 struct ldb_message **res;
938 struct ldb_dn *domain_dn;
942 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
943 dce_call->conn->dce_ctx->lp_ctx,
944 dce_call->conn->auth_state.session_info);
945 if (sam_ctx == NULL) {
946 return WERR_DS_UNAVAILABLE;
949 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
951 if (domain_dn == NULL) {
952 return WERR_DS_UNAVAILABLE;
955 ret = gendb_search_dn(sam_ctx, mem_ctx,
956 domain_dn, &res, attrs);
958 return WERR_NO_SUCH_DOMAIN;
961 /* TODO: - return real IP address
962 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
964 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
965 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
966 W_ERROR_HAVE_NO_MEMORY(dcname);
968 *r->out.dcname = dcname;
976 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
977 struct netr_LogonControl2Ex *r)
979 return WERR_NOT_SUPPORTED;
986 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
987 struct netr_LogonControl *r)
989 struct netr_LogonControl2Ex r2;
992 if (r->in.level == 0x00000001) {
995 r2.in.logon_server = r->in.logon_server;
996 r2.in.function_code = r->in.function_code;
997 r2.in.level = r->in.level;
999 r2.out.query = r->out.query;
1001 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1002 } else if (r->in.level == 0x00000002) {
1003 werr = WERR_NOT_SUPPORTED;
1005 werr = WERR_UNKNOWN_LEVEL;
1015 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1016 struct netr_LogonControl2 *r)
1018 struct netr_LogonControl2Ex r2;
1023 r2.in.logon_server = r->in.logon_server;
1024 r2.in.function_code = r->in.function_code;
1025 r2.in.level = r->in.level;
1026 r2.in.data = r->in.data;
1027 r2.out.query = r->out.query;
1029 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1034 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1035 struct ldb_context *sam_ctx,
1036 struct netr_DomainTrustList *trusts,
1037 uint32_t trust_flags);
1042 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1043 struct netr_GetAnyDCName *r)
1045 struct netr_DomainTrustList *trusts;
1046 struct ldb_context *sam_ctx;
1047 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1051 *r->out.dcname = NULL;
1053 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1054 /* if the domainname parameter wasn't set assume our domain */
1055 r->in.domainname = lpcfg_workgroup(lp_ctx);
1058 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1059 dce_call->conn->auth_state.session_info);
1060 if (sam_ctx == NULL) {
1061 return WERR_DS_UNAVAILABLE;
1064 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1065 /* well we asked for a DC of our own domain */
1066 if (samdb_is_pdc(sam_ctx)) {
1067 /* we are the PDC of the specified domain */
1068 return WERR_NO_SUCH_DOMAIN;
1071 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1072 lpcfg_netbios_name(lp_ctx));
1073 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1078 /* Okay, now we have to consider the trusted domains */
1080 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1081 W_ERROR_HAVE_NO_MEMORY(trusts);
1085 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1086 NETR_TRUST_FLAG_INBOUND
1087 | NETR_TRUST_FLAG_OUTBOUND);
1088 W_ERROR_NOT_OK_RETURN(werr);
1090 for (i = 0; i < trusts->count; i++) {
1091 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1092 /* FIXME: Here we need to find a DC for the specified
1093 * trusted domain. */
1095 /* return WERR_OK; */
1096 return WERR_NO_SUCH_DOMAIN;
1100 return WERR_NO_SUCH_DOMAIN;
1107 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1108 struct netr_DatabaseRedo *r)
1110 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1115 netr_NetrEnumerateTrustedDomains
1117 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1118 struct netr_NetrEnumerateTrustedDomains *r)
1120 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1125 netr_LogonGetCapabilities
1127 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1128 struct netr_LogonGetCapabilities *r)
1130 /* we don't support AES yet */
1131 return NT_STATUS_NOT_IMPLEMENTED;
1136 netr_NETRLOGONSETSERVICEBITS
1138 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1139 struct netr_NETRLOGONSETSERVICEBITS *r)
1141 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1146 netr_LogonGetTrustRid
1148 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1149 struct netr_LogonGetTrustRid *r)
1151 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1156 netr_NETRLOGONCOMPUTESERVERDIGEST
1158 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1159 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1166 netr_NETRLOGONCOMPUTECLIENTDIGEST
1168 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1169 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1171 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1179 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1180 struct netr_DsRGetSiteName *r)
1182 struct ldb_context *sam_ctx;
1183 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1185 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1186 dce_call->conn->auth_state.session_info);
1187 if (sam_ctx == NULL) {
1188 return WERR_DS_UNAVAILABLE;
1191 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1192 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1199 fill in a netr_OneDomainInfo from a ldb search result
1201 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1202 struct loadparm_context *lp_ctx,
1203 struct ldb_context *sam_ctx,
1204 struct ldb_message *res,
1205 struct netr_OneDomainInfo *info,
1206 bool is_local, bool is_trust_list)
1210 if (is_trust_list) {
1211 /* w2k8 only fills this on trusted domains */
1212 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1213 info->trust_extension.length = 16;
1214 info->trust_extension.info->flags =
1215 NETR_TRUST_FLAG_TREEROOT |
1216 NETR_TRUST_FLAG_IN_FOREST |
1217 NETR_TRUST_FLAG_PRIMARY |
1218 NETR_TRUST_FLAG_NATIVE;
1220 info->trust_extension.info->parent_index = 0; /* should be index into array
1222 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1223 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1226 if (is_trust_list) {
1227 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1228 info->dns_forestname.string = NULL;
1230 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1231 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1232 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1233 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1237 info->domainname.string = lpcfg_workgroup(lp_ctx);
1238 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1239 info->domain_guid = samdb_result_guid(res, "objectGUID");
1240 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1242 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1243 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1244 info->domain_guid = samdb_result_guid(res, "objectGUID");
1245 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1247 if (!is_trust_list) {
1248 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1251 return NT_STATUS_OK;
1255 netr_LogonGetDomainInfo
1256 this is called as part of the ADS domain logon procedure.
1258 It has an important role in convaying details about the client, such
1259 as Operating System, Version, Service Pack etc.
1261 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1262 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1264 struct netlogon_creds_CredentialState *creds;
1265 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1266 "securityIdentifier", "trustPartner", NULL };
1267 const char * const attrs2[] = { "dNSHostName",
1268 "msDS-SupportedEncryptionTypes", NULL };
1269 const char *temp_str, *temp_str2;
1270 const char *old_dns_hostname;
1271 struct ldb_context *sam_ctx;
1272 struct ldb_message **res1, **res2, **res3, *new_msg;
1273 struct ldb_dn *workstation_dn;
1274 struct netr_DomainInformation *domain_info;
1275 struct netr_LsaPolicyInformation *lsa_policy_info;
1276 struct netr_OsVersionInfoEx *os_version;
1277 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1278 bool update_dns_hostname = true;
1282 status = dcesrv_netr_creds_server_step_check(dce_call,
1284 r->in.computer_name,
1286 r->out.return_authenticator,
1288 if (!NT_STATUS_IS_OK(status)) {
1289 DEBUG(0,(__location__ " Bad credentials - error\n"));
1291 NT_STATUS_NOT_OK_RETURN(status);
1293 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1294 dce_call->conn->dce_ctx->lp_ctx,
1295 system_session(dce_call->conn->dce_ctx->lp_ctx));
1296 if (sam_ctx == NULL) {
1297 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1300 switch (r->in.level) {
1301 case 1: /* Domain information */
1303 if (r->in.query->workstation_info == NULL) {
1304 return NT_STATUS_INVALID_PARAMETER;
1308 * Checks that the computer name parameter without possible "$"
1309 * matches as prefix with the DNS hostname in the workstation
1312 temp_str = talloc_strndup(mem_ctx,
1313 r->in.computer_name,
1314 strcspn(r->in.computer_name, "$"));
1315 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1316 temp_str2 = talloc_strndup(mem_ctx,
1317 r->in.query->workstation_info->dns_hostname,
1318 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1319 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1320 if (strcasecmp(temp_str, temp_str2) != 0) {
1321 update_dns_hostname = false;
1324 /* Prepare the workstation DN */
1325 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1326 dom_sid_string(mem_ctx, creds->sid));
1327 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1329 /* Lookup for attributes in workstation object */
1330 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1333 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1336 /* Gets the old DNS hostname */
1337 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1341 * Updates the DNS hostname when the client wishes that the
1342 * server should handle this for him
1343 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1344 * obviously only checked when we do already have a
1346 * See MS-NRPC section 3.5.4.3.9
1348 if ((old_dns_hostname != NULL) &&
1349 (r->in.query->workstation_info->workstation_flags
1350 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1351 update_dns_hostname = false;
1354 /* Gets host informations and put them into our directory */
1356 new_msg = ldb_msg_new(mem_ctx);
1357 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1359 new_msg->dn = workstation_dn;
1361 /* Sets the OS name */
1362 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1364 r->in.query->workstation_info->os_name.string);
1367 * Sets informations from "os_version". On an empty structure
1368 * the values are cleared.
1370 if (r->in.query->workstation_info->os_version.os != NULL) {
1371 os_version = &r->in.query->workstation_info->os_version.os->os;
1373 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1374 "operatingSystemServicePack",
1375 os_version->CSDVersion);
1377 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1378 "operatingSystemVersion",
1379 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1380 os_version->MajorVersion,
1381 os_version->MinorVersion,
1382 os_version->BuildNumber
1386 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1387 "operatingSystemServicePack");
1389 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1390 "operatingSystemVersion");
1394 * If the boolean "update_dns_hostname" remained true, then we
1395 * are fine to start the update.
1397 if (update_dns_hostname) {
1398 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1400 r->in.query->workstation_info->dns_hostname);
1402 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1403 "servicePrincipalName",
1404 talloc_asprintf(mem_ctx, "HOST/%s",
1405 r->in.computer_name)
1407 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1408 "servicePrincipalName",
1409 talloc_asprintf(mem_ctx, "HOST/%s",
1410 r->in.query->workstation_info->dns_hostname)
1414 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1415 DEBUG(3,("Impossible to update samdb: %s\n",
1416 ldb_errstring(sam_ctx)));
1419 talloc_free(new_msg);
1421 /* Writes back the domain information */
1423 /* We need to do two searches. The first will pull our primary
1424 domain and the second will pull any trusted domains. Our
1425 primary domain is also a "trusted" domain, so we need to
1426 put the primary domain into the lists of returned trusts as
1428 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1431 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1434 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1435 "(objectClass=trustedDomain)");
1437 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1440 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1441 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1443 ZERO_STRUCTP(domain_info);
1445 /* Informations about the local and trusted domains */
1447 status = fill_one_domain_info(mem_ctx,
1448 dce_call->conn->dce_ctx->lp_ctx,
1449 sam_ctx, res2[0], &domain_info->primary_domain,
1451 NT_STATUS_NOT_OK_RETURN(status);
1453 domain_info->trusted_domain_count = ret3 + 1;
1454 domain_info->trusted_domains = talloc_array(mem_ctx,
1455 struct netr_OneDomainInfo,
1456 domain_info->trusted_domain_count);
1457 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1459 for (i=0;i<ret3;i++) {
1460 status = fill_one_domain_info(mem_ctx,
1461 dce_call->conn->dce_ctx->lp_ctx,
1463 &domain_info->trusted_domains[i],
1465 NT_STATUS_NOT_OK_RETURN(status);
1468 status = fill_one_domain_info(mem_ctx,
1469 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1470 &domain_info->trusted_domains[i], true, true);
1471 NT_STATUS_NOT_OK_RETURN(status);
1473 /* Sets the supported encryption types */
1474 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1475 "msDS-SupportedEncryptionTypes",
1476 default_supported_enc_types);
1478 /* Other host domain informations */
1480 lsa_policy_info = talloc(mem_ctx,
1481 struct netr_LsaPolicyInformation);
1482 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1483 ZERO_STRUCTP(lsa_policy_info);
1485 domain_info->lsa_policy = *lsa_policy_info;
1487 /* The DNS hostname is only returned back when there is a chance
1489 if ((r->in.query->workstation_info->workstation_flags
1490 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1491 domain_info->dns_hostname.string = old_dns_hostname;
1493 domain_info->dns_hostname.string = NULL;
1496 domain_info->workstation_flags =
1497 r->in.query->workstation_info->workstation_flags;
1499 r->out.info->domain_info = domain_info;
1501 case 2: /* LSA policy information - not used at the moment */
1502 lsa_policy_info = talloc(mem_ctx,
1503 struct netr_LsaPolicyInformation);
1504 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1505 ZERO_STRUCTP(lsa_policy_info);
1507 r->out.info->lsa_policy_info = lsa_policy_info;
1510 return NT_STATUS_INVALID_LEVEL;
1514 return NT_STATUS_OK;
1520 netr_ServerPasswordGet
1522 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1523 struct netr_ServerPasswordGet *r)
1525 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1530 netr_NETRLOGONSENDTOSAM
1532 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1533 struct netr_NETRLOGONSENDTOSAM *r)
1535 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1540 netr_DsRGetDCNameEx2
1542 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1543 TALLOC_CTX *mem_ctx,
1544 struct netr_DsRGetDCNameEx2 *r)
1546 struct ldb_context *sam_ctx;
1547 struct netr_DsRGetDCNameInfo *info;
1548 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1549 const struct tsocket_address *remote_address;
1551 const char *server_site_name;
1553 struct netlogon_samlogon_response response;
1556 ZERO_STRUCTP(r->out.info);
1558 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1559 dce_call->conn->auth_state.session_info);
1560 if (sam_ctx == NULL) {
1561 return WERR_DS_UNAVAILABLE;
1564 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1565 if (tsocket_address_is_inet(remote_address, "ip")) {
1566 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1567 W_ERROR_HAVE_NO_MEMORY(addr);
1570 /* "server_unc" is ignored by w2k3 */
1572 /* Proof server site parameter "site_name" if it was specified */
1573 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1574 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1575 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1576 server_site_name) != 0)) {
1577 return WERR_NO_SUCH_DOMAIN;
1580 /* TODO: the flags are ignored for now */
1582 guid_str = r->in.domain_guid != NULL ?
1583 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1585 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1589 r->in.client_account,
1591 NETLOGON_NT_VERSION_5EX_WITH_IP,
1592 lp_ctx, &response, true);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 return ntstatus_to_werror(status);
1597 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1598 W_ERROR_HAVE_NO_MEMORY(info);
1599 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1600 response.data.nt5_ex.pdc_dns_name);
1601 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1602 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1603 response.data.nt5_ex.sockaddr.pdc_ip);
1604 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1605 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1606 info->domain_guid = response.data.nt5_ex.domain_uuid;
1607 info->domain_name = response.data.nt5_ex.dns_domain;
1608 info->forest_name = response.data.nt5_ex.forest;
1609 info->dc_flags = response.data.nt5_ex.server_type;
1610 info->dc_site_name = response.data.nt5_ex.server_site;
1611 info->client_site_name = response.data.nt5_ex.client_site;
1613 *r->out.info = info;
1621 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1622 struct netr_DsRGetDCNameEx *r)
1624 struct netr_DsRGetDCNameEx2 r2;
1629 r2.in.server_unc = r->in.server_unc;
1630 r2.in.client_account = NULL;
1632 r2.in.domain_guid = r->in.domain_guid;
1633 r2.in.domain_name = r->in.domain_name;
1634 r2.in.site_name = r->in.site_name;
1635 r2.in.flags = r->in.flags;
1636 r2.out.info = r->out.info;
1638 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1646 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647 struct netr_DsRGetDCName *r)
1649 struct netr_DsRGetDCNameEx2 r2;
1654 r2.in.server_unc = r->in.server_unc;
1655 r2.in.client_account = NULL;
1657 r2.in.domain_name = r->in.domain_name;
1658 r2.in.domain_guid = r->in.domain_guid;
1660 r2.in.site_name = NULL; /* should fill in from site GUID */
1661 r2.in.flags = r->in.flags;
1662 r2.out.info = r->out.info;
1664 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1669 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1671 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1672 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1674 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1679 netr_NetrEnumerateTrustedDomainsEx
1681 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1682 struct netr_NetrEnumerateTrustedDomainsEx *r)
1684 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1689 netr_DsRAddressToSitenamesExW
1691 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1692 struct netr_DsRAddressToSitenamesExW *r)
1694 struct ldb_context *sam_ctx;
1695 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1696 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1697 sa_family_t sin_family;
1698 struct sockaddr_in *addr;
1700 struct sockaddr_in6 *addr6;
1701 char addr_str[INET6_ADDRSTRLEN];
1703 char addr_str[INET_ADDRSTRLEN];
1709 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1710 dce_call->conn->auth_state.session_info);
1711 if (sam_ctx == NULL) {
1712 return WERR_DS_UNAVAILABLE;
1715 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1716 W_ERROR_HAVE_NO_MEMORY(ctr);
1720 ctr->count = r->in.count;
1721 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1722 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1723 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1724 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1726 for (i=0; i<ctr->count; i++) {
1727 ctr->sitename[i].string = NULL;
1728 ctr->subnetname[i].string = NULL;
1730 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1733 /* The first two byte of the buffer are reserved for the
1734 * "sin_family" but for now only the first one is used. */
1735 sin_family = r->in.addresses[i].buffer[0];
1737 switch (sin_family) {
1739 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1742 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1743 res = inet_ntop(AF_INET, &addr->sin_addr,
1744 addr_str, sizeof(addr_str));
1748 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1751 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1752 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1753 addr_str, sizeof(addr_str));
1764 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1768 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1769 ctr->subnetname[i].string = subnet_name;
1777 netr_DsRAddressToSitenamesW
1779 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1780 struct netr_DsRAddressToSitenamesW *r)
1782 struct netr_DsRAddressToSitenamesExW r2;
1783 struct netr_DsRAddressToSitenamesWCtr *ctr;
1789 r2.in.server_name = r->in.server_name;
1790 r2.in.count = r->in.count;
1791 r2.in.addresses = r->in.addresses;
1793 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1794 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1796 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1797 W_ERROR_HAVE_NO_MEMORY(ctr);
1801 ctr->count = r->in.count;
1802 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1803 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1805 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1807 for (i=0; i<ctr->count; i++) {
1808 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1816 netr_DsrGetDcSiteCoverageW
1818 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1819 struct netr_DsrGetDcSiteCoverageW *r)
1821 struct ldb_context *sam_ctx;
1822 struct DcSitesCtr *ctr;
1823 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1825 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1826 dce_call->conn->auth_state.session_info);
1827 if (sam_ctx == NULL) {
1828 return WERR_DS_UNAVAILABLE;
1831 ctr = talloc(mem_ctx, struct DcSitesCtr);
1832 W_ERROR_HAVE_NO_MEMORY(ctr);
1836 /* For now only return our default site */
1838 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1839 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1840 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1841 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1847 #define GET_CHECK_STR(dest, mem, msg, attr) \
1850 s = samdb_result_string(msg, attr, NULL); \
1852 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1853 "without flatname\n", \
1854 ldb_dn_get_linearized(msg->dn))); \
1857 dest = talloc_strdup(mem, s); \
1858 W_ERROR_HAVE_NO_MEMORY(dest); \
1862 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1863 struct ldb_context *sam_ctx,
1864 struct netr_DomainTrustList *trusts,
1865 uint32_t trust_flags)
1867 struct ldb_dn *system_dn;
1868 struct ldb_message **dom_res = NULL;
1869 const char *trust_attrs[] = { "flatname", "trustPartner",
1870 "securityIdentifier", "trustDirection",
1871 "trustType", "trustAttributes", NULL };
1876 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1877 NETR_TRUST_FLAG_OUTBOUND))) {
1878 return WERR_INVALID_FLAGS;
1881 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1882 ldb_get_default_basedn(sam_ctx),
1883 "(&(objectClass=container)(cn=System))");
1885 return WERR_GENERAL_FAILURE;
1888 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1889 &dom_res, trust_attrs,
1890 "(objectclass=trustedDomain)");
1892 for (i = 0; i < ret; i++) {
1893 unsigned int trust_dir;
1896 trust_dir = samdb_result_uint(dom_res[i],
1897 "trustDirection", 0);
1899 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1900 flags |= NETR_TRUST_FLAG_INBOUND;
1902 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1903 flags |= NETR_TRUST_FLAG_OUTBOUND;
1906 if (!(flags & trust_flags)) {
1907 /* this trust direction was not requested */
1912 trusts->array = talloc_realloc(trusts, trusts->array,
1913 struct netr_DomainTrust,
1915 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1917 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1918 dom_res[i], "flatname");
1919 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1920 dom_res[i], "trustPartner");
1922 trusts->array[n].trust_flags = flags;
1923 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1924 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1925 /* TODO: find if we have parent in the list */
1926 trusts->array[n].parent_index = 0;
1929 trusts->array[n].trust_type =
1930 samdb_result_uint(dom_res[i],
1932 trusts->array[n].trust_attributes =
1933 samdb_result_uint(dom_res[i],
1934 "trustAttributes", 0);
1936 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1937 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1938 struct dom_sid zero_sid;
1939 ZERO_STRUCT(zero_sid);
1940 trusts->array[n].sid =
1941 dom_sid_dup(trusts, &zero_sid);
1943 trusts->array[n].sid =
1944 samdb_result_dom_sid(trusts, dom_res[i],
1945 "securityIdentifier");
1947 trusts->array[n].guid = GUID_zero();
1949 trusts->count = n + 1;
1952 talloc_free(dom_res);
1957 netr_DsrEnumerateDomainTrusts
1959 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1960 TALLOC_CTX *mem_ctx,
1961 struct netr_DsrEnumerateDomainTrusts *r)
1963 struct netr_DomainTrustList *trusts;
1964 struct ldb_context *sam_ctx;
1966 struct ldb_message **dom_res;
1967 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1968 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1969 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
1973 if (r->in.trust_flags & 0xFFFFFE00) {
1974 return WERR_INVALID_FLAGS;
1977 /* TODO: turn to hard check once we are sure this is 100% correct */
1978 if (!r->in.server_name) {
1979 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1980 "But received NULL!\n", dnsdomain));
1982 p = strchr(r->in.server_name, '.');
1984 DEBUG(3, ("Invalid domain! Expected name in domain "
1985 "[%s]. But received [%s]!\n",
1986 dnsdomain, r->in.server_name));
1987 p = r->in.server_name;
1991 if (strcasecmp(p, dnsdomain)) {
1992 DEBUG(3, ("Invalid domain! Expected name in domain "
1993 "[%s]. But received [%s]!\n",
1994 dnsdomain, r->in.server_name));
1998 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1999 W_ERROR_HAVE_NO_MEMORY(trusts);
2002 r->out.trusts = trusts;
2004 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2005 dce_call->conn->auth_state.session_info);
2006 if (sam_ctx == NULL) {
2007 return WERR_GENERAL_FAILURE;
2010 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2011 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2013 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2014 trusts, r->in.trust_flags);
2015 W_ERROR_NOT_OK_RETURN(werr);
2018 /* NOTE: we currently are always the root of the forest */
2019 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2020 uint32_t n = trusts->count;
2022 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2023 &dom_res, dom_attrs);
2025 return WERR_GENERAL_FAILURE;
2028 trusts->count = n + 1;
2029 trusts->array = talloc_realloc(trusts, trusts->array,
2030 struct netr_DomainTrust,
2032 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2034 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2035 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2036 trusts->array[n].trust_flags =
2037 NETR_TRUST_FLAG_NATIVE |
2038 NETR_TRUST_FLAG_TREEROOT |
2039 NETR_TRUST_FLAG_IN_FOREST |
2040 NETR_TRUST_FLAG_PRIMARY;
2041 /* we are always the root domain for now */
2042 trusts->array[n].parent_index = 0;
2043 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2044 trusts->array[n].trust_attributes = 0;
2045 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2048 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2050 talloc_free(dom_res);
2058 netr_DsrDeregisterDNSHostRecords
2060 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2061 struct netr_DsrDeregisterDNSHostRecords *r)
2063 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2068 netr_ServerTrustPasswordsGet
2070 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2071 struct netr_ServerTrustPasswordsGet *r)
2073 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2077 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2078 struct ldb_context *sam_ctx,
2079 struct loadparm_context *lp_ctx,
2080 struct lsa_ForestTrustInformation *info)
2082 struct lsa_ForestTrustDomainInfo *domain_info;
2083 struct lsa_ForestTrustRecord *e;
2084 struct ldb_message **dom_res;
2085 const char * const dom_attrs[] = { "objectSid", NULL };
2088 /* we need to provide 2 entries:
2089 * 1. the Root Forest name
2090 * 2. the Domain Information
2094 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2095 W_ERROR_HAVE_NO_MEMORY(info->entries);
2097 /* Forest root info */
2098 e = talloc(info, struct lsa_ForestTrustRecord);
2099 W_ERROR_HAVE_NO_MEMORY(e);
2102 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2103 e->time = 0; /* so far always 0 in trces. */
2104 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2106 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2108 info->entries[0] = e;
2111 e = talloc(info, struct lsa_ForestTrustRecord);
2112 W_ERROR_HAVE_NO_MEMORY(e);
2114 /* get our own domain info */
2115 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2117 return WERR_GENERAL_FAILURE;
2120 /* TODO: check if disabled and set flags accordingly */
2122 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2123 e->time = 0; /* so far always 0 in traces. */
2125 domain_info = &e->forest_trust_data.domain_info;
2126 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2128 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2129 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2131 info->entries[1] = e;
2133 talloc_free(dom_res);
2139 netr_DsRGetForestTrustInformation
2141 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2142 TALLOC_CTX *mem_ctx,
2143 struct netr_DsRGetForestTrustInformation *r)
2145 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2146 struct lsa_ForestTrustInformation *info, **info_ptr;
2147 struct ldb_context *sam_ctx;
2150 if (r->in.flags & 0xFFFFFFFE) {
2151 return WERR_INVALID_FLAGS;
2154 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2155 dce_call->conn->auth_state.session_info);
2156 if (sam_ctx == NULL) {
2157 return WERR_GENERAL_FAILURE;
2160 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2161 if (!samdb_is_pdc(sam_ctx)) {
2162 return WERR_NERR_NOTPRIMARY;
2165 if (r->in.trusted_domain_name == NULL) {
2166 return WERR_INVALID_FLAGS;
2169 /* TODO: establish an schannel connection with
2170 * r->in.trusted_domain_name and perform a
2171 * netr_GetForestTrustInformation call against it */
2173 /* for now return not implementd */
2174 return WERR_CALL_NOT_IMPLEMENTED;
2177 /* TODO: check r->in.server_name is our name */
2179 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2180 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2182 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2183 W_ERROR_HAVE_NO_MEMORY(info);
2185 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2186 W_ERROR_NOT_OK_RETURN(werr);
2189 r->out.forest_trust_info = info_ptr;
2196 netr_GetForestTrustInformation
2198 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2199 TALLOC_CTX *mem_ctx,
2200 struct netr_GetForestTrustInformation *r)
2202 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2203 struct netlogon_creds_CredentialState *creds;
2204 struct lsa_ForestTrustInformation *info, **info_ptr;
2205 struct ldb_context *sam_ctx;
2209 status = dcesrv_netr_creds_server_step_check(dce_call,
2211 r->in.computer_name,
2213 r->out.return_authenticator,
2215 if (!NT_STATUS_IS_OK(status)) {
2219 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2220 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2221 return NT_STATUS_NOT_IMPLEMENTED;
2224 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2225 dce_call->conn->auth_state.session_info);
2226 if (sam_ctx == NULL) {
2227 return NT_STATUS_UNSUCCESSFUL;
2230 /* TODO: check r->in.server_name is our name */
2232 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2234 return NT_STATUS_NO_MEMORY;
2236 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2238 return NT_STATUS_NO_MEMORY;
2241 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2242 if (!W_ERROR_IS_OK(werr)) {
2243 return werror_to_ntstatus(werr);
2247 r->out.forest_trust_info = info_ptr;
2249 return NT_STATUS_OK;
2254 netr_ServerGetTrustInfo
2256 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2257 struct netr_ServerGetTrustInfo *r)
2259 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2265 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2266 struct netr_Unused47 *r)
2268 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2272 netr_DsrUpdateReadOnlyServerDnsRecords
2274 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2275 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2277 NDR_PRINT_FUNCTION_DEBUG(netr_DsrUpdateReadOnlyServerDnsRecords, NDR_IN, r);
2278 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2282 /* include the generated boilerplate */
2283 #include "librpc/gen_ndr/ndr_netlogon_s.c"