s4:netlogon enhance DsrEnumerateDomainTrusts
[Samba/ekacnet.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobde741d52848cdea9c3cc2422acc335abcf9b4114
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 "auth/gensec/schannel_state.h"
32 #include "libcli/security/security.h"
33 #include "param/param.h"
34 #include "lib/messaging/irpc.h"
35 #include "librpc/gen_ndr/ndr_irpc.h"
37 struct netlogon_server_pipe_state {
38 struct netr_Credential client_challenge;
39 struct netr_Credential server_challenge;
42 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
43 struct netr_ServerReqChallenge *r)
45 struct netlogon_server_pipe_state *pipe_state =
46 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
48 ZERO_STRUCTP(r->out.return_credentials);
50 /* destroyed on pipe shutdown */
52 if (pipe_state) {
53 talloc_free(pipe_state);
54 dce_call->context->private_data = NULL;
57 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
58 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
60 pipe_state->client_challenge = *r->in.credentials;
62 generate_random_buffer(pipe_state->server_challenge.data,
63 sizeof(pipe_state->server_challenge.data));
65 *r->out.return_credentials = pipe_state->server_challenge;
67 dce_call->context->private_data = pipe_state;
69 return NT_STATUS_OK;
72 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
73 struct netr_ServerAuthenticate3 *r)
75 struct netlogon_server_pipe_state *pipe_state =
76 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
77 struct netlogon_creds_CredentialState *creds;
78 struct ldb_context *schannel_ldb;
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 schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
252 if (!schannel_ldb) {
253 return NT_STATUS_ACCESS_DENIED;
256 nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
257 talloc_unlink(mem_ctx, schannel_ldb);
259 return nt_status;
262 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
263 struct netr_ServerAuthenticate *r)
265 struct netr_ServerAuthenticate3 a;
266 uint32_t rid;
267 /* TODO:
268 * negotiate_flags is used as an [in] parameter
269 * so it need to be initialised.
271 * (I think ... = 0; seems wrong here --metze)
273 uint32_t negotiate_flags_in = 0;
274 uint32_t negotiate_flags_out = 0;
276 a.in.server_name = r->in.server_name;
277 a.in.account_name = r->in.account_name;
278 a.in.secure_channel_type = r->in.secure_channel_type;
279 a.in.computer_name = r->in.computer_name;
280 a.in.credentials = r->in.credentials;
281 a.in.negotiate_flags = &negotiate_flags_in;
283 a.out.return_credentials = r->out.return_credentials;
284 a.out.rid = &rid;
285 a.out.negotiate_flags = &negotiate_flags_out;
287 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
290 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 struct netr_ServerAuthenticate2 *r)
293 struct netr_ServerAuthenticate3 r3;
294 uint32_t rid = 0;
296 r3.in.server_name = r->in.server_name;
297 r3.in.account_name = r->in.account_name;
298 r3.in.secure_channel_type = r->in.secure_channel_type;
299 r3.in.computer_name = r->in.computer_name;
300 r3.in.credentials = r->in.credentials;
301 r3.out.return_credentials = r->out.return_credentials;
302 r3.in.negotiate_flags = r->in.negotiate_flags;
303 r3.out.negotiate_flags = r->out.negotiate_flags;
304 r3.out.rid = &rid;
306 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
310 Validate an incoming authenticator against the credentials for the remote machine.
312 The credentials are (re)read and from the schannel database, and
313 written back after the caclulations are performed.
315 The creds_out parameter (if not NULL) returns the credentials, if
316 the caller needs some of that information.
319 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
320 TALLOC_CTX *mem_ctx,
321 const char *computer_name,
322 struct netr_Authenticator *received_authenticator,
323 struct netr_Authenticator *return_authenticator,
324 struct netlogon_creds_CredentialState **creds_out)
326 NTSTATUS nt_status;
327 struct ldb_context *ldb;
328 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
329 bool schannel_in_use = dce_call->conn->auth_state.auth_info
330 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
331 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY
332 || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
334 ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
335 if (!ldb) {
336 return NT_STATUS_ACCESS_DENIED;
338 nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
339 computer_name,
340 schannel_global_required,
341 schannel_in_use,
342 received_authenticator,
343 return_authenticator, creds_out);
344 talloc_unlink(mem_ctx, ldb);
345 return nt_status;
349 Change the machine account password for the currently connected
350 client. Supplies only the NT#.
353 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
354 struct netr_ServerPasswordSet *r)
356 struct netlogon_creds_CredentialState *creds;
357 struct ldb_context *sam_ctx;
358 NTSTATUS nt_status;
360 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
361 mem_ctx,
362 r->in.computer_name,
363 r->in.credential, r->out.return_authenticator,
364 &creds);
365 NT_STATUS_NOT_OK_RETURN(nt_status);
367 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));
368 if (sam_ctx == NULL) {
369 return NT_STATUS_INVALID_SYSTEM_SERVICE;
372 netlogon_creds_des_decrypt(creds, r->in.new_password);
374 /* Using the sid for the account as the key, set the password */
375 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
376 creds->sid,
377 NULL, /* Don't have plaintext */
378 NULL, r->in.new_password,
379 true, /* Password change */
380 NULL, NULL);
381 return nt_status;
385 Change the machine account password for the currently connected
386 client. Supplies new plaintext.
388 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
389 struct netr_ServerPasswordSet2 *r)
391 struct netlogon_creds_CredentialState *creds;
392 struct ldb_context *sam_ctx;
393 NTSTATUS nt_status;
394 DATA_BLOB new_password;
396 struct samr_CryptPassword password_buf;
398 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
399 mem_ctx,
400 r->in.computer_name,
401 r->in.credential, r->out.return_authenticator,
402 &creds);
403 NT_STATUS_NOT_OK_RETURN(nt_status);
405 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));
406 if (sam_ctx == NULL) {
407 return NT_STATUS_INVALID_SYSTEM_SERVICE;
410 memcpy(password_buf.data, r->in.new_password->data, 512);
411 SIVAL(password_buf.data, 512, r->in.new_password->length);
412 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
414 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
415 DEBUG(3,("samr: failed to decode password buffer\n"));
416 return NT_STATUS_WRONG_PASSWORD;
419 /* Using the sid for the account as the key, set the password */
420 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
421 creds->sid,
422 &new_password, /* we have plaintext */
423 NULL, NULL,
424 true, /* Password change */
425 NULL, NULL);
426 return nt_status;
431 netr_LogonUasLogon
433 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
434 struct netr_LogonUasLogon *r)
436 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
441 netr_LogonUasLogoff
443 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
444 struct netr_LogonUasLogoff *r)
446 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
451 netr_LogonSamLogon_base
453 This version of the function allows other wrappers to say 'do not check the credentials'
455 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
457 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
458 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
460 struct auth_context *auth_context;
461 struct auth_usersupplied_info *user_info;
462 struct auth_serversupplied_info *server_info;
463 NTSTATUS nt_status;
464 static const char zeros[16];
465 struct netr_SamBaseInfo *sam;
466 struct netr_SamInfo2 *sam2;
467 struct netr_SamInfo3 *sam3;
468 struct netr_SamInfo6 *sam6;
470 user_info = talloc(mem_ctx, struct auth_usersupplied_info);
471 NT_STATUS_HAVE_NO_MEMORY(user_info);
473 user_info->flags = 0;
474 user_info->mapped_state = false;
475 user_info->remote_host = NULL;
477 switch (r->in.logon_level) {
478 case NetlogonInteractiveInformation:
479 case NetlogonServiceInformation:
480 case NetlogonInteractiveTransitiveInformation:
481 case NetlogonServiceTransitiveInformation:
482 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
483 netlogon_creds_arcfour_crypt(creds,
484 r->in.logon->password->lmpassword.hash,
485 sizeof(r->in.logon->password->lmpassword.hash));
486 netlogon_creds_arcfour_crypt(creds,
487 r->in.logon->password->ntpassword.hash,
488 sizeof(r->in.logon->password->ntpassword.hash));
489 } else {
490 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
491 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
494 /* TODO: we need to deny anonymous access here */
495 nt_status = auth_context_create(mem_ctx,
496 dce_call->event_ctx, dce_call->msg_ctx,
497 dce_call->conn->dce_ctx->lp_ctx,
498 &auth_context);
499 NT_STATUS_NOT_OK_RETURN(nt_status);
501 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
502 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
503 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
504 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
506 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
507 user_info->password_state = AUTH_PASSWORD_HASH;
509 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
510 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
511 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
513 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
514 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
515 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
517 break;
518 case NetlogonNetworkInformation:
519 case NetlogonNetworkTransitiveInformation:
521 /* TODO: we need to deny anonymous access here */
522 nt_status = auth_context_create(mem_ctx,
523 dce_call->event_ctx, dce_call->msg_ctx,
524 dce_call->conn->dce_ctx->lp_ctx,
525 &auth_context);
526 NT_STATUS_NOT_OK_RETURN(nt_status);
528 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
529 NT_STATUS_NOT_OK_RETURN(nt_status);
531 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
532 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
533 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
534 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
536 user_info->password_state = AUTH_PASSWORD_RESPONSE;
537 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
538 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
540 break;
543 case NetlogonGenericInformation:
545 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
546 netlogon_creds_arcfour_crypt(creds,
547 r->in.logon->generic->data, r->in.logon->generic->length);
548 } else {
549 /* Using DES to verify kerberos tickets makes no sense */
550 return NT_STATUS_INVALID_PARAMETER;
553 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
554 NTSTATUS status;
555 struct server_id *kdc;
556 struct kdc_check_generic_kerberos check;
557 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
558 NT_STATUS_HAVE_NO_MEMORY(generic);
559 *r->out.authoritative = 1;
561 /* TODO: Describe and deal with these flags */
562 *r->out.flags = 0;
564 r->out.validation->generic = generic;
566 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
567 if ((kdc == NULL) || (kdc[0].id == 0)) {
568 return NT_STATUS_NO_LOGON_SERVERS;
571 check.in.generic_request =
572 data_blob_const(r->in.logon->generic->data,
573 r->in.logon->generic->length);
575 status = irpc_call(dce_call->msg_ctx, kdc[0],
576 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
577 &check, mem_ctx);
578 if (!NT_STATUS_IS_OK(status)) {
579 return status;
581 generic->length = check.out.generic_reply.length;
582 generic->data = check.out.generic_reply.data;
583 return NT_STATUS_OK;
586 /* Until we get an implemetnation of these other packages */
587 return NT_STATUS_INVALID_PARAMETER;
589 default:
590 return NT_STATUS_INVALID_PARAMETER;
593 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
594 NT_STATUS_NOT_OK_RETURN(nt_status);
596 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
597 NT_STATUS_NOT_OK_RETURN(nt_status);
599 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
600 /* It appears that level 6 is not individually encrypted */
601 if ((r->in.validation_level != 6) &&
602 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
603 /* This key is sent unencrypted without the ARCFOUR flag set */
604 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
605 netlogon_creds_arcfour_crypt(creds,
606 sam->key.key,
607 sizeof(sam->key.key));
611 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
612 /* It appears that level 6 is not individually encrypted */
613 if ((r->in.validation_level != 6) &&
614 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
615 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
616 netlogon_creds_arcfour_crypt(creds,
617 sam->LMSessKey.key,
618 sizeof(sam->LMSessKey.key));
619 } else {
620 netlogon_creds_des_encrypt_LMKey(creds,
621 &sam->LMSessKey);
625 switch (r->in.validation_level) {
626 case 2:
627 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
628 NT_STATUS_HAVE_NO_MEMORY(sam2);
629 sam2->base = *sam;
630 r->out.validation->sam2 = sam2;
631 break;
633 case 3:
634 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
635 NT_STATUS_HAVE_NO_MEMORY(sam3);
636 sam3->base = *sam;
637 r->out.validation->sam3 = sam3;
638 break;
640 case 6:
641 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
642 NT_STATUS_HAVE_NO_MEMORY(sam6);
643 sam6->base = *sam;
644 sam6->forest.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
645 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
646 sam->account_name.string, sam6->forest.string);
647 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
648 r->out.validation->sam6 = sam6;
649 break;
651 default:
652 break;
655 *r->out.authoritative = 1;
657 /* TODO: Describe and deal with these flags */
658 *r->out.flags = 0;
660 return NT_STATUS_OK;
663 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
664 struct netr_LogonSamLogonEx *r)
666 NTSTATUS nt_status;
667 struct netlogon_creds_CredentialState *creds;
668 struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
669 if (!ldb) {
670 return NT_STATUS_ACCESS_DENIED;
673 nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
674 if (!NT_STATUS_IS_OK(nt_status)) {
675 return nt_status;
678 if (!dce_call->conn->auth_state.auth_info ||
679 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
680 return NT_STATUS_ACCESS_DENIED;
682 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
686 netr_LogonSamLogonWithFlags
689 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690 struct netr_LogonSamLogonWithFlags *r)
692 NTSTATUS nt_status;
693 struct netlogon_creds_CredentialState *creds;
694 struct netr_LogonSamLogonEx r2;
696 struct netr_Authenticator *return_authenticator;
698 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
699 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
701 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
702 mem_ctx,
703 r->in.computer_name,
704 r->in.credential, return_authenticator,
705 &creds);
706 NT_STATUS_NOT_OK_RETURN(nt_status);
708 ZERO_STRUCT(r2);
710 r2.in.server_name = r->in.server_name;
711 r2.in.computer_name = r->in.computer_name;
712 r2.in.logon_level = r->in.logon_level;
713 r2.in.logon = r->in.logon;
714 r2.in.validation_level = r->in.validation_level;
715 r2.in.flags = r->in.flags;
716 r2.out.validation = r->out.validation;
717 r2.out.authoritative = r->out.authoritative;
718 r2.out.flags = r->out.flags;
720 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
722 r->out.return_authenticator = return_authenticator;
724 return nt_status;
728 netr_LogonSamLogon
730 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
731 struct netr_LogonSamLogon *r)
733 struct netr_LogonSamLogonWithFlags r2;
734 uint32_t flags = 0;
735 NTSTATUS status;
737 ZERO_STRUCT(r2);
739 r2.in.server_name = r->in.server_name;
740 r2.in.computer_name = r->in.computer_name;
741 r2.in.credential = r->in.credential;
742 r2.in.return_authenticator = r->in.return_authenticator;
743 r2.in.logon_level = r->in.logon_level;
744 r2.in.logon = r->in.logon;
745 r2.in.validation_level = r->in.validation_level;
746 r2.in.flags = &flags;
747 r2.out.validation = r->out.validation;
748 r2.out.authoritative = r->out.authoritative;
749 r2.out.flags = &flags;
751 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
753 r->out.return_authenticator = r2.out.return_authenticator;
755 return status;
760 netr_LogonSamLogoff
762 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
763 struct netr_LogonSamLogoff *r)
765 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
771 netr_DatabaseDeltas
773 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
774 struct netr_DatabaseDeltas *r)
776 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
781 netr_DatabaseSync2
783 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
784 struct netr_DatabaseSync2 *r)
786 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
787 return NT_STATUS_NOT_IMPLEMENTED;
792 netr_DatabaseSync
794 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
795 struct netr_DatabaseSync *r)
797 struct netr_DatabaseSync2 r2;
798 NTSTATUS status;
800 ZERO_STRUCT(r2);
802 r2.in.logon_server = r->in.logon_server;
803 r2.in.computername = r->in.computername;
804 r2.in.credential = r->in.credential;
805 r2.in.database_id = r->in.database_id;
806 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
807 r2.in.sync_context = r->in.sync_context;
808 r2.out.sync_context = r->out.sync_context;
809 r2.out.delta_enum_array = r->out.delta_enum_array;
810 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
812 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
814 return status;
819 netr_AccountDeltas
821 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
822 struct netr_AccountDeltas *r)
824 /* w2k3 returns "NOT IMPLEMENTED" for this call */
825 return NT_STATUS_NOT_IMPLEMENTED;
830 netr_AccountSync
832 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
833 struct netr_AccountSync *r)
835 /* w2k3 returns "NOT IMPLEMENTED" for this call */
836 return NT_STATUS_NOT_IMPLEMENTED;
841 netr_GetDcName
843 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
844 struct netr_GetDcName *r)
846 const char * const attrs[] = { NULL };
847 struct ldb_context *sam_ctx;
848 struct ldb_message **res;
849 struct ldb_dn *domain_dn;
850 int ret;
851 const char *dcname;
853 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
854 dce_call->conn->dce_ctx->lp_ctx,
855 dce_call->conn->auth_state.session_info);
856 if (sam_ctx == NULL) {
857 return WERR_DS_UNAVAILABLE;
860 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
861 r->in.domainname);
862 if (domain_dn == NULL) {
863 return WERR_DS_UNAVAILABLE;
866 ret = gendb_search_dn(sam_ctx, mem_ctx,
867 domain_dn, &res, attrs);
868 if (ret != 1) {
869 return WERR_NO_SUCH_DOMAIN;
872 /* TODO: - return real IP address
873 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
875 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
876 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
877 W_ERROR_HAVE_NO_MEMORY(dcname);
879 *r->out.dcname = dcname;
880 return WERR_OK;
885 netr_LogonControl2Ex
887 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
888 struct netr_LogonControl2Ex *r)
890 return WERR_NOT_SUPPORTED;
895 netr_LogonControl
897 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
898 struct netr_LogonControl *r)
900 struct netr_LogonControl2Ex r2;
901 WERROR werr;
903 if (r->in.level == 0x00000001) {
904 ZERO_STRUCT(r2);
906 r2.in.logon_server = r->in.logon_server;
907 r2.in.function_code = r->in.function_code;
908 r2.in.level = r->in.level;
909 r2.in.data = NULL;
910 r2.out.query = r->out.query;
912 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
913 } else if (r->in.level == 0x00000002) {
914 werr = WERR_NOT_SUPPORTED;
915 } else {
916 werr = WERR_UNKNOWN_LEVEL;
919 return werr;
924 netr_LogonControl2
926 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
927 struct netr_LogonControl2 *r)
929 struct netr_LogonControl2Ex r2;
930 WERROR werr;
932 ZERO_STRUCT(r2);
934 r2.in.logon_server = r->in.logon_server;
935 r2.in.function_code = r->in.function_code;
936 r2.in.level = r->in.level;
937 r2.in.data = r->in.data;
938 r2.out.query = r->out.query;
940 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
942 return werr;
947 netr_GetAnyDCName
949 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
950 struct netr_GetAnyDCName *r)
952 struct netr_GetDcName r2;
953 WERROR werr;
955 ZERO_STRUCT(r2);
957 r2.in.logon_server = r->in.logon_server;
958 r2.in.domainname = r->in.domainname;
959 r2.out.dcname = r->out.dcname;
961 werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
963 return werr;
968 netr_DatabaseRedo
970 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
971 struct netr_DatabaseRedo *r)
973 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
978 netr_NetrEnumerateTurstedDomains
980 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
981 struct netr_NetrEnumerateTrustedDomains *r)
983 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
988 netr_LogonGetCapabilities
990 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
991 struct netr_LogonGetCapabilities *r)
993 /* we don't support AES yet */
994 return NT_STATUS_NOT_IMPLEMENTED;
999 netr_NETRLOGONSETSERVICEBITS
1001 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1002 struct netr_NETRLOGONSETSERVICEBITS *r)
1004 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1009 netr_LogonGetTrustRid
1011 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1012 struct netr_LogonGetTrustRid *r)
1014 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1019 netr_NETRLOGONCOMPUTESERVERDIGEST
1021 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1022 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1024 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1029 netr_NETRLOGONCOMPUTECLIENTDIGEST
1031 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1032 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1034 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1040 netr_DsRGetSiteName
1042 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1043 struct netr_DsRGetSiteName *r)
1045 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1050 fill in a netr_OneDomainInfo from a ldb search result
1052 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1053 struct loadparm_context *lp_ctx,
1054 struct ldb_context *sam_ctx,
1055 struct ldb_message *res,
1056 struct netr_OneDomainInfo *info,
1057 bool is_local, bool is_trust_list)
1059 ZERO_STRUCTP(info);
1061 if (is_trust_list) {
1062 /* w2k8 only fills this on trusted domains */
1063 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1064 info->trust_extension.length = 16;
1065 info->trust_extension.info->flags =
1066 NETR_TRUST_FLAG_TREEROOT |
1067 NETR_TRUST_FLAG_IN_FOREST |
1068 NETR_TRUST_FLAG_PRIMARY |
1069 NETR_TRUST_FLAG_NATIVE;
1071 info->trust_extension.info->parent_index = 0; /* should be index into array
1072 of parent */
1073 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1074 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1077 if (is_trust_list) {
1078 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1079 info->dns_forestname.string = NULL;
1080 } else {
1081 char *p;
1082 /* TODO: we need a common function for pulling the forest */
1083 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1084 if (!info->dns_forestname.string) {
1085 return NT_STATUS_NO_SUCH_DOMAIN;
1087 p = strchr(info->dns_forestname.string, '/');
1088 if (p) {
1089 *p = '\0';
1091 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1095 if (is_local) {
1096 info->domainname.string = lp_sam_name(lp_ctx);
1097 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1098 info->domain_guid = samdb_result_guid(res, "objectGUID");
1099 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1100 } else {
1101 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1102 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1103 info->domain_guid = samdb_result_guid(res, "objectGUID");
1104 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1106 if (!is_trust_list) {
1107 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1110 return NT_STATUS_OK;
1114 netr_LogonGetDomainInfo
1115 this is called as part of the ADS domain logon procedure.
1117 It has an important role in convaying details about the client, such
1118 as Operating System, Version, Service Pack etc.
1120 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1121 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1123 struct netlogon_creds_CredentialState *creds;
1124 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1125 "securityIdentifier", "trustPartner", NULL };
1126 const char * const attrs2[] = { "dNSHostName",
1127 "msDS-SupportedEncryptionTypes", NULL };
1128 const char *temp_str;
1129 const char *old_dns_hostname;
1130 struct ldb_context *sam_ctx;
1131 struct ldb_message **res1, **res2, **res3, *new_msg;
1132 struct ldb_dn *workstation_dn;
1133 struct netr_DomainInformation *domain_info;
1134 struct netr_LsaPolicyInformation *lsa_policy_info;
1135 struct netr_OsVersionInfoEx *os_version;
1136 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1137 int ret1, ret2, ret3, i;
1138 NTSTATUS status;
1140 status = dcesrv_netr_creds_server_step_check(dce_call,
1141 mem_ctx,
1142 r->in.computer_name,
1143 r->in.credential,
1144 r->out.return_authenticator,
1145 &creds);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 DEBUG(0,(__location__ " Bad credentials - error\n"));
1149 NT_STATUS_NOT_OK_RETURN(status);
1151 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1152 dce_call->conn->dce_ctx->lp_ctx,
1153 system_session(dce_call->conn->dce_ctx->lp_ctx));
1154 if (sam_ctx == NULL) {
1155 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1158 switch (r->in.level) {
1159 case 1: /* Domain information */
1161 /* TODO: check NTSTATUS results - and fail also on SAMDB
1162 * errors (needs some testing against Windows Server 2008) */
1165 * Check that the computer name parameter matches as prefix with
1166 * the DNS hostname in the workstation info structure.
1168 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1169 strcspn(r->in.query->workstation_info->dns_hostname,
1170 "."));
1171 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1172 return NT_STATUS_INVALID_PARAMETER;
1174 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1175 dom_sid_string(mem_ctx, creds->sid));
1176 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1178 /* Lookup for attributes in workstation object */
1179 ret1 = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1180 &res1, attrs2);
1181 if (ret1 != 1) {
1182 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1185 /* Gets the old DNS hostname */
1186 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1187 NULL);
1189 /* Gets host informations and put them in our directory */
1190 new_msg = ldb_msg_new(mem_ctx);
1191 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1193 new_msg->dn = workstation_dn;
1195 /* Deletes old OS version values */
1196 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1197 "operatingSystemServicePack");
1198 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1199 "operatingSystemVersion");
1201 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1202 DEBUG(3,("Impossible to update samdb: %s\n",
1203 ldb_errstring(sam_ctx)));
1206 talloc_free(new_msg);
1208 new_msg = ldb_msg_new(mem_ctx);
1209 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1211 new_msg->dn = workstation_dn;
1213 /* Sets the OS name */
1214 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1215 "operatingSystem",
1216 r->in.query->workstation_info->os_name.string);
1219 * Sets informations from "os_version". On a empty structure
1220 * the values are cleared.
1222 if (r->in.query->workstation_info->os_version.os != NULL) {
1223 os_version = &r->in.query->workstation_info->os_version.os->os;
1225 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1226 "operatingSystemServicePack",
1227 os_version->CSDVersion);
1229 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1230 "operatingSystemVersion",
1231 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1232 os_version->MajorVersion,
1233 os_version->MinorVersion,
1234 os_version->BuildNumber
1240 * Updates the "dNSHostname" and the "servicePrincipalName"s
1241 * since the client wishes that the server should handle this
1242 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1243 * See MS-NRPC section 3.5.4.3.9
1245 if ((r->in.query->workstation_info->workstation_flags
1246 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1247 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1248 "dNSHostname",
1249 r->in.query->workstation_info->dns_hostname);
1251 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1252 "servicePrincipalName",
1253 talloc_asprintf(mem_ctx, "HOST/%s",
1254 r->in.computer_name)
1256 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1257 "servicePrincipalName",
1258 talloc_asprintf(mem_ctx, "HOST/%s",
1259 r->in.query->workstation_info->dns_hostname)
1263 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1264 DEBUG(3,("Impossible to update samdb: %s\n",
1265 ldb_errstring(sam_ctx)));
1268 talloc_free(new_msg);
1270 /* Writes back the domain information */
1272 /* We need to do two searches. The first will pull our primary
1273 domain and the second will pull any trusted domains. Our
1274 primary domain is also a "trusted" domain, so we need to
1275 put the primary domain into the lists of returned trusts as
1276 well. */
1277 ret2 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1278 &res2, attrs);
1279 if (ret2 != 1) {
1280 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1283 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1284 "(objectClass=trustedDomain)");
1285 if (ret3 == -1) {
1286 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1289 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1290 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1292 ZERO_STRUCTP(domain_info);
1294 /* Informations about the local and trusted domains */
1296 status = fill_one_domain_info(mem_ctx,
1297 dce_call->conn->dce_ctx->lp_ctx,
1298 sam_ctx, res2[0], &domain_info->primary_domain,
1299 true, false);
1300 NT_STATUS_NOT_OK_RETURN(status);
1302 domain_info->trusted_domain_count = ret3 + 1;
1303 domain_info->trusted_domains = talloc_array(mem_ctx,
1304 struct netr_OneDomainInfo,
1305 domain_info->trusted_domain_count);
1306 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1308 for (i=0;i<ret3;i++) {
1309 status = fill_one_domain_info(mem_ctx,
1310 dce_call->conn->dce_ctx->lp_ctx,
1311 sam_ctx, res3[i],
1312 &domain_info->trusted_domains[i],
1313 false, true);
1314 NT_STATUS_NOT_OK_RETURN(status);
1317 status = fill_one_domain_info(mem_ctx,
1318 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1319 &domain_info->trusted_domains[i], true, true);
1320 NT_STATUS_NOT_OK_RETURN(status);
1322 /* Sets the supported encryption types */
1323 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1324 "msDS-SupportedEncryptionTypes",
1325 default_supported_enc_types);
1327 /* Other host domain informations */
1329 lsa_policy_info = talloc(mem_ctx,
1330 struct netr_LsaPolicyInformation);
1331 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1332 ZERO_STRUCTP(lsa_policy_info);
1334 domain_info->lsa_policy = *lsa_policy_info;
1336 domain_info->dns_hostname.string = old_dns_hostname;
1337 domain_info->workstation_flags =
1338 r->in.query->workstation_info->workstation_flags;
1340 r->out.info->domain_info = domain_info;
1341 break;
1342 case 2: /* LSA policy information - not used at the moment */
1343 lsa_policy_info = talloc(mem_ctx,
1344 struct netr_LsaPolicyInformation);
1345 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1346 ZERO_STRUCTP(lsa_policy_info);
1348 r->out.info->lsa_policy_info = lsa_policy_info;
1349 break;
1350 default:
1351 return NT_STATUS_INVALID_LEVEL;
1352 break;
1355 return NT_STATUS_OK;
1361 netr_ServerPasswordGet
1363 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1364 struct netr_ServerPasswordGet *r)
1366 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1371 netr_NETRLOGONSENDTOSAM
1373 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1374 struct netr_NETRLOGONSENDTOSAM *r)
1376 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1381 netr_DsRAddressToSitenamesW
1383 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1384 struct netr_DsRAddressToSitenamesW *r)
1386 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1391 netr_DsRGetDCNameEx2
1393 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1394 TALLOC_CTX *mem_ctx,
1395 struct netr_DsRGetDCNameEx2 *r)
1397 const char * const attrs[] = { "objectGUID", NULL };
1398 struct ldb_context *sam_ctx;
1399 struct ldb_message **res;
1400 struct ldb_dn *domain_dn;
1401 int ret;
1402 struct netr_DsRGetDCNameInfo *info;
1403 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1405 ZERO_STRUCTP(r->out.info);
1407 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1408 dce_call->conn->auth_state.session_info);
1409 if (sam_ctx == NULL) {
1410 return WERR_DS_UNAVAILABLE;
1413 /* Windows 7 sends the domain name in the form the user typed, so we
1414 * have to cope with both the short and long form here */
1415 if (r->in.domain_name != NULL &&
1416 !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1417 return WERR_NO_SUCH_DOMAIN;
1420 domain_dn = ldb_get_default_basedn(sam_ctx);
1421 if (domain_dn == NULL) {
1422 return WERR_DS_UNAVAILABLE;
1425 ret = gendb_search_dn(sam_ctx, mem_ctx,
1426 domain_dn, &res, attrs);
1427 if (ret != 1) {
1428 return WERR_GENERAL_FAILURE;
1431 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1432 W_ERROR_HAVE_NO_MEMORY(info);
1434 /* TODO: - return real IP address
1435 * - check all r->in.* parameters
1436 * (server_unc is ignored by w2k3!)
1438 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1439 lp_netbios_name(lp_ctx),
1440 lp_dnsdomain(lp_ctx));
1441 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1443 info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1444 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1446 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1447 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1448 info->domain_name = lp_dnsdomain(lp_ctx);
1449 info->forest_name = lp_dnsdomain(lp_ctx);
1450 info->dc_flags = DS_DNS_FOREST_ROOT |
1451 DS_DNS_DOMAIN |
1452 DS_DNS_CONTROLLER |
1453 DS_SERVER_WRITABLE |
1454 DS_SERVER_CLOSEST |
1455 DS_SERVER_TIMESERV |
1456 DS_SERVER_KDC |
1457 DS_SERVER_DS |
1458 DS_SERVER_LDAP |
1459 DS_SERVER_GC |
1460 DS_SERVER_PDC;
1462 info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1463 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1465 /* FIXME: Hardcoded site name */
1466 info->client_site_name = talloc_strdup(mem_ctx,
1467 "Default-First-Site-Name");
1468 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1470 *r->out.info = info;
1472 return WERR_OK;
1476 netr_DsRGetDCNameEx
1478 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1479 struct netr_DsRGetDCNameEx *r)
1481 struct netr_DsRGetDCNameEx2 r2;
1482 WERROR werr;
1484 ZERO_STRUCT(r2);
1486 r2.in.server_unc = r->in.server_unc;
1487 r2.in.client_account = NULL;
1488 r2.in.mask = 0;
1489 r2.in.domain_guid = r->in.domain_guid;
1490 r2.in.domain_name = r->in.domain_name;
1491 r2.in.site_name = r->in.site_name;
1492 r2.in.flags = r->in.flags;
1493 r2.out.info = r->out.info;
1495 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1497 return werr;
1501 netr_DsRGetDCName
1503 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1504 struct netr_DsRGetDCName *r)
1506 struct netr_DsRGetDCNameEx2 r2;
1507 WERROR werr;
1509 ZERO_STRUCT(r2);
1511 r2.in.server_unc = r->in.server_unc;
1512 r2.in.client_account = NULL;
1513 r2.in.mask = 0;
1514 r2.in.domain_name = r->in.domain_name;
1515 r2.in.domain_guid = r->in.domain_guid;
1517 r2.in.site_name = NULL; /* should fill in from site GUID */
1518 r2.in.flags = r->in.flags;
1519 r2.out.info = r->out.info;
1521 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1523 return werr;
1526 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1528 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1529 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1531 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1536 netr_NetrEnumerateTrustedDomainsEx
1538 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1539 struct netr_NetrEnumerateTrustedDomainsEx *r)
1541 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1546 netr_DsRAddressToSitenamesExW
1548 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1549 struct netr_DsRAddressToSitenamesExW *r)
1551 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1552 int i;
1554 /* we should map the provided IPs to site names, once we have
1555 * sites support
1557 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1558 W_ERROR_HAVE_NO_MEMORY(ctr);
1560 *r->out.ctr = ctr;
1562 ctr->count = r->in.count;
1563 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1564 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1565 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1566 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1568 for (i=0; i<ctr->count; i++) {
1569 /* FIXME: Hardcoded site name */
1570 ctr->sitename[i].string = "Default-First-Site-Name";
1571 ctr->subnetname[i].string = NULL;
1574 return WERR_OK;
1579 netr_DsrGetDcSiteCoverageW
1581 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1582 struct netr_DsrGetDcSiteCoverageW *r)
1584 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1588 #define GET_CHECK_STR(dest, mem, msg, attr) \
1589 do {\
1590 const char *s; \
1591 s = samdb_result_string(msg, attr, NULL); \
1592 if (!s) { \
1593 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1594 "without flatname\n", \
1595 ldb_dn_get_linearized(msg->dn))); \
1596 continue; \
1598 dest = talloc_strdup(mem, s); \
1599 W_ERROR_HAVE_NO_MEMORY(dest); \
1600 } while(0)
1603 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1604 struct ldb_context *sam_ctx,
1605 struct netr_DomainTrustList *trusts,
1606 uint32_t trust_flags)
1608 struct ldb_dn *system_dn;
1609 struct ldb_message **dom_res = NULL;
1610 const char *trust_attrs[] = { "flatname", "trustPartner",
1611 "securityIdentifier", "trustDirection",
1612 "trustType", "trustAttributes", NULL };
1613 int i, n;
1614 int ret;
1616 if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1617 NETR_TRUST_FLAG_OUTBOUND))) {
1618 return WERR_INVALID_FLAGS;
1621 system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1622 ldb_get_default_basedn(sam_ctx),
1623 "(&(objectClass=container)(cn=System))");
1624 if (!system_dn) {
1625 return WERR_GENERAL_FAILURE;
1628 ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1629 &dom_res, trust_attrs,
1630 "(objectclass=trustedDomain)");
1632 for (i = 0; i < ret; i++) {
1633 unsigned int trust_dir;
1634 uint32_t flags = 0;
1636 trust_dir = samdb_result_uint(dom_res[i],
1637 "trustDirection", 0);
1639 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1640 flags |= NETR_TRUST_FLAG_INBOUND;
1642 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1643 flags |= NETR_TRUST_FLAG_OUTBOUND;
1646 if (!(flags & trust_flags)) {
1647 /* this trust direction was not requested */
1648 continue;
1651 n = trusts->count;
1652 trusts->array = talloc_realloc(trusts, trusts->array,
1653 struct netr_DomainTrust,
1654 n + 1);
1655 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1657 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1658 dom_res[i], "flatname");
1659 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1660 dom_res[i], "trustPartner");
1662 trusts->array[n].trust_flags = flags;
1663 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1664 !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1665 /* TODO: find if we have parent in the list */
1666 trusts->array[n].parent_index = 0;
1669 trusts->array[n].trust_type =
1670 samdb_result_uint(dom_res[i],
1671 "trustType", 0);
1672 trusts->array[n].trust_attributes =
1673 samdb_result_uint(dom_res[i],
1674 "trustAttributes", 0);
1676 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1677 (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1678 struct dom_sid zero_sid;
1679 ZERO_STRUCT(zero_sid);
1680 trusts->array[n].sid =
1681 dom_sid_dup(trusts, &zero_sid);
1682 } else {
1683 trusts->array[n].sid =
1684 samdb_result_dom_sid(trusts, dom_res[i],
1685 "securityIdentifier");
1687 trusts->array[n].guid = GUID_zero();
1689 trusts->count = n + 1;
1692 talloc_free(dom_res);
1693 return WERR_OK;
1697 netr_DsrEnumerateDomainTrusts
1699 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1700 TALLOC_CTX *mem_ctx,
1701 struct netr_DsrEnumerateDomainTrusts *r)
1703 struct netr_DomainTrustList *trusts;
1704 struct ldb_context *sam_ctx;
1705 int ret;
1706 struct ldb_message **dom_res;
1707 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1708 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1709 const char *dnsdomain = lp_dnsdomain(lp_ctx);
1710 char *p;
1711 WERROR werr;
1713 if (r->in.trust_flags & 0xFFFFFE00) {
1714 return WERR_INVALID_FLAGS;
1717 /* TODO: turn to hard check once we are sure this is 100% correct */
1718 p = strchr(r->in.server_name, '.');
1719 if (!p) {
1720 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1721 "But received [%s]!\n",
1722 dnsdomain, r->in.server_name));
1724 p++;
1725 if (strcasecmp(p, dnsdomain)) {
1726 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1727 "But received [%s]!\n",
1728 dnsdomain, r->in.server_name));
1731 ZERO_STRUCT(r->out);
1733 trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1734 W_ERROR_HAVE_NO_MEMORY(trusts);
1736 trusts->count = 0;
1737 r->out.trusts = trusts;
1739 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1740 dce_call->conn->auth_state.session_info);
1741 if (sam_ctx == NULL) {
1742 return WERR_GENERAL_FAILURE;
1745 if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1746 (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1748 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1749 trusts, r->in.trust_flags);
1750 W_ERROR_NOT_OK_RETURN(werr);
1753 /* NOTE: we currently are always the root of the forest */
1754 if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1755 int n = trusts->count;
1757 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1758 &dom_res, dom_attrs);
1759 if (ret != 1) {
1760 return WERR_GENERAL_FAILURE;
1763 trusts->count = n + 1;
1764 trusts->array = talloc_realloc(trusts, trusts->array,
1765 struct netr_DomainTrust,
1766 trusts->count);
1767 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1769 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1770 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1771 trusts->array[n].trust_flags =
1772 NETR_TRUST_FLAG_NATIVE |
1773 NETR_TRUST_FLAG_TREEROOT |
1774 NETR_TRUST_FLAG_IN_FOREST |
1775 NETR_TRUST_FLAG_PRIMARY;
1776 /* we are always the root domain for now */
1777 trusts->array[n].parent_index = 0;
1778 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1779 trusts->array[n].trust_attributes = 0;
1780 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1781 dom_res[0],
1782 "objectSid");
1783 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1784 "objectGUID");
1785 talloc_free(dom_res);
1788 return WERR_OK;
1793 netr_DsrDeregisterDNSHostRecords
1795 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1796 struct netr_DsrDeregisterDNSHostRecords *r)
1798 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1803 netr_ServerTrustPasswordsGet
1805 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1806 struct netr_ServerTrustPasswordsGet *r)
1808 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1813 netr_DsRGetForestTrustInformation
1815 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1816 struct netr_DsRGetForestTrustInformation *r)
1818 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1823 netr_GetForestTrustInformation
1825 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1826 struct netr_GetForestTrustInformation *r)
1828 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1833 netr_ServerGetTrustInfo
1835 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1836 struct netr_ServerGetTrustInfo *r)
1838 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1842 /* include the generated boilerplate */
1843 #include "librpc/gen_ndr/ndr_netlogon_s.c"