s4-netlogon: implement dcesrv_netr_DsRAddressToSitenamesExW
[Samba/aatanasov.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
blobab7cc3409929b401b7dac0b781ee54995e117173
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 "rpc_server/common/common.h"
27 #include "lib/ldb/include/ldb.h"
28 #include "auth/auth.h"
29 #include "auth/auth_sam_reply.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "../libds/common/flags.h"
32 #include "rpc_server/samr/proto.h"
33 #include "../lib/util/util_ldb.h"
34 #include "libcli/auth/libcli_auth.h"
35 #include "../libcli/auth/schannel.h"
36 #include "auth/gensec/schannel_state.h"
37 #include "libcli/security/security.h"
38 #include "param/param.h"
39 #include "lib/messaging/irpc.h"
40 #include "librpc/gen_ndr/ndr_irpc.h"
41 #include "librpc/gen_ndr/ndr_netlogon.h"
43 struct netlogon_server_pipe_state {
44 struct netr_Credential client_challenge;
45 struct netr_Credential server_challenge;
49 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
50 struct netr_ServerReqChallenge *r)
52 struct netlogon_server_pipe_state *pipe_state =
53 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
55 ZERO_STRUCTP(r->out.return_credentials);
57 /* destroyed on pipe shutdown */
59 if (pipe_state) {
60 talloc_free(pipe_state);
61 dce_call->context->private_data = NULL;
64 pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
65 NT_STATUS_HAVE_NO_MEMORY(pipe_state);
67 pipe_state->client_challenge = *r->in.credentials;
69 generate_random_buffer(pipe_state->server_challenge.data,
70 sizeof(pipe_state->server_challenge.data));
72 *r->out.return_credentials = pipe_state->server_challenge;
74 dce_call->context->private_data = pipe_state;
76 return NT_STATUS_OK;
79 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
80 struct netr_ServerAuthenticate3 *r)
82 struct netlogon_server_pipe_state *pipe_state =
83 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
84 struct netlogon_creds_CredentialState *creds;
85 struct ldb_context *schannel_ldb;
86 struct ldb_context *sam_ctx;
87 struct samr_Password *mach_pwd;
88 uint32_t user_account_control;
89 int num_records;
90 struct ldb_message **msgs;
91 NTSTATUS nt_status;
92 const char *attrs[] = {"unicodePwd", "userAccountControl",
93 "objectSid", NULL};
95 const char *trust_dom_attrs[] = {"flatname", NULL};
96 const char *account_name;
98 ZERO_STRUCTP(r->out.return_credentials);
99 *r->out.rid = 0;
102 * According to Microsoft (see bugid #6099)
103 * Windows 7 looks at the negotiate_flags
104 * returned in this structure *even if the
105 * call fails with access denied!
107 *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
108 NETLOGON_NEG_PERSISTENT_SAMREPL |
109 NETLOGON_NEG_ARCFOUR |
110 NETLOGON_NEG_PROMOTION_COUNT |
111 NETLOGON_NEG_CHANGELOG_BDC |
112 NETLOGON_NEG_FULL_SYNC_REPL |
113 NETLOGON_NEG_MULTIPLE_SIDS |
114 NETLOGON_NEG_REDO |
115 NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
116 NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
117 NETLOGON_NEG_GENERIC_PASSTHROUGH |
118 NETLOGON_NEG_CONCURRENT_RPC |
119 NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
120 NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
121 NETLOGON_NEG_STRONG_KEYS |
122 NETLOGON_NEG_TRANSITIVE_TRUSTS |
123 NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
124 NETLOGON_NEG_PASSWORD_SET2 |
125 NETLOGON_NEG_GETDOMAININFO |
126 NETLOGON_NEG_CROSS_FOREST_TRUSTS |
127 NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
128 NETLOGON_NEG_RODC_PASSTHROUGH |
129 NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
130 NETLOGON_NEG_AUTHENTICATED_RPC;
132 if (!pipe_state) {
133 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
134 return NT_STATUS_ACCESS_DENIED;
137 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
138 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
139 if (sam_ctx == NULL) {
140 return NT_STATUS_INVALID_SYSTEM_SERVICE;
143 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
144 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
145 const char *flatname;
146 if (!encoded_account) {
147 return NT_STATUS_NO_MEMORY;
150 /* Kill the trailing dot */
151 if (encoded_account[strlen(encoded_account)-1] == '.') {
152 encoded_account[strlen(encoded_account)-1] = '\0';
155 /* pull the user attributes */
156 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
157 trust_dom_attrs,
158 "(&(trustPartner=%s)(objectclass=trustedDomain))",
159 encoded_account);
161 if (num_records == 0) {
162 DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
163 encoded_account));
164 return NT_STATUS_ACCESS_DENIED;
167 if (num_records > 1) {
168 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
169 return NT_STATUS_INTERNAL_DB_CORRUPTION;
172 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
173 if (!flatname) {
174 /* No flatname for this trust - we can't proceed */
175 return NT_STATUS_ACCESS_DENIED;
177 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
179 if (!account_name) {
180 return NT_STATUS_NO_MEMORY;
183 } else {
184 account_name = r->in.account_name;
187 /* pull the user attributes */
188 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
189 "(&(sAMAccountName=%s)(objectclass=user))",
190 ldb_binary_encode_string(mem_ctx, account_name));
192 if (num_records == 0) {
193 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
194 r->in.account_name));
195 return NT_STATUS_ACCESS_DENIED;
198 if (num_records > 1) {
199 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
200 return NT_STATUS_INTERNAL_DB_CORRUPTION;
204 user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
206 if (user_account_control & UF_ACCOUNTDISABLE) {
207 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
208 return NT_STATUS_ACCESS_DENIED;
211 if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
212 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
213 DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
214 return NT_STATUS_ACCESS_DENIED;
216 } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
217 r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
218 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
219 DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
221 return NT_STATUS_ACCESS_DENIED;
223 } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
224 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
225 DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
226 return NT_STATUS_ACCESS_DENIED;
228 } else {
229 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
230 r->in.secure_channel_type));
231 return NT_STATUS_ACCESS_DENIED;
234 *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
235 "objectSid", 0);
237 mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
238 if (mach_pwd == NULL) {
239 return NT_STATUS_ACCESS_DENIED;
242 creds = netlogon_creds_server_init(mem_ctx,
243 r->in.account_name,
244 r->in.computer_name,
245 r->in.secure_channel_type,
246 &pipe_state->client_challenge,
247 &pipe_state->server_challenge,
248 mach_pwd,
249 r->in.credentials,
250 r->out.return_credentials,
251 *r->in.negotiate_flags);
253 if (!creds) {
254 return NT_STATUS_ACCESS_DENIED;
257 creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
259 schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
260 if (!schannel_ldb) {
261 return NT_STATUS_ACCESS_DENIED;
264 nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
265 talloc_free(schannel_ldb);
267 return nt_status;
270 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
271 struct netr_ServerAuthenticate *r)
273 struct netr_ServerAuthenticate3 a;
274 uint32_t rid;
275 /* TODO:
276 * negotiate_flags is used as an [in] parameter
277 * so it need to be initialised.
279 * (I think ... = 0; seems wrong here --metze)
281 uint32_t negotiate_flags_in = 0;
282 uint32_t negotiate_flags_out = 0;
284 a.in.server_name = r->in.server_name;
285 a.in.account_name = r->in.account_name;
286 a.in.secure_channel_type = r->in.secure_channel_type;
287 a.in.computer_name = r->in.computer_name;
288 a.in.credentials = r->in.credentials;
289 a.in.negotiate_flags = &negotiate_flags_in;
291 a.out.return_credentials = r->out.return_credentials;
292 a.out.rid = &rid;
293 a.out.negotiate_flags = &negotiate_flags_out;
295 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
298 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
299 struct netr_ServerAuthenticate2 *r)
301 struct netr_ServerAuthenticate3 r3;
302 uint32_t rid = 0;
304 r3.in.server_name = r->in.server_name;
305 r3.in.account_name = r->in.account_name;
306 r3.in.secure_channel_type = r->in.secure_channel_type;
307 r3.in.computer_name = r->in.computer_name;
308 r3.in.credentials = r->in.credentials;
309 r3.out.return_credentials = r->out.return_credentials;
310 r3.in.negotiate_flags = r->in.negotiate_flags;
311 r3.out.negotiate_flags = r->out.negotiate_flags;
312 r3.out.rid = &rid;
314 return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
318 Validate an incoming authenticator against the credentials for the remote machine.
320 The credentials are (re)read and from the schannel database, and
321 written back after the caclulations are performed.
323 The creds_out parameter (if not NULL) returns the credentials, if
324 the caller needs some of that information.
327 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
328 TALLOC_CTX *mem_ctx,
329 const char *computer_name,
330 struct netr_Authenticator *received_authenticator,
331 struct netr_Authenticator *return_authenticator,
332 struct netlogon_creds_CredentialState **creds_out)
334 NTSTATUS nt_status;
335 struct ldb_context *ldb;
336 bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
337 bool schannel_in_use = dce_call->conn->auth_state.auth_info
338 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
339 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY
340 || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
342 ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
343 if (!ldb) {
344 return NT_STATUS_ACCESS_DENIED;
346 nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
347 computer_name,
348 schannel_global_required,
349 schannel_in_use,
350 received_authenticator,
351 return_authenticator, creds_out);
352 talloc_free(ldb);
353 return nt_status;
357 Change the machine account password for the currently connected
358 client. Supplies only the NT#.
361 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
362 struct netr_ServerPasswordSet *r)
364 struct netlogon_creds_CredentialState *creds;
365 struct ldb_context *sam_ctx;
366 NTSTATUS nt_status;
368 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
369 mem_ctx,
370 r->in.computer_name,
371 r->in.credential, r->out.return_authenticator,
372 &creds);
373 NT_STATUS_NOT_OK_RETURN(nt_status);
375 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
376 if (sam_ctx == NULL) {
377 return NT_STATUS_INVALID_SYSTEM_SERVICE;
380 netlogon_creds_des_decrypt(creds, r->in.new_password);
382 /* Using the sid for the account as the key, set the password */
383 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
384 creds->sid,
385 NULL, /* Don't have plaintext */
386 NULL, r->in.new_password,
387 true, /* Password change */
388 NULL, NULL);
389 return nt_status;
393 Change the machine account password for the currently connected
394 client. Supplies new plaintext.
396 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
397 struct netr_ServerPasswordSet2 *r)
399 struct netlogon_creds_CredentialState *creds;
400 struct ldb_context *sam_ctx;
401 NTSTATUS nt_status;
402 DATA_BLOB new_password;
404 struct samr_CryptPassword password_buf;
406 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
407 mem_ctx,
408 r->in.computer_name,
409 r->in.credential, r->out.return_authenticator,
410 &creds);
411 NT_STATUS_NOT_OK_RETURN(nt_status);
413 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
414 if (sam_ctx == NULL) {
415 return NT_STATUS_INVALID_SYSTEM_SERVICE;
418 memcpy(password_buf.data, r->in.new_password->data, 512);
419 SIVAL(password_buf.data, 512, r->in.new_password->length);
420 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
422 if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
423 DEBUG(3,("samr: failed to decode password buffer\n"));
424 return NT_STATUS_WRONG_PASSWORD;
427 /* Using the sid for the account as the key, set the password */
428 nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
429 creds->sid,
430 &new_password, /* we have plaintext */
431 NULL, NULL,
432 true, /* Password change */
433 NULL, NULL);
434 return nt_status;
439 netr_LogonUasLogon
441 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
442 struct netr_LogonUasLogon *r)
444 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
449 netr_LogonUasLogoff
451 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
452 struct netr_LogonUasLogoff *r)
454 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
459 netr_LogonSamLogon_base
461 This version of the function allows other wrappers to say 'do not check the credentials'
463 We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
465 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
466 struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
468 struct auth_context *auth_context;
469 struct auth_usersupplied_info *user_info;
470 struct auth_serversupplied_info *server_info;
471 NTSTATUS nt_status;
472 static const char zeros[16];
473 struct netr_SamBaseInfo *sam;
474 struct netr_SamInfo2 *sam2;
475 struct netr_SamInfo3 *sam3;
476 struct netr_SamInfo6 *sam6;
478 user_info = talloc(mem_ctx, struct auth_usersupplied_info);
479 NT_STATUS_HAVE_NO_MEMORY(user_info);
481 user_info->flags = 0;
482 user_info->mapped_state = false;
483 user_info->remote_host = NULL;
485 switch (r->in.logon_level) {
486 case NetlogonInteractiveInformation:
487 case NetlogonServiceInformation:
488 case NetlogonInteractiveTransitiveInformation:
489 case NetlogonServiceTransitiveInformation:
490 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
491 netlogon_creds_arcfour_crypt(creds,
492 r->in.logon->password->lmpassword.hash,
493 sizeof(r->in.logon->password->lmpassword.hash));
494 netlogon_creds_arcfour_crypt(creds,
495 r->in.logon->password->ntpassword.hash,
496 sizeof(r->in.logon->password->ntpassword.hash));
497 } else {
498 netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
499 netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
502 /* TODO: we need to deny anonymous access here */
503 nt_status = auth_context_create(mem_ctx,
504 dce_call->event_ctx, dce_call->msg_ctx,
505 dce_call->conn->dce_ctx->lp_ctx,
506 &auth_context);
507 NT_STATUS_NOT_OK_RETURN(nt_status);
509 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
510 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
511 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
512 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
514 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
515 user_info->password_state = AUTH_PASSWORD_HASH;
517 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
518 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
519 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
521 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
522 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
523 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
525 break;
526 case NetlogonNetworkInformation:
527 case NetlogonNetworkTransitiveInformation:
529 /* TODO: we need to deny anonymous access here */
530 nt_status = auth_context_create(mem_ctx,
531 dce_call->event_ctx, dce_call->msg_ctx,
532 dce_call->conn->dce_ctx->lp_ctx,
533 &auth_context);
534 NT_STATUS_NOT_OK_RETURN(nt_status);
536 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
537 NT_STATUS_NOT_OK_RETURN(nt_status);
539 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
540 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
541 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
542 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
544 user_info->password_state = AUTH_PASSWORD_RESPONSE;
545 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
546 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
548 break;
551 case NetlogonGenericInformation:
553 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
554 netlogon_creds_arcfour_crypt(creds,
555 r->in.logon->generic->data, r->in.logon->generic->length);
556 } else {
557 /* Using DES to verify kerberos tickets makes no sense */
558 return NT_STATUS_INVALID_PARAMETER;
561 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
562 NTSTATUS status;
563 struct server_id *kdc;
564 struct kdc_check_generic_kerberos check;
565 struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
566 NT_STATUS_HAVE_NO_MEMORY(generic);
567 *r->out.authoritative = 1;
569 /* TODO: Describe and deal with these flags */
570 *r->out.flags = 0;
572 r->out.validation->generic = generic;
574 kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
575 if ((kdc == NULL) || (kdc[0].id == 0)) {
576 return NT_STATUS_NO_LOGON_SERVERS;
579 check.in.generic_request =
580 data_blob_const(r->in.logon->generic->data,
581 r->in.logon->generic->length);
583 status = irpc_call(dce_call->msg_ctx, kdc[0],
584 &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
585 &check, mem_ctx);
586 if (!NT_STATUS_IS_OK(status)) {
587 return status;
589 generic->length = check.out.generic_reply.length;
590 generic->data = check.out.generic_reply.data;
591 return NT_STATUS_OK;
594 /* Until we get an implemetnation of these other packages */
595 return NT_STATUS_INVALID_PARAMETER;
597 default:
598 return NT_STATUS_INVALID_PARAMETER;
601 nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
602 NT_STATUS_NOT_OK_RETURN(nt_status);
604 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
605 NT_STATUS_NOT_OK_RETURN(nt_status);
607 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
608 /* It appears that level 6 is not individually encrypted */
609 if ((r->in.validation_level != 6) &&
610 memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
611 /* This key is sent unencrypted without the ARCFOUR flag set */
612 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
613 netlogon_creds_arcfour_crypt(creds,
614 sam->key.key,
615 sizeof(sam->key.key));
619 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
620 /* It appears that level 6 is not individually encrypted */
621 if ((r->in.validation_level != 6) &&
622 memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
623 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
624 netlogon_creds_arcfour_crypt(creds,
625 sam->LMSessKey.key,
626 sizeof(sam->LMSessKey.key));
627 } else {
628 netlogon_creds_des_encrypt_LMKey(creds,
629 &sam->LMSessKey);
633 switch (r->in.validation_level) {
634 case 2:
635 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
636 NT_STATUS_HAVE_NO_MEMORY(sam2);
637 sam2->base = *sam;
638 r->out.validation->sam2 = sam2;
639 break;
641 case 3:
642 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
643 NT_STATUS_HAVE_NO_MEMORY(sam3);
644 sam3->base = *sam;
645 r->out.validation->sam3 = sam3;
646 break;
648 case 6:
649 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
650 NT_STATUS_HAVE_NO_MEMORY(sam6);
651 sam6->base = *sam;
652 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
653 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
654 sam->account_name.string, sam6->forest.string);
655 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
656 r->out.validation->sam6 = sam6;
657 break;
659 default:
660 break;
663 *r->out.authoritative = 1;
665 /* TODO: Describe and deal with these flags */
666 *r->out.flags = 0;
668 return NT_STATUS_OK;
671 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
672 struct netr_LogonSamLogonEx *r)
674 NTSTATUS nt_status;
675 struct netlogon_creds_CredentialState *creds;
676 struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
677 if (!ldb) {
678 return NT_STATUS_ACCESS_DENIED;
681 nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
682 if (!NT_STATUS_IS_OK(nt_status)) {
683 return nt_status;
686 if (!dce_call->conn->auth_state.auth_info ||
687 dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
688 return NT_STATUS_ACCESS_DENIED;
690 return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
694 netr_LogonSamLogonWithFlags
697 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
698 struct netr_LogonSamLogonWithFlags *r)
700 NTSTATUS nt_status;
701 struct netlogon_creds_CredentialState *creds;
702 struct netr_LogonSamLogonEx r2;
704 struct netr_Authenticator *return_authenticator;
706 return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
707 NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
709 nt_status = dcesrv_netr_creds_server_step_check(dce_call,
710 mem_ctx,
711 r->in.computer_name,
712 r->in.credential, return_authenticator,
713 &creds);
714 NT_STATUS_NOT_OK_RETURN(nt_status);
716 ZERO_STRUCT(r2);
718 r2.in.server_name = r->in.server_name;
719 r2.in.computer_name = r->in.computer_name;
720 r2.in.logon_level = r->in.logon_level;
721 r2.in.logon = r->in.logon;
722 r2.in.validation_level = r->in.validation_level;
723 r2.in.flags = r->in.flags;
724 r2.out.validation = r->out.validation;
725 r2.out.authoritative = r->out.authoritative;
726 r2.out.flags = r->out.flags;
728 nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
730 r->out.return_authenticator = return_authenticator;
732 return nt_status;
736 netr_LogonSamLogon
738 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739 struct netr_LogonSamLogon *r)
741 struct netr_LogonSamLogonWithFlags r2;
742 uint32_t flags = 0;
743 NTSTATUS status;
745 ZERO_STRUCT(r2);
747 r2.in.server_name = r->in.server_name;
748 r2.in.computer_name = r->in.computer_name;
749 r2.in.credential = r->in.credential;
750 r2.in.return_authenticator = r->in.return_authenticator;
751 r2.in.logon_level = r->in.logon_level;
752 r2.in.logon = r->in.logon;
753 r2.in.validation_level = r->in.validation_level;
754 r2.in.flags = &flags;
755 r2.out.validation = r->out.validation;
756 r2.out.authoritative = r->out.authoritative;
757 r2.out.flags = &flags;
759 status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
761 r->out.return_authenticator = r2.out.return_authenticator;
763 return status;
768 netr_LogonSamLogoff
770 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
771 struct netr_LogonSamLogoff *r)
773 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
779 netr_DatabaseDeltas
781 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
782 struct netr_DatabaseDeltas *r)
784 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
789 netr_DatabaseSync2
791 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
792 struct netr_DatabaseSync2 *r)
794 /* win2k3 native mode returns "NOT IMPLEMENTED" for this call */
795 return NT_STATUS_NOT_IMPLEMENTED;
800 netr_DatabaseSync
802 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
803 struct netr_DatabaseSync *r)
805 struct netr_DatabaseSync2 r2;
806 NTSTATUS status;
808 ZERO_STRUCT(r2);
810 r2.in.logon_server = r->in.logon_server;
811 r2.in.computername = r->in.computername;
812 r2.in.credential = r->in.credential;
813 r2.in.database_id = r->in.database_id;
814 r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
815 r2.in.sync_context = r->in.sync_context;
816 r2.out.sync_context = r->out.sync_context;
817 r2.out.delta_enum_array = r->out.delta_enum_array;
818 r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
820 status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
822 return status;
827 netr_AccountDeltas
829 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830 struct netr_AccountDeltas *r)
832 /* w2k3 returns "NOT IMPLEMENTED" for this call */
833 return NT_STATUS_NOT_IMPLEMENTED;
838 netr_AccountSync
840 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841 struct netr_AccountSync *r)
843 /* w2k3 returns "NOT IMPLEMENTED" for this call */
844 return NT_STATUS_NOT_IMPLEMENTED;
849 netr_GetDcName
851 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
852 struct netr_GetDcName *r)
854 const char * const attrs[] = { NULL };
855 struct ldb_context *sam_ctx;
856 struct ldb_message **res;
857 struct ldb_dn *domain_dn;
858 int ret;
859 const char *dcname;
861 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
862 dce_call->conn->dce_ctx->lp_ctx,
863 dce_call->conn->auth_state.session_info);
864 if (sam_ctx == NULL) {
865 return WERR_DS_UNAVAILABLE;
868 domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
869 r->in.domainname);
870 if (domain_dn == NULL) {
871 return WERR_DS_UNAVAILABLE;
874 ret = gendb_search_dn(sam_ctx, mem_ctx,
875 domain_dn, &res, attrs);
876 if (ret != 1) {
877 return WERR_NO_SUCH_DOMAIN;
880 /* TODO: - return real IP address
881 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
883 dcname = talloc_asprintf(mem_ctx, "\\\\%s",
884 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
885 W_ERROR_HAVE_NO_MEMORY(dcname);
887 *r->out.dcname = dcname;
888 return WERR_OK;
893 netr_LogonControl2Ex
895 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
896 struct netr_LogonControl2Ex *r)
898 return WERR_NOT_SUPPORTED;
903 netr_LogonControl
905 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
906 struct netr_LogonControl *r)
908 struct netr_LogonControl2Ex r2;
909 WERROR werr;
911 if (r->in.level == 0x00000001) {
912 ZERO_STRUCT(r2);
914 r2.in.logon_server = r->in.logon_server;
915 r2.in.function_code = r->in.function_code;
916 r2.in.level = r->in.level;
917 r2.in.data = NULL;
918 r2.out.query = r->out.query;
920 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
921 } else if (r->in.level == 0x00000002) {
922 werr = WERR_NOT_SUPPORTED;
923 } else {
924 werr = WERR_UNKNOWN_LEVEL;
927 return werr;
932 netr_LogonControl2
934 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
935 struct netr_LogonControl2 *r)
937 struct netr_LogonControl2Ex r2;
938 WERROR werr;
940 ZERO_STRUCT(r2);
942 r2.in.logon_server = r->in.logon_server;
943 r2.in.function_code = r->in.function_code;
944 r2.in.level = r->in.level;
945 r2.in.data = r->in.data;
946 r2.out.query = r->out.query;
948 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
950 return werr;
955 netr_GetAnyDCName
957 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
958 struct netr_GetAnyDCName *r)
960 struct netr_GetDcName r2;
961 WERROR werr;
963 ZERO_STRUCT(r2);
965 r2.in.logon_server = r->in.logon_server;
966 r2.in.domainname = r->in.domainname;
967 r2.out.dcname = r->out.dcname;
969 werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
971 return werr;
976 netr_DatabaseRedo
978 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
979 struct netr_DatabaseRedo *r)
981 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
986 netr_NetrEnumerateTurstedDomains
988 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
989 struct netr_NetrEnumerateTrustedDomains *r)
991 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
996 netr_LogonGetCapabilities
998 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
999 struct netr_LogonGetCapabilities *r)
1001 /* we don't support AES yet */
1002 return NT_STATUS_NOT_IMPLEMENTED;
1007 netr_NETRLOGONSETSERVICEBITS
1009 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1010 struct netr_NETRLOGONSETSERVICEBITS *r)
1012 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1017 netr_LogonGetTrustRid
1019 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1020 struct netr_LogonGetTrustRid *r)
1022 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1027 netr_NETRLOGONCOMPUTESERVERDIGEST
1029 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1030 struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1032 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1037 netr_NETRLOGONCOMPUTECLIENTDIGEST
1039 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1040 struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1042 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1048 netr_DsRGetSiteName
1050 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1051 struct netr_DsRGetSiteName *r)
1053 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1058 fill in a netr_OneDomainInfo from a ldb search result
1060 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1061 struct loadparm_context *lp_ctx,
1062 struct ldb_context *sam_ctx,
1063 struct ldb_message *res,
1064 struct netr_OneDomainInfo *info,
1065 bool is_local, bool is_trust_list)
1067 ZERO_STRUCTP(info);
1069 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1070 info->trust_extension.length = 16;
1071 info->trust_extension.info->flags =
1072 NETR_TRUST_FLAG_TREEROOT |
1073 NETR_TRUST_FLAG_IN_FOREST |
1074 NETR_TRUST_FLAG_PRIMARY;
1076 info->trust_extension.info->parent_index = 0; /* should be index into array
1077 of parent */
1078 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1079 info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
1081 if (is_trust_list) {
1082 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1083 info->dns_forestname.string = NULL;
1084 } else {
1085 char *p;
1086 /* TODO: we need a common function for pulling the forest */
1087 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1088 if (!info->dns_forestname.string) {
1089 return NT_STATUS_NO_SUCH_DOMAIN;
1091 p = strchr(info->dns_forestname.string, '/');
1092 if (p) {
1093 *p = '\0';
1097 if (is_local) {
1098 info->domainname.string = lp_sam_name(lp_ctx);
1099 info->dns_domainname.string = lp_realm(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");
1109 return NT_STATUS_OK;
1113 netr_LogonGetDomainInfo
1114 this is called as part of the ADS domain logon procedure.
1116 It has an important role in convaying details about the client, such
1117 as Operating System, Version, Service Pack etc.
1119 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1120 TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1122 struct netlogon_creds_CredentialState *creds;
1123 const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1124 "securityIdentifier", "trustPartner", NULL };
1125 const char *temp_str;
1126 const char *old_dns_hostname;
1127 struct ldb_context *sam_ctx;
1128 struct ldb_message **res1, **res2, *new_msg;
1129 struct ldb_dn *workstation_dn;
1130 struct netr_DomainInformation *domain_info;
1131 struct netr_LsaPolicyInformation *lsa_policy_info;
1132 struct netr_OsVersionInfoEx *os_version;
1133 uint32_t default_supported_enc_types =
1134 ENC_CRC32|ENC_RSA_MD5|ENC_RC4_HMAC_MD5;
1135 int ret1, ret2, i;
1136 NTSTATUS status;
1138 status = dcesrv_netr_creds_server_step_check(dce_call,
1139 mem_ctx,
1140 r->in.computer_name,
1141 r->in.credential,
1142 r->out.return_authenticator,
1143 &creds);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 DEBUG(0,(__location__ " Bad credentials - error\n"));
1147 NT_STATUS_NOT_OK_RETURN(status);
1149 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1150 dce_call->conn->dce_ctx->lp_ctx,
1151 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
1152 if (sam_ctx == NULL) {
1153 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1156 switch (r->in.level) {
1157 case 1: /* Domain information */
1159 /* TODO: check NTSTATUS results - and fail also on SAMDB
1160 * errors (needs some testing against Windows Server 2008) */
1163 * Check that the computer name parameter matches as prefix with
1164 * the DNS hostname in the workstation info structure.
1166 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
1167 strcspn(r->in.query->workstation_info->dns_hostname,
1168 "."));
1169 if (strcasecmp(r->in.computer_name, temp_str) != 0)
1170 return NT_STATUS_INVALID_PARAMETER;
1172 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1173 dom_sid_string(mem_ctx, creds->sid));
1174 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1176 /* Gets the old DNS hostname */
1177 old_dns_hostname = samdb_search_string(sam_ctx, mem_ctx,
1178 workstation_dn,
1179 "dNSHostName",
1180 NULL);
1182 /* Gets host informations and put them in our directory */
1183 new_msg = ldb_msg_new(mem_ctx);
1184 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1186 new_msg->dn = workstation_dn;
1188 /* Deletes old OS version values */
1189 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1190 "operatingSystemServicePack");
1191 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1192 "operatingSystemVersion");
1194 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1195 DEBUG(3,("Impossible to update samdb: %s\n",
1196 ldb_errstring(sam_ctx)));
1199 talloc_free(new_msg);
1201 new_msg = ldb_msg_new(mem_ctx);
1202 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1204 new_msg->dn = workstation_dn;
1206 /* Sets the OS name */
1207 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1208 "operatingSystem",
1209 r->in.query->workstation_info->os_name.string);
1212 * Sets informations from "os_version". On a empty structure
1213 * the values are cleared.
1215 if (r->in.query->workstation_info->os_version.os != NULL) {
1216 os_version = &r->in.query->workstation_info->os_version.os->os;
1218 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1219 "operatingSystemServicePack",
1220 os_version->CSDVersion);
1222 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1223 "operatingSystemVersion",
1224 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1225 os_version->MajorVersion,
1226 os_version->MinorVersion,
1227 os_version->BuildNumber
1233 * Updates the "dNSHostname" and the "servicePrincipalName"s
1234 * since the client wishes that the server should handle this
1235 * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1236 * See MS-NRPC section 3.5.4.3.9
1238 if ((r->in.query->workstation_info->workstation_flags
1239 & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
1241 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1242 "dNSHostname",
1243 r->in.query->workstation_info->dns_hostname);
1244 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1245 "servicePrincipalName",
1246 talloc_asprintf(mem_ctx, "HOST/%s",
1247 r->in.computer_name)
1249 samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1250 "servicePrincipalName",
1251 talloc_asprintf(mem_ctx, "HOST/%s",
1252 r->in.query->workstation_info->dns_hostname)
1256 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
1257 DEBUG(3,("Impossible to update samdb: %s\n",
1258 ldb_errstring(sam_ctx)));
1261 talloc_free(new_msg);
1263 /* Writes back the domain information */
1265 /* We need to do two searches. The first will pull our primary
1266 domain and the second will pull any trusted domains. Our
1267 primary domain is also a "trusted" domain, so we need to
1268 put the primary domain into the lists of returned trusts as
1269 well. */
1270 ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
1271 &res1, attrs);
1272 if (ret1 != 1) {
1273 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1276 ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs,
1277 "(objectClass=trustedDomain)");
1278 if (ret2 == -1) {
1279 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1282 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1283 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1285 ZERO_STRUCTP(domain_info);
1287 /* Informations about the local and trusted domains */
1289 status = fill_one_domain_info(mem_ctx,
1290 dce_call->conn->dce_ctx->lp_ctx,
1291 sam_ctx, res1[0], &domain_info->primary_domain,
1292 true, false);
1293 NT_STATUS_NOT_OK_RETURN(status);
1295 domain_info->trusted_domain_count = ret2 + 1;
1296 domain_info->trusted_domains = talloc_array(mem_ctx,
1297 struct netr_OneDomainInfo,
1298 domain_info->trusted_domain_count);
1299 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1301 for (i=0;i<ret2;i++) {
1302 status = fill_one_domain_info(mem_ctx,
1303 dce_call->conn->dce_ctx->lp_ctx,
1304 sam_ctx, res2[i],
1305 &domain_info->trusted_domains[i],
1306 false, true);
1307 NT_STATUS_NOT_OK_RETURN(status);
1310 status = fill_one_domain_info(mem_ctx,
1311 dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0],
1312 &domain_info->trusted_domains[i], true, true);
1313 NT_STATUS_NOT_OK_RETURN(status);
1315 /* Sets the supported encryption types */
1316 domain_info->supported_enc_types = samdb_search_uint(
1317 sam_ctx, mem_ctx,
1318 default_supported_enc_types, workstation_dn,
1319 "msDS-SupportedEncryptionTypes", NULL);
1321 /* Other host domain informations */
1323 lsa_policy_info = talloc(mem_ctx,
1324 struct netr_LsaPolicyInformation);
1325 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1326 ZERO_STRUCTP(lsa_policy_info);
1328 domain_info->lsa_policy = *lsa_policy_info;
1330 domain_info->dns_hostname.string = old_dns_hostname;
1331 domain_info->workstation_flags =
1332 r->in.query->workstation_info->workstation_flags;
1334 r->out.info->domain_info = domain_info;
1335 break;
1336 case 2: /* LSA policy information - not used at the moment */
1337 lsa_policy_info = talloc(mem_ctx,
1338 struct netr_LsaPolicyInformation);
1339 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1340 ZERO_STRUCTP(lsa_policy_info);
1342 r->out.info->lsa_policy_info = lsa_policy_info;
1343 break;
1344 default:
1345 return NT_STATUS_INVALID_LEVEL;
1346 break;
1349 return NT_STATUS_OK;
1355 netr_ServerPasswordGet
1357 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1358 struct netr_ServerPasswordGet *r)
1360 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1365 netr_NETRLOGONSENDTOSAM
1367 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1368 struct netr_NETRLOGONSENDTOSAM *r)
1370 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1375 netr_DsRAddressToSitenamesW
1377 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1378 struct netr_DsRAddressToSitenamesW *r)
1380 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1385 netr_DsRGetDCNameEx2
1387 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1388 struct netr_DsRGetDCNameEx2 *r)
1390 const char * const attrs[] = { "objectGUID", NULL };
1391 struct ldb_context *sam_ctx;
1392 struct ldb_message **res;
1393 struct ldb_dn *domain_dn;
1394 int ret;
1395 struct netr_DsRGetDCNameInfo *info;
1397 ZERO_STRUCTP(r->out.info);
1399 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1400 if (sam_ctx == NULL) {
1401 return WERR_DS_UNAVAILABLE;
1404 /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1405 with both the short and long form here */
1406 if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx,
1407 r->in.domain_name)) {
1408 return WERR_NO_SUCH_DOMAIN;
1411 domain_dn = ldb_get_default_basedn(sam_ctx);
1412 if (domain_dn == NULL) {
1413 return WERR_DS_UNAVAILABLE;
1416 ret = gendb_search_dn(sam_ctx, mem_ctx,
1417 domain_dn, &res, attrs);
1418 if (ret != 1) {
1421 info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1422 W_ERROR_HAVE_NO_MEMORY(info);
1424 /* TODO: - return real IP address
1425 * - check all r->in.* parameters (server_unc is ignored by w2k3!)
1427 info->dc_unc = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1428 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
1429 lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1430 W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1431 info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1432 W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1433 info->dc_address_type = DS_ADDRESS_TYPE_INET;
1434 info->domain_guid = samdb_result_guid(res[0], "objectGUID");
1435 info->domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1436 info->forest_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1437 info->dc_flags = DS_DNS_FOREST |
1438 DS_DNS_DOMAIN |
1439 DS_DNS_CONTROLLER |
1440 DS_SERVER_WRITABLE |
1441 DS_SERVER_CLOSEST |
1442 DS_SERVER_TIMESERV |
1443 DS_SERVER_KDC |
1444 DS_SERVER_DS |
1445 DS_SERVER_LDAP |
1446 DS_SERVER_GC |
1447 DS_SERVER_PDC;
1448 info->dc_site_name = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1449 W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1450 info->client_site_name = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1451 W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1453 *r->out.info = info;
1455 return WERR_OK;
1459 netr_DsRGetDCNameEx
1461 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1462 struct netr_DsRGetDCNameEx *r)
1464 struct netr_DsRGetDCNameEx2 r2;
1465 WERROR werr;
1467 ZERO_STRUCT(r2);
1469 r2.in.server_unc = r->in.server_unc;
1470 r2.in.client_account = NULL;
1471 r2.in.mask = 0;
1472 r2.in.domain_guid = r->in.domain_guid;
1473 r2.in.domain_name = r->in.domain_name;
1474 r2.in.site_name = r->in.site_name;
1475 r2.in.flags = r->in.flags;
1476 r2.out.info = r->out.info;
1478 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1480 return werr;
1484 netr_DsRGetDCName
1486 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1487 struct netr_DsRGetDCName *r)
1489 struct netr_DsRGetDCNameEx2 r2;
1490 WERROR werr;
1492 ZERO_STRUCT(r2);
1494 r2.in.server_unc = r->in.server_unc;
1495 r2.in.client_account = NULL;
1496 r2.in.mask = 0;
1497 r2.in.domain_name = r->in.domain_name;
1498 r2.in.domain_guid = r->in.domain_guid;
1500 r2.in.site_name = NULL; /* should fill in from site GUID */
1501 r2.in.flags = r->in.flags;
1502 r2.out.info = r->out.info;
1504 werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1506 return werr;
1509 netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1511 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1512 struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1514 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1519 netr_NetrEnumerateTrustedDomainsEx
1521 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1522 struct netr_NetrEnumerateTrustedDomainsEx *r)
1524 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1529 netr_DsRAddressToSitenamesExW
1531 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1532 struct netr_DsRAddressToSitenamesExW *r)
1534 struct netr_DsRAddressToSitenamesExWCtr *ctr;
1535 int i;
1537 /* we should map the provided IPs to site names, once we have
1538 * sites support
1540 ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1541 W_ERROR_HAVE_NO_MEMORY(ctr);
1543 *r->out.ctr = ctr;
1545 ctr->count = r->in.count;
1546 ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1547 W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1548 ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1549 W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1551 for (i=0; i<ctr->count; i++) {
1552 ctr->sitename[i].string = "Default-First-Site-Name";
1553 ctr->subnetname[i].string = NULL;
1556 return WERR_OK;
1561 netr_DsrGetDcSiteCoverageW
1563 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1564 struct netr_DsrGetDcSiteCoverageW *r)
1566 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1571 netr_DsrEnumerateDomainTrusts
1573 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1574 struct netr_DsrEnumerateDomainTrusts *r)
1576 struct netr_DomainTrustList *trusts;
1577 struct ldb_context *sam_ctx;
1578 int ret;
1579 struct ldb_message **dom_res;
1580 const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1582 ZERO_STRUCT(r->out);
1584 sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1585 if (sam_ctx == NULL) {
1586 return WERR_GENERAL_FAILURE;
1589 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1590 &dom_res, dom_attrs);
1591 if (ret == -1) {
1592 return WERR_GENERAL_FAILURE;
1594 if (ret != 1) {
1595 return WERR_GENERAL_FAILURE;
1598 trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1599 W_ERROR_HAVE_NO_MEMORY(trusts);
1601 trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1602 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1604 trusts->count = 1; /* ?? */
1606 r->out.trusts = trusts;
1608 /* TODO: add filtering by trust_flags, and correct trust_type
1609 and attributes */
1610 trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1611 trusts->array[0].dns_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1612 trusts->array[0].trust_flags =
1613 NETR_TRUST_FLAG_TREEROOT |
1614 NETR_TRUST_FLAG_IN_FOREST |
1615 NETR_TRUST_FLAG_PRIMARY;
1616 trusts->array[0].parent_index = 0;
1617 trusts->array[0].trust_type = 2;
1618 trusts->array[0].trust_attributes = 0;
1619 trusts->array[0].sid = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1620 trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1622 return WERR_OK;
1627 netr_DsrDeregisterDNSHostRecords
1629 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1630 struct netr_DsrDeregisterDNSHostRecords *r)
1632 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1637 netr_ServerTrustPasswordsGet
1639 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1640 struct netr_ServerTrustPasswordsGet *r)
1642 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1647 netr_DsRGetForestTrustInformation
1649 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1650 struct netr_DsRGetForestTrustInformation *r)
1652 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1657 netr_GetForestTrustInformation
1659 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1660 struct netr_GetForestTrustInformation *r)
1662 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1667 netr_ServerGetTrustInfo
1669 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1670 struct netr_ServerGetTrustInfo *r)
1672 DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1676 /* include the generated boilerplate */
1677 #include "librpc/gen_ndr/ndr_netlogon_s.c"