readability reformatting
[Samba/ekacnet.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blob314a359d2ed30bd2726ab5084ee2579e146c68a9
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;
43 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
44 struct netr_ServerReqChallenge *r)
46 struct netlogon_server_pipe_state *pipe_state =
47 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
49 ZERO_STRUCTP(r->out.return_credentials);
51 /* destroyed on pipe shutdown */
53 if (pipe_state) {
54 talloc_free(pipe_state);
55 dce_call->context->private_data = NULL;
58 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
59 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
61 pipe_state->client_challenge = *r->in.credentials;
63 generate_random_buffer(pipe_state->server_challenge.data,
64 sizeof(pipe_state->server_challenge.data));
66 *r->out.return_credentials = pipe_state->server_challenge;
68 dce_call->context->private_data = pipe_state;
70 return NT_STATUS_OK;
73 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
74 struct netr_ServerAuthenticate3 *r)
76 struct netlogon_server_pipe_state *pipe_state =
77 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
78 struct netlogon_creds_CredentialState *creds;
79 struct ldb_context *schannel_ldb;
80 struct ldb_context *sam_ctx;
81 struct samr_Password *mach_pwd;
82 uint32_t user_account_control;
83 int num_records;
84 struct ldb_message **msgs;
85 NTSTATUS nt_status;
86 const char *attrs[] = {"unicodePwd", "userAccountControl",
87 "objectSid", NULL};
89 const char *trust_dom_attrs[] = {"flatname", NULL};
90 const char *account_name;
92 ZERO_STRUCTP(r->out.return_credentials);
93 *r->out.rid = 0;
96 * According to Microsoft (see bugid #6099)
97 * Windows 7 looks at the negotiate_flags
98 * returned in this structure *even if the
99 * call fails with access denied!
101 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
102 NETLOGON_NEG_PERSISTENT_SAMREPL |
103 NETLOGON_NEG_ARCFOUR |
104 NETLOGON_NEG_PROMOTION_COUNT |
105 NETLOGON_NEG_CHANGELOG_BDC |
106 NETLOGON_NEG_FULL_SYNC_REPL |
107 NETLOGON_NEG_MULTIPLE_SIDS |
108 NETLOGON_NEG_REDO |
109 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
110 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
111 NETLOGON_NEG_GENERIC_PASSTHROUGH |
112 NETLOGON_NEG_CONCURRENT_RPC |
113 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
114 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
115 NETLOGON_NEG_STRONG_KEYS |
116 NETLOGON_NEG_TRANSITIVE_TRUSTS |
117 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
118 NETLOGON_NEG_PASSWORD_SET2 |
119 NETLOGON_NEG_GETDOMAININFO |
120 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
121 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
122 NETLOGON_NEG_RODC_PASSTHROUGH |
123 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
124 NETLOGON_NEG_AUTHENTICATED_RPC;
126 if (!pipe_state) {
127 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
128 return NT_STATUS_ACCESS_DENIED;
131 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
132 system_session(dce_call->conn->dce_ctx->lp_ctx));
133 if (sam_ctx == NULL) {
134 return NT_STATUS_INVALID_SYSTEM_SERVICE;
137 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
138 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
139 const char *flatname;
140 if (!encoded_account) {
141 return NT_STATUS_NO_MEMORY;
144 /* Kill the trailing dot */
145 if (encoded_account[strlen(encoded_account)-1] == '.') {
146 encoded_account[strlen(encoded_account)-1] = '\0';
149 /* pull the user attributes */
150 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
151 trust_dom_attrs,
152 "(&(trustPartner=%s)(objectclass=trustedDomain))",
153 encoded_account);
155 if (num_records == 0) {
156 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
157 encoded_account));
158 return NT_STATUS_ACCESS_DENIED;
161 if (num_records > 1) {
162 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
163 return NT_STATUS_INTERNAL_DB_CORRUPTION;
166 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
167 if (!flatname) {
168 /* No flatname for this trust - we can't proceed */
169 return NT_STATUS_ACCESS_DENIED;
171 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
173 if (!account_name) {
174 return NT_STATUS_NO_MEMORY;
177 } else {
178 account_name = r->in.account_name;
181 /* pull the user attributes */
182 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
183 "(&(sAMAccountName=%s)(objectclass=user))",
184 ldb_binary_encode_string(mem_ctx, account_name));
186 if (num_records == 0) {
187 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
188 r->in.account_name));
189 return NT_STATUS_ACCESS_DENIED;
192 if (num_records > 1) {
193 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
194 return NT_STATUS_INTERNAL_DB_CORRUPTION;
198 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
200 if (user_account_control & UF_ACCOUNTDISABLE) {
201 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
202 return NT_STATUS_ACCESS_DENIED;
205 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
206 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
207 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
208 return NT_STATUS_ACCESS_DENIED;
210 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
211 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
212 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
213 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
215 return NT_STATUS_ACCESS_DENIED;
217 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
218 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
219 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
220 return NT_STATUS_ACCESS_DENIED;
222 } else {
223 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
224 r->in.secure_channel_type));
225 return NT_STATUS_ACCESS_DENIED;
228 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
229 "objectSid", 0);
231 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
232 if (mach_pwd == NULL) {
233 return NT_STATUS_ACCESS_DENIED;
236 creds = netlogon_creds_server_init(mem_ctx,
237 r->in.account_name,
238 r->in.computer_name,
239 r->in.secure_channel_type,
240 &pipe_state->client_challenge,
241 &pipe_state->server_challenge,
242 mach_pwd,
243 r->in.credentials,
244 r->out.return_credentials,
245 *r->in.negotiate_flags);
247 if (!creds) {
248 return NT_STATUS_ACCESS_DENIED;
251 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
253 schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
254 if (!schannel_ldb) {
255 return NT_STATUS_ACCESS_DENIED;
258 nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
259 talloc_unlink(mem_ctx, schannel_ldb);
261 return nt_status;
264 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
265 struct netr_ServerAuthenticate *r)
267 struct netr_ServerAuthenticate3 a;
268 uint32_t rid;
269 /* TODO:
270 * negotiate_flags is used as an [in] parameter
271 * so it need to be initialised.
273 * (I think ... = 0; seems wrong here --metze)
275 uint32_t negotiate_flags_in = 0;
276 uint32_t negotiate_flags_out = 0;
278 a.in.server_name = r->in.server_name;
279 a.in.account_name = r->in.account_name;
280 a.in.secure_channel_type = r->in.secure_channel_type;
281 a.in.computer_name = r->in.computer_name;
282 a.in.credentials = r->in.credentials;
283 a.in.negotiate_flags = &negotiate_flags_in;
285 a.out.return_credentials = r->out.return_credentials;
286 a.out.rid = &rid;
287 a.out.negotiate_flags = &negotiate_flags_out;
289 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
292 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
293 struct netr_ServerAuthenticate2 *r)
295 struct netr_ServerAuthenticate3 r3;
296 uint32_t rid = 0;
298 r3.in.server_name = r->in.server_name;
299 r3.in.account_name = r->in.account_name;
300 r3.in.secure_channel_type = r->in.secure_channel_type;
301 r3.in.computer_name = r->in.computer_name;
302 r3.in.credentials = r->in.credentials;
303 r3.out.return_credentials = r->out.return_credentials;
304 r3.in.negotiate_flags = r->in.negotiate_flags;
305 r3.out.negotiate_flags = r->out.negotiate_flags;
306 r3.out.rid = &rid;
308 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
312 Validate an incoming authenticator against the credentials for the remote machine.
314 The credentials are (re)read and from the schannel database, and
315 written back after the caclulations are performed.
317 The creds_out parameter (if not NULL) returns the credentials, if
318 the caller needs some of that information.
321 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
322 TALLOC_CTX *mem_ctx,
323 const char *computer_name,
324 struct netr_Authenticator *received_authenticator,
325 struct netr_Authenticator *return_authenticator,
326 struct netlogon_creds_CredentialState **creds_out)
328 NTSTATUS nt_status;
329 struct ldb_context *ldb;
330 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
331 bool schannel_in_use = dce_call->conn->auth_state.auth_info
332 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
333 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY
334 || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
336 ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
337 if (!ldb) {
338 return NT_STATUS_ACCESS_DENIED;
340 nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
341 computer_name,
342 schannel_global_required,
343 schannel_in_use,
344 received_authenticator,
345 return_authenticator, creds_out);
346 talloc_unlink(mem_ctx, ldb);
347 return nt_status;
351 Change the machine account password for the currently connected
352 client. Supplies only the NT#.
355 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
356 struct netr_ServerPasswordSet *r)
358 struct netlogon_creds_CredentialState *creds;
359 struct ldb_context *sam_ctx;
360 NTSTATUS nt_status;
362 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
363 mem_ctx,
364 r->in.computer_name,
365 r->in.credential, r->out.return_authenticator,
366 &creds);
367 NT_STATUS_NOT_OK_RETURN(nt_status);
369 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));
370 if (sam_ctx == NULL) {
371 return NT_STATUS_INVALID_SYSTEM_SERVICE;
374 netlogon_creds_des_decrypt(creds, r->in.new_password);
376 /* Using the sid for the account as the key, set the password */
377 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
378 creds->sid,
379 NULL, /* Don't have plaintext */
380 NULL, r->in.new_password,
381 true, /* Password change */
382 NULL, NULL);
383 return nt_status;
387 Change the machine account password for the currently connected
388 client. Supplies new plaintext.
390 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
391 struct netr_ServerPasswordSet2 *r)
393 struct netlogon_creds_CredentialState *creds;
394 struct ldb_context *sam_ctx;
395 NTSTATUS nt_status;
396 DATA_BLOB new_password;
398 struct samr_CryptPassword password_buf;
400 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
401 mem_ctx,
402 r->in.computer_name,
403 r->in.credential, r->out.return_authenticator,
404 &creds);
405 NT_STATUS_NOT_OK_RETURN(nt_status);
407 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));
408 if (sam_ctx == NULL) {
409 return NT_STATUS_INVALID_SYSTEM_SERVICE;
412 memcpy(password_buf.data, r->in.new_password->data, 512);
413 SIVAL(password_buf.data, 512, r->in.new_password->length);
414 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
416 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
417 DEBUG(3,("samr: failed to decode password buffer\n"));
418 return NT_STATUS_WRONG_PASSWORD;
421 /* Using the sid for the account as the key, set the password */
422 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
423 creds->sid,
424 &new_password, /* we have plaintext */
425 NULL, NULL,
426 true, /* Password change */
427 NULL, NULL);
428 return nt_status;
433 netr_LogonUasLogon
435 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
436 struct netr_LogonUasLogon *r)
438 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
443 netr_LogonUasLogoff
445 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
446 struct netr_LogonUasLogoff *r)
448 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
453 netr_LogonSamLogon_base
455 This version of the function allows other wrappers to say 'do not check the credentials'
457 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
459 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
460 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
462 struct auth_context *auth_context;
463 struct auth_usersupplied_info *user_info;
464 struct auth_serversupplied_info *server_info;
465 NTSTATUS nt_status;
466 static const char zeros[16];
467 struct netr_SamBaseInfo *sam;
468 struct netr_SamInfo2 *sam2;
469 struct netr_SamInfo3 *sam3;
470 struct netr_SamInfo6 *sam6;
472 user_info = talloc(mem_ctx, struct auth_usersupplied_info);
473 NT_STATUS_HAVE_NO_MEMORY(user_info);
475 user_info->flags = 0;
476 user_info->mapped_state = false;
477 user_info->remote_host = NULL;
479 switch (r->in.logon_level) {
480 case NetlogonInteractiveInformation:
481 case NetlogonServiceInformation:
482 case NetlogonInteractiveTransitiveInformation:
483 case NetlogonServiceTransitiveInformation:
484 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
485 netlogon_creds_arcfour_crypt(creds,
486 r->in.logon->password->lmpassword.hash,
487 sizeof(r->in.logon->password->lmpassword.hash));
488 netlogon_creds_arcfour_crypt(creds,
489 r->in.logon->password->ntpassword.hash,
490 sizeof(r->in.logon->password->ntpassword.hash));
491 } else {
492 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
493 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
496 /* TODO: we need to deny anonymous access here */
497 nt_status = auth_context_create(mem_ctx,
498 dce_call->event_ctx, dce_call->msg_ctx,
499 dce_call->conn->dce_ctx->lp_ctx,
500 &auth_context);
501 NT_STATUS_NOT_OK_RETURN(nt_status);
503 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
504 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
505 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
506 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
508 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
509 user_info->password_state = AUTH_PASSWORD_HASH;
511 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
512 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
513 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
515 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
516 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
517 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
519 break;
520 case NetlogonNetworkInformation:
521 case NetlogonNetworkTransitiveInformation:
523 /* TODO: we need to deny anonymous access here */
524 nt_status = auth_context_create(mem_ctx,
525 dce_call->event_ctx, dce_call->msg_ctx,
526 dce_call->conn->dce_ctx->lp_ctx,
527 &auth_context);
528 NT_STATUS_NOT_OK_RETURN(nt_status);
530 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
531 NT_STATUS_NOT_OK_RETURN(nt_status);
533 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
534 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
535 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
536 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
538 user_info->password_state = AUTH_PASSWORD_RESPONSE;
539 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
540 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
542 break;
545 case NetlogonGenericInformation:
547 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
548 netlogon_creds_arcfour_crypt(creds,
549 r->in.logon->generic->data, r->in.logon->generic->length);
550 } else {
551 /* Using DES to verify kerberos tickets makes no sense */
552 return NT_STATUS_INVALID_PARAMETER;
555 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
556 NTSTATUS status;
557 struct server_id *kdc;
558 struct kdc_check_generic_kerberos check;
559 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
560 NT_STATUS_HAVE_NO_MEMORY(generic);
561 *r->out.authoritative = 1;
563 /* TODO: Describe and deal with these flags */
564 *r->out.flags = 0;
566 r->out.validation->generic = generic;
568 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
569 if ((kdc == NULL) || (kdc[0].id == 0)) {
570 return NT_STATUS_NO_LOGON_SERVERS;
573 check.in.generic_request =
574 data_blob_const(r->in.logon->generic->data,
575 r->in.logon->generic->length);
577 status = irpc_call(dce_call->msg_ctx, kdc[0],
578 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
579 &check, mem_ctx);
580 if (!NT_STATUS_IS_OK(status)) {
581 return status;
583 generic->length = check.out.generic_reply.length;
584 generic->data = check.out.generic_reply.data;
585 return NT_STATUS_OK;
588 /* Until we get an implemetnation of these other packages */
589 return NT_STATUS_INVALID_PARAMETER;
591 default:
592 return NT_STATUS_INVALID_PARAMETER;
595 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
596 NT_STATUS_NOT_OK_RETURN(nt_status);
598 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
599 NT_STATUS_NOT_OK_RETURN(nt_status);
601 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
602 /* It appears that level 6 is not individually encrypted */
603 if ((r->in.validation_level != 6) &&
604 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
605 /* This key is sent unencrypted without the ARCFOUR flag set */
606 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
607 netlogon_creds_arcfour_crypt(creds,
608 sam->key.key,
609 sizeof(sam->key.key));
613 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
614 /* It appears that level 6 is not individually encrypted */
615 if ((r->in.validation_level != 6) &&
616 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
617 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
618 netlogon_creds_arcfour_crypt(creds,
619 sam->LMSessKey.key,
620 sizeof(sam->LMSessKey.key));
621 } else {
622 netlogon_creds_des_encrypt_LMKey(creds,
623 &sam->LMSessKey);
627 switch (r->in.validation_level) {
628 case 2:
629 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
630 NT_STATUS_HAVE_NO_MEMORY(sam2);
631 sam2->base = *sam;
632 r->out.validation->sam2 = sam2;
633 break;
635 case 3:
636 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
637 NT_STATUS_HAVE_NO_MEMORY(sam3);
638 sam3->base = *sam;
639 r->out.validation->sam3 = sam3;
640 break;
642 case 6:
643 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
644 NT_STATUS_HAVE_NO_MEMORY(sam6);
645 sam6->base = *sam;
646 sam6->forest.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
647 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
648 sam->account_name.string, sam6->forest.string);
649 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
650 r->out.validation->sam6 = sam6;
651 break;
653 default:
654 break;
657 *r->out.authoritative = 1;
659 /* TODO: Describe and deal with these flags */
660 *r->out.flags = 0;
662 return NT_STATUS_OK;
665 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
666 struct netr_LogonSamLogonEx *r)
668 NTSTATUS nt_status;
669 struct netlogon_creds_CredentialState *creds;
670 struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
671 if (!ldb) {
672 return NT_STATUS_ACCESS_DENIED;
675 nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
676 if (!NT_STATUS_IS_OK(nt_status)) {
677 return nt_status;
680 if (!dce_call->conn->auth_state.auth_info ||
681 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
682 return NT_STATUS_ACCESS_DENIED;
684 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
688 netr_LogonSamLogonWithFlags
691 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
692 struct netr_LogonSamLogonWithFlags *r)
694 NTSTATUS nt_status;
695 struct netlogon_creds_CredentialState *creds;
696 struct netr_LogonSamLogonEx r2;
698 struct netr_Authenticator *return_authenticator;
700 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
701 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
703 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
704 mem_ctx,
705 r->in.computer_name,
706 r->in.credential, return_authenticator,
707 &creds);
708 NT_STATUS_NOT_OK_RETURN(nt_status);
710 ZERO_STRUCT(r2);
712 r2.in.server_name = r->in.server_name;
713 r2.in.computer_name = r->in.computer_name;
714 r2.in.logon_level = r->in.logon_level;
715 r2.in.logon = r->in.logon;
716 r2.in.validation_level = r->in.validation_level;
717 r2.in.flags = r->in.flags;
718 r2.out.validation = r->out.validation;
719 r2.out.authoritative = r->out.authoritative;
720 r2.out.flags = r->out.flags;
722 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
724 r->out.return_authenticator = return_authenticator;
726 return nt_status;
730 netr_LogonSamLogon
732 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
733 struct netr_LogonSamLogon *r)
735 struct netr_LogonSamLogonWithFlags r2;
736 uint32_t flags = 0;
737 NTSTATUS status;
739 ZERO_STRUCT(r2);
741 r2.in.server_name = r->in.server_name;
742 r2.in.computer_name = r->in.computer_name;
743 r2.in.credential = r->in.credential;
744 r2.in.return_authenticator = r->in.return_authenticator;
745 r2.in.logon_level = r->in.logon_level;
746 r2.in.logon = r->in.logon;
747 r2.in.validation_level = r->in.validation_level;
748 r2.in.flags = &flags;
749 r2.out.validation = r->out.validation;
750 r2.out.authoritative = r->out.authoritative;
751 r2.out.flags = &flags;
753 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
755 r->out.return_authenticator = r2.out.return_authenticator;
757 return status;
762 netr_LogonSamLogoff
764 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
765 struct netr_LogonSamLogoff *r)
767 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
773 netr_DatabaseDeltas
775 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
776 struct netr_DatabaseDeltas *r)
778 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
783 netr_DatabaseSync2
785 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
786 struct netr_DatabaseSync2 *r)
788 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
789 return NT_STATUS_NOT_IMPLEMENTED;
794 netr_DatabaseSync
796 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
797 struct netr_DatabaseSync *r)
799 struct netr_DatabaseSync2 r2;
800 NTSTATUS status;
802 ZERO_STRUCT(r2);
804 r2.in.logon_server = r->in.logon_server;
805 r2.in.computername = r->in.computername;
806 r2.in.credential = r->in.credential;
807 r2.in.database_id = r->in.database_id;
808 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
809 r2.in.sync_context = r->in.sync_context;
810 r2.out.sync_context = r->out.sync_context;
811 r2.out.delta_enum_array = r->out.delta_enum_array;
812 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
814 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
816 return status;
821 netr_AccountDeltas
823 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
824 struct netr_AccountDeltas *r)
826 /* w2k3 returns "NOT IMPLEMENTED" for this call */
827 return NT_STATUS_NOT_IMPLEMENTED;
832 netr_AccountSync
834 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
835 struct netr_AccountSync *r)
837 /* w2k3 returns "NOT IMPLEMENTED" for this call */
838 return NT_STATUS_NOT_IMPLEMENTED;
843 netr_GetDcName
845 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
846 struct netr_GetDcName *r)
848 const char * const attrs[] = { NULL };
849 struct ldb_context *sam_ctx;
850 struct ldb_message **res;
851 struct ldb_dn *domain_dn;
852 int ret;
853 const char *dcname;
855 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
856 dce_call->conn->dce_ctx->lp_ctx,
857 dce_call->conn->auth_state.session_info);
858 if (sam_ctx == NULL) {
859 return WERR_DS_UNAVAILABLE;
862 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
863 r->in.domainname);
864 if (domain_dn == NULL) {
865 return WERR_DS_UNAVAILABLE;
868 ret = gendb_search_dn(sam_ctx, mem_ctx,
869 domain_dn, &res, attrs);
870 if (ret != 1) {
871 return WERR_NO_SUCH_DOMAIN;
874 /* TODO: - return real IP address
875 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
877 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
878 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
879 W_ERROR_HAVE_NO_MEMORY(dcname);
881 *r->out.dcname = dcname;
882 return WERR_OK;
887 netr_LogonControl2Ex
889 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
890 struct netr_LogonControl2Ex *r)
892 return WERR_NOT_SUPPORTED;
897 netr_LogonControl
899 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
900 struct netr_LogonControl *r)
902 struct netr_LogonControl2Ex r2;
903 WERROR werr;
905 if (r->in.level == 0x00000001) {
906 ZERO_STRUCT(r2);
908 r2.in.logon_server = r->in.logon_server;
909 r2.in.function_code = r->in.function_code;
910 r2.in.level = r->in.level;
911 r2.in.data = NULL;
912 r2.out.query = r->out.query;
914 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
915 } else if (r->in.level == 0x00000002) {
916 werr = WERR_NOT_SUPPORTED;
917 } else {
918 werr = WERR_UNKNOWN_LEVEL;
921 return werr;
926 netr_LogonControl2
928 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
929 struct netr_LogonControl2 *r)
931 struct netr_LogonControl2Ex r2;
932 WERROR werr;
934 ZERO_STRUCT(r2);
936 r2.in.logon_server = r->in.logon_server;
937 r2.in.function_code = r->in.function_code;
938 r2.in.level = r->in.level;
939 r2.in.data = r->in.data;
940 r2.out.query = r->out.query;
942 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
944 return werr;
949 netr_GetAnyDCName
951 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
952 struct netr_GetAnyDCName *r)
954 struct netr_GetDcName r2;
955 WERROR werr;
957 ZERO_STRUCT(r2);
959 r2.in.logon_server = r->in.logon_server;
960 r2.in.domainname = r->in.domainname;
961 r2.out.dcname = r->out.dcname;
963 werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
965 return werr;
970 netr_DatabaseRedo
972 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973 struct netr_DatabaseRedo *r)
975 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
980 netr_NetrEnumerateTurstedDomains
982 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
983 struct netr_NetrEnumerateTrustedDomains *r)
985 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
990 netr_LogonGetCapabilities
992 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
993 struct netr_LogonGetCapabilities *r)
995 /* we don't support AES yet */
996 return NT_STATUS_NOT_IMPLEMENTED;
1001 netr_NETRLOGONSETSERVICEBITS
1003 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1004 struct netr_NETRLOGONSETSERVICEBITS *r)
1006 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1011 netr_LogonGetTrustRid
1013 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1014 struct netr_LogonGetTrustRid *r)
1016 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1021 netr_NETRLOGONCOMPUTESERVERDIGEST
1023 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1024 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1026 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1031 netr_NETRLOGONCOMPUTECLIENTDIGEST
1033 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1034 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1036 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1042 netr_DsRGetSiteName
1044 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1045 struct netr_DsRGetSiteName *r)
1047 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1052 fill in a netr_OneDomainInfo from a ldb search result
1054 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1055 struct loadparm_context *lp_ctx,
1056 struct ldb_context *sam_ctx,
1057 struct ldb_message *res,
1058 struct netr_OneDomainInfo *info,
1059 bool is_local, bool is_trust_list)
1061 ZERO_STRUCTP(info);
1063 if (is_trust_list) {
1064 /* w2k8 only fills this on trusted domains */
1065 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1066 info->trust_extension.length = 16;
1067 info->trust_extension.info->flags =
1068 NETR_TRUST_FLAG_TREEROOT |
1069 NETR_TRUST_FLAG_IN_FOREST |
1070 NETR_TRUST_FLAG_PRIMARY |
1071 NETR_TRUST_FLAG_NATIVE;
1073 info->trust_extension.info->parent_index = 0; /* should be index into array
1074 of parent */
1075 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1076 info->trust_extension.info->trust_attributes = 0; /* TODO: base on ldb search? */
1079 if (is_trust_list) {
1080 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1081 info->dns_forestname.string = NULL;
1082 } else {
1083 char *p;
1084 /* TODO: we need a common function for pulling the forest */
1085 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1086 if (!info->dns_forestname.string) {
1087 return NT_STATUS_NO_SUCH_DOMAIN;
1089 p = strchr(info->dns_forestname.string, '/');
1090 if (p) {
1091 *p = '\0';
1093 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1097 if (is_local) {
1098 info->domainname.string = lp_sam_name(lp_ctx);
1099 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1100 info->domain_guid = samdb_result_guid(res, "objectGUID");
1101 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1102 } else {
1103 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1104 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1105 info->domain_guid = samdb_result_guid(res, "objectGUID");
1106 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1108 if (!is_trust_list) {
1109 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1112 return NT_STATUS_OK;
1116 netr_LogonGetDomainInfo
1117 this is called as part of the ADS domain logon procedure.
1119 It has an important role in convaying details about the client, such
1120 as Operating System, Version, Service Pack etc.
1122 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1123 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1125 struct netlogon_creds_CredentialState *creds;
1126 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1127 "securityIdentifier", "trustPartner", NULL };
1128 const char * const attrs2[] = { "dNSHostName",
1129 "msDS-SupportedEncryptionTypes", NULL };
1130 const char *temp_str;
1131 const char *old_dns_hostname;
1132 struct ldb_context *sam_ctx;
1133 struct ldb_message **res1, **res2, **res3, *new_msg;
1134 struct ldb_dn *workstation_dn;
1135 struct netr_DomainInformation *domain_info;
1136 struct netr_LsaPolicyInformation *lsa_policy_info;
1137 struct netr_OsVersionInfoEx *os_version;
1138 uint32_t default_supported_enc_types = 0xFFFFFFFF;
1139 int ret1, ret2, ret3, i;
1140 NTSTATUS status;
1142 status = dcesrv_netr_creds_server_step_check(dce_call,
1143 mem_ctx,
1144 r->in.computer_name,
1145 r->in.credential,
1146 r->out.return_authenticator,
1147 &creds);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 DEBUG(0,(__location__ " Bad credentials - error\n"));
1151 NT_STATUS_NOT_OK_RETURN(status);
1153 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1154 dce_call->conn->dce_ctx->lp_ctx,
1155 system_session(dce_call->conn->dce_ctx->lp_ctx));
1156 if (sam_ctx == NULL) {
1157 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1160 switch (r->in.level) {
1161 case 1: /* Domain information */
1163 /* TODO: check NTSTATUS results - and fail also on SAMDB
1164 * errors (needs some testing against Windows Server 2008) */
1167 * Check that the computer name parameter matches as prefix with
1168 * the DNS hostname in the workstation info structure.
1170 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1171 strcspn(r->in.query->workstation_info->dns_hostname,
1172 "."));
1173 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1174 return NT_STATUS_INVALID_PARAMETER;
1176 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1177 dom_sid_string(mem_ctx, creds->sid));
1178 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1180 /* Lookup for attributes in workstation object */
1181 ret1 = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1182 &res1, attrs2);
1183 if (ret1 != 1) {
1184 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1187 /* Gets the old DNS hostname */
1188 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1189 NULL);
1191 /* Gets host informations and put them in our directory */
1192 new_msg = ldb_msg_new(mem_ctx);
1193 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1195 new_msg->dn = workstation_dn;
1197 /* Deletes old OS version values */
1198 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1199 "operatingSystemServicePack");
1200 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1201 "operatingSystemVersion");
1203 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1204 DEBUG(3,("Impossible to update samdb: %s\n",
1205 ldb_errstring(sam_ctx)));
1208 talloc_free(new_msg);
1210 new_msg = ldb_msg_new(mem_ctx);
1211 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1213 new_msg->dn = workstation_dn;
1215 /* Sets the OS name */
1216 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1217 "operatingSystem",
1218 r->in.query->workstation_info->os_name.string);
1221 * Sets informations from "os_version". On a empty structure
1222 * the values are cleared.
1224 if (r->in.query->workstation_info->os_version.os != NULL) {
1225 os_version = &r->in.query->workstation_info->os_version.os->os;
1227 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1228 "operatingSystemServicePack",
1229 os_version->CSDVersion);
1231 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1232 "operatingSystemVersion",
1233 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1234 os_version->MajorVersion,
1235 os_version->MinorVersion,
1236 os_version->BuildNumber
1242 * Updates the "dNSHostname" and the "servicePrincipalName"s
1243 * since the client wishes that the server should handle this
1244 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1245 * See MS-NRPC section 3.5.4.3.9
1247 if ((r->in.query->workstation_info->workstation_flags
1248 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1249 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1250 "dNSHostname",
1251 r->in.query->workstation_info->dns_hostname);
1253 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1254 "servicePrincipalName",
1255 talloc_asprintf(mem_ctx, "HOST/%s",
1256 r->in.computer_name)
1258 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1259 "servicePrincipalName",
1260 talloc_asprintf(mem_ctx, "HOST/%s",
1261 r->in.query->workstation_info->dns_hostname)
1265 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1266 DEBUG(3,("Impossible to update samdb: %s\n",
1267 ldb_errstring(sam_ctx)));
1270 talloc_free(new_msg);
1272 /* Writes back the domain information */
1274 /* We need to do two searches. The first will pull our primary
1275 domain and the second will pull any trusted domains. Our
1276 primary domain is also a "trusted" domain, so we need to
1277 put the primary domain into the lists of returned trusts as
1278 well. */
1279 ret2 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1280 &res2, attrs);
1281 if (ret2 != 1) {
1282 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1285 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1286 "(objectClass=trustedDomain)");
1287 if (ret3 == -1) {
1288 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1291 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1292 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1294 ZERO_STRUCTP(domain_info);
1296 /* Informations about the local and trusted domains */
1298 status = fill_one_domain_info(mem_ctx,
1299 dce_call->conn->dce_ctx->lp_ctx,
1300 sam_ctx, res2[0], &domain_info->primary_domain,
1301 true, false);
1302 NT_STATUS_NOT_OK_RETURN(status);
1304 domain_info->trusted_domain_count = ret3 + 1;
1305 domain_info->trusted_domains = talloc_array(mem_ctx,
1306 struct netr_OneDomainInfo,
1307 domain_info->trusted_domain_count);
1308 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1310 for (i=0;i<ret3;i++) {
1311 status = fill_one_domain_info(mem_ctx,
1312 dce_call->conn->dce_ctx->lp_ctx,
1313 sam_ctx, res3[i],
1314 &domain_info->trusted_domains[i],
1315 false, true);
1316 NT_STATUS_NOT_OK_RETURN(status);
1319 status = fill_one_domain_info(mem_ctx,
1320 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1321 &domain_info->trusted_domains[i], true, true);
1322 NT_STATUS_NOT_OK_RETURN(status);
1324 /* Sets the supported encryption types */
1325 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1326 "msDS-SupportedEncryptionTypes",
1327 default_supported_enc_types);
1329 /* Other host domain informations */
1331 lsa_policy_info = talloc(mem_ctx,
1332 struct netr_LsaPolicyInformation);
1333 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1334 ZERO_STRUCTP(lsa_policy_info);
1336 domain_info->lsa_policy = *lsa_policy_info;
1338 domain_info->dns_hostname.string = old_dns_hostname;
1339 domain_info->workstation_flags =
1340 r->in.query->workstation_info->workstation_flags;
1342 r->out.info->domain_info = domain_info;
1343 break;
1344 case 2: /* LSA policy information - not used at the moment */
1345 lsa_policy_info = talloc(mem_ctx,
1346 struct netr_LsaPolicyInformation);
1347 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1348 ZERO_STRUCTP(lsa_policy_info);
1350 r->out.info->lsa_policy_info = lsa_policy_info;
1351 break;
1352 default:
1353 return NT_STATUS_INVALID_LEVEL;
1354 break;
1357 return NT_STATUS_OK;
1363 netr_ServerPasswordGet
1365 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1366 struct netr_ServerPasswordGet *r)
1368 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1373 netr_NETRLOGONSENDTOSAM
1375 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1376 struct netr_NETRLOGONSENDTOSAM *r)
1378 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1383 netr_DsRAddressToSitenamesW
1385 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1386 struct netr_DsRAddressToSitenamesW *r)
1388 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1393 netr_DsRGetDCNameEx2
1395 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1396 TALLOC_CTX *mem_ctx,
1397 struct netr_DsRGetDCNameEx2 *r)
1399 const char * const attrs[] = { "objectGUID", NULL };
1400 struct ldb_context *sam_ctx;
1401 struct ldb_message **res;
1402 struct ldb_dn *domain_dn;
1403 int ret;
1404 struct netr_DsRGetDCNameInfo *info;
1405 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1407 ZERO_STRUCTP(r->out.info);
1409 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1410 dce_call->conn->auth_state.session_info);
1411 if (sam_ctx == NULL) {
1412 return WERR_DS_UNAVAILABLE;
1415 /* Windows 7 sends the domain name in the form the user typed, so we
1416 * have to cope with both the short and long form here */
1417 if (r->in.domain_name != NULL &&
1418 !lp_is_my_domain_or_realm(lp_ctx, r->in.domain_name)) {
1419 return WERR_NO_SUCH_DOMAIN;
1422 domain_dn = ldb_get_default_basedn(sam_ctx);
1423 if (domain_dn == NULL) {
1424 return WERR_DS_UNAVAILABLE;
1427 ret = gendb_search_dn(sam_ctx, mem_ctx,
1428 domain_dn, &res, attrs);
1429 if (ret != 1) {
1430 return WERR_GENERAL_FAILURE;
1433 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1434 W_ERROR_HAVE_NO_MEMORY(info);
1436 /* TODO: - return real IP address
1437 * - check all r->in.* parameters
1438 * (server_unc is ignored by w2k3!)
1440 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1441 lp_netbios_name(lp_ctx),
1442 lp_dnsdomain(lp_ctx));
1443 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1445 info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1446 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1448 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1449 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1450 info->domain_name = lp_dnsdomain(lp_ctx);
1451 info->forest_name = lp_dnsdomain(lp_ctx);
1452 info->dc_flags = DS_DNS_FOREST_ROOT |
1453 DS_DNS_DOMAIN |
1454 DS_DNS_CONTROLLER |
1455 DS_SERVER_WRITABLE |
1456 DS_SERVER_CLOSEST |
1457 DS_SERVER_TIMESERV |
1458 DS_SERVER_KDC |
1459 DS_SERVER_DS |
1460 DS_SERVER_LDAP |
1461 DS_SERVER_GC |
1462 DS_SERVER_PDC;
1464 info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1465 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1467 /* FIXME: Hardcoded site name */
1468 info->client_site_name = talloc_strdup(mem_ctx,
1469 "Default-First-Site-Name");
1470 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1472 *r->out.info = info;
1474 return WERR_OK;
1478 netr_DsRGetDCNameEx
1480 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1481 struct netr_DsRGetDCNameEx *r)
1483 struct netr_DsRGetDCNameEx2 r2;
1484 WERROR werr;
1486 ZERO_STRUCT(r2);
1488 r2.in.server_unc = r->in.server_unc;
1489 r2.in.client_account = NULL;
1490 r2.in.mask = 0;
1491 r2.in.domain_guid = r->in.domain_guid;
1492 r2.in.domain_name = r->in.domain_name;
1493 r2.in.site_name = r->in.site_name;
1494 r2.in.flags = r->in.flags;
1495 r2.out.info = r->out.info;
1497 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1499 return werr;
1503 netr_DsRGetDCName
1505 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1506 struct netr_DsRGetDCName *r)
1508 struct netr_DsRGetDCNameEx2 r2;
1509 WERROR werr;
1511 ZERO_STRUCT(r2);
1513 r2.in.server_unc = r->in.server_unc;
1514 r2.in.client_account = NULL;
1515 r2.in.mask = 0;
1516 r2.in.domain_name = r->in.domain_name;
1517 r2.in.domain_guid = r->in.domain_guid;
1519 r2.in.site_name = NULL; /* should fill in from site GUID */
1520 r2.in.flags = r->in.flags;
1521 r2.out.info = r->out.info;
1523 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1525 return werr;
1528 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1530 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1531 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1533 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1538 netr_NetrEnumerateTrustedDomainsEx
1540 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1541 struct netr_NetrEnumerateTrustedDomainsEx *r)
1543 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1548 netr_DsRAddressToSitenamesExW
1550 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1551 struct netr_DsRAddressToSitenamesExW *r)
1553 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1554 int i;
1556 /* we should map the provided IPs to site names, once we have
1557 * sites support
1559 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1560 W_ERROR_HAVE_NO_MEMORY(ctr);
1562 *r->out.ctr = ctr;
1564 ctr->count = r->in.count;
1565 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1566 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1567 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1568 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1570 for (i=0; i<ctr->count; i++) {
1571 /* FIXME: Hardcoded site name */
1572 ctr->sitename[i].string = "Default-First-Site-Name";
1573 ctr->subnetname[i].string = NULL;
1576 return WERR_OK;
1581 netr_DsrGetDcSiteCoverageW
1583 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1584 struct netr_DsrGetDcSiteCoverageW *r)
1586 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1591 netr_DsrEnumerateDomainTrusts
1593 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1594 struct netr_DsrEnumerateDomainTrusts *r)
1596 struct netr_DomainTrustList *trusts;
1597 struct ldb_context *sam_ctx;
1598 int ret;
1599 struct ldb_message **dom_res;
1600 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1602 ZERO_STRUCT(r->out);
1604 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1605 if (sam_ctx == NULL) {
1606 return WERR_GENERAL_FAILURE;
1609 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1610 &dom_res, dom_attrs);
1611 if (ret != 1) {
1612 return WERR_GENERAL_FAILURE;
1615 trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1616 W_ERROR_HAVE_NO_MEMORY(trusts);
1618 trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1619 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1621 trusts->count = 1; /* ?? */
1623 r->out.trusts = trusts;
1625 /* TODO: add filtering by trust_flags, and correct trust_type
1626 and attributes */
1627 trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1628 trusts->array[0].dns_name = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1629 trusts->array[0].trust_flags =
1630 NETR_TRUST_FLAG_TREEROOT |
1631 NETR_TRUST_FLAG_IN_FOREST |
1632 NETR_TRUST_FLAG_PRIMARY;
1633 trusts->array[0].parent_index = 0;
1634 trusts->array[0].trust_type = 2;
1635 trusts->array[0].trust_attributes = 0;
1636 trusts->array[0].sid = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1637 trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1639 return WERR_OK;
1644 netr_DsrDeregisterDNSHostRecords
1646 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647 struct netr_DsrDeregisterDNSHostRecords *r)
1649 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1654 netr_ServerTrustPasswordsGet
1656 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1657 struct netr_ServerTrustPasswordsGet *r)
1659 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1664 netr_DsRGetForestTrustInformation
1666 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1667 struct netr_DsRGetForestTrustInformation *r)
1669 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1674 netr_GetForestTrustInformation
1676 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1677 struct netr_GetForestTrustInformation *r)
1679 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1684 netr_ServerGetTrustInfo
1686 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1687 struct netr_ServerGetTrustInfo *r)
1689 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1693 /* include the generated boilerplate */
1694 #include "librpc/gen_ndr/ndr_netlogon_s.c"