s4:dcesrv_netr_GetAnyDCName - improve the call according to the MS-NRPC documentation
[Samba/ekacnet.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobc5a9b302ac62df260f959017997e5d5523a9f6e1
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc.h"
35 #include "cldap_server/cldap_server.h"
36 #include "lib/socket/socket.h"
38 struct netlogon_server_pipe_state {
39 struct netr_Credential client_challenge;
40 struct netr_Credential server_challenge;
43 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
44 struct netr_ServerReqChallenge *r)
46 struct netlogon_server_pipe_state *pipe_state =
47 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
49 ZERO_STRUCTP(r->out.return_credentials);
51 /* destroyed on pipe shutdown */
53 if (pipe_state) {
54 talloc_free(pipe_state);
55 dce_call->context->private_data = NULL;
58 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
59 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
61 pipe_state->client_challenge = *r->in.credentials;
63 generate_random_buffer(pipe_state->server_challenge.data,
64 sizeof(pipe_state->server_challenge.data));
66 *r->out.return_credentials = pipe_state->server_challenge;
68 dce_call->context->private_data = pipe_state;
70 return NT_STATUS_OK;
73 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
74 struct netr_ServerAuthenticate3 *r)
76 struct netlogon_server_pipe_state *pipe_state =
77 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
78 struct netlogon_creds_CredentialState *creds;
79 struct ldb_context *sam_ctx;
80 struct samr_Password *mach_pwd;
81 uint32_t user_account_control;
82 int num_records;
83 struct ldb_message **msgs;
84 NTSTATUS nt_status;
85 const char *attrs[] = {"unicodePwd", "userAccountControl",
86 "objectSid", NULL};
88 const char *trust_dom_attrs[] = {"flatname", NULL};
89 const char *account_name;
91 ZERO_STRUCTP(r->out.return_credentials);
92 *r->out.rid = 0;
95 * According to Microsoft (see bugid #6099)
96 * Windows 7 looks at the negotiate_flags
97 * returned in this structure *even if the
98 * call fails with access denied!
100 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
101 NETLOGON_NEG_PERSISTENT_SAMREPL |
102 NETLOGON_NEG_ARCFOUR |
103 NETLOGON_NEG_PROMOTION_COUNT |
104 NETLOGON_NEG_CHANGELOG_BDC |
105 NETLOGON_NEG_FULL_SYNC_REPL |
106 NETLOGON_NEG_MULTIPLE_SIDS |
107 NETLOGON_NEG_REDO |
108 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
109 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
110 NETLOGON_NEG_GENERIC_PASSTHROUGH |
111 NETLOGON_NEG_CONCURRENT_RPC |
112 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
113 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
114 NETLOGON_NEG_STRONG_KEYS |
115 NETLOGON_NEG_TRANSITIVE_TRUSTS |
116 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
117 NETLOGON_NEG_PASSWORD_SET2 |
118 NETLOGON_NEG_GETDOMAININFO |
119 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
120 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
121 NETLOGON_NEG_RODC_PASSTHROUGH |
122 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
123 NETLOGON_NEG_AUTHENTICATED_RPC;
125 if (!pipe_state) {
126 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
127 return NT_STATUS_ACCESS_DENIED;
130 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
131 system_session(dce_call->conn->dce_ctx->lp_ctx));
132 if (sam_ctx == NULL) {
133 return NT_STATUS_INVALID_SYSTEM_SERVICE;
136 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
137 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
138 const char *flatname;
139 if (!encoded_account) {
140 return NT_STATUS_NO_MEMORY;
143 /* Kill the trailing dot */
144 if (encoded_account[strlen(encoded_account)-1] == '.') {
145 encoded_account[strlen(encoded_account)-1] = '\0';
148 /* pull the user attributes */
149 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
150 trust_dom_attrs,
151 "(&(trustPartner=%s)(objectclass=trustedDomain))",
152 encoded_account);
154 if (num_records == 0) {
155 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
156 encoded_account));
157 return NT_STATUS_ACCESS_DENIED;
160 if (num_records > 1) {
161 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
162 return NT_STATUS_INTERNAL_DB_CORRUPTION;
165 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
166 if (!flatname) {
167 /* No flatname for this trust - we can't proceed */
168 return NT_STATUS_ACCESS_DENIED;
170 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
172 if (!account_name) {
173 return NT_STATUS_NO_MEMORY;
176 } else {
177 account_name = r->in.account_name;
180 /* pull the user attributes */
181 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
182 "(&(sAMAccountName=%s)(objectclass=user))",
183 ldb_binary_encode_string(mem_ctx, account_name));
185 if (num_records == 0) {
186 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
187 r->in.account_name));
188 return NT_STATUS_ACCESS_DENIED;
191 if (num_records > 1) {
192 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
193 return NT_STATUS_INTERNAL_DB_CORRUPTION;
196 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
198 if (user_account_control & UF_ACCOUNTDISABLE) {
199 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
200 return NT_STATUS_ACCESS_DENIED;
203 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
204 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
205 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
206 return NT_STATUS_ACCESS_DENIED;
208 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
209 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
210 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
211 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
213 return NT_STATUS_ACCESS_DENIED;
215 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
216 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
217 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
218 return NT_STATUS_ACCESS_DENIED;
220 } else {
221 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
222 r->in.secure_channel_type));
223 return NT_STATUS_ACCESS_DENIED;
226 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
227 "objectSid", 0);
229 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
230 if (mach_pwd == NULL) {
231 return NT_STATUS_ACCESS_DENIED;
234 creds = netlogon_creds_server_init(mem_ctx,
235 r->in.account_name,
236 r->in.computer_name,
237 r->in.secure_channel_type,
238 &pipe_state->client_challenge,
239 &pipe_state->server_challenge,
240 mach_pwd,
241 r->in.credentials,
242 r->out.return_credentials,
243 *r->in.negotiate_flags);
245 if (!creds) {
246 return NT_STATUS_ACCESS_DENIED;
249 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
251 nt_status = schannel_save_creds_state(mem_ctx,
252 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
253 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
254 creds);
256 return nt_status;
259 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
260 struct netr_ServerAuthenticate *r)
262 struct netr_ServerAuthenticate3 a;
263 uint32_t rid;
264 /* TODO:
265 * negotiate_flags is used as an [in] parameter
266 * so it need to be initialised.
268 * (I think ... = 0; seems wrong here --metze)
270 uint32_t negotiate_flags_in = 0;
271 uint32_t negotiate_flags_out = 0;
273 a.in.server_name = r->in.server_name;
274 a.in.account_name = r->in.account_name;
275 a.in.secure_channel_type = r->in.secure_channel_type;
276 a.in.computer_name = r->in.computer_name;
277 a.in.credentials = r->in.credentials;
278 a.in.negotiate_flags = &negotiate_flags_in;
280 a.out.return_credentials = r->out.return_credentials;
281 a.out.rid = &rid;
282 a.out.negotiate_flags = &negotiate_flags_out;
284 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
287 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
288 struct netr_ServerAuthenticate2 *r)
290 struct netr_ServerAuthenticate3 r3;
291 uint32_t rid = 0;
293 r3.in.server_name = r->in.server_name;
294 r3.in.account_name = r->in.account_name;
295 r3.in.secure_channel_type = r->in.secure_channel_type;
296 r3.in.computer_name = r->in.computer_name;
297 r3.in.credentials = r->in.credentials;
298 r3.out.return_credentials = r->out.return_credentials;
299 r3.in.negotiate_flags = r->in.negotiate_flags;
300 r3.out.negotiate_flags = r->out.negotiate_flags;
301 r3.out.rid = &rid;
303 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
307 * NOTE: The following functions are nearly identical to the ones available in
308 * source3/rpc_server/srv_nelog_nt.c
309 * The reason we keep 2 copies is that they use different structures to
310 * represent the auth_info and the decrpc pipes.
314 * If schannel is required for this call test that it actually is available.
316 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
317 const char *computer_name,
318 bool integrity, bool privacy)
321 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
322 if (!privacy && !integrity) {
323 return NT_STATUS_OK;
326 if ((!privacy && integrity) &&
327 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
328 return NT_STATUS_OK;
331 if ((privacy || integrity) &&
332 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
333 return NT_STATUS_OK;
337 /* test didn't pass */
338 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
339 computer_name));
341 return NT_STATUS_ACCESS_DENIED;
344 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
345 TALLOC_CTX *mem_ctx,
346 const char *computer_name,
347 struct netr_Authenticator *received_authenticator,
348 struct netr_Authenticator *return_authenticator,
349 struct netlogon_creds_CredentialState **creds_out)
351 NTSTATUS nt_status;
352 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
353 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
355 if (schannel_global_required) {
356 nt_status = schannel_check_required(auth_info,
357 computer_name,
358 true, false);
359 if (!NT_STATUS_IS_OK(nt_status)) {
360 return nt_status;
364 nt_status = schannel_check_creds_state(mem_ctx,
365 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
366 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
367 computer_name,
368 received_authenticator,
369 return_authenticator,
370 creds_out);
371 return nt_status;
375 Change the machine account password for the currently connected
376 client. Supplies only the NT#.
379 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380 struct netr_ServerPasswordSet *r)
382 struct netlogon_creds_CredentialState *creds;
383 struct ldb_context *sam_ctx;
384 NTSTATUS nt_status;
386 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
387 mem_ctx,
388 r->in.computer_name,
389 r->in.credential, r->out.return_authenticator,
390 &creds);
391 NT_STATUS_NOT_OK_RETURN(nt_status);
393 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));
394 if (sam_ctx == NULL) {
395 return NT_STATUS_INVALID_SYSTEM_SERVICE;
398 netlogon_creds_des_decrypt(creds, r->in.new_password);
400 /* Using the sid for the account as the key, set the password */
401 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
402 creds->sid,
403 NULL, /* Don't have plaintext */
404 NULL, r->in.new_password,
405 true, /* Password change */
406 NULL, NULL);
407 return nt_status;
411 Change the machine account password for the currently connected
412 client. Supplies new plaintext.
414 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
415 struct netr_ServerPasswordSet2 *r)
417 struct netlogon_creds_CredentialState *creds;
418 struct ldb_context *sam_ctx;
419 NTSTATUS nt_status;
420 DATA_BLOB new_password;
422 struct samr_CryptPassword password_buf;
424 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
425 mem_ctx,
426 r->in.computer_name,
427 r->in.credential, r->out.return_authenticator,
428 &creds);
429 NT_STATUS_NOT_OK_RETURN(nt_status);
431 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));
432 if (sam_ctx == NULL) {
433 return NT_STATUS_INVALID_SYSTEM_SERVICE;
436 memcpy(password_buf.data, r->in.new_password->data, 512);
437 SIVAL(password_buf.data, 512, r->in.new_password->length);
438 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
440 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
441 DEBUG(3,("samr: failed to decode password buffer\n"));
442 return NT_STATUS_WRONG_PASSWORD;
445 /* Using the sid for the account as the key, set the password */
446 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
447 creds->sid,
448 &new_password, /* we have plaintext */
449 NULL, NULL,
450 true, /* Password change */
451 NULL, NULL);
452 return nt_status;
457 netr_LogonUasLogon
459 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
460 struct netr_LogonUasLogon *r)
462 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
467 netr_LogonUasLogoff
469 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
470 struct netr_LogonUasLogoff *r)
472 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
477 netr_LogonSamLogon_base
479 This version of the function allows other wrappers to say 'do not check the credentials'
481 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
483 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
484 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
486 struct auth_context *auth_context;
487 struct auth_usersupplied_info *user_info;
488 struct auth_serversupplied_info *server_info;
489 NTSTATUS nt_status;
490 static const char zeros[16];
491 struct netr_SamBaseInfo *sam;
492 struct netr_SamInfo2 *sam2;
493 struct netr_SamInfo3 *sam3;
494 struct netr_SamInfo6 *sam6;
496 user_info = talloc(mem_ctx, struct auth_usersupplied_info);
497 NT_STATUS_HAVE_NO_MEMORY(user_info);
499 user_info->flags = 0;
500 user_info->mapped_state = false;
501 user_info->remote_host = NULL;
503 switch (r->in.logon_level) {
504 case NetlogonInteractiveInformation:
505 case NetlogonServiceInformation:
506 case NetlogonInteractiveTransitiveInformation:
507 case NetlogonServiceTransitiveInformation:
508 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
509 netlogon_creds_arcfour_crypt(creds,
510 r->in.logon->password->lmpassword.hash,
511 sizeof(r->in.logon->password->lmpassword.hash));
512 netlogon_creds_arcfour_crypt(creds,
513 r->in.logon->password->ntpassword.hash,
514 sizeof(r->in.logon->password->ntpassword.hash));
515 } else {
516 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
517 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
520 /* TODO: we need to deny anonymous access here */
521 nt_status = auth_context_create(mem_ctx,
522 dce_call->event_ctx, dce_call->msg_ctx,
523 dce_call->conn->dce_ctx->lp_ctx,
524 &auth_context);
525 NT_STATUS_NOT_OK_RETURN(nt_status);
527 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
528 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
529 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
530 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
532 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
533 user_info->password_state = AUTH_PASSWORD_HASH;
535 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
536 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
537 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
539 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
540 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
541 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
543 break;
544 case NetlogonNetworkInformation:
545 case NetlogonNetworkTransitiveInformation:
547 /* TODO: we need to deny anonymous access here */
548 nt_status = auth_context_create(mem_ctx,
549 dce_call->event_ctx, dce_call->msg_ctx,
550 dce_call->conn->dce_ctx->lp_ctx,
551 &auth_context);
552 NT_STATUS_NOT_OK_RETURN(nt_status);
554 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
555 NT_STATUS_NOT_OK_RETURN(nt_status);
557 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
558 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
559 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
560 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
562 user_info->password_state = AUTH_PASSWORD_RESPONSE;
563 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
564 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
566 break;
569 case NetlogonGenericInformation:
571 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
572 netlogon_creds_arcfour_crypt(creds,
573 r->in.logon->generic->data, r->in.logon->generic->length);
574 } else {
575 /* Using DES to verify kerberos tickets makes no sense */
576 return NT_STATUS_INVALID_PARAMETER;
579 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
580 NTSTATUS status;
581 struct server_id *kdc;
582 struct kdc_check_generic_kerberos check;
583 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
584 NT_STATUS_HAVE_NO_MEMORY(generic);
585 *r->out.authoritative = 1;
587 /* TODO: Describe and deal with these flags */
588 *r->out.flags = 0;
590 r->out.validation->generic = generic;
592 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
593 if ((kdc == NULL) || (kdc[0].id == 0)) {
594 return NT_STATUS_NO_LOGON_SERVERS;
597 check.in.generic_request =
598 data_blob_const(r->in.logon->generic->data,
599 r->in.logon->generic->length);
601 status = irpc_call(dce_call->msg_ctx, kdc[0],
602 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
603 &check, mem_ctx);
604 if (!NT_STATUS_IS_OK(status)) {
605 return status;
607 generic->length = check.out.generic_reply.length;
608 generic->data = check.out.generic_reply.data;
609 return NT_STATUS_OK;
612 /* Until we get an implemetnation of these other packages */
613 return NT_STATUS_INVALID_PARAMETER;
615 default:
616 return NT_STATUS_INVALID_PARAMETER;
619 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
620 NT_STATUS_NOT_OK_RETURN(nt_status);
622 switch (r->in.validation_level) {
623 case 2:
624 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
625 NT_STATUS_NOT_OK_RETURN(nt_status);
627 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
628 NT_STATUS_HAVE_NO_MEMORY(sam2);
629 sam2->base = *sam;
631 /* And put into the talloc tree */
632 talloc_steal(sam2, sam);
633 r->out.validation->sam2 = sam2;
635 sam = &sam2->base;
636 break;
638 case 3:
639 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
640 server_info,
641 &sam3);
642 NT_STATUS_NOT_OK_RETURN(nt_status);
644 r->out.validation->sam3 = sam3;
646 sam = &sam3->base;
647 break;
649 case 6:
650 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
651 server_info,
652 &sam3);
653 NT_STATUS_NOT_OK_RETURN(nt_status);
655 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
656 NT_STATUS_HAVE_NO_MEMORY(sam6);
657 sam6->base = sam3->base;
658 sam = &sam6->base;
659 sam6->sidcount = sam3->sidcount;
660 sam6->sids = sam3->sids;
662 sam6->dns_domainname.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
663 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
664 sam->account_name.string, sam6->dns_domainname.string);
665 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
666 /* And put into the talloc tree */
667 talloc_steal(sam6, sam3);
669 r->out.validation->sam6 = sam6;
670 break;
672 default:
673 break;
676 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
677 /* It appears that level 6 is not individually encrypted */
678 if ((r->in.validation_level != 6) &&
679 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
680 /* This key is sent unencrypted without the ARCFOUR flag set */
681 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
682 netlogon_creds_arcfour_crypt(creds,
683 sam->key.key,
684 sizeof(sam->key.key));
688 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
689 /* It appears that level 6 is not individually encrypted */
690 if ((r->in.validation_level != 6) &&
691 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
692 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
693 netlogon_creds_arcfour_crypt(creds,
694 sam->LMSessKey.key,
695 sizeof(sam->LMSessKey.key));
696 } else {
697 netlogon_creds_des_encrypt_LMKey(creds,
698 &sam->LMSessKey);
702 *r->out.authoritative = 1;
704 /* TODO: Describe and deal with these flags */
705 *r->out.flags = 0;
707 return NT_STATUS_OK;
710 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
711 struct netr_LogonSamLogonEx *r)
713 NTSTATUS nt_status;
714 struct netlogon_creds_CredentialState *creds;
716 nt_status = schannel_get_creds_state(mem_ctx,
717 lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
718 lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
719 r->in.computer_name, &creds);
720 if (!NT_STATUS_IS_OK(nt_status)) {
721 return nt_status;
724 if (!dce_call->conn->auth_state.auth_info ||
725 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
726 return NT_STATUS_ACCESS_DENIED;
728 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
732 netr_LogonSamLogonWithFlags
735 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
736 struct netr_LogonSamLogonWithFlags *r)
738 NTSTATUS nt_status;
739 struct netlogon_creds_CredentialState *creds;
740 struct netr_LogonSamLogonEx r2;
742 struct netr_Authenticator *return_authenticator;
744 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
745 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
747 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
748 mem_ctx,
749 r->in.computer_name,
750 r->in.credential, return_authenticator,
751 &creds);
752 NT_STATUS_NOT_OK_RETURN(nt_status);
754 ZERO_STRUCT(r2);
756 r2.in.server_name = r->in.server_name;
757 r2.in.computer_name = r->in.computer_name;
758 r2.in.logon_level = r->in.logon_level;
759 r2.in.logon = r->in.logon;
760 r2.in.validation_level = r->in.validation_level;
761 r2.in.flags = r->in.flags;
762 r2.out.validation = r->out.validation;
763 r2.out.authoritative = r->out.authoritative;
764 r2.out.flags = r->out.flags;
766 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
768 r->out.return_authenticator = return_authenticator;
770 return nt_status;
774 netr_LogonSamLogon
776 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
777 struct netr_LogonSamLogon *r)
779 struct netr_LogonSamLogonWithFlags r2;
780 uint32_t flags = 0;
781 NTSTATUS status;
783 ZERO_STRUCT(r2);
785 r2.in.server_name = r->in.server_name;
786 r2.in.computer_name = r->in.computer_name;
787 r2.in.credential = r->in.credential;
788 r2.in.return_authenticator = r->in.return_authenticator;
789 r2.in.logon_level = r->in.logon_level;
790 r2.in.logon = r->in.logon;
791 r2.in.validation_level = r->in.validation_level;
792 r2.in.flags = &flags;
793 r2.out.validation = r->out.validation;
794 r2.out.authoritative = r->out.authoritative;
795 r2.out.flags = &flags;
797 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
799 r->out.return_authenticator = r2.out.return_authenticator;
801 return status;
806 netr_LogonSamLogoff
808 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
809 struct netr_LogonSamLogoff *r)
811 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
817 netr_DatabaseDeltas
819 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
820 struct netr_DatabaseDeltas *r)
822 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
827 netr_DatabaseSync2
829 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830 struct netr_DatabaseSync2 *r)
832 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
833 return NT_STATUS_NOT_IMPLEMENTED;
838 netr_DatabaseSync
840 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841 struct netr_DatabaseSync *r)
843 struct netr_DatabaseSync2 r2;
844 NTSTATUS status;
846 ZERO_STRUCT(r2);
848 r2.in.logon_server = r->in.logon_server;
849 r2.in.computername = r->in.computername;
850 r2.in.credential = r->in.credential;
851 r2.in.database_id = r->in.database_id;
852 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
853 r2.in.sync_context = r->in.sync_context;
854 r2.out.sync_context = r->out.sync_context;
855 r2.out.delta_enum_array = r->out.delta_enum_array;
856 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
858 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
860 return status;
865 netr_AccountDeltas
867 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
868 struct netr_AccountDeltas *r)
870 /* w2k3 returns "NOT IMPLEMENTED" for this call */
871 return NT_STATUS_NOT_IMPLEMENTED;
876 netr_AccountSync
878 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
879 struct netr_AccountSync *r)
881 /* w2k3 returns "NOT IMPLEMENTED" for this call */
882 return NT_STATUS_NOT_IMPLEMENTED;
887 netr_GetDcName
889 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
890 struct netr_GetDcName *r)
892 const char * const attrs[] = { NULL };
893 struct ldb_context *sam_ctx;
894 struct ldb_message **res;
895 struct ldb_dn *domain_dn;
896 int ret;
897 const char *dcname;
899 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
900 dce_call->conn->dce_ctx->lp_ctx,
901 dce_call->conn->auth_state.session_info);
902 if (sam_ctx == NULL) {
903 return WERR_DS_UNAVAILABLE;
906 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
907 r->in.domainname);
908 if (domain_dn == NULL) {
909 return WERR_DS_UNAVAILABLE;
912 ret = gendb_search_dn(sam_ctx, mem_ctx,
913 domain_dn, &res, attrs);
914 if (ret != 1) {
915 return WERR_NO_SUCH_DOMAIN;
918 /* TODO: - return real IP address
919 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
921 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
922 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
923 W_ERROR_HAVE_NO_MEMORY(dcname);
925 *r->out.dcname = dcname;
926 return WERR_OK;
931 netr_LogonControl2Ex
933 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934 struct netr_LogonControl2Ex *r)
936 return WERR_NOT_SUPPORTED;
941 netr_LogonControl
943 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
944 struct netr_LogonControl *r)
946 struct netr_LogonControl2Ex r2;
947 WERROR werr;
949 if (r->in.level == 0x00000001) {
950 ZERO_STRUCT(r2);
952 r2.in.logon_server = r->in.logon_server;
953 r2.in.function_code = r->in.function_code;
954 r2.in.level = r->in.level;
955 r2.in.data = NULL;
956 r2.out.query = r->out.query;
958 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
959 } else if (r->in.level == 0x00000002) {
960 werr = WERR_NOT_SUPPORTED;
961 } else {
962 werr = WERR_UNKNOWN_LEVEL;
965 return werr;
970 netr_LogonControl2
972 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973 struct netr_LogonControl2 *r)
975 struct netr_LogonControl2Ex r2;
976 WERROR werr;
978 ZERO_STRUCT(r2);
980 r2.in.logon_server = r->in.logon_server;
981 r2.in.function_code = r->in.function_code;
982 r2.in.level = r->in.level;
983 r2.in.data = r->in.data;
984 r2.out.query = r->out.query;
986 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
988 return werr;
991 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
992 struct ldb_context *sam_ctx,
993 struct netr_DomainTrustList *trusts,
994 uint32_t trust_flags);
997 netr_GetAnyDCName
999 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1000 struct netr_GetAnyDCName *r)
1002 struct netr_DomainTrustList *trusts;
1003 struct ldb_context *sam_ctx;
1004 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1005 uint32_t i;
1006 WERROR werr;
1008 *r->out.dcname = NULL;
1010 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1011 /* if the domainname parameter wasn't set assume our domain */
1012 r->in.domainname = lp_workgroup(lp_ctx);
1015 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1016 dce_call->conn->auth_state.session_info);
1017 if (sam_ctx == NULL) {
1018 return WERR_DS_UNAVAILABLE;
1021 if (strcasecmp(r->in.domainname, lp_workgroup(lp_ctx)) == 0) {
1022 /* well we asked for a DC of our own domain */
1023 if (samdb_is_pdc(sam_ctx)) {
1024 /* we are the PDC of the specified domain */
1025 return WERR_NO_SUCH_DOMAIN;
1028 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1029 lp_netbios_name(lp_ctx));
1030 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1032 return WERR_OK;
1035 /* Okay, now we have to consider the trusted domains */
1037 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1038 W_ERROR_HAVE_NO_MEMORY(trusts);
1040 trusts->count = 0;
1042 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1043 NETR_TRUST_FLAG_INBOUND
1044 | NETR_TRUST_FLAG_OUTBOUND);
1045 W_ERROR_NOT_OK_RETURN(werr);
1047 for (i = 0; i < trusts->count; i++) {
1048 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1049 /* FIXME: Here we need to find a DC for the specified
1050 * trusted domain. */
1052 /* return WERR_OK; */
1053 return WERR_NO_SUCH_DOMAIN;
1057 return WERR_NO_SUCH_DOMAIN;
1062 netr_DatabaseRedo
1064 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1065 struct netr_DatabaseRedo *r)
1067 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1072 netr_NetrEnumerateTurstedDomains
1074 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075 struct netr_NetrEnumerateTrustedDomains *r)
1077 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1082 netr_LogonGetCapabilities
1084 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1085 struct netr_LogonGetCapabilities *r)
1087 /* we don't support AES yet */
1088 return NT_STATUS_NOT_IMPLEMENTED;
1093 netr_NETRLOGONSETSERVICEBITS
1095 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1096 struct netr_NETRLOGONSETSERVICEBITS *r)
1098 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1103 netr_LogonGetTrustRid
1105 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1106 struct netr_LogonGetTrustRid *r)
1108 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1113 netr_NETRLOGONCOMPUTESERVERDIGEST
1115 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1116 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1118 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1123 netr_NETRLOGONCOMPUTECLIENTDIGEST
1125 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1126 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1128 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1134 netr_DsRGetSiteName
1136 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1137 struct netr_DsRGetSiteName *r)
1139 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1144 fill in a netr_OneDomainInfo from a ldb search result
1146 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1147 struct loadparm_context *lp_ctx,
1148 struct ldb_context *sam_ctx,
1149 struct ldb_message *res,
1150 struct netr_OneDomainInfo *info,
1151 bool is_local, bool is_trust_list)
1153 ZERO_STRUCTP(info);
1155 if (is_trust_list) {
1156 /* w2k8 only fills this on trusted domains */
1157 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1158 info->trust_extension.length = 16;
1159 info->trust_extension.info->flags =
1160 NETR_TRUST_FLAG_TREEROOT |
1161 NETR_TRUST_FLAG_IN_FOREST |
1162 NETR_TRUST_FLAG_PRIMARY |
1163 NETR_TRUST_FLAG_NATIVE;
1165 info->trust_extension.info->parent_index = 0; /* should be index into array
1166 of parent */
1167 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1168 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1171 if (is_trust_list) {
1172 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1173 info->dns_forestname.string = NULL;
1174 } else {
1175 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1176 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1177 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1178 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1181 if (is_local) {
1182 info->domainname.string = lp_workgroup(lp_ctx);
1183 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1184 info->domain_guid = samdb_result_guid(res, "objectGUID");
1185 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1186 } else {
1187 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1188 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1189 info->domain_guid = samdb_result_guid(res, "objectGUID");
1190 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1192 if (!is_trust_list) {
1193 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1196 return NT_STATUS_OK;
1200 netr_LogonGetDomainInfo
1201 this is called as part of the ADS domain logon procedure.
1203 It has an important role in convaying details about the client, such
1204 as Operating System, Version, Service Pack etc.
1206 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1207 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1209 struct netlogon_creds_CredentialState *creds;
1210 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1211 "securityIdentifier", "trustPartner", NULL };
1212 const char * const attrs2[] = { "dNSHostName",
1213 "msDS-SupportedEncryptionTypes", NULL };
1214 const char * const attrs3[] = { NULL };
1215 const char *temp_str, *temp_str2;
1216 const char *old_dns_hostname;
1217 struct ldb_context *sam_ctx;
1218 struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1219 struct ldb_dn *workstation_dn;
1220 struct netr_DomainInformation *domain_info;
1221 struct netr_LsaPolicyInformation *lsa_policy_info;
1222 struct netr_OsVersionInfoEx *os_version;
1223 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1224 bool update_dns_hostname = true;
1225 int ret, ret3, i;
1226 NTSTATUS status;
1228 status = dcesrv_netr_creds_server_step_check(dce_call,
1229 mem_ctx,
1230 r->in.computer_name,
1231 r->in.credential,
1232 r->out.return_authenticator,
1233 &creds);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 DEBUG(0,(__location__ " Bad credentials - error\n"));
1237 NT_STATUS_NOT_OK_RETURN(status);
1239 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1240 dce_call->conn->dce_ctx->lp_ctx,
1241 system_session(dce_call->conn->dce_ctx->lp_ctx));
1242 if (sam_ctx == NULL) {
1243 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1246 switch (r->in.level) {
1247 case 1: /* Domain information */
1250 * Updates the DNS hostname when the client wishes that the
1251 * server should handle this for him
1252 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1253 * See MS-NRPC section 3.5.4.3.9
1255 if ((r->in.query->workstation_info->workstation_flags
1256 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1257 update_dns_hostname = false;
1261 * Checks that the computer name parameter without possible "$"
1262 * matches as prefix with the DNS hostname in the workstation
1263 * info structure.
1265 temp_str = talloc_strndup(mem_ctx,
1266 r->in.computer_name,
1267 strcspn(r->in.computer_name, "$"));
1268 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1269 temp_str2 = talloc_strndup(mem_ctx,
1270 r->in.query->workstation_info->dns_hostname,
1271 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1272 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1273 if (strcasecmp(temp_str, temp_str2) != 0) {
1274 update_dns_hostname = false;
1278 * Check that the DNS hostname when it should be updated
1279 * will be used only by maximum one host.
1281 ret = gendb_search(sam_ctx, mem_ctx,
1282 ldb_get_default_basedn(sam_ctx),
1283 &res0, attrs3, "(dNSHostName=%s)",
1284 r->in.query->workstation_info->dns_hostname);
1285 if (ret < 0) {
1286 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1288 if (ret >= 1) {
1289 update_dns_hostname = false;
1292 talloc_free(res0);
1294 /* Prepare the workstation DN */
1295 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1296 dom_sid_string(mem_ctx, creds->sid));
1297 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1299 /* Lookup for attributes in workstation object */
1300 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1301 &res1, attrs2);
1302 if (ret != 1) {
1303 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1306 /* Gets the old DNS hostname */
1307 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1308 NULL);
1310 /* Gets host informations and put them in our directory */
1311 new_msg = ldb_msg_new(mem_ctx);
1312 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1314 new_msg->dn = workstation_dn;
1316 /* Deletes old OS version values */
1317 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1318 "operatingSystemServicePack");
1319 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1320 "operatingSystemVersion");
1322 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1323 DEBUG(3,("Impossible to update samdb: %s\n",
1324 ldb_errstring(sam_ctx)));
1327 talloc_free(new_msg);
1329 new_msg = ldb_msg_new(mem_ctx);
1330 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1332 new_msg->dn = workstation_dn;
1334 /* Sets the OS name */
1335 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1336 "operatingSystem",
1337 r->in.query->workstation_info->os_name.string);
1340 * Sets informations from "os_version". On a empty structure
1341 * the values are cleared.
1343 if (r->in.query->workstation_info->os_version.os != NULL) {
1344 os_version = &r->in.query->workstation_info->os_version.os->os;
1346 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1347 "operatingSystemServicePack",
1348 os_version->CSDVersion);
1350 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1351 "operatingSystemVersion",
1352 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1353 os_version->MajorVersion,
1354 os_version->MinorVersion,
1355 os_version->BuildNumber
1361 * If the boolean "update_dns_hostname" remained true, then we
1362 * are fine to start the update.
1364 if (update_dns_hostname) {
1365 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1366 "dNSHostname",
1367 r->in.query->workstation_info->dns_hostname);
1369 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1370 "servicePrincipalName",
1371 talloc_asprintf(mem_ctx, "HOST/%s",
1372 r->in.computer_name)
1374 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1375 "servicePrincipalName",
1376 talloc_asprintf(mem_ctx, "HOST/%s",
1377 r->in.query->workstation_info->dns_hostname)
1381 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1382 DEBUG(3,("Impossible to update samdb: %s\n",
1383 ldb_errstring(sam_ctx)));
1386 talloc_free(new_msg);
1388 /* Writes back the domain information */
1390 /* We need to do two searches. The first will pull our primary
1391 domain and the second will pull any trusted domains. Our
1392 primary domain is also a "trusted" domain, so we need to
1393 put the primary domain into the lists of returned trusts as
1394 well. */
1395 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1396 &res2, attrs);
1397 if (ret != 1) {
1398 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1401 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1402 "(objectClass=trustedDomain)");
1403 if (ret3 == -1) {
1404 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1407 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1408 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1410 ZERO_STRUCTP(domain_info);
1412 /* Informations about the local and trusted domains */
1414 status = fill_one_domain_info(mem_ctx,
1415 dce_call->conn->dce_ctx->lp_ctx,
1416 sam_ctx, res2[0], &domain_info->primary_domain,
1417 true, false);
1418 NT_STATUS_NOT_OK_RETURN(status);
1420 domain_info->trusted_domain_count = ret3 + 1;
1421 domain_info->trusted_domains = talloc_array(mem_ctx,
1422 struct netr_OneDomainInfo,
1423 domain_info->trusted_domain_count);
1424 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1426 for (i=0;i<ret3;i++) {
1427 status = fill_one_domain_info(mem_ctx,
1428 dce_call->conn->dce_ctx->lp_ctx,
1429 sam_ctx, res3[i],
1430 &domain_info->trusted_domains[i],
1431 false, true);
1432 NT_STATUS_NOT_OK_RETURN(status);
1435 status = fill_one_domain_info(mem_ctx,
1436 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1437 &domain_info->trusted_domains[i], true, true);
1438 NT_STATUS_NOT_OK_RETURN(status);
1440 /* Sets the supported encryption types */
1441 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1442 "msDS-SupportedEncryptionTypes",
1443 default_supported_enc_types);
1445 /* Other host domain informations */
1447 lsa_policy_info = talloc(mem_ctx,
1448 struct netr_LsaPolicyInformation);
1449 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1450 ZERO_STRUCTP(lsa_policy_info);
1452 domain_info->lsa_policy = *lsa_policy_info;
1454 /* The DNS hostname is only returned back when there is a chance
1455 * for a change. */
1456 if ((r->in.query->workstation_info->workstation_flags
1457 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1458 domain_info->dns_hostname.string = old_dns_hostname;
1459 } else {
1460 domain_info->dns_hostname.string = NULL;
1463 domain_info->workstation_flags =
1464 r->in.query->workstation_info->workstation_flags;
1466 r->out.info->domain_info = domain_info;
1467 break;
1468 case 2: /* LSA policy information - not used at the moment */
1469 lsa_policy_info = talloc(mem_ctx,
1470 struct netr_LsaPolicyInformation);
1471 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1472 ZERO_STRUCTP(lsa_policy_info);
1474 r->out.info->lsa_policy_info = lsa_policy_info;
1475 break;
1476 default:
1477 return NT_STATUS_INVALID_LEVEL;
1478 break;
1481 return NT_STATUS_OK;
1487 netr_ServerPasswordGet
1489 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1490 struct netr_ServerPasswordGet *r)
1492 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1497 netr_NETRLOGONSENDTOSAM
1499 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1500 struct netr_NETRLOGONSENDTOSAM *r)
1502 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1507 netr_DsRGetDCNameEx2
1509 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1510 TALLOC_CTX *mem_ctx,
1511 struct netr_DsRGetDCNameEx2 *r)
1513 struct ldb_context *sam_ctx;
1514 struct netr_DsRGetDCNameInfo *info;
1515 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1516 struct socket_address *addr;
1517 const char *server_site_name;
1518 char *guid_str;
1519 struct netlogon_samlogon_response response;
1520 NTSTATUS status;
1522 ZERO_STRUCTP(r->out.info);
1524 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1525 dce_call->conn->auth_state.session_info);
1526 if (sam_ctx == NULL) {
1527 return WERR_DS_UNAVAILABLE;
1530 addr = dce_call->conn->transport.get_peer_addr(dce_call->conn, mem_ctx);
1531 W_ERROR_HAVE_NO_MEMORY(addr);
1533 /* "server_unc" is ignored by w2k3 */
1535 /* Proof server site parameter "site_name" if it was specified */
1536 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1537 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1538 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1539 server_site_name) != 0)) {
1540 return WERR_NO_SUCH_DOMAIN;
1543 /* TODO: the flags are ignored for now */
1545 guid_str = r->in.domain_guid != NULL ?
1546 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1548 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1549 r->in.domain_name,
1550 r->in.domain_name,
1551 NULL, guid_str,
1552 r->in.client_account,
1553 r->in.mask, addr->addr,
1554 NETLOGON_NT_VERSION_5EX_WITH_IP,
1555 lp_ctx, &response);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 return ntstatus_to_werror(status);
1560 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1561 W_ERROR_HAVE_NO_MEMORY(info);
1562 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s",
1563 response.data.nt5_ex.pdc_dns_name);
1564 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1565 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1566 response.data.nt5_ex.sockaddr.pdc_ip);
1567 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1568 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1569 info->domain_guid = response.data.nt5_ex.domain_uuid;
1570 info->domain_name = response.data.nt5_ex.dns_domain;
1571 info->forest_name = response.data.nt5_ex.forest;
1572 info->dc_flags = response.data.nt5_ex.server_type;
1573 info->dc_site_name = response.data.nt5_ex.server_site;
1574 info->client_site_name = response.data.nt5_ex.client_site;
1576 *r->out.info = info;
1578 return WERR_OK;
1582 netr_DsRGetDCNameEx
1584 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1585 struct netr_DsRGetDCNameEx *r)
1587 struct netr_DsRGetDCNameEx2 r2;
1588 WERROR werr;
1590 ZERO_STRUCT(r2);
1592 r2.in.server_unc = r->in.server_unc;
1593 r2.in.client_account = NULL;
1594 r2.in.mask = 0;
1595 r2.in.domain_guid = r->in.domain_guid;
1596 r2.in.domain_name = r->in.domain_name;
1597 r2.in.site_name = r->in.site_name;
1598 r2.in.flags = r->in.flags;
1599 r2.out.info = r->out.info;
1601 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1603 return werr;
1607 netr_DsRGetDCName
1609 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1610 struct netr_DsRGetDCName *r)
1612 struct netr_DsRGetDCNameEx2 r2;
1613 WERROR werr;
1615 ZERO_STRUCT(r2);
1617 r2.in.server_unc = r->in.server_unc;
1618 r2.in.client_account = NULL;
1619 r2.in.mask = 0;
1620 r2.in.domain_name = r->in.domain_name;
1621 r2.in.domain_guid = r->in.domain_guid;
1623 r2.in.site_name = NULL; /* should fill in from site GUID */
1624 r2.in.flags = r->in.flags;
1625 r2.out.info = r->out.info;
1627 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1629 return werr;
1632 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1634 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1635 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1637 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1642 netr_NetrEnumerateTrustedDomainsEx
1644 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1645 struct netr_NetrEnumerateTrustedDomainsEx *r)
1647 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1652 netr_DsRAddressToSitenamesExW
1654 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1655 struct netr_DsRAddressToSitenamesExW *r)
1657 struct ldb_context *sam_ctx;
1658 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1659 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1660 uint16_t sin_family;
1661 struct sockaddr_in *addr;
1662 struct sockaddr_in6 *addr6;
1663 char addr_str[INET6_ADDRSTRLEN];
1664 char *subnet_name;
1665 const char *res;
1666 uint32_t i;
1668 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1669 dce_call->conn->auth_state.session_info);
1670 if (sam_ctx == NULL) {
1671 return WERR_DS_UNAVAILABLE;
1674 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1675 W_ERROR_HAVE_NO_MEMORY(ctr);
1677 *r->out.ctr = ctr;
1679 ctr->count = r->in.count;
1680 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1681 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1682 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1683 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1685 for (i=0; i<ctr->count; i++) {
1686 ctr->sitename[i].string = NULL;
1687 ctr->subnetname[i].string = NULL;
1689 if (r->in.addresses[i].size < sizeof(sin_family)) {
1690 continue;
1692 sin_family = SVAL(r->in.addresses[i].buffer, 0);
1694 switch (sin_family) {
1695 case AF_INET:
1696 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1697 continue;
1699 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1700 res = inet_ntop(AF_INET, &addr->sin_addr,
1701 addr_str, sizeof(addr_str));
1702 break;
1703 case AF_INET6:
1704 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1705 continue;
1707 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1708 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1709 addr_str, sizeof(addr_str));
1710 break;
1711 default:
1712 continue;
1713 break;
1716 if (res == NULL) {
1717 continue;
1720 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1721 mem_ctx,
1722 addr_str,
1723 &subnet_name);
1724 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1725 ctr->subnetname[i].string = subnet_name;
1728 return WERR_OK;
1733 netr_DsRAddressToSitenamesW
1735 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1736 struct netr_DsRAddressToSitenamesW *r)
1738 struct netr_DsRAddressToSitenamesExW r2;
1739 struct netr_DsRAddressToSitenamesWCtr *ctr;
1740 uint32_t i;
1741 WERROR werr;
1743 ZERO_STRUCT(r2);
1745 r2.in.server_name = r->in.server_name;
1746 r2.in.count = r->in.count;
1747 r2.in.addresses = r->in.addresses;
1749 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1750 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1752 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1754 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1755 W_ERROR_HAVE_NO_MEMORY(ctr);
1757 *r->out.ctr = ctr;
1759 ctr->count = r->in.count;
1760 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1761 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1763 for (i=0; i<ctr->count; i++) {
1764 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1767 return werr;
1772 netr_DsrGetDcSiteCoverageW
1774 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1775 struct netr_DsrGetDcSiteCoverageW *r)
1777 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1781 #define GET_CHECK_STR(dest, mem, msg, attr) \
1782 do {\
1783 const char *s; \
1784 s = samdb_result_string(msg, attr, NULL); \
1785 if (!s) { \
1786 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1787 "without flatname\n", \
1788 ldb_dn_get_linearized(msg->dn))); \
1789 continue; \
1791 dest = talloc_strdup(mem, s); \
1792 W_ERROR_HAVE_NO_MEMORY(dest); \
1793 } while(0)
1796 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1797 struct ldb_context *sam_ctx,
1798 struct netr_DomainTrustList *trusts,
1799 uint32_t trust_flags)
1801 struct ldb_dn *system_dn;
1802 struct ldb_message **dom_res = NULL;
1803 const char *trust_attrs[] = { "flatname", "trustPartner",
1804 "securityIdentifier", "trustDirection",
1805 "trustType", "trustAttributes", NULL };
1806 uint32_t n;
1807 int i;
1808 int ret;
1810 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1811 NETR_TRUST_FLAG_OUTBOUND))) {
1812 return WERR_INVALID_FLAGS;
1815 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1816 ldb_get_default_basedn(sam_ctx),
1817 "(&(objectClass=container)(cn=System))");
1818 if (!system_dn) {
1819 return WERR_GENERAL_FAILURE;
1822 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1823 &dom_res, trust_attrs,
1824 "(objectclass=trustedDomain)");
1826 for (i = 0; i < ret; i++) {
1827 unsigned int trust_dir;
1828 uint32_t flags = 0;
1830 trust_dir = samdb_result_uint(dom_res[i],
1831 "trustDirection", 0);
1833 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1834 flags |= NETR_TRUST_FLAG_INBOUND;
1836 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1837 flags |= NETR_TRUST_FLAG_OUTBOUND;
1840 if (!(flags & trust_flags)) {
1841 /* this trust direction was not requested */
1842 continue;
1845 n = trusts->count;
1846 trusts->array = talloc_realloc(trusts, trusts->array,
1847 struct netr_DomainTrust,
1848 n + 1);
1849 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1851 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1852 dom_res[i], "flatname");
1853 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1854 dom_res[i], "trustPartner");
1856 trusts->array[n].trust_flags = flags;
1857 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1858 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1859 /* TODO: find if we have parent in the list */
1860 trusts->array[n].parent_index = 0;
1863 trusts->array[n].trust_type =
1864 samdb_result_uint(dom_res[i],
1865 "trustType", 0);
1866 trusts->array[n].trust_attributes =
1867 samdb_result_uint(dom_res[i],
1868 "trustAttributes", 0);
1870 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1871 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1872 struct dom_sid zero_sid;
1873 ZERO_STRUCT(zero_sid);
1874 trusts->array[n].sid =
1875 dom_sid_dup(trusts, &zero_sid);
1876 } else {
1877 trusts->array[n].sid =
1878 samdb_result_dom_sid(trusts, dom_res[i],
1879 "securityIdentifier");
1881 trusts->array[n].guid = GUID_zero();
1883 trusts->count = n + 1;
1886 talloc_free(dom_res);
1887 return WERR_OK;
1891 netr_DsrEnumerateDomainTrusts
1893 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1894 TALLOC_CTX *mem_ctx,
1895 struct netr_DsrEnumerateDomainTrusts *r)
1897 struct netr_DomainTrustList *trusts;
1898 struct ldb_context *sam_ctx;
1899 int ret;
1900 struct ldb_message **dom_res;
1901 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1902 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1903 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1904 const char *p;
1905 WERROR werr;
1907 if (r->in.trust_flags & 0xFFFFFE00) {
1908 return WERR_INVALID_FLAGS;
1911 /* TODO: turn to hard check once we are sure this is 100% correct */
1912 if (!r->in.server_name) {
1913 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1914 "But received NULL!\n", dnsdomain));
1915 } else {
1916 p = strchr(r->in.server_name, '.');
1917 if (!p) {
1918 DEBUG(3, ("Invalid domain! Expected name in domain "
1919 "[%s]. But received [%s]!\n",
1920 dnsdomain, r->in.server_name));
1921 p = r->in.server_name;
1922 } else {
1923 p++;
1925 if (strcasecmp(p, dnsdomain)) {
1926 DEBUG(3, ("Invalid domain! Expected name in domain "
1927 "[%s]. But received [%s]!\n",
1928 dnsdomain, r->in.server_name));
1932 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1933 W_ERROR_HAVE_NO_MEMORY(trusts);
1935 trusts->count = 0;
1936 r->out.trusts = trusts;
1938 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1939 dce_call->conn->auth_state.session_info);
1940 if (sam_ctx == NULL) {
1941 return WERR_GENERAL_FAILURE;
1944 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1945 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1947 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1948 trusts, r->in.trust_flags);
1949 W_ERROR_NOT_OK_RETURN(werr);
1952 /* NOTE: we currently are always the root of the forest */
1953 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1954 int n = trusts->count;
1956 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1957 &dom_res, dom_attrs);
1958 if (ret != 1) {
1959 return WERR_GENERAL_FAILURE;
1962 trusts->count = n + 1;
1963 trusts->array = talloc_realloc(trusts, trusts->array,
1964 struct netr_DomainTrust,
1965 trusts->count);
1966 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1968 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1969 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1970 trusts->array[n].trust_flags =
1971 NETR_TRUST_FLAG_NATIVE |
1972 NETR_TRUST_FLAG_TREEROOT |
1973 NETR_TRUST_FLAG_IN_FOREST |
1974 NETR_TRUST_FLAG_PRIMARY;
1975 /* we are always the root domain for now */
1976 trusts->array[n].parent_index = 0;
1977 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1978 trusts->array[n].trust_attributes = 0;
1979 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1980 dom_res[0],
1981 "objectSid");
1982 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1983 "objectGUID");
1984 talloc_free(dom_res);
1987 return WERR_OK;
1992 netr_DsrDeregisterDNSHostRecords
1994 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1995 struct netr_DsrDeregisterDNSHostRecords *r)
1997 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2002 netr_ServerTrustPasswordsGet
2004 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2005 struct netr_ServerTrustPasswordsGet *r)
2007 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2011 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2012 struct ldb_context *sam_ctx,
2013 struct loadparm_context *lp_ctx,
2014 struct lsa_ForestTrustInformation *info)
2016 struct lsa_ForestTrustDomainInfo *domain_info;
2017 struct lsa_ForestTrustRecord *e;
2018 struct ldb_message **dom_res;
2019 const char * const dom_attrs[] = { "objectSid", NULL };
2020 int ret;
2022 /* we need to provide 2 entries:
2023 * 1. the Root Forest name
2024 * 2. the Domain Information
2027 info->count = 2;
2028 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2029 W_ERROR_HAVE_NO_MEMORY(info->entries);
2031 /* Forest root info */
2032 e = talloc(info, struct lsa_ForestTrustRecord);
2033 W_ERROR_HAVE_NO_MEMORY(e);
2035 e->flags = 0;
2036 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2037 e->time = 0; /* so far always 0 in trces. */
2038 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2039 mem_ctx);
2040 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2042 info->entries[0] = e;
2044 /* Domain info */
2045 e = talloc(info, struct lsa_ForestTrustRecord);
2046 W_ERROR_HAVE_NO_MEMORY(e);
2048 /* get our own domain info */
2049 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2050 if (ret != 1) {
2051 return WERR_GENERAL_FAILURE;
2054 /* TODO: check if disabled and set flags accordingly */
2055 e->flags = 0;
2056 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2057 e->time = 0; /* so far always 0 in traces. */
2059 domain_info = &e->forest_trust_data.domain_info;
2060 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2061 "objectSid");
2062 domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
2063 domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
2065 info->entries[1] = e;
2067 talloc_free(dom_res);
2069 return WERR_OK;
2073 netr_DsRGetForestTrustInformation
2075 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2076 TALLOC_CTX *mem_ctx,
2077 struct netr_DsRGetForestTrustInformation *r)
2079 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2080 struct lsa_ForestTrustInformation *info, **info_ptr;
2081 struct ldb_context *sam_ctx;
2082 WERROR werr;
2084 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2085 return WERR_CALL_NOT_IMPLEMENTED;
2088 if (r->in.flags & 0xFFFFFFFE) {
2089 return WERR_INVALID_FLAGS;
2092 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2093 dce_call->conn->auth_state.session_info);
2094 if (sam_ctx == NULL) {
2095 return WERR_GENERAL_FAILURE;
2098 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2099 if (!samdb_is_pdc(sam_ctx)) {
2100 return WERR_NERR_NOTPRIMARY;
2103 if (r->in.trusted_domain_name == NULL) {
2104 return WERR_INVALID_FLAGS;
2107 /* TODO: establish an schannel connection with
2108 * r->in.trusted_domain_name and perform a
2109 * netr_GetForestTrustInformation call against it */
2111 /* for now return not implementd */
2112 return WERR_CALL_NOT_IMPLEMENTED;
2115 /* TODO: check r->in.server_name is our name */
2117 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2118 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2120 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2121 W_ERROR_HAVE_NO_MEMORY(info);
2123 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2124 W_ERROR_NOT_OK_RETURN(werr);
2126 *info_ptr = info;
2127 r->out.forest_trust_info = info_ptr;
2129 return WERR_OK;
2134 netr_GetForestTrustInformation
2136 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2137 TALLOC_CTX *mem_ctx,
2138 struct netr_GetForestTrustInformation *r)
2140 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2141 struct netlogon_creds_CredentialState *creds;
2142 struct lsa_ForestTrustInformation *info, **info_ptr;
2143 struct ldb_context *sam_ctx;
2144 NTSTATUS status;
2145 WERROR werr;
2147 if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2148 return NT_STATUS_NOT_IMPLEMENTED;
2151 status = dcesrv_netr_creds_server_step_check(dce_call,
2152 mem_ctx,
2153 r->in.computer_name,
2154 r->in.credential,
2155 r->out.return_authenticator,
2156 &creds);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 return status;
2161 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2162 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2163 return NT_STATUS_NOT_IMPLEMENTED;
2166 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2167 dce_call->conn->auth_state.session_info);
2168 if (sam_ctx == NULL) {
2169 return NT_STATUS_UNSUCCESSFUL;
2172 /* TODO: check r->in.server_name is our name */
2174 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2175 if (!info_ptr) {
2176 return NT_STATUS_NO_MEMORY;
2178 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2179 if (!info) {
2180 return NT_STATUS_NO_MEMORY;
2183 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2184 if (!W_ERROR_IS_OK(werr)) {
2185 return werror_to_ntstatus(werr);
2188 *info_ptr = info;
2189 r->out.forest_trust_info = info_ptr;
2191 return NT_STATUS_OK;
2196 netr_ServerGetTrustInfo
2198 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2199 struct netr_ServerGetTrustInfo *r)
2201 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2205 /* include the generated boilerplate */
2206 #include "librpc/gen_ndr/ndr_netlogon_s.c"