s4:dsdb - remove some calls of "samdb_msg_add_string" when we have talloc'ed strings
[Samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob2f80c1bcceab726bb4b8c97ab062054a6b12d4c0
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the netlogon pipe
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
8 Copyright (C) Matthias Dieter Wallnöfer 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
41 struct netlogon_server_pipe_state {
42 struct netr_Credential client_challenge;
43 struct netr_Credential server_challenge;
46 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
47 struct netr_ServerReqChallenge *r)
49 struct netlogon_server_pipe_state *pipe_state =
50 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52 ZERO_STRUCTP(r->out.return_credentials);
54 /* destroyed on pipe shutdown */
56 if (pipe_state) {
57 talloc_free(pipe_state);
58 dce_call->context->private_data = NULL;
61 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
62 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64 pipe_state->client_challenge = *r->in.credentials;
66 generate_random_buffer(pipe_state->server_challenge.data,
67 sizeof(pipe_state->server_challenge.data));
69 *r->out.return_credentials = pipe_state->server_challenge;
71 dce_call->context->private_data = pipe_state;
73 return NT_STATUS_OK;
76 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
77 struct netr_ServerAuthenticate3 *r)
79 struct netlogon_server_pipe_state *pipe_state =
80 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
81 struct netlogon_creds_CredentialState *creds;
82 struct ldb_context *sam_ctx;
83 struct samr_Password *mach_pwd;
84 uint32_t user_account_control;
85 int num_records;
86 struct ldb_message **msgs;
87 NTSTATUS nt_status;
88 const char *attrs[] = {"unicodePwd", "userAccountControl",
89 "objectSid", NULL};
91 const char *trust_dom_attrs[] = {"flatname", NULL};
92 const char *account_name;
94 ZERO_STRUCTP(r->out.return_credentials);
95 *r->out.rid = 0;
98 * According to Microsoft (see bugid #6099)
99 * Windows 7 looks at the negotiate_flags
100 * returned in this structure *even if the
101 * call fails with access denied!
103 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
104 NETLOGON_NEG_PERSISTENT_SAMREPL |
105 NETLOGON_NEG_ARCFOUR |
106 NETLOGON_NEG_PROMOTION_COUNT |
107 NETLOGON_NEG_CHANGELOG_BDC |
108 NETLOGON_NEG_FULL_SYNC_REPL |
109 NETLOGON_NEG_MULTIPLE_SIDS |
110 NETLOGON_NEG_REDO |
111 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
112 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
113 NETLOGON_NEG_GENERIC_PASSTHROUGH |
114 NETLOGON_NEG_CONCURRENT_RPC |
115 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
116 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
117 NETLOGON_NEG_STRONG_KEYS |
118 NETLOGON_NEG_TRANSITIVE_TRUSTS |
119 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
120 NETLOGON_NEG_PASSWORD_SET2 |
121 NETLOGON_NEG_GETDOMAININFO |
122 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
123 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
124 NETLOGON_NEG_RODC_PASSTHROUGH |
125 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
126 NETLOGON_NEG_AUTHENTICATED_RPC;
128 switch (r->in.secure_channel_type) {
129 case SEC_CHAN_WKSTA:
130 case SEC_CHAN_DNS_DOMAIN:
131 case SEC_CHAN_DOMAIN:
132 case SEC_CHAN_BDC:
133 case SEC_CHAN_RODC:
134 break;
135 default:
136 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
137 r->in.secure_channel_type));
138 return NT_STATUS_INVALID_PARAMETER;
141 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
142 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
143 if (sam_ctx == NULL) {
144 return NT_STATUS_INVALID_SYSTEM_SERVICE;
147 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
148 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
149 const char *flatname;
150 if (!encoded_account) {
151 return NT_STATUS_NO_MEMORY;
154 /* Kill the trailing dot */
155 if (encoded_account[strlen(encoded_account)-1] == '.') {
156 encoded_account[strlen(encoded_account)-1] = '\0';
159 /* pull the user attributes */
160 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
161 trust_dom_attrs,
162 "(&(trustPartner=%s)(objectclass=trustedDomain))",
163 encoded_account);
165 if (num_records == 0) {
166 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
167 encoded_account));
168 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
171 if (num_records > 1) {
172 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
173 return NT_STATUS_INTERNAL_DB_CORRUPTION;
176 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
177 if (!flatname) {
178 /* No flatname for this trust - we can't proceed */
179 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
181 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
183 if (!account_name) {
184 return NT_STATUS_NO_MEMORY;
187 } else {
188 account_name = r->in.account_name;
191 /* pull the user attributes */
192 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
193 "(&(sAMAccountName=%s)(objectclass=user))",
194 ldb_binary_encode_string(mem_ctx, account_name));
196 if (num_records == 0) {
197 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
198 r->in.account_name));
199 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
202 if (num_records > 1) {
203 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
204 return NT_STATUS_INTERNAL_DB_CORRUPTION;
207 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
209 if (user_account_control & UF_ACCOUNTDISABLE) {
210 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
211 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
214 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
215 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
216 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
217 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
219 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
220 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
221 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
222 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
224 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
226 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
227 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
228 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
229 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
231 } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
232 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
233 DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
234 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
236 } else {
237 /* we should never reach this */
238 return NT_STATUS_INTERNAL_ERROR;
241 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
242 "objectSid", 0);
244 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
245 if (mach_pwd == NULL) {
246 return NT_STATUS_ACCESS_DENIED;
249 if (!pipe_state) {
250 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
251 return NT_STATUS_ACCESS_DENIED;
254 creds = netlogon_creds_server_init(mem_ctx,
255 r->in.account_name,
256 r->in.computer_name,
257 r->in.secure_channel_type,
258 &pipe_state->client_challenge,
259 &pipe_state->server_challenge,
260 mach_pwd,
261 r->in.credentials,
262 r->out.return_credentials,
263 *r->in.negotiate_flags);
265 if (!creds) {
266 return NT_STATUS_ACCESS_DENIED;
269 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
271 nt_status = schannel_save_creds_state(mem_ctx,
272 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
273 creds);
275 return nt_status;
278 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
279 struct netr_ServerAuthenticate *r)
281 struct netr_ServerAuthenticate3 a;
282 uint32_t rid;
283 /* TODO:
284 * negotiate_flags is used as an [in] parameter
285 * so it need to be initialised.
287 * (I think ... = 0; seems wrong here --metze)
289 uint32_t negotiate_flags_in = 0;
290 uint32_t negotiate_flags_out = 0;
292 a.in.server_name = r->in.server_name;
293 a.in.account_name = r->in.account_name;
294 a.in.secure_channel_type = r->in.secure_channel_type;
295 a.in.computer_name = r->in.computer_name;
296 a.in.credentials = r->in.credentials;
297 a.in.negotiate_flags = &negotiate_flags_in;
299 a.out.return_credentials = r->out.return_credentials;
300 a.out.rid = &rid;
301 a.out.negotiate_flags = &negotiate_flags_out;
303 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
306 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
307 struct netr_ServerAuthenticate2 *r)
309 struct netr_ServerAuthenticate3 r3;
310 uint32_t rid = 0;
312 r3.in.server_name = r->in.server_name;
313 r3.in.account_name = r->in.account_name;
314 r3.in.secure_channel_type = r->in.secure_channel_type;
315 r3.in.computer_name = r->in.computer_name;
316 r3.in.credentials = r->in.credentials;
317 r3.out.return_credentials = r->out.return_credentials;
318 r3.in.negotiate_flags = r->in.negotiate_flags;
319 r3.out.negotiate_flags = r->out.negotiate_flags;
320 r3.out.rid = &rid;
322 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
326 * NOTE: The following functions are nearly identical to the ones available in
327 * source3/rpc_server/srv_nelog_nt.c
328 * The reason we keep 2 copies is that they use different structures to
329 * represent the auth_info and the decrpc pipes.
333 * If schannel is required for this call test that it actually is available.
335 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
336 const char *computer_name,
337 bool integrity, bool privacy)
340 if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
341 if (!privacy && !integrity) {
342 return NT_STATUS_OK;
345 if ((!privacy && integrity) &&
346 auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
347 return NT_STATUS_OK;
350 if ((privacy || integrity) &&
351 auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
352 return NT_STATUS_OK;
356 /* test didn't pass */
357 DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
358 computer_name));
360 return NT_STATUS_ACCESS_DENIED;
363 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
364 TALLOC_CTX *mem_ctx,
365 const char *computer_name,
366 struct netr_Authenticator *received_authenticator,
367 struct netr_Authenticator *return_authenticator,
368 struct netlogon_creds_CredentialState **creds_out)
370 NTSTATUS nt_status;
371 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
372 bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
374 if (schannel_global_required) {
375 nt_status = schannel_check_required(auth_info,
376 computer_name,
377 true, false);
378 if (!NT_STATUS_IS_OK(nt_status)) {
379 return nt_status;
383 nt_status = schannel_check_creds_state(mem_ctx,
384 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
385 computer_name,
386 received_authenticator,
387 return_authenticator,
388 creds_out);
389 return nt_status;
393 Change the machine account password for the currently connected
394 client. Supplies only the NT#.
397 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
398 struct netr_ServerPasswordSet *r)
400 struct netlogon_creds_CredentialState *creds;
401 struct ldb_context *sam_ctx;
402 const char * const attrs[] = { "unicodePwd", NULL };
403 struct ldb_message **res;
404 struct samr_Password *oldNtHash;
405 NTSTATUS nt_status;
406 int ret;
408 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
409 mem_ctx,
410 r->in.computer_name,
411 r->in.credential, r->out.return_authenticator,
412 &creds);
413 NT_STATUS_NOT_OK_RETURN(nt_status);
415 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
416 if (sam_ctx == NULL) {
417 return NT_STATUS_INVALID_SYSTEM_SERVICE;
420 netlogon_creds_des_decrypt(creds, r->in.new_password);
422 /* fetch the old password hashes (the NT hash has to exist) */
424 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
425 "(&(objectClass=user)(objectSid=%s))",
426 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
427 if (ret != 1) {
428 return NT_STATUS_WRONG_PASSWORD;
431 nt_status = samdb_result_passwords(mem_ctx,
432 dce_call->conn->dce_ctx->lp_ctx,
433 res[0], NULL, &oldNtHash);
434 if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
435 return NT_STATUS_WRONG_PASSWORD;
438 /* Using the sid for the account as the key, set the password */
439 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
440 creds->sid,
441 NULL, /* Don't have plaintext */
442 NULL, r->in.new_password,
443 NULL, oldNtHash, /* Password change */
444 NULL, NULL);
445 return nt_status;
449 Change the machine account password for the currently connected
450 client. Supplies new plaintext.
452 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
453 struct netr_ServerPasswordSet2 *r)
455 struct netlogon_creds_CredentialState *creds;
456 struct ldb_context *sam_ctx;
457 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
458 struct ldb_message **res;
459 struct samr_Password *oldLmHash, *oldNtHash;
460 NTSTATUS nt_status;
461 DATA_BLOB new_password;
462 int ret;
464 struct samr_CryptPassword password_buf;
466 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
467 mem_ctx,
468 r->in.computer_name,
469 r->in.credential, r->out.return_authenticator,
470 &creds);
471 NT_STATUS_NOT_OK_RETURN(nt_status);
473 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
474 if (sam_ctx == NULL) {
475 return NT_STATUS_INVALID_SYSTEM_SERVICE;
478 memcpy(password_buf.data, r->in.new_password->data, 512);
479 SIVAL(password_buf.data, 512, r->in.new_password->length);
480 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
482 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
483 DEBUG(3,("samr: failed to decode password buffer\n"));
484 return NT_STATUS_WRONG_PASSWORD;
487 /* fetch the old password hashes (at least one of both has to exist) */
489 ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
490 "(&(objectClass=user)(objectSid=%s))",
491 ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
492 if (ret != 1) {
493 return NT_STATUS_WRONG_PASSWORD;
496 nt_status = samdb_result_passwords(mem_ctx,
497 dce_call->conn->dce_ctx->lp_ctx,
498 res[0], &oldLmHash, &oldNtHash);
499 if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
500 return NT_STATUS_WRONG_PASSWORD;
503 /* Using the sid for the account as the key, set the password */
504 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
505 creds->sid,
506 &new_password, /* we have plaintext */
507 NULL, NULL,
508 oldLmHash, oldNtHash, /* Password change */
509 NULL, NULL);
510 return nt_status;
515 netr_LogonUasLogon
517 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
518 struct netr_LogonUasLogon *r)
520 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
525 netr_LogonUasLogoff
527 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
528 struct netr_LogonUasLogoff *r)
530 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
535 netr_LogonSamLogon_base
537 This version of the function allows other wrappers to say 'do not check the credentials'
539 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
541 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
542 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
544 struct auth_context *auth_context;
545 struct auth_usersupplied_info *user_info;
546 struct auth_serversupplied_info *server_info;
547 NTSTATUS nt_status;
548 static const char zeros[16];
549 struct netr_SamBaseInfo *sam;
550 struct netr_SamInfo2 *sam2;
551 struct netr_SamInfo3 *sam3;
552 struct netr_SamInfo6 *sam6;
554 user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
555 NT_STATUS_HAVE_NO_MEMORY(user_info);
557 switch (r->in.logon_level) {
558 case NetlogonInteractiveInformation:
559 case NetlogonServiceInformation:
560 case NetlogonInteractiveTransitiveInformation:
561 case NetlogonServiceTransitiveInformation:
562 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
563 netlogon_creds_arcfour_crypt(creds,
564 r->in.logon->password->lmpassword.hash,
565 sizeof(r->in.logon->password->lmpassword.hash));
566 netlogon_creds_arcfour_crypt(creds,
567 r->in.logon->password->ntpassword.hash,
568 sizeof(r->in.logon->password->ntpassword.hash));
569 } else {
570 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
571 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
574 /* TODO: we need to deny anonymous access here */
575 nt_status = auth_context_create(mem_ctx,
576 dce_call->event_ctx, dce_call->msg_ctx,
577 dce_call->conn->dce_ctx->lp_ctx,
578 &auth_context);
579 NT_STATUS_NOT_OK_RETURN(nt_status);
581 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
582 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
583 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
584 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
586 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
587 user_info->password_state = AUTH_PASSWORD_HASH;
589 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
590 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
591 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
593 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
594 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
595 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
597 break;
598 case NetlogonNetworkInformation:
599 case NetlogonNetworkTransitiveInformation:
601 /* TODO: we need to deny anonymous access here */
602 nt_status = auth_context_create(mem_ctx,
603 dce_call->event_ctx, dce_call->msg_ctx,
604 dce_call->conn->dce_ctx->lp_ctx,
605 &auth_context);
606 NT_STATUS_NOT_OK_RETURN(nt_status);
608 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
609 NT_STATUS_NOT_OK_RETURN(nt_status);
611 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
612 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
613 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
614 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
616 user_info->password_state = AUTH_PASSWORD_RESPONSE;
617 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
618 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
620 break;
623 case NetlogonGenericInformation:
625 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
626 netlogon_creds_arcfour_crypt(creds,
627 r->in.logon->generic->data, r->in.logon->generic->length);
628 } else {
629 /* Using DES to verify kerberos tickets makes no sense */
630 return NT_STATUS_INVALID_PARAMETER;
633 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
634 NTSTATUS status;
635 struct dcerpc_binding_handle *irpc_handle;
636 struct kdc_check_generic_kerberos check;
637 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
638 NT_STATUS_HAVE_NO_MEMORY(generic);
639 *r->out.authoritative = 1;
641 /* TODO: Describe and deal with these flags */
642 *r->out.flags = 0;
644 r->out.validation->generic = generic;
646 irpc_handle = irpc_binding_handle_by_name(mem_ctx,
647 dce_call->msg_ctx,
648 "kdc_server",
649 &ndr_table_irpc);
650 if (irpc_handle == NULL) {
651 return NT_STATUS_NO_LOGON_SERVERS;
654 check.in.generic_request =
655 data_blob_const(r->in.logon->generic->data,
656 r->in.logon->generic->length);
658 status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
659 mem_ctx,
660 &check);
661 if (!NT_STATUS_IS_OK(status)) {
662 return status;
664 generic->length = check.out.generic_reply.length;
665 generic->data = check.out.generic_reply.data;
666 return NT_STATUS_OK;
669 /* Until we get an implemetnation of these other packages */
670 return NT_STATUS_INVALID_PARAMETER;
672 default:
673 return NT_STATUS_INVALID_PARAMETER;
676 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
677 NT_STATUS_NOT_OK_RETURN(nt_status);
679 switch (r->in.validation_level) {
680 case 2:
681 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
682 NT_STATUS_NOT_OK_RETURN(nt_status);
684 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
685 NT_STATUS_HAVE_NO_MEMORY(sam2);
686 sam2->base = *sam;
688 /* And put into the talloc tree */
689 talloc_steal(sam2, sam);
690 r->out.validation->sam2 = sam2;
692 sam = &sam2->base;
693 break;
695 case 3:
696 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
697 server_info,
698 &sam3);
699 NT_STATUS_NOT_OK_RETURN(nt_status);
701 r->out.validation->sam3 = sam3;
703 sam = &sam3->base;
704 break;
706 case 6:
707 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
708 server_info,
709 &sam3);
710 NT_STATUS_NOT_OK_RETURN(nt_status);
712 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
713 NT_STATUS_HAVE_NO_MEMORY(sam6);
714 sam6->base = sam3->base;
715 sam = &sam6->base;
716 sam6->sidcount = sam3->sidcount;
717 sam6->sids = sam3->sids;
719 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
720 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
721 sam->account_name.string, sam6->dns_domainname.string);
722 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
723 /* And put into the talloc tree */
724 talloc_steal(sam6, sam3);
726 r->out.validation->sam6 = sam6;
727 break;
729 default:
730 break;
733 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
734 /* It appears that level 6 is not individually encrypted */
735 if ((r->in.validation_level != 6) &&
736 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
737 /* This key is sent unencrypted without the ARCFOUR flag set */
738 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
739 netlogon_creds_arcfour_crypt(creds,
740 sam->key.key,
741 sizeof(sam->key.key));
745 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
746 /* It appears that level 6 is not individually encrypted */
747 if ((r->in.validation_level != 6) &&
748 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
749 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
750 netlogon_creds_arcfour_crypt(creds,
751 sam->LMSessKey.key,
752 sizeof(sam->LMSessKey.key));
753 } else {
754 netlogon_creds_des_encrypt_LMKey(creds,
755 &sam->LMSessKey);
759 *r->out.authoritative = 1;
761 /* TODO: Describe and deal with these flags */
762 *r->out.flags = 0;
764 return NT_STATUS_OK;
767 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
768 struct netr_LogonSamLogonEx *r)
770 NTSTATUS nt_status;
771 struct netlogon_creds_CredentialState *creds;
773 nt_status = schannel_get_creds_state(mem_ctx,
774 lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
775 r->in.computer_name, &creds);
776 if (!NT_STATUS_IS_OK(nt_status)) {
777 return nt_status;
780 if (!dce_call->conn->auth_state.auth_info ||
781 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
782 return NT_STATUS_ACCESS_DENIED;
784 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
788 netr_LogonSamLogonWithFlags
791 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
792 struct netr_LogonSamLogonWithFlags *r)
794 NTSTATUS nt_status;
795 struct netlogon_creds_CredentialState *creds;
796 struct netr_LogonSamLogonEx r2;
798 struct netr_Authenticator *return_authenticator;
800 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
801 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
803 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
804 mem_ctx,
805 r->in.computer_name,
806 r->in.credential, return_authenticator,
807 &creds);
808 NT_STATUS_NOT_OK_RETURN(nt_status);
810 ZERO_STRUCT(r2);
812 r2.in.server_name = r->in.server_name;
813 r2.in.computer_name = r->in.computer_name;
814 r2.in.logon_level = r->in.logon_level;
815 r2.in.logon = r->in.logon;
816 r2.in.validation_level = r->in.validation_level;
817 r2.in.flags = r->in.flags;
818 r2.out.validation = r->out.validation;
819 r2.out.authoritative = r->out.authoritative;
820 r2.out.flags = r->out.flags;
822 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
824 r->out.return_authenticator = return_authenticator;
826 return nt_status;
830 netr_LogonSamLogon
832 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833 struct netr_LogonSamLogon *r)
835 struct netr_LogonSamLogonWithFlags r2;
836 uint32_t flags = 0;
837 NTSTATUS status;
839 ZERO_STRUCT(r2);
841 r2.in.server_name = r->in.server_name;
842 r2.in.computer_name = r->in.computer_name;
843 r2.in.credential = r->in.credential;
844 r2.in.return_authenticator = r->in.return_authenticator;
845 r2.in.logon_level = r->in.logon_level;
846 r2.in.logon = r->in.logon;
847 r2.in.validation_level = r->in.validation_level;
848 r2.in.flags = &flags;
849 r2.out.validation = r->out.validation;
850 r2.out.authoritative = r->out.authoritative;
851 r2.out.flags = &flags;
853 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
855 r->out.return_authenticator = r2.out.return_authenticator;
857 return status;
862 netr_LogonSamLogoff
864 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
865 struct netr_LogonSamLogoff *r)
867 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
873 netr_DatabaseDeltas
875 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
876 struct netr_DatabaseDeltas *r)
878 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
883 netr_DatabaseSync2
885 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
886 struct netr_DatabaseSync2 *r)
888 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
889 return NT_STATUS_NOT_IMPLEMENTED;
894 netr_DatabaseSync
896 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
897 struct netr_DatabaseSync *r)
899 struct netr_DatabaseSync2 r2;
900 NTSTATUS status;
902 ZERO_STRUCT(r2);
904 r2.in.logon_server = r->in.logon_server;
905 r2.in.computername = r->in.computername;
906 r2.in.credential = r->in.credential;
907 r2.in.database_id = r->in.database_id;
908 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
909 r2.in.sync_context = r->in.sync_context;
910 r2.out.sync_context = r->out.sync_context;
911 r2.out.delta_enum_array = r->out.delta_enum_array;
912 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
914 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
916 return status;
921 netr_AccountDeltas
923 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
924 struct netr_AccountDeltas *r)
926 /* w2k3 returns "NOT IMPLEMENTED" for this call */
927 return NT_STATUS_NOT_IMPLEMENTED;
932 netr_AccountSync
934 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
935 struct netr_AccountSync *r)
937 /* w2k3 returns "NOT IMPLEMENTED" for this call */
938 return NT_STATUS_NOT_IMPLEMENTED;
943 netr_GetDcName
945 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946 struct netr_GetDcName *r)
948 const char * const attrs[] = { NULL };
949 struct ldb_context *sam_ctx;
950 struct ldb_message **res;
951 struct ldb_dn *domain_dn;
952 int ret;
953 const char *dcname;
956 * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
957 * that the domainname needs to be a valid netbios domain
958 * name, if it is not NULL.
960 if (r->in.domainname) {
961 const char *dot = strchr(r->in.domainname, '.');
962 size_t len = strlen(r->in.domainname);
964 if (dot || len > 15) {
965 return WERR_DCNOTFOUND;
969 * TODO: Should we also varify that only valid
970 * netbios name characters are used?
974 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
975 dce_call->conn->dce_ctx->lp_ctx,
976 dce_call->conn->auth_state.session_info, 0);
977 if (sam_ctx == NULL) {
978 return WERR_DS_UNAVAILABLE;
981 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
982 r->in.domainname);
983 if (domain_dn == NULL) {
984 return WERR_DS_UNAVAILABLE;
987 ret = gendb_search_dn(sam_ctx, mem_ctx,
988 domain_dn, &res, attrs);
989 if (ret != 1) {
990 return WERR_NO_SUCH_DOMAIN;
993 /* TODO: - return real IP address
994 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
996 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
997 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
998 W_ERROR_HAVE_NO_MEMORY(dcname);
1000 *r->out.dcname = dcname;
1001 return WERR_OK;
1006 netr_LogonControl2Ex
1008 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1009 struct netr_LogonControl2Ex *r)
1011 return WERR_NOT_SUPPORTED;
1016 netr_LogonControl
1018 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1019 struct netr_LogonControl *r)
1021 struct netr_LogonControl2Ex r2;
1022 WERROR werr;
1024 if (r->in.level == 0x00000001) {
1025 ZERO_STRUCT(r2);
1027 r2.in.logon_server = r->in.logon_server;
1028 r2.in.function_code = r->in.function_code;
1029 r2.in.level = r->in.level;
1030 r2.in.data = NULL;
1031 r2.out.query = r->out.query;
1033 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1034 } else if (r->in.level == 0x00000002) {
1035 werr = WERR_NOT_SUPPORTED;
1036 } else {
1037 werr = WERR_UNKNOWN_LEVEL;
1040 return werr;
1045 netr_LogonControl2
1047 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1048 struct netr_LogonControl2 *r)
1050 struct netr_LogonControl2Ex r2;
1051 WERROR werr;
1053 ZERO_STRUCT(r2);
1055 r2.in.logon_server = r->in.logon_server;
1056 r2.in.function_code = r->in.function_code;
1057 r2.in.level = r->in.level;
1058 r2.in.data = r->in.data;
1059 r2.out.query = r->out.query;
1061 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1063 return werr;
1066 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1067 struct ldb_context *sam_ctx,
1068 struct netr_DomainTrustList *trusts,
1069 uint32_t trust_flags);
1072 netr_GetAnyDCName
1074 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1075 struct netr_GetAnyDCName *r)
1077 struct netr_DomainTrustList *trusts;
1078 struct ldb_context *sam_ctx;
1079 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1080 uint32_t i;
1081 WERROR werr;
1083 *r->out.dcname = NULL;
1085 if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1086 /* if the domainname parameter wasn't set assume our domain */
1087 r->in.domainname = lpcfg_workgroup(lp_ctx);
1090 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1091 dce_call->conn->auth_state.session_info, 0);
1092 if (sam_ctx == NULL) {
1093 return WERR_DS_UNAVAILABLE;
1096 if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1097 /* well we asked for a DC of our own domain */
1098 if (samdb_is_pdc(sam_ctx)) {
1099 /* we are the PDC of the specified domain */
1100 return WERR_NO_SUCH_DOMAIN;
1103 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1104 lpcfg_netbios_name(lp_ctx));
1105 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1107 return WERR_OK;
1110 /* Okay, now we have to consider the trusted domains */
1112 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1113 W_ERROR_HAVE_NO_MEMORY(trusts);
1115 trusts->count = 0;
1117 werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1118 NETR_TRUST_FLAG_INBOUND
1119 | NETR_TRUST_FLAG_OUTBOUND);
1120 W_ERROR_NOT_OK_RETURN(werr);
1122 for (i = 0; i < trusts->count; i++) {
1123 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1124 /* FIXME: Here we need to find a DC for the specified
1125 * trusted domain. */
1127 /* return WERR_OK; */
1128 return WERR_NO_SUCH_DOMAIN;
1132 return WERR_NO_SUCH_DOMAIN;
1137 netr_DatabaseRedo
1139 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1140 struct netr_DatabaseRedo *r)
1142 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1147 netr_NetrEnumerateTrustedDomains
1149 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1150 struct netr_NetrEnumerateTrustedDomains *r)
1152 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1157 netr_LogonGetCapabilities
1159 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1160 struct netr_LogonGetCapabilities *r)
1162 /* we don't support AES yet */
1163 return NT_STATUS_NOT_IMPLEMENTED;
1168 netr_NETRLOGONSETSERVICEBITS
1170 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1171 struct netr_NETRLOGONSETSERVICEBITS *r)
1173 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1178 netr_LogonGetTrustRid
1180 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1181 struct netr_LogonGetTrustRid *r)
1183 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1188 netr_NETRLOGONCOMPUTESERVERDIGEST
1190 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1191 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1193 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1198 netr_NETRLOGONCOMPUTECLIENTDIGEST
1200 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1201 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1203 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1209 netr_DsRGetSiteName
1211 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1212 struct netr_DsRGetSiteName *r)
1214 struct ldb_context *sam_ctx;
1215 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1217 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1218 dce_call->conn->auth_state.session_info, 0);
1219 if (sam_ctx == NULL) {
1220 return WERR_DS_UNAVAILABLE;
1223 *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1224 W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1226 return WERR_OK;
1231 fill in a netr_OneDomainInfo from a ldb search result
1233 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1234 struct loadparm_context *lp_ctx,
1235 struct ldb_context *sam_ctx,
1236 struct ldb_message *res,
1237 struct netr_OneDomainInfo *info,
1238 bool is_local, bool is_trust_list)
1240 ZERO_STRUCTP(info);
1242 if (is_trust_list) {
1243 /* w2k8 only fills this on trusted domains */
1244 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1245 info->trust_extension.length = 16;
1246 info->trust_extension.info->flags =
1247 NETR_TRUST_FLAG_TREEROOT |
1248 NETR_TRUST_FLAG_IN_FOREST |
1249 NETR_TRUST_FLAG_PRIMARY |
1250 NETR_TRUST_FLAG_NATIVE;
1252 info->trust_extension.info->parent_index = 0; /* should be index into array
1253 of parent */
1254 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1255 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1258 if (is_trust_list) {
1259 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1260 info->dns_forestname.string = NULL;
1261 } else {
1262 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1263 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1264 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1265 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1268 if (is_local) {
1269 info->domainname.string = lpcfg_workgroup(lp_ctx);
1270 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1271 info->domain_guid = samdb_result_guid(res, "objectGUID");
1272 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1273 } else {
1274 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1275 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1276 info->domain_guid = samdb_result_guid(res, "objectGUID");
1277 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1279 if (!is_trust_list) {
1280 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1283 return NT_STATUS_OK;
1287 netr_LogonGetDomainInfo
1288 this is called as part of the ADS domain logon procedure.
1290 It has an important role in convaying details about the client, such
1291 as Operating System, Version, Service Pack etc.
1293 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1294 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1296 struct netlogon_creds_CredentialState *creds;
1297 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1298 "securityIdentifier", "trustPartner", NULL };
1299 const char * const attrs2[] = { "dNSHostName",
1300 "msDS-SupportedEncryptionTypes", NULL };
1301 const char *temp_str, *temp_str2;
1302 const char *old_dns_hostname;
1303 struct ldb_context *sam_ctx;
1304 struct ldb_message **res1, **res2, **res3, *new_msg;
1305 struct ldb_dn *workstation_dn;
1306 struct netr_DomainInformation *domain_info;
1307 struct netr_LsaPolicyInformation *lsa_policy_info;
1308 struct netr_OsVersionInfoEx *os_version;
1309 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1310 bool update_dns_hostname = true;
1311 int ret, ret3, i;
1312 NTSTATUS status;
1314 status = dcesrv_netr_creds_server_step_check(dce_call,
1315 mem_ctx,
1316 r->in.computer_name,
1317 r->in.credential,
1318 r->out.return_authenticator,
1319 &creds);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 DEBUG(0,(__location__ " Bad credentials - error\n"));
1323 NT_STATUS_NOT_OK_RETURN(status);
1325 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1326 dce_call->conn->dce_ctx->lp_ctx,
1327 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1328 if (sam_ctx == NULL) {
1329 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1332 switch (r->in.level) {
1333 case 1: /* Domain information */
1335 if (r->in.query->workstation_info == NULL) {
1336 return NT_STATUS_INVALID_PARAMETER;
1340 * Checks that the computer name parameter without possible "$"
1341 * matches as prefix with the DNS hostname in the workstation
1342 * info structure.
1344 temp_str = talloc_strndup(mem_ctx,
1345 r->in.computer_name,
1346 strcspn(r->in.computer_name, "$"));
1347 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1348 temp_str2 = talloc_strndup(mem_ctx,
1349 r->in.query->workstation_info->dns_hostname,
1350 strcspn(r->in.query->workstation_info->dns_hostname, "."));
1351 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1352 if (strcasecmp(temp_str, temp_str2) != 0) {
1353 update_dns_hostname = false;
1356 /* Prepare the workstation DN */
1357 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1358 dom_sid_string(mem_ctx, creds->sid));
1359 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1361 /* Lookup for attributes in workstation object */
1362 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1363 &res1, attrs2);
1364 if (ret != 1) {
1365 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1368 /* Gets the old DNS hostname */
1369 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0], "dNSHostName",
1370 NULL);
1373 * Updates the DNS hostname when the client wishes that the
1374 * server should handle this for him
1375 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1376 * obviously only checked when we do already have a
1377 * "dNSHostName".
1378 * See MS-NRPC section 3.5.4.3.9
1380 if ((old_dns_hostname != NULL) &&
1381 (r->in.query->workstation_info->workstation_flags
1382 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1383 update_dns_hostname = false;
1386 /* Gets host informations and put them into our directory */
1388 new_msg = ldb_msg_new(mem_ctx);
1389 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1391 new_msg->dn = workstation_dn;
1393 /* Sets the OS name */
1394 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1395 "operatingSystem",
1396 r->in.query->workstation_info->os_name.string);
1399 * Sets informations from "os_version". On an empty structure
1400 * the values are cleared.
1402 if (r->in.query->workstation_info->os_version.os != NULL) {
1403 os_version = &r->in.query->workstation_info->os_version.os->os;
1405 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1406 "operatingSystemServicePack",
1407 os_version->CSDVersion);
1409 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1410 "operatingSystemVersion",
1411 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1412 os_version->MajorVersion,
1413 os_version->MinorVersion,
1414 os_version->BuildNumber
1417 } else {
1418 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1419 "operatingSystemServicePack");
1421 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1422 "operatingSystemVersion");
1426 * If the boolean "update_dns_hostname" remained true, then we
1427 * are fine to start the update.
1429 if (update_dns_hostname) {
1430 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1431 "dNSHostname",
1432 r->in.query->workstation_info->dns_hostname);
1434 ldb_msg_add_string(new_msg, "servicePrincipalName",
1435 talloc_asprintf(new_msg, "HOST/%s",
1436 r->in.computer_name));
1437 ldb_msg_add_string(new_msg, "servicePrincipalName",
1438 talloc_asprintf(new_msg, "HOST/%s",
1439 r->in.query->workstation_info->dns_hostname));
1442 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1443 DEBUG(3,("Impossible to update samdb: %s\n",
1444 ldb_errstring(sam_ctx)));
1447 talloc_free(new_msg);
1449 /* Writes back the domain information */
1451 /* We need to do two searches. The first will pull our primary
1452 domain and the second will pull any trusted domains. Our
1453 primary domain is also a "trusted" domain, so we need to
1454 put the primary domain into the lists of returned trusts as
1455 well. */
1456 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1457 &res2, attrs);
1458 if (ret != 1) {
1459 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1462 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1463 "(objectClass=trustedDomain)");
1464 if (ret3 == -1) {
1465 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1468 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1469 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1471 ZERO_STRUCTP(domain_info);
1473 /* Informations about the local and trusted domains */
1475 status = fill_one_domain_info(mem_ctx,
1476 dce_call->conn->dce_ctx->lp_ctx,
1477 sam_ctx, res2[0], &domain_info->primary_domain,
1478 true, false);
1479 NT_STATUS_NOT_OK_RETURN(status);
1481 domain_info->trusted_domain_count = ret3 + 1;
1482 domain_info->trusted_domains = talloc_array(mem_ctx,
1483 struct netr_OneDomainInfo,
1484 domain_info->trusted_domain_count);
1485 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1487 for (i=0;i<ret3;i++) {
1488 status = fill_one_domain_info(mem_ctx,
1489 dce_call->conn->dce_ctx->lp_ctx,
1490 sam_ctx, res3[i],
1491 &domain_info->trusted_domains[i],
1492 false, true);
1493 NT_STATUS_NOT_OK_RETURN(status);
1496 status = fill_one_domain_info(mem_ctx,
1497 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1498 &domain_info->trusted_domains[i], true, true);
1499 NT_STATUS_NOT_OK_RETURN(status);
1501 /* Sets the supported encryption types */
1502 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1503 "msDS-SupportedEncryptionTypes",
1504 default_supported_enc_types);
1506 /* Other host domain informations */
1508 lsa_policy_info = talloc(mem_ctx,
1509 struct netr_LsaPolicyInformation);
1510 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1511 ZERO_STRUCTP(lsa_policy_info);
1513 domain_info->lsa_policy = *lsa_policy_info;
1515 /* The DNS hostname is only returned back when there is a chance
1516 * for a change. */
1517 if ((r->in.query->workstation_info->workstation_flags
1518 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1519 domain_info->dns_hostname.string = old_dns_hostname;
1520 } else {
1521 domain_info->dns_hostname.string = NULL;
1524 domain_info->workstation_flags =
1525 r->in.query->workstation_info->workstation_flags;
1527 r->out.info->domain_info = domain_info;
1528 break;
1529 case 2: /* LSA policy information - not used at the moment */
1530 lsa_policy_info = talloc(mem_ctx,
1531 struct netr_LsaPolicyInformation);
1532 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1533 ZERO_STRUCTP(lsa_policy_info);
1535 r->out.info->lsa_policy_info = lsa_policy_info;
1536 break;
1537 default:
1538 return NT_STATUS_INVALID_LEVEL;
1539 break;
1542 return NT_STATUS_OK;
1548 netr_ServerPasswordGet
1550 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551 struct netr_ServerPasswordGet *r)
1553 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1558 netr_NETRLOGONSENDTOSAM
1560 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1561 struct netr_NETRLOGONSENDTOSAM *r)
1563 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1568 netr_DsRGetDCNameEx2
1570 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1571 TALLOC_CTX *mem_ctx,
1572 struct netr_DsRGetDCNameEx2 *r)
1574 struct ldb_context *sam_ctx;
1575 struct netr_DsRGetDCNameInfo *info;
1576 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1577 const struct tsocket_address *remote_address;
1578 char *addr = NULL;
1579 const char *server_site_name;
1580 char *guid_str;
1581 struct netlogon_samlogon_response response;
1582 NTSTATUS status;
1583 const char *dc_name = NULL;
1584 const char *domain_name = NULL;
1586 ZERO_STRUCTP(r->out.info);
1588 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1589 dce_call->conn->auth_state.session_info, 0);
1590 if (sam_ctx == NULL) {
1591 return WERR_DS_UNAVAILABLE;
1594 remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1595 if (tsocket_address_is_inet(remote_address, "ip")) {
1596 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1597 W_ERROR_HAVE_NO_MEMORY(addr);
1600 /* "server_unc" is ignored by w2k3 */
1602 if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1603 return WERR_INVALID_FLAGS;
1606 if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1607 r->in.flags & DS_PDC_REQUIRED &&
1608 r->in.flags & DS_KDC_REQUIRED) {
1609 return WERR_INVALID_FLAGS;
1611 if (r->in.flags & DS_IS_FLAT_NAME &&
1612 r->in.flags & DS_IS_DNS_NAME) {
1613 return WERR_INVALID_FLAGS;
1615 if (r->in.flags & DS_RETURN_DNS_NAME &&
1616 r->in.flags & DS_RETURN_FLAT_NAME) {
1617 return WERR_INVALID_FLAGS;
1619 if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1620 r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1621 return WERR_INVALID_FLAGS;
1624 if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1625 r->in.flags &
1626 (DS_DIRECTORY_SERVICE_REQUIRED |
1627 DS_DIRECTORY_SERVICE_PREFERRED |
1628 DS_GC_SERVER_REQUIRED |
1629 DS_PDC_REQUIRED |
1630 DS_KDC_REQUIRED)) {
1631 return WERR_INVALID_FLAGS;
1634 if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1635 r->in.site_name) {
1636 return WERR_INVALID_FLAGS;
1639 /* Proof server site parameter "site_name" if it was specified */
1640 server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1641 W_ERROR_HAVE_NO_MEMORY(server_site_name);
1642 if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1643 server_site_name) != 0)) {
1644 return WERR_NO_SUCH_DOMAIN;
1647 guid_str = r->in.domain_guid != NULL ?
1648 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1650 status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1651 r->in.domain_name,
1652 r->in.domain_name,
1653 NULL, guid_str,
1654 r->in.client_account,
1655 r->in.mask, addr,
1656 NETLOGON_NT_VERSION_5EX_WITH_IP,
1657 lp_ctx, &response, true);
1658 if (!NT_STATUS_IS_OK(status)) {
1659 return ntstatus_to_werror(status);
1662 if (r->in.flags & DS_RETURN_DNS_NAME) {
1663 dc_name = response.data.nt5_ex.pdc_dns_name;
1664 domain_name = response.data.nt5_ex.dns_domain;
1665 } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1666 dc_name = response.data.nt5_ex.pdc_name;
1667 domain_name = response.data.nt5_ex.domain_name;
1668 } else {
1671 * TODO: autodetect what we need to return
1672 * based on the given arguments
1674 dc_name = response.data.nt5_ex.pdc_name;
1675 domain_name = response.data.nt5_ex.domain_name;
1678 if (!dc_name || !dc_name[0]) {
1679 return WERR_NO_SUCH_DOMAIN;
1682 if (!domain_name || !domain_name[0]) {
1683 return WERR_NO_SUCH_DOMAIN;
1686 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1687 W_ERROR_HAVE_NO_MEMORY(info);
1688 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1689 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1690 info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1691 response.data.nt5_ex.sockaddr.pdc_ip);
1692 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1693 info->dc_address_type = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
1694 info->domain_guid = response.data.nt5_ex.domain_uuid;
1695 info->domain_name = domain_name;
1696 info->forest_name = response.data.nt5_ex.forest;
1697 info->dc_flags = response.data.nt5_ex.server_type;
1698 info->dc_site_name = response.data.nt5_ex.server_site;
1699 info->client_site_name = response.data.nt5_ex.client_site;
1701 *r->out.info = info;
1703 return WERR_OK;
1707 netr_DsRGetDCNameEx
1709 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1710 struct netr_DsRGetDCNameEx *r)
1712 struct netr_DsRGetDCNameEx2 r2;
1713 WERROR werr;
1715 ZERO_STRUCT(r2);
1717 r2.in.server_unc = r->in.server_unc;
1718 r2.in.client_account = NULL;
1719 r2.in.mask = 0;
1720 r2.in.domain_guid = r->in.domain_guid;
1721 r2.in.domain_name = r->in.domain_name;
1722 r2.in.site_name = r->in.site_name;
1723 r2.in.flags = r->in.flags;
1724 r2.out.info = r->out.info;
1726 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1728 return werr;
1732 netr_DsRGetDCName
1734 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1735 struct netr_DsRGetDCName *r)
1737 struct netr_DsRGetDCNameEx2 r2;
1738 WERROR werr;
1740 ZERO_STRUCT(r2);
1742 r2.in.server_unc = r->in.server_unc;
1743 r2.in.client_account = NULL;
1744 r2.in.mask = 0;
1745 r2.in.domain_name = r->in.domain_name;
1746 r2.in.domain_guid = r->in.domain_guid;
1748 r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1749 r2.in.flags = r->in.flags;
1750 r2.out.info = r->out.info;
1752 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1754 return werr;
1757 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1759 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1760 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1762 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1767 netr_NetrEnumerateTrustedDomainsEx
1769 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1770 struct netr_NetrEnumerateTrustedDomainsEx *r)
1772 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1777 netr_DsRAddressToSitenamesExW
1779 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1780 struct netr_DsRAddressToSitenamesExW *r)
1782 struct ldb_context *sam_ctx;
1783 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1784 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1785 sa_family_t sin_family;
1786 struct sockaddr_in *addr;
1787 #ifdef HAVE_IPV6
1788 struct sockaddr_in6 *addr6;
1789 char addr_str[INET6_ADDRSTRLEN];
1790 #else
1791 char addr_str[INET_ADDRSTRLEN];
1792 #endif
1793 char *subnet_name;
1794 const char *res;
1795 uint32_t i;
1797 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1798 dce_call->conn->auth_state.session_info, 0);
1799 if (sam_ctx == NULL) {
1800 return WERR_DS_UNAVAILABLE;
1803 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1804 W_ERROR_HAVE_NO_MEMORY(ctr);
1806 *r->out.ctr = ctr;
1808 ctr->count = r->in.count;
1809 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1810 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1811 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1812 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1814 for (i=0; i<ctr->count; i++) {
1815 ctr->sitename[i].string = NULL;
1816 ctr->subnetname[i].string = NULL;
1818 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1819 continue;
1821 /* The first two byte of the buffer are reserved for the
1822 * "sin_family" but for now only the first one is used. */
1823 sin_family = r->in.addresses[i].buffer[0];
1825 switch (sin_family) {
1826 case AF_INET:
1827 if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
1828 continue;
1830 addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
1831 res = inet_ntop(AF_INET, &addr->sin_addr,
1832 addr_str, sizeof(addr_str));
1833 break;
1834 #ifdef HAVE_IPV6
1835 case AF_INET6:
1836 if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
1837 continue;
1839 addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
1840 res = inet_ntop(AF_INET6, &addr6->sin6_addr,
1841 addr_str, sizeof(addr_str));
1842 break;
1843 #endif
1844 default:
1845 continue;
1848 if (res == NULL) {
1849 continue;
1852 ctr->sitename[i].string = samdb_client_site_name(sam_ctx,
1853 mem_ctx,
1854 addr_str,
1855 &subnet_name);
1856 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
1857 ctr->subnetname[i].string = subnet_name;
1860 return WERR_OK;
1865 netr_DsRAddressToSitenamesW
1867 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1868 struct netr_DsRAddressToSitenamesW *r)
1870 struct netr_DsRAddressToSitenamesExW r2;
1871 struct netr_DsRAddressToSitenamesWCtr *ctr;
1872 uint32_t i;
1873 WERROR werr;
1875 ZERO_STRUCT(r2);
1877 r2.in.server_name = r->in.server_name;
1878 r2.in.count = r->in.count;
1879 r2.in.addresses = r->in.addresses;
1881 r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
1882 W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
1884 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
1885 W_ERROR_HAVE_NO_MEMORY(ctr);
1887 *r->out.ctr = ctr;
1889 ctr->count = r->in.count;
1890 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1891 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1893 werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
1895 for (i=0; i<ctr->count; i++) {
1896 ctr->sitename[i].string = (*r2.out.ctr)->sitename[i].string;
1899 return werr;
1904 netr_DsrGetDcSiteCoverageW
1906 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1907 struct netr_DsrGetDcSiteCoverageW *r)
1909 struct ldb_context *sam_ctx;
1910 struct DcSitesCtr *ctr;
1911 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1913 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1914 dce_call->conn->auth_state.session_info, 0);
1915 if (sam_ctx == NULL) {
1916 return WERR_DS_UNAVAILABLE;
1919 ctr = talloc(mem_ctx, struct DcSitesCtr);
1920 W_ERROR_HAVE_NO_MEMORY(ctr);
1922 *r->out.ctr = ctr;
1924 /* For now only return our default site */
1925 ctr->num_sites = 1;
1926 ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
1927 W_ERROR_HAVE_NO_MEMORY(ctr->sites);
1928 ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
1929 W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
1931 return WERR_OK;
1935 #define GET_CHECK_STR(dest, mem, msg, attr) \
1936 do {\
1937 const char *s; \
1938 s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
1939 if (!s) { \
1940 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1941 "without flatname\n", \
1942 ldb_dn_get_linearized(msg->dn))); \
1943 continue; \
1945 dest = talloc_strdup(mem, s); \
1946 W_ERROR_HAVE_NO_MEMORY(dest); \
1947 } while(0)
1950 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1951 struct ldb_context *sam_ctx,
1952 struct netr_DomainTrustList *trusts,
1953 uint32_t trust_flags)
1955 struct ldb_dn *system_dn;
1956 struct ldb_message **dom_res = NULL;
1957 const char *trust_attrs[] = { "flatname", "trustPartner",
1958 "securityIdentifier", "trustDirection",
1959 "trustType", "trustAttributes", NULL };
1960 uint32_t n;
1961 int i;
1962 int ret;
1964 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1965 NETR_TRUST_FLAG_OUTBOUND))) {
1966 return WERR_INVALID_FLAGS;
1969 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1970 ldb_get_default_basedn(sam_ctx),
1971 "(&(objectClass=container)(cn=System))");
1972 if (!system_dn) {
1973 return WERR_GENERAL_FAILURE;
1976 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1977 &dom_res, trust_attrs,
1978 "(objectclass=trustedDomain)");
1980 for (i = 0; i < ret; i++) {
1981 unsigned int trust_dir;
1982 uint32_t flags = 0;
1984 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
1985 "trustDirection", 0);
1987 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1988 flags |= NETR_TRUST_FLAG_INBOUND;
1990 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1991 flags |= NETR_TRUST_FLAG_OUTBOUND;
1994 if (!(flags & trust_flags)) {
1995 /* this trust direction was not requested */
1996 continue;
1999 n = trusts->count;
2000 trusts->array = talloc_realloc(trusts, trusts->array,
2001 struct netr_DomainTrust,
2002 n + 1);
2003 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2005 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
2006 dom_res[i], "flatname");
2007 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
2008 dom_res[i], "trustPartner");
2010 trusts->array[n].trust_flags = flags;
2011 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2012 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2013 /* TODO: find if we have parent in the list */
2014 trusts->array[n].parent_index = 0;
2017 trusts->array[n].trust_type =
2018 ldb_msg_find_attr_as_uint(dom_res[i],
2019 "trustType", 0);
2020 trusts->array[n].trust_attributes =
2021 ldb_msg_find_attr_as_uint(dom_res[i],
2022 "trustAttributes", 0);
2024 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2025 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2026 struct dom_sid zero_sid;
2027 ZERO_STRUCT(zero_sid);
2028 trusts->array[n].sid =
2029 dom_sid_dup(trusts, &zero_sid);
2030 } else {
2031 trusts->array[n].sid =
2032 samdb_result_dom_sid(trusts, dom_res[i],
2033 "securityIdentifier");
2035 trusts->array[n].guid = GUID_zero();
2037 trusts->count = n + 1;
2040 talloc_free(dom_res);
2041 return WERR_OK;
2045 netr_DsrEnumerateDomainTrusts
2047 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2048 TALLOC_CTX *mem_ctx,
2049 struct netr_DsrEnumerateDomainTrusts *r)
2051 struct netr_DomainTrustList *trusts;
2052 struct ldb_context *sam_ctx;
2053 int ret;
2054 struct ldb_message **dom_res;
2055 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2056 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2057 const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2058 const char *p;
2059 WERROR werr;
2061 if (r->in.trust_flags & 0xFFFFFE00) {
2062 return WERR_INVALID_FLAGS;
2065 /* TODO: turn to hard check once we are sure this is 100% correct */
2066 if (!r->in.server_name) {
2067 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2068 "But received NULL!\n", dnsdomain));
2069 } else {
2070 p = strchr(r->in.server_name, '.');
2071 if (!p) {
2072 DEBUG(3, ("Invalid domain! Expected name in domain "
2073 "[%s]. But received [%s]!\n",
2074 dnsdomain, r->in.server_name));
2075 p = r->in.server_name;
2076 } else {
2077 p++;
2079 if (strcasecmp(p, dnsdomain)) {
2080 DEBUG(3, ("Invalid domain! Expected name in domain "
2081 "[%s]. But received [%s]!\n",
2082 dnsdomain, r->in.server_name));
2086 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2087 W_ERROR_HAVE_NO_MEMORY(trusts);
2089 trusts->count = 0;
2090 r->out.trusts = trusts;
2092 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2093 dce_call->conn->auth_state.session_info, 0);
2094 if (sam_ctx == NULL) {
2095 return WERR_GENERAL_FAILURE;
2098 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2099 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2101 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2102 trusts, r->in.trust_flags);
2103 W_ERROR_NOT_OK_RETURN(werr);
2106 /* NOTE: we currently are always the root of the forest */
2107 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2108 uint32_t n = trusts->count;
2110 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2111 &dom_res, dom_attrs);
2112 if (ret != 1) {
2113 return WERR_GENERAL_FAILURE;
2116 trusts->count = n + 1;
2117 trusts->array = talloc_realloc(trusts, trusts->array,
2118 struct netr_DomainTrust,
2119 trusts->count);
2120 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2122 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2123 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2124 trusts->array[n].trust_flags =
2125 NETR_TRUST_FLAG_NATIVE |
2126 NETR_TRUST_FLAG_TREEROOT |
2127 NETR_TRUST_FLAG_IN_FOREST |
2128 NETR_TRUST_FLAG_PRIMARY;
2129 /* we are always the root domain for now */
2130 trusts->array[n].parent_index = 0;
2131 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2132 trusts->array[n].trust_attributes = 0;
2133 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2134 dom_res[0],
2135 "objectSid");
2136 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2137 "objectGUID");
2138 talloc_free(dom_res);
2141 return WERR_OK;
2146 netr_DsrDeregisterDNSHostRecords
2148 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2149 struct netr_DsrDeregisterDNSHostRecords *r)
2151 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2156 netr_ServerTrustPasswordsGet
2158 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2159 struct netr_ServerTrustPasswordsGet *r)
2161 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2165 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2166 struct ldb_context *sam_ctx,
2167 struct loadparm_context *lp_ctx,
2168 struct lsa_ForestTrustInformation *info)
2170 struct lsa_ForestTrustDomainInfo *domain_info;
2171 struct lsa_ForestTrustRecord *e;
2172 struct ldb_message **dom_res;
2173 const char * const dom_attrs[] = { "objectSid", NULL };
2174 int ret;
2176 /* we need to provide 2 entries:
2177 * 1. the Root Forest name
2178 * 2. the Domain Information
2181 info->count = 2;
2182 info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2183 W_ERROR_HAVE_NO_MEMORY(info->entries);
2185 /* Forest root info */
2186 e = talloc(info, struct lsa_ForestTrustRecord);
2187 W_ERROR_HAVE_NO_MEMORY(e);
2189 e->flags = 0;
2190 e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2191 e->time = 0; /* so far always 0 in trces. */
2192 e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2193 mem_ctx);
2194 W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2196 info->entries[0] = e;
2198 /* Domain info */
2199 e = talloc(info, struct lsa_ForestTrustRecord);
2200 W_ERROR_HAVE_NO_MEMORY(e);
2202 /* get our own domain info */
2203 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2204 if (ret != 1) {
2205 return WERR_GENERAL_FAILURE;
2208 /* TODO: check if disabled and set flags accordingly */
2209 e->flags = 0;
2210 e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2211 e->time = 0; /* so far always 0 in traces. */
2213 domain_info = &e->forest_trust_data.domain_info;
2214 domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2215 "objectSid");
2216 domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2217 domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2219 info->entries[1] = e;
2221 talloc_free(dom_res);
2223 return WERR_OK;
2227 netr_DsRGetForestTrustInformation
2229 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2230 TALLOC_CTX *mem_ctx,
2231 struct netr_DsRGetForestTrustInformation *r)
2233 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2234 struct lsa_ForestTrustInformation *info, **info_ptr;
2235 struct ldb_context *sam_ctx;
2236 WERROR werr;
2238 if (r->in.flags & 0xFFFFFFFE) {
2239 return WERR_INVALID_FLAGS;
2242 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2243 dce_call->conn->auth_state.session_info, 0);
2244 if (sam_ctx == NULL) {
2245 return WERR_GENERAL_FAILURE;
2248 if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2249 if (!samdb_is_pdc(sam_ctx)) {
2250 return WERR_NERR_NOTPRIMARY;
2253 if (r->in.trusted_domain_name == NULL) {
2254 return WERR_INVALID_FLAGS;
2257 /* TODO: establish an schannel connection with
2258 * r->in.trusted_domain_name and perform a
2259 * netr_GetForestTrustInformation call against it */
2261 /* for now return not implementd */
2262 return WERR_CALL_NOT_IMPLEMENTED;
2265 /* TODO: check r->in.server_name is our name */
2267 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2268 W_ERROR_HAVE_NO_MEMORY(info_ptr);
2270 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2271 W_ERROR_HAVE_NO_MEMORY(info);
2273 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2274 W_ERROR_NOT_OK_RETURN(werr);
2276 *info_ptr = info;
2277 r->out.forest_trust_info = info_ptr;
2279 return WERR_OK;
2284 netr_GetForestTrustInformation
2286 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2287 TALLOC_CTX *mem_ctx,
2288 struct netr_GetForestTrustInformation *r)
2290 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2291 struct netlogon_creds_CredentialState *creds;
2292 struct lsa_ForestTrustInformation *info, **info_ptr;
2293 struct ldb_context *sam_ctx;
2294 NTSTATUS status;
2295 WERROR werr;
2297 status = dcesrv_netr_creds_server_step_check(dce_call,
2298 mem_ctx,
2299 r->in.computer_name,
2300 r->in.credential,
2301 r->out.return_authenticator,
2302 &creds);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 return status;
2307 if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2308 (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2309 return NT_STATUS_NOT_IMPLEMENTED;
2312 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2313 dce_call->conn->auth_state.session_info, 0);
2314 if (sam_ctx == NULL) {
2315 return NT_STATUS_UNSUCCESSFUL;
2318 /* TODO: check r->in.server_name is our name */
2320 info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2321 if (!info_ptr) {
2322 return NT_STATUS_NO_MEMORY;
2324 info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2325 if (!info) {
2326 return NT_STATUS_NO_MEMORY;
2329 werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2330 if (!W_ERROR_IS_OK(werr)) {
2331 return werror_to_ntstatus(werr);
2334 *info_ptr = info;
2335 r->out.forest_trust_info = info_ptr;
2337 return NT_STATUS_OK;
2342 netr_ServerGetTrustInfo
2344 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2345 struct netr_ServerGetTrustInfo *r)
2347 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2351 netr_Unused47
2353 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2354 struct netr_Unused47 *r)
2356 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2360 struct netr_dnsupdate_RODC_state {
2361 struct dcesrv_call_state *dce_call;
2362 struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2363 struct dnsupdate_RODC *r2;
2367 called when the forwarded RODC dns update request is finished
2369 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2371 struct netr_dnsupdate_RODC_state *st =
2372 tevent_req_callback_data(subreq,
2373 struct netr_dnsupdate_RODC_state);
2374 NTSTATUS status;
2376 status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2377 TALLOC_FREE(subreq);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2380 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2383 st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2385 status = dcesrv_reply(st->dce_call);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2392 netr_DsrUpdateReadOnlyServerDnsRecords
2394 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2395 TALLOC_CTX *mem_ctx,
2396 struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2398 struct netlogon_creds_CredentialState *creds;
2399 NTSTATUS nt_status;
2400 struct dcerpc_binding_handle *binding_handle;
2401 struct netr_dnsupdate_RODC_state *st;
2402 struct tevent_req *subreq;
2404 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2405 mem_ctx,
2406 r->in.computer_name,
2407 r->in.credential,
2408 r->out.return_authenticator,
2409 &creds);
2410 NT_STATUS_NOT_OK_RETURN(nt_status);
2412 if (creds->secure_channel_type != SEC_CHAN_RODC) {
2413 return NT_STATUS_ACCESS_DENIED;
2416 st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2417 NT_STATUS_HAVE_NO_MEMORY(st);
2419 st->dce_call = dce_call;
2420 st->r = r;
2421 st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2422 NT_STATUS_HAVE_NO_MEMORY(st->r2);
2424 st->r2->in.dom_sid = creds->sid;
2425 st->r2->in.site_name = r->in.site_name;
2426 st->r2->in.dns_ttl = r->in.dns_ttl;
2427 st->r2->in.dns_names = r->in.dns_names;
2428 st->r2->out.dns_names = r->out.dns_names;
2430 binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2431 "dnsupdate", &ndr_table_irpc);
2432 if (binding_handle == NULL) {
2433 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2434 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2435 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2438 /* forward the call */
2439 subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2440 binding_handle, st->r2);
2441 NT_STATUS_HAVE_NO_MEMORY(subreq);
2443 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2445 /* setup the callback */
2446 tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2448 return NT_STATUS_OK;
2452 /* include the generated boilerplate */
2453 #include "librpc/gen_ndr/ndr_netlogon_s.c"