s4-ldbwrap: added re-use of ldb contexts in ldb_wrap_connect()
[Samba/cd1.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobd59cb6fb823d480903d4a66195672e18d15f79c5
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 (samdb_replace(sam_ctx, mem_ctx, new_msg) != 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);
1220 if (r->in.query->workstation_info->dns_hostname) {
1221 /* TODO: should this always be done? */
1222 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1223 "dNSHostname",
1224 r->in.query->workstation_info->dns_hostname);
1228 * Sets informations from "os_version". On a empty structure
1229 * the values are cleared.
1231 if (r->in.query->workstation_info->os_version.os != NULL) {
1232 os_version = &r->in.query->workstation_info->os_version.os->os;
1234 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1235 "operatingSystemServicePack",
1236 os_version->CSDVersion);
1238 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1239 "operatingSystemVersion",
1240 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1241 os_version->MajorVersion,
1242 os_version->MinorVersion,
1243 os_version->BuildNumber
1249 * Updates the "dNSHostname" and the "servicePrincipalName"s
1250 * since the client wishes that the server should handle this
1251 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1252 * See MS-NRPC section 3.5.4.3.9
1254 if ((r->in.query->workstation_info->workstation_flags
1255 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1257 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1258 "servicePrincipalName",
1259 talloc_asprintf(mem_ctx, "HOST/%s",
1260 r->in.computer_name)
1262 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1263 "servicePrincipalName",
1264 talloc_asprintf(mem_ctx, "HOST/%s",
1265 r->in.query->workstation_info->dns_hostname)
1269 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1270 DEBUG(3,("Impossible to update samdb: %s\n",
1271 ldb_errstring(sam_ctx)));
1274 talloc_free(new_msg);
1276 /* Writes back the domain information */
1278 /* We need to do two searches. The first will pull our primary
1279 domain and the second will pull any trusted domains. Our
1280 primary domain is also a "trusted" domain, so we need to
1281 put the primary domain into the lists of returned trusts as
1282 well. */
1283 ret2 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1284 &res2, attrs);
1285 if (ret2 != 1) {
1286 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1289 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1290 "(objectClass=trustedDomain)");
1291 if (ret3 == -1) {
1292 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1295 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1296 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1298 ZERO_STRUCTP(domain_info);
1300 /* Informations about the local and trusted domains */
1302 status = fill_one_domain_info(mem_ctx,
1303 dce_call->conn->dce_ctx->lp_ctx,
1304 sam_ctx, res2[0], &domain_info->primary_domain,
1305 true, false);
1306 NT_STATUS_NOT_OK_RETURN(status);
1308 domain_info->trusted_domain_count = ret3 + 1;
1309 domain_info->trusted_domains = talloc_array(mem_ctx,
1310 struct netr_OneDomainInfo,
1311 domain_info->trusted_domain_count);
1312 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1314 for (i=0;i<ret3;i++) {
1315 status = fill_one_domain_info(mem_ctx,
1316 dce_call->conn->dce_ctx->lp_ctx,
1317 sam_ctx, res3[i],
1318 &domain_info->trusted_domains[i],
1319 false, true);
1320 NT_STATUS_NOT_OK_RETURN(status);
1323 status = fill_one_domain_info(mem_ctx,
1324 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1325 &domain_info->trusted_domains[i], true, true);
1326 NT_STATUS_NOT_OK_RETURN(status);
1328 /* Sets the supported encryption types */
1329 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1330 "msDS-SupportedEncryptionTypes",
1331 default_supported_enc_types);
1333 /* Other host domain informations */
1335 lsa_policy_info = talloc(mem_ctx,
1336 struct netr_LsaPolicyInformation);
1337 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1338 ZERO_STRUCTP(lsa_policy_info);
1340 domain_info->lsa_policy = *lsa_policy_info;
1342 domain_info->dns_hostname.string = old_dns_hostname;
1343 domain_info->workstation_flags =
1344 r->in.query->workstation_info->workstation_flags;
1346 r->out.info->domain_info = domain_info;
1347 break;
1348 case 2: /* LSA policy information - not used at the moment */
1349 lsa_policy_info = talloc(mem_ctx,
1350 struct netr_LsaPolicyInformation);
1351 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1352 ZERO_STRUCTP(lsa_policy_info);
1354 r->out.info->lsa_policy_info = lsa_policy_info;
1355 break;
1356 default:
1357 return NT_STATUS_INVALID_LEVEL;
1358 break;
1361 return NT_STATUS_OK;
1367 netr_ServerPasswordGet
1369 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1370 struct netr_ServerPasswordGet *r)
1372 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1377 netr_NETRLOGONSENDTOSAM
1379 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1380 struct netr_NETRLOGONSENDTOSAM *r)
1382 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1387 netr_DsRAddressToSitenamesW
1389 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1390 struct netr_DsRAddressToSitenamesW *r)
1392 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1397 netr_DsRGetDCNameEx2
1399 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1400 struct netr_DsRGetDCNameEx2 *r)
1402 const char * const attrs[] = { "objectGUID", NULL };
1403 struct ldb_context *sam_ctx;
1404 struct ldb_message **res;
1405 struct ldb_dn *domain_dn;
1406 int ret;
1407 struct netr_DsRGetDCNameInfo *info;
1409 ZERO_STRUCTP(r->out.info);
1411 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1412 if (sam_ctx == NULL) {
1413 return WERR_DS_UNAVAILABLE;
1416 /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1417 with both the short and long form here */
1418 if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx,
1419 r->in.domain_name)) {
1420 return WERR_NO_SUCH_DOMAIN;
1423 domain_dn = ldb_get_default_basedn(sam_ctx);
1424 if (domain_dn == NULL) {
1425 return WERR_DS_UNAVAILABLE;
1428 ret = gendb_search_dn(sam_ctx, mem_ctx,
1429 domain_dn, &res, attrs);
1430 if (ret != 1) {
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 (server_unc is ignored by w2k3!)
1439 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1440 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
1441 lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx));
1442 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);
1445 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1446 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1447 info->domain_name = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1448 info->forest_name = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1449 info->dc_flags = DS_DNS_FOREST_ROOT |
1450 DS_DNS_DOMAIN |
1451 DS_DNS_CONTROLLER |
1452 DS_SERVER_WRITABLE |
1453 DS_SERVER_CLOSEST |
1454 DS_SERVER_TIMESERV |
1455 DS_SERVER_KDC |
1456 DS_SERVER_DS |
1457 DS_SERVER_LDAP |
1458 DS_SERVER_GC |
1459 DS_SERVER_PDC;
1460 info->dc_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1461 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1462 /* FIXME: Hardcoded site name */
1463 info->client_site_name = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1464 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1466 *r->out.info = info;
1468 return WERR_OK;
1472 netr_DsRGetDCNameEx
1474 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1475 struct netr_DsRGetDCNameEx *r)
1477 struct netr_DsRGetDCNameEx2 r2;
1478 WERROR werr;
1480 ZERO_STRUCT(r2);
1482 r2.in.server_unc = r->in.server_unc;
1483 r2.in.client_account = NULL;
1484 r2.in.mask = 0;
1485 r2.in.domain_guid = r->in.domain_guid;
1486 r2.in.domain_name = r->in.domain_name;
1487 r2.in.site_name = r->in.site_name;
1488 r2.in.flags = r->in.flags;
1489 r2.out.info = r->out.info;
1491 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1493 return werr;
1497 netr_DsRGetDCName
1499 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1500 struct netr_DsRGetDCName *r)
1502 struct netr_DsRGetDCNameEx2 r2;
1503 WERROR werr;
1505 ZERO_STRUCT(r2);
1507 r2.in.server_unc = r->in.server_unc;
1508 r2.in.client_account = NULL;
1509 r2.in.mask = 0;
1510 r2.in.domain_name = r->in.domain_name;
1511 r2.in.domain_guid = r->in.domain_guid;
1513 r2.in.site_name = NULL; /* should fill in from site GUID */
1514 r2.in.flags = r->in.flags;
1515 r2.out.info = r->out.info;
1517 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1519 return werr;
1522 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1524 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1525 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1527 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1532 netr_NetrEnumerateTrustedDomainsEx
1534 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1535 struct netr_NetrEnumerateTrustedDomainsEx *r)
1537 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1542 netr_DsRAddressToSitenamesExW
1544 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1545 struct netr_DsRAddressToSitenamesExW *r)
1547 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1548 int i;
1550 /* we should map the provided IPs to site names, once we have
1551 * sites support
1553 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1554 W_ERROR_HAVE_NO_MEMORY(ctr);
1556 *r->out.ctr = ctr;
1558 ctr->count = r->in.count;
1559 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1560 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1561 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1562 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1564 for (i=0; i<ctr->count; i++) {
1565 /* FIXME: Hardcoded site name */
1566 ctr->sitename[i].string = "Default-First-Site-Name";
1567 ctr->subnetname[i].string = NULL;
1570 return WERR_OK;
1575 netr_DsrGetDcSiteCoverageW
1577 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1578 struct netr_DsrGetDcSiteCoverageW *r)
1580 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1585 netr_DsrEnumerateDomainTrusts
1587 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1588 struct netr_DsrEnumerateDomainTrusts *r)
1590 struct netr_DomainTrustList *trusts;
1591 struct ldb_context *sam_ctx;
1592 int ret;
1593 struct ldb_message **dom_res;
1594 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1596 ZERO_STRUCT(r->out);
1598 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1599 if (sam_ctx == NULL) {
1600 return WERR_GENERAL_FAILURE;
1603 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1604 &dom_res, dom_attrs);
1605 if (ret == -1) {
1606 return WERR_GENERAL_FAILURE;
1608 if (ret != 1) {
1609 return WERR_GENERAL_FAILURE;
1612 trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1613 W_ERROR_HAVE_NO_MEMORY(trusts);
1615 trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1616 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1618 trusts->count = 1; /* ?? */
1620 r->out.trusts = trusts;
1622 /* TODO: add filtering by trust_flags, and correct trust_type
1623 and attributes */
1624 trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1625 trusts->array[0].dns_name = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
1626 trusts->array[0].trust_flags =
1627 NETR_TRUST_FLAG_TREEROOT |
1628 NETR_TRUST_FLAG_IN_FOREST |
1629 NETR_TRUST_FLAG_PRIMARY;
1630 trusts->array[0].parent_index = 0;
1631 trusts->array[0].trust_type = 2;
1632 trusts->array[0].trust_attributes = 0;
1633 trusts->array[0].sid = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1634 trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1636 return WERR_OK;
1641 netr_DsrDeregisterDNSHostRecords
1643 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1644 struct netr_DsrDeregisterDNSHostRecords *r)
1646 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1651 netr_ServerTrustPasswordsGet
1653 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1654 struct netr_ServerTrustPasswordsGet *r)
1656 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1661 netr_DsRGetForestTrustInformation
1663 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1664 struct netr_DsRGetForestTrustInformation *r)
1666 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1671 netr_GetForestTrustInformation
1673 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1674 struct netr_GetForestTrustInformation *r)
1676 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1681 netr_ServerGetTrustInfo
1683 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1684 struct netr_ServerGetTrustInfo *r)
1686 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1690 /* include the generated boilerplate */
1691 #include "librpc/gen_ndr/ndr_netlogon_s.c"