s4:netlogon RPC - "fill_one_domain_info" - use "lp_workgroup" for the DC short domain...
[kamenim/samba.git] / source4 / rpc_server / netlogon / dcerpc_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the netlogon pipe
5
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
9
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.
14
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.
19
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/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc.h"
35 #include "cldap_server/cldap_server.h"
36 #include "lib/socket/socket.h"
37
38 struct netlogon_server_pipe_state {
39         struct netr_Credential client_challenge;
40         struct netr_Credential server_challenge;
41 };
42
43 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
44                                         struct netr_ServerReqChallenge *r)
45 {
46         struct netlogon_server_pipe_state *pipe_state =
47                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
48
49         ZERO_STRUCTP(r->out.return_credentials);
50
51         /* destroyed on pipe shutdown */
52
53         if (pipe_state) {
54                 talloc_free(pipe_state);
55                 dce_call->context->private_data = NULL;
56         }
57
58         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
59         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
60
61         pipe_state->client_challenge = *r->in.credentials;
62
63         generate_random_buffer(pipe_state->server_challenge.data,
64                                sizeof(pipe_state->server_challenge.data));
65
66         *r->out.return_credentials = pipe_state->server_challenge;
67
68         dce_call->context->private_data = pipe_state;
69
70         return NT_STATUS_OK;
71 }
72
73 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
74                                          struct netr_ServerAuthenticate3 *r)
75 {
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 *sam_ctx;
80         struct samr_Password *mach_pwd;
81         uint32_t user_account_control;
82         int num_records;
83         struct ldb_message **msgs;
84         NTSTATUS nt_status;
85         const char *attrs[] = {"unicodePwd", "userAccountControl",
86                                "objectSid", NULL};
87
88         const char *trust_dom_attrs[] = {"flatname", NULL};
89         const char *account_name;
90
91         ZERO_STRUCTP(r->out.return_credentials);
92         *r->out.rid = 0;
93
94         /*
95          * According to Microsoft (see bugid #6099)
96          * Windows 7 looks at the negotiate_flags
97          * returned in this structure *even if the
98          * call fails with access denied!
99          */
100         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
101                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
102                                   NETLOGON_NEG_ARCFOUR |
103                                   NETLOGON_NEG_PROMOTION_COUNT |
104                                   NETLOGON_NEG_CHANGELOG_BDC |
105                                   NETLOGON_NEG_FULL_SYNC_REPL |
106                                   NETLOGON_NEG_MULTIPLE_SIDS |
107                                   NETLOGON_NEG_REDO |
108                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
109                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
110                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
111                                   NETLOGON_NEG_CONCURRENT_RPC |
112                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
113                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
114                                   NETLOGON_NEG_STRONG_KEYS |
115                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
116                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
117                                   NETLOGON_NEG_PASSWORD_SET2 |
118                                   NETLOGON_NEG_GETDOMAININFO |
119                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
120                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
121                                   NETLOGON_NEG_RODC_PASSTHROUGH |
122                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
123                                   NETLOGON_NEG_AUTHENTICATED_RPC;
124
125         if (!pipe_state) {
126                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
127                 return NT_STATUS_ACCESS_DENIED;
128         }
129
130         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
131                                 system_session(dce_call->conn->dce_ctx->lp_ctx));
132         if (sam_ctx == NULL) {
133                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
134         }
135
136         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
137                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
138                 const char *flatname;
139                 if (!encoded_account) {
140                         return NT_STATUS_NO_MEMORY;
141                 }
142
143                 /* Kill the trailing dot */
144                 if (encoded_account[strlen(encoded_account)-1] == '.') {
145                         encoded_account[strlen(encoded_account)-1] = '\0';
146                 }
147
148                 /* pull the user attributes */
149                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
150                                            trust_dom_attrs,
151                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
152                                            encoded_account);
153
154                 if (num_records == 0) {
155                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
156                                  encoded_account));
157                         return NT_STATUS_ACCESS_DENIED;
158                 }
159
160                 if (num_records > 1) {
161                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
162                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
163                 }
164
165                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
166                 if (!flatname) {
167                         /* No flatname for this trust - we can't proceed */
168                         return NT_STATUS_ACCESS_DENIED;
169                 }
170                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
171
172                 if (!account_name) {
173                         return NT_STATUS_NO_MEMORY;
174                 }
175
176         } else {
177                 account_name = r->in.account_name;
178         }
179
180         /* pull the user attributes */
181         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
182                                    "(&(sAMAccountName=%s)(objectclass=user))",
183                                    ldb_binary_encode_string(mem_ctx, account_name));
184
185         if (num_records == 0) {
186                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
187                          r->in.account_name));
188                 return NT_STATUS_ACCESS_DENIED;
189         }
190
191         if (num_records > 1) {
192                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
193                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
194         }
195
196         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
197
198         if (user_account_control & UF_ACCOUNTDISABLE) {
199                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
200                 return NT_STATUS_ACCESS_DENIED;
201         }
202
203         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
204                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
205                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
206                         return NT_STATUS_ACCESS_DENIED;
207                 }
208         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
209                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
210                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
211                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
212
213                         return NT_STATUS_ACCESS_DENIED;
214                 }
215         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
216                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
217                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
218                         return NT_STATUS_ACCESS_DENIED;
219                 }
220         } else {
221                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
222                           r->in.secure_channel_type));
223                 return NT_STATUS_ACCESS_DENIED;
224         }
225
226         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
227                                                 "objectSid", 0);
228
229         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
230         if (mach_pwd == NULL) {
231                 return NT_STATUS_ACCESS_DENIED;
232         }
233
234         creds = netlogon_creds_server_init(mem_ctx,
235                                            r->in.account_name,
236                                            r->in.computer_name,
237                                            r->in.secure_channel_type,
238                                            &pipe_state->client_challenge,
239                                            &pipe_state->server_challenge,
240                                            mach_pwd,
241                                            r->in.credentials,
242                                            r->out.return_credentials,
243                                            *r->in.negotiate_flags);
244
245         if (!creds) {
246                 return NT_STATUS_ACCESS_DENIED;
247         }
248
249         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
250
251         nt_status = schannel_save_creds_state(mem_ctx,
252                                               lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
253                                               lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
254                                               creds);
255
256         return nt_status;
257 }
258
259 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
260                                         struct netr_ServerAuthenticate *r)
261 {
262         struct netr_ServerAuthenticate3 a;
263         uint32_t rid;
264         /* TODO:
265          * negotiate_flags is used as an [in] parameter
266          * so it need to be initialised.
267          *
268          * (I think ... = 0; seems wrong here --metze)
269          */
270         uint32_t negotiate_flags_in = 0;
271         uint32_t negotiate_flags_out = 0;
272
273         a.in.server_name                = r->in.server_name;
274         a.in.account_name               = r->in.account_name;
275         a.in.secure_channel_type        = r->in.secure_channel_type;
276         a.in.computer_name              = r->in.computer_name;
277         a.in.credentials                = r->in.credentials;
278         a.in.negotiate_flags            = &negotiate_flags_in;
279
280         a.out.return_credentials        = r->out.return_credentials;
281         a.out.rid                       = &rid;
282         a.out.negotiate_flags           = &negotiate_flags_out;
283
284         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
285 }
286
287 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
288                                          struct netr_ServerAuthenticate2 *r)
289 {
290         struct netr_ServerAuthenticate3 r3;
291         uint32_t rid = 0;
292
293         r3.in.server_name = r->in.server_name;
294         r3.in.account_name = r->in.account_name;
295         r3.in.secure_channel_type = r->in.secure_channel_type;
296         r3.in.computer_name = r->in.computer_name;
297         r3.in.credentials = r->in.credentials;
298         r3.out.return_credentials = r->out.return_credentials;
299         r3.in.negotiate_flags = r->in.negotiate_flags;
300         r3.out.negotiate_flags = r->out.negotiate_flags;
301         r3.out.rid = &rid;
302
303         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
304 }
305
306 /*
307  * NOTE: The following functions are nearly identical to the ones available in
308  * source3/rpc_server/srv_nelog_nt.c
309  * The reason we keep 2 copies is that they use different structures to
310  * represent the auth_info and the decrpc pipes.
311  */
312
313 /*
314  * If schannel is required for this call test that it actually is available.
315  */
316 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
317                                         const char *computer_name,
318                                         bool integrity, bool privacy)
319 {
320
321         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
322                 if (!privacy && !integrity) {
323                         return NT_STATUS_OK;
324                 }
325
326                 if ((!privacy && integrity) &&
327                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
328                         return NT_STATUS_OK;
329                 }
330
331                 if ((privacy || integrity) &&
332                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
333                         return NT_STATUS_OK;
334                 }
335         }
336
337         /* test didn't pass */
338         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
339                   computer_name));
340
341         return NT_STATUS_ACCESS_DENIED;
342 }
343
344 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
345                                                     TALLOC_CTX *mem_ctx,
346                                                     const char *computer_name,
347                                                     struct netr_Authenticator *received_authenticator,
348                                                     struct netr_Authenticator *return_authenticator,
349                                                     struct netlogon_creds_CredentialState **creds_out)
350 {
351         NTSTATUS nt_status;
352         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
353         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
354
355         if (schannel_global_required) {
356                 nt_status = schannel_check_required(auth_info,
357                                                     computer_name,
358                                                     true, false);
359                 if (!NT_STATUS_IS_OK(nt_status)) {
360                         return nt_status;
361                 }
362         }
363
364         nt_status = schannel_check_creds_state(mem_ctx,
365                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
366                                                lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
367                                                computer_name,
368                                                received_authenticator,
369                                                return_authenticator,
370                                                creds_out);
371         return nt_status;
372 }
373
374 /*
375   Change the machine account password for the currently connected
376   client.  Supplies only the NT#.
377 */
378
379 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
380                                        struct netr_ServerPasswordSet *r)
381 {
382         struct netlogon_creds_CredentialState *creds;
383         struct ldb_context *sam_ctx;
384         NTSTATUS nt_status;
385
386         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
387                                                         mem_ctx,
388                                                         r->in.computer_name,
389                                                         r->in.credential, r->out.return_authenticator,
390                                                         &creds);
391         NT_STATUS_NOT_OK_RETURN(nt_status);
392
393         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));
394         if (sam_ctx == NULL) {
395                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
396         }
397
398         netlogon_creds_des_decrypt(creds, r->in.new_password);
399
400         /* Using the sid for the account as the key, set the password */
401         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
402                                            creds->sid,
403                                            NULL, /* Don't have plaintext */
404                                            NULL, r->in.new_password,
405                                            true, /* Password change */
406                                            NULL, NULL);
407         return nt_status;
408 }
409
410 /*
411   Change the machine account password for the currently connected
412   client.  Supplies new plaintext.
413 */
414 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
415                                        struct netr_ServerPasswordSet2 *r)
416 {
417         struct netlogon_creds_CredentialState *creds;
418         struct ldb_context *sam_ctx;
419         NTSTATUS nt_status;
420         DATA_BLOB new_password;
421
422         struct samr_CryptPassword password_buf;
423
424         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
425                                                         mem_ctx,
426                                                         r->in.computer_name,
427                                                         r->in.credential, r->out.return_authenticator,
428                                                         &creds);
429         NT_STATUS_NOT_OK_RETURN(nt_status);
430
431         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));
432         if (sam_ctx == NULL) {
433                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
434         }
435
436         memcpy(password_buf.data, r->in.new_password->data, 512);
437         SIVAL(password_buf.data, 512, r->in.new_password->length);
438         netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
439
440         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
441                 DEBUG(3,("samr: failed to decode password buffer\n"));
442                 return NT_STATUS_WRONG_PASSWORD;
443         }
444
445         /* Using the sid for the account as the key, set the password */
446         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
447                                            creds->sid,
448                                            &new_password, /* we have plaintext */
449                                            NULL, NULL,
450                                            true, /* Password change */
451                                            NULL, NULL);
452         return nt_status;
453 }
454
455
456 /*
457   netr_LogonUasLogon
458 */
459 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
460                                  struct netr_LogonUasLogon *r)
461 {
462         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
463 }
464
465
466 /*
467   netr_LogonUasLogoff
468 */
469 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
470                        struct netr_LogonUasLogoff *r)
471 {
472         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
473 }
474
475
476 /*
477   netr_LogonSamLogon_base
478
479   This version of the function allows other wrappers to say 'do not check the credentials'
480
481   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
482 */
483 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
484                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
485 {
486         struct auth_context *auth_context;
487         struct auth_usersupplied_info *user_info;
488         struct auth_serversupplied_info *server_info;
489         NTSTATUS nt_status;
490         static const char zeros[16];
491         struct netr_SamBaseInfo *sam;
492         struct netr_SamInfo2 *sam2;
493         struct netr_SamInfo3 *sam3;
494         struct netr_SamInfo6 *sam6;
495
496         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
497         NT_STATUS_HAVE_NO_MEMORY(user_info);
498
499         user_info->flags = 0;
500         user_info->mapped_state = false;
501         user_info->remote_host = NULL;
502
503         switch (r->in.logon_level) {
504         case NetlogonInteractiveInformation:
505         case NetlogonServiceInformation:
506         case NetlogonInteractiveTransitiveInformation:
507         case NetlogonServiceTransitiveInformation:
508                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
509                         netlogon_creds_arcfour_crypt(creds,
510                                             r->in.logon->password->lmpassword.hash,
511                                             sizeof(r->in.logon->password->lmpassword.hash));
512                         netlogon_creds_arcfour_crypt(creds,
513                                             r->in.logon->password->ntpassword.hash,
514                                             sizeof(r->in.logon->password->ntpassword.hash));
515                 } else {
516                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
517                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
518                 }
519
520                 /* TODO: we need to deny anonymous access here */
521                 nt_status = auth_context_create(mem_ctx,
522                                                 dce_call->event_ctx, dce_call->msg_ctx,
523                                                 dce_call->conn->dce_ctx->lp_ctx,
524                                                 &auth_context);
525                 NT_STATUS_NOT_OK_RETURN(nt_status);
526
527                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
528                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
529                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
530                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
531
532                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
533                 user_info->password_state = AUTH_PASSWORD_HASH;
534
535                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
536                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
537                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
538
539                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
540                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
541                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
542
543                 break;
544         case NetlogonNetworkInformation:
545         case NetlogonNetworkTransitiveInformation:
546
547                 /* TODO: we need to deny anonymous access here */
548                 nt_status = auth_context_create(mem_ctx,
549                                                 dce_call->event_ctx, dce_call->msg_ctx,
550                                                 dce_call->conn->dce_ctx->lp_ctx,
551                                                 &auth_context);
552                 NT_STATUS_NOT_OK_RETURN(nt_status);
553
554                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
555                 NT_STATUS_NOT_OK_RETURN(nt_status);
556
557                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
558                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
559                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
560                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
561
562                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
563                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
564                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
565
566                 break;
567
568
569         case NetlogonGenericInformation:
570         {
571                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
572                         netlogon_creds_arcfour_crypt(creds,
573                                             r->in.logon->generic->data, r->in.logon->generic->length);
574                 } else {
575                         /* Using DES to verify kerberos tickets makes no sense */
576                         return NT_STATUS_INVALID_PARAMETER;
577                 }
578
579                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
580                         NTSTATUS status;
581                         struct server_id *kdc;
582                         struct kdc_check_generic_kerberos check;
583                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
584                         NT_STATUS_HAVE_NO_MEMORY(generic);
585                         *r->out.authoritative = 1;
586
587                         /* TODO: Describe and deal with these flags */
588                         *r->out.flags = 0;
589
590                         r->out.validation->generic = generic;
591
592                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
593                         if ((kdc == NULL) || (kdc[0].id == 0)) {
594                                 return NT_STATUS_NO_LOGON_SERVERS;
595                         }
596
597                         check.in.generic_request =
598                                 data_blob_const(r->in.logon->generic->data,
599                                                 r->in.logon->generic->length);
600
601                         status = irpc_call(dce_call->msg_ctx, kdc[0],
602                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
603                                            &check, mem_ctx);
604                         if (!NT_STATUS_IS_OK(status)) {
605                                 return status;
606                         }
607                         generic->length = check.out.generic_reply.length;
608                         generic->data = check.out.generic_reply.data;
609                         return NT_STATUS_OK;
610                 }
611
612                 /* Until we get an implemetnation of these other packages */
613                 return NT_STATUS_INVALID_PARAMETER;
614         }
615         default:
616                 return NT_STATUS_INVALID_PARAMETER;
617         }
618
619         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
620         NT_STATUS_NOT_OK_RETURN(nt_status);
621
622         switch (r->in.validation_level) {
623         case 2:
624                 nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
625                 NT_STATUS_NOT_OK_RETURN(nt_status);
626
627                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
628                 NT_STATUS_HAVE_NO_MEMORY(sam2);
629                 sam2->base = *sam;
630
631                 /* And put into the talloc tree */
632                 talloc_steal(sam2, sam);
633                 r->out.validation->sam2 = sam2;
634
635                 sam = &sam2->base;
636                 break;
637
638         case 3:
639                 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
640                                                               server_info,
641                                                               &sam3);
642                 NT_STATUS_NOT_OK_RETURN(nt_status);
643
644                 r->out.validation->sam3 = sam3;
645
646                 sam = &sam3->base;
647                 break;
648
649         case 6:
650                 nt_status = auth_convert_server_info_saminfo3(mem_ctx,
651                                                            server_info,
652                                                            &sam3);
653                 NT_STATUS_NOT_OK_RETURN(nt_status);
654
655                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
656                 NT_STATUS_HAVE_NO_MEMORY(sam6);
657                 sam6->base = sam3->base;
658                 sam = &sam6->base;
659                 sam6->sidcount = sam3->sidcount;
660                 sam6->sids = sam3->sids;
661
662                 sam6->dns_domainname.string = lp_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
663                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
664                                                          sam->account_name.string, sam6->dns_domainname.string);
665                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
666                 /* And put into the talloc tree */
667                 talloc_steal(sam6, sam3);
668
669                 r->out.validation->sam6 = sam6;
670                 break;
671
672         default:
673                 break;
674         }
675
676         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
677         /* It appears that level 6 is not individually encrypted */
678         if ((r->in.validation_level != 6) &&
679             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
680                 /* This key is sent unencrypted without the ARCFOUR flag set */
681                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
682                         netlogon_creds_arcfour_crypt(creds,
683                                             sam->key.key,
684                                             sizeof(sam->key.key));
685                 }
686         }
687
688         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
689         /* It appears that level 6 is not individually encrypted */
690         if ((r->in.validation_level != 6) &&
691             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
692                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
693                         netlogon_creds_arcfour_crypt(creds,
694                                             sam->LMSessKey.key,
695                                             sizeof(sam->LMSessKey.key));
696                 } else {
697                         netlogon_creds_des_encrypt_LMKey(creds,
698                                                 &sam->LMSessKey);
699                 }
700         }
701
702         *r->out.authoritative = 1;
703
704         /* TODO: Describe and deal with these flags */
705         *r->out.flags = 0;
706
707         return NT_STATUS_OK;
708 }
709
710 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
711                                      struct netr_LogonSamLogonEx *r)
712 {
713         NTSTATUS nt_status;
714         struct netlogon_creds_CredentialState *creds;
715
716         nt_status = schannel_get_creds_state(mem_ctx,
717                                              lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
718                                              lp_private_dir(dce_call->conn->dce_ctx->lp_ctx),
719                                              r->in.computer_name, &creds);
720         if (!NT_STATUS_IS_OK(nt_status)) {
721                 return nt_status;
722         }
723
724         if (!dce_call->conn->auth_state.auth_info ||
725             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
726                 return NT_STATUS_ACCESS_DENIED;
727         }
728         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
729 }
730
731 /*
732   netr_LogonSamLogonWithFlags
733
734 */
735 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
736                                             struct netr_LogonSamLogonWithFlags *r)
737 {
738         NTSTATUS nt_status;
739         struct netlogon_creds_CredentialState *creds;
740         struct netr_LogonSamLogonEx r2;
741
742         struct netr_Authenticator *return_authenticator;
743
744         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
745         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
746
747         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
748                                                         mem_ctx,
749                                                         r->in.computer_name,
750                                                         r->in.credential, return_authenticator,
751                                                         &creds);
752         NT_STATUS_NOT_OK_RETURN(nt_status);
753
754         ZERO_STRUCT(r2);
755
756         r2.in.server_name       = r->in.server_name;
757         r2.in.computer_name     = r->in.computer_name;
758         r2.in.logon_level       = r->in.logon_level;
759         r2.in.logon             = r->in.logon;
760         r2.in.validation_level  = r->in.validation_level;
761         r2.in.flags             = r->in.flags;
762         r2.out.validation       = r->out.validation;
763         r2.out.authoritative    = r->out.authoritative;
764         r2.out.flags            = r->out.flags;
765
766         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
767
768         r->out.return_authenticator     = return_authenticator;
769
770         return nt_status;
771 }
772
773 /*
774   netr_LogonSamLogon
775 */
776 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
777                                    struct netr_LogonSamLogon *r)
778 {
779         struct netr_LogonSamLogonWithFlags r2;
780         uint32_t flags = 0;
781         NTSTATUS status;
782
783         ZERO_STRUCT(r2);
784
785         r2.in.server_name = r->in.server_name;
786         r2.in.computer_name = r->in.computer_name;
787         r2.in.credential  = r->in.credential;
788         r2.in.return_authenticator = r->in.return_authenticator;
789         r2.in.logon_level = r->in.logon_level;
790         r2.in.logon = r->in.logon;
791         r2.in.validation_level = r->in.validation_level;
792         r2.in.flags = &flags;
793         r2.out.validation = r->out.validation;
794         r2.out.authoritative = r->out.authoritative;
795         r2.out.flags = &flags;
796
797         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
798
799         r->out.return_authenticator = r2.out.return_authenticator;
800
801         return status;
802 }
803
804
805 /*
806   netr_LogonSamLogoff
807 */
808 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
809                        struct netr_LogonSamLogoff *r)
810 {
811         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
812 }
813
814
815
816 /*
817   netr_DatabaseDeltas
818 */
819 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
820                        struct netr_DatabaseDeltas *r)
821 {
822         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
823 }
824
825
826 /*
827   netr_DatabaseSync2
828 */
829 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830                        struct netr_DatabaseSync2 *r)
831 {
832         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
833         return NT_STATUS_NOT_IMPLEMENTED;
834 }
835
836
837 /*
838   netr_DatabaseSync
839 */
840 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841                        struct netr_DatabaseSync *r)
842 {
843         struct netr_DatabaseSync2 r2;
844         NTSTATUS status;
845
846         ZERO_STRUCT(r2);
847
848         r2.in.logon_server = r->in.logon_server;
849         r2.in.computername = r->in.computername;
850         r2.in.credential = r->in.credential;
851         r2.in.database_id = r->in.database_id;
852         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
853         r2.in.sync_context = r->in.sync_context;
854         r2.out.sync_context = r->out.sync_context;
855         r2.out.delta_enum_array = r->out.delta_enum_array;
856         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
857
858         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
859
860         return status;
861 }
862
863
864 /*
865   netr_AccountDeltas
866 */
867 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
868                        struct netr_AccountDeltas *r)
869 {
870         /* w2k3 returns "NOT IMPLEMENTED" for this call */
871         return NT_STATUS_NOT_IMPLEMENTED;
872 }
873
874
875 /*
876   netr_AccountSync
877 */
878 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
879                        struct netr_AccountSync *r)
880 {
881         /* w2k3 returns "NOT IMPLEMENTED" for this call */
882         return NT_STATUS_NOT_IMPLEMENTED;
883 }
884
885
886 /*
887   netr_GetDcName
888 */
889 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
890                        struct netr_GetDcName *r)
891 {
892         const char * const attrs[] = { NULL };
893         struct ldb_context *sam_ctx;
894         struct ldb_message **res;
895         struct ldb_dn *domain_dn;
896         int ret;
897         const char *dcname;
898
899         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
900                                 dce_call->conn->dce_ctx->lp_ctx,
901                                 dce_call->conn->auth_state.session_info);
902         if (sam_ctx == NULL) {
903                 return WERR_DS_UNAVAILABLE;
904         }
905
906         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
907                                        r->in.domainname);
908         if (domain_dn == NULL) {
909                 return WERR_DS_UNAVAILABLE;
910         }
911
912         ret = gendb_search_dn(sam_ctx, mem_ctx,
913                               domain_dn, &res, attrs);
914         if (ret != 1) {
915                 return WERR_NO_SUCH_DOMAIN;
916         }
917
918         /* TODO: - return real IP address
919          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
920          */
921         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
922                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
923         W_ERROR_HAVE_NO_MEMORY(dcname);
924
925         *r->out.dcname = dcname;
926         return WERR_OK;
927 }
928
929
930 /*
931   netr_LogonControl2Ex
932 */
933 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
934                        struct netr_LogonControl2Ex *r)
935 {
936         return WERR_NOT_SUPPORTED;
937 }
938
939
940 /*
941   netr_LogonControl
942 */
943 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
944                        struct netr_LogonControl *r)
945 {
946         struct netr_LogonControl2Ex r2;
947         WERROR werr;
948
949         if (r->in.level == 0x00000001) {
950                 ZERO_STRUCT(r2);
951
952                 r2.in.logon_server = r->in.logon_server;
953                 r2.in.function_code = r->in.function_code;
954                 r2.in.level = r->in.level;
955                 r2.in.data = NULL;
956                 r2.out.query = r->out.query;
957
958                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
959         } else if (r->in.level == 0x00000002) {
960                 werr = WERR_NOT_SUPPORTED;
961         } else {
962                 werr = WERR_UNKNOWN_LEVEL;
963         }
964
965         return werr;
966 }
967
968
969 /*
970   netr_LogonControl2
971 */
972 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973                        struct netr_LogonControl2 *r)
974 {
975         struct netr_LogonControl2Ex r2;
976         WERROR werr;
977
978         ZERO_STRUCT(r2);
979
980         r2.in.logon_server = r->in.logon_server;
981         r2.in.function_code = r->in.function_code;
982         r2.in.level = r->in.level;
983         r2.in.data = r->in.data;
984         r2.out.query = r->out.query;
985
986         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
987
988         return werr;
989 }
990
991
992 /*
993   netr_GetAnyDCName
994 */
995 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
996                        struct netr_GetAnyDCName *r)
997 {
998         struct netr_GetDcName r2;
999         WERROR werr;
1000
1001         ZERO_STRUCT(r2);
1002
1003         r2.in.logon_server      = r->in.logon_server;
1004         r2.in.domainname        = r->in.domainname;
1005         r2.out.dcname           = r->out.dcname;
1006
1007         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
1008
1009         return werr;
1010 }
1011
1012
1013 /*
1014   netr_DatabaseRedo
1015 */
1016 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1017                        struct netr_DatabaseRedo *r)
1018 {
1019         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1020 }
1021
1022
1023 /*
1024   netr_NetrEnumerateTurstedDomains
1025 */
1026 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1027                        struct netr_NetrEnumerateTrustedDomains *r)
1028 {
1029         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1030 }
1031
1032
1033 /*
1034   netr_LogonGetCapabilities
1035 */
1036 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1037                        struct netr_LogonGetCapabilities *r)
1038 {
1039         /* we don't support AES yet */
1040         return NT_STATUS_NOT_IMPLEMENTED;
1041 }
1042
1043
1044 /*
1045   netr_NETRLOGONSETSERVICEBITS
1046 */
1047 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1048                        struct netr_NETRLOGONSETSERVICEBITS *r)
1049 {
1050         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1051 }
1052
1053
1054 /*
1055   netr_LogonGetTrustRid
1056 */
1057 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1058                        struct netr_LogonGetTrustRid *r)
1059 {
1060         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1061 }
1062
1063
1064 /*
1065   netr_NETRLOGONCOMPUTESERVERDIGEST
1066 */
1067 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1068                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1069 {
1070         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1071 }
1072
1073
1074 /*
1075   netr_NETRLOGONCOMPUTECLIENTDIGEST
1076 */
1077 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1078                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1079 {
1080         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1081 }
1082
1083
1084
1085 /*
1086   netr_DsRGetSiteName
1087 */
1088 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1089                                   struct netr_DsRGetSiteName *r)
1090 {
1091         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1092 }
1093
1094
1095 /*
1096   fill in a netr_OneDomainInfo from a ldb search result
1097 */
1098 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1099                                      struct loadparm_context *lp_ctx,
1100                                      struct ldb_context *sam_ctx,
1101                                      struct ldb_message *res,
1102                                      struct netr_OneDomainInfo *info,
1103                                      bool is_local, bool is_trust_list)
1104 {
1105         ZERO_STRUCTP(info);
1106
1107         if (is_trust_list) {
1108                 /* w2k8 only fills this on trusted domains */
1109                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1110                 info->trust_extension.length = 16;
1111                 info->trust_extension.info->flags =
1112                         NETR_TRUST_FLAG_TREEROOT |
1113                         NETR_TRUST_FLAG_IN_FOREST |
1114                         NETR_TRUST_FLAG_PRIMARY |
1115                         NETR_TRUST_FLAG_NATIVE;
1116
1117                 info->trust_extension.info->parent_index = 0; /* should be index into array
1118                                                                  of parent */
1119                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1120                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1121         }
1122
1123         if (is_trust_list) {
1124                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1125                 info->dns_forestname.string = NULL;
1126         } else {
1127                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1128                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1129                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1130                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1131         }
1132
1133         if (is_local) {
1134                 info->domainname.string = lp_workgroup(lp_ctx);
1135                 info->dns_domainname.string = lp_dnsdomain(lp_ctx);
1136                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1137                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1138         } else {
1139                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1140                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
1141                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1142                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1143         }
1144         if (!is_trust_list) {
1145                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1146         }
1147
1148         return NT_STATUS_OK;
1149 }
1150
1151 /*
1152   netr_LogonGetDomainInfo
1153   this is called as part of the ADS domain logon procedure.
1154
1155   It has an important role in convaying details about the client, such
1156   as Operating System, Version, Service Pack etc.
1157 */
1158 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1159         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1160 {
1161         struct netlogon_creds_CredentialState *creds;
1162         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1163                 "securityIdentifier", "trustPartner", NULL };
1164         const char * const attrs2[] = { "dNSHostName",
1165                 "msDS-SupportedEncryptionTypes", NULL };
1166         const char * const attrs3[] = { NULL };
1167         const char *temp_str, *temp_str2;
1168         const char *old_dns_hostname;
1169         struct ldb_context *sam_ctx;
1170         struct ldb_message **res0, **res1, **res2, **res3, *new_msg;
1171         struct ldb_dn *workstation_dn;
1172         struct netr_DomainInformation *domain_info;
1173         struct netr_LsaPolicyInformation *lsa_policy_info;
1174         struct netr_OsVersionInfoEx *os_version;
1175         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1176         bool update_dns_hostname = true;
1177         int ret, ret3, i;
1178         NTSTATUS status;
1179
1180         status = dcesrv_netr_creds_server_step_check(dce_call,
1181                                                      mem_ctx,
1182                                                      r->in.computer_name,
1183                                                      r->in.credential,
1184                                                      r->out.return_authenticator,
1185                                                      &creds);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1188         }
1189         NT_STATUS_NOT_OK_RETURN(status);
1190
1191         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1192                 dce_call->conn->dce_ctx->lp_ctx,
1193                 system_session(dce_call->conn->dce_ctx->lp_ctx));
1194         if (sam_ctx == NULL) {
1195                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1196         }
1197
1198         switch (r->in.level) {
1199         case 1: /* Domain information */
1200
1201                 /*
1202                  * Updates the DNS hostname when the client wishes that the
1203                  * server should handle this for him
1204                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
1205                  * See MS-NRPC section 3.5.4.3.9
1206                  */
1207                 if ((r->in.query->workstation_info->workstation_flags
1208                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1209                         update_dns_hostname = false;
1210                 }
1211
1212                 /*
1213                  * Checks that the computer name parameter without possible "$"
1214                  * matches as prefix with the DNS hostname in the workstation
1215                  * info structure.
1216                  */
1217                 temp_str = talloc_strndup(mem_ctx,
1218                                           r->in.computer_name,
1219                                           strcspn(r->in.computer_name, "$"));
1220                 NT_STATUS_HAVE_NO_MEMORY(temp_str);
1221                 temp_str2 = talloc_strndup(mem_ctx,
1222                                            r->in.query->workstation_info->dns_hostname,
1223                                            strcspn(r->in.query->workstation_info->dns_hostname, "."));
1224                 NT_STATUS_HAVE_NO_MEMORY(temp_str2);
1225                 if (strcasecmp(temp_str, temp_str2) != 0) {
1226                         update_dns_hostname = false;
1227                 }
1228
1229                 /*
1230                  * Check that the DNS hostname when it should be updated
1231                  * will be used only by maximum one host.
1232                  */
1233                 ret = gendb_search(sam_ctx, mem_ctx,
1234                                    ldb_get_default_basedn(sam_ctx),
1235                                    &res0, attrs3, "(dNSHostName=%s)",
1236                                    r->in.query->workstation_info->dns_hostname);
1237                 if (ret < 0) {
1238                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1239                 }
1240                 if (ret >= 1) {
1241                         update_dns_hostname = false;
1242                 }
1243
1244                 talloc_free(res0);
1245
1246                 /* Prepare the workstation DN */
1247                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1248                         dom_sid_string(mem_ctx, creds->sid));
1249                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1250
1251                 /* Lookup for attributes in workstation object */
1252                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn,
1253                         &res1, attrs2);
1254                 if (ret != 1) {
1255                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1256                 }
1257
1258                 /* Gets the old DNS hostname */
1259                 old_dns_hostname = samdb_result_string(res1[0], "dNSHostName",
1260                         NULL);
1261
1262                 /* Gets host informations and put them in our directory */
1263                 new_msg = ldb_msg_new(mem_ctx);
1264                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1265
1266                 new_msg->dn = workstation_dn;
1267
1268                 /* Deletes old OS version values */
1269                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1270                         "operatingSystemServicePack");
1271                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1272                         "operatingSystemVersion");
1273
1274                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1275                         DEBUG(3,("Impossible to update samdb: %s\n",
1276                                 ldb_errstring(sam_ctx)));
1277                 }
1278
1279                 talloc_free(new_msg);
1280
1281                 new_msg = ldb_msg_new(mem_ctx);
1282                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1283
1284                 new_msg->dn = workstation_dn;
1285
1286                 /* Sets the OS name */
1287                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1288                         "operatingSystem",
1289                         r->in.query->workstation_info->os_name.string);
1290
1291                 /*
1292                  * Sets informations from "os_version". On a empty structure
1293                  * the values are cleared.
1294                  */
1295                 if (r->in.query->workstation_info->os_version.os != NULL) {
1296                         os_version = &r->in.query->workstation_info->os_version.os->os;
1297
1298                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1299                                              "operatingSystemServicePack",
1300                                              os_version->CSDVersion);
1301
1302                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1303                                 "operatingSystemVersion",
1304                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
1305                                         os_version->MajorVersion,
1306                                         os_version->MinorVersion,
1307                                         os_version->BuildNumber
1308                                 )
1309                         );
1310                 }
1311
1312                 /*
1313                  * If the boolean "update_dns_hostname" remained true, then we
1314                  * are fine to start the update.
1315                  */
1316                 if (update_dns_hostname) {
1317                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
1318                                 "dNSHostname",
1319                         r->in.query->workstation_info->dns_hostname);
1320
1321                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1322                                 "servicePrincipalName",
1323                                 talloc_asprintf(mem_ctx, "HOST/%s",
1324                                 r->in.computer_name)
1325                         );
1326                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
1327                                 "servicePrincipalName",
1328                                 talloc_asprintf(mem_ctx, "HOST/%s",
1329                                 r->in.query->workstation_info->dns_hostname)
1330                         );
1331                 }
1332
1333                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1334                         DEBUG(3,("Impossible to update samdb: %s\n",
1335                                 ldb_errstring(sam_ctx)));
1336                 }
1337
1338                 talloc_free(new_msg);
1339
1340                 /* Writes back the domain information */
1341
1342                 /* We need to do two searches. The first will pull our primary
1343                    domain and the second will pull any trusted domains. Our
1344                    primary domain is also a "trusted" domain, so we need to
1345                    put the primary domain into the lists of returned trusts as
1346                    well. */
1347                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1348                         &res2, attrs);
1349                 if (ret != 1) {
1350                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1351                 }
1352
1353                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1354                         "(objectClass=trustedDomain)");
1355                 if (ret3 == -1) {
1356                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1357                 }
1358
1359                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1360                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1361
1362                 ZERO_STRUCTP(domain_info);
1363
1364                 /* Informations about the local and trusted domains */
1365
1366                 status = fill_one_domain_info(mem_ctx,
1367                         dce_call->conn->dce_ctx->lp_ctx,
1368                         sam_ctx, res2[0], &domain_info->primary_domain,
1369                         true, false);
1370                 NT_STATUS_NOT_OK_RETURN(status);
1371
1372                 domain_info->trusted_domain_count = ret3 + 1;
1373                 domain_info->trusted_domains = talloc_array(mem_ctx,
1374                         struct netr_OneDomainInfo,
1375                         domain_info->trusted_domain_count);
1376                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1377
1378                 for (i=0;i<ret3;i++) {
1379                         status = fill_one_domain_info(mem_ctx,
1380                                 dce_call->conn->dce_ctx->lp_ctx,
1381                                 sam_ctx, res3[i],
1382                                 &domain_info->trusted_domains[i],
1383                                 false, true);
1384                         NT_STATUS_NOT_OK_RETURN(status);
1385                 }
1386
1387                 status = fill_one_domain_info(mem_ctx,
1388                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1389                         &domain_info->trusted_domains[i], true, true);
1390                 NT_STATUS_NOT_OK_RETURN(status);
1391
1392                 /* Sets the supported encryption types */
1393                 domain_info->supported_enc_types = samdb_result_uint(res1[0],
1394                         "msDS-SupportedEncryptionTypes",
1395                         default_supported_enc_types);
1396
1397                 /* Other host domain informations */
1398
1399                 lsa_policy_info = talloc(mem_ctx,
1400                         struct netr_LsaPolicyInformation);
1401                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1402                 ZERO_STRUCTP(lsa_policy_info);
1403
1404                 domain_info->lsa_policy = *lsa_policy_info;
1405
1406                 /* The DNS hostname is only returned back when there is a chance
1407                  * for a change. */
1408                 if ((r->in.query->workstation_info->workstation_flags
1409                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1410                         domain_info->dns_hostname.string = old_dns_hostname;
1411                 } else {
1412                         domain_info->dns_hostname.string = NULL;
1413                 }
1414
1415                 domain_info->workstation_flags =
1416                         r->in.query->workstation_info->workstation_flags;
1417
1418                 r->out.info->domain_info = domain_info;
1419         break;
1420         case 2: /* LSA policy information - not used at the moment */
1421                 lsa_policy_info = talloc(mem_ctx,
1422                         struct netr_LsaPolicyInformation);
1423                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1424                 ZERO_STRUCTP(lsa_policy_info);
1425
1426                 r->out.info->lsa_policy_info = lsa_policy_info;
1427         break;
1428         default:
1429                 return NT_STATUS_INVALID_LEVEL;
1430         break;
1431         }
1432
1433         return NT_STATUS_OK;
1434 }
1435
1436
1437
1438 /*
1439   netr_ServerPasswordGet
1440 */
1441 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1442                        struct netr_ServerPasswordGet *r)
1443 {
1444         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1445 }
1446
1447
1448 /*
1449   netr_NETRLOGONSENDTOSAM
1450 */
1451 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1452                        struct netr_NETRLOGONSENDTOSAM *r)
1453 {
1454         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1455 }
1456
1457
1458 /*
1459   netr_DsRAddressToSitenamesW
1460 */
1461 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1462                        struct netr_DsRAddressToSitenamesW *r)
1463 {
1464         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1465 }
1466
1467
1468 /*
1469   netr_DsRGetDCNameEx2
1470 */
1471 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1472                                           TALLOC_CTX *mem_ctx,
1473                                           struct netr_DsRGetDCNameEx2 *r)
1474 {
1475         struct ldb_context *sam_ctx;
1476         struct netr_DsRGetDCNameInfo *info;
1477         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1478         struct socket_address *addr;
1479         const char *server_site_name;
1480         char *guid_str;
1481         struct netlogon_samlogon_response response;
1482         NTSTATUS status;
1483
1484         ZERO_STRUCTP(r->out.info);
1485
1486         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1487                                 dce_call->conn->auth_state.session_info);
1488         if (sam_ctx == NULL) {
1489                 return WERR_DS_UNAVAILABLE;
1490         }
1491
1492         addr = dce_call->conn->transport.get_peer_addr(dce_call->conn, mem_ctx);
1493         W_ERROR_HAVE_NO_MEMORY(addr);
1494
1495         /* "server_unc" is ignored by w2k3 */
1496
1497         /* Proof server site parameter "site_name" if it was specified */
1498         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1499         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1500         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1501                                                      server_site_name) != 0)) {
1502                 return WERR_NO_SUCH_DOMAIN;
1503         }
1504
1505         /* TODO: the flags are ignored for now */
1506
1507         guid_str = r->in.domain_guid != NULL ?
1508                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1509
1510         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1511                                                  r->in.domain_name,
1512                                                  r->in.domain_name,
1513                                                  NULL, guid_str,
1514                                                  r->in.client_account,
1515                                                  r->in.mask, addr->addr,
1516                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1517                                                  lp_ctx, &response);
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 return ntstatus_to_werror(status);
1520         }
1521
1522         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1523         W_ERROR_HAVE_NO_MEMORY(info);
1524         info->dc_unc           = response.data.nt5_ex.pdc_dns_name;
1525         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
1526                                            response.data.nt5_ex.sockaddr.pdc_ip);
1527         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1528         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1529         info->domain_name      = response.data.nt5_ex.dns_domain;
1530         info->forest_name      = response.data.nt5_ex.forest;
1531         info->dc_flags         = response.data.nt5_ex.server_type;
1532         info->dc_site_name     = response.data.nt5_ex.server_site;
1533         info->client_site_name = response.data.nt5_ex.client_site;
1534
1535         *r->out.info = info;
1536
1537         return WERR_OK;
1538 }
1539
1540 /*
1541   netr_DsRGetDCNameEx
1542 */
1543 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1544                                   struct netr_DsRGetDCNameEx *r)
1545 {
1546         struct netr_DsRGetDCNameEx2 r2;
1547         WERROR werr;
1548
1549         ZERO_STRUCT(r2);
1550
1551         r2.in.server_unc = r->in.server_unc;
1552         r2.in.client_account = NULL;
1553         r2.in.mask = 0;
1554         r2.in.domain_guid = r->in.domain_guid;
1555         r2.in.domain_name = r->in.domain_name;
1556         r2.in.site_name = r->in.site_name;
1557         r2.in.flags = r->in.flags;
1558         r2.out.info = r->out.info;
1559
1560         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1561
1562         return werr;
1563 }
1564
1565 /*
1566   netr_DsRGetDCName
1567 */
1568 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1569                                 struct netr_DsRGetDCName *r)
1570 {
1571         struct netr_DsRGetDCNameEx2 r2;
1572         WERROR werr;
1573
1574         ZERO_STRUCT(r2);
1575
1576         r2.in.server_unc = r->in.server_unc;
1577         r2.in.client_account = NULL;
1578         r2.in.mask = 0;
1579         r2.in.domain_name = r->in.domain_name;
1580         r2.in.domain_guid = r->in.domain_guid;
1581
1582         r2.in.site_name = NULL; /* should fill in from site GUID */
1583         r2.in.flags = r->in.flags;
1584         r2.out.info = r->out.info;
1585
1586         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1587
1588         return werr;
1589 }
1590 /*
1591   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1592 */
1593 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1594                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1595 {
1596         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1597 }
1598
1599
1600 /*
1601   netr_NetrEnumerateTrustedDomainsEx
1602 */
1603 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1604                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1605 {
1606         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1607 }
1608
1609
1610 /*
1611   netr_DsRAddressToSitenamesExW
1612 */
1613 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1614                                                    struct netr_DsRAddressToSitenamesExW *r)
1615 {
1616         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1617         int i;
1618
1619         /* we should map the provided IPs to site names, once we have
1620          * sites support
1621          */
1622         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1623         W_ERROR_HAVE_NO_MEMORY(ctr);
1624
1625         *r->out.ctr = ctr;
1626
1627         ctr->count = r->in.count;
1628         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1629         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1630         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1631         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1632
1633         for (i=0; i<ctr->count; i++) {
1634                 /* FIXME: Hardcoded site name */
1635                 ctr->sitename[i].string   = "Default-First-Site-Name";
1636                 ctr->subnetname[i].string = NULL;
1637         }
1638
1639         return WERR_OK;
1640 }
1641
1642
1643 /*
1644   netr_DsrGetDcSiteCoverageW
1645 */
1646 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1647                        struct netr_DsrGetDcSiteCoverageW *r)
1648 {
1649         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1650 }
1651
1652
1653 #define GET_CHECK_STR(dest, mem, msg, attr) \
1654 do {\
1655         const char *s; \
1656         s = samdb_result_string(msg, attr, NULL); \
1657         if (!s) { \
1658                 DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
1659                           "without flatname\n", \
1660                           ldb_dn_get_linearized(msg->dn))); \
1661                 continue; \
1662         } \
1663         dest = talloc_strdup(mem, s); \
1664         W_ERROR_HAVE_NO_MEMORY(dest); \
1665 } while(0)
1666
1667
1668 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1669                                          struct ldb_context *sam_ctx,
1670                                          struct netr_DomainTrustList *trusts,
1671                                          uint32_t trust_flags)
1672 {
1673         struct ldb_dn *system_dn;
1674         struct ldb_message **dom_res = NULL;
1675         const char *trust_attrs[] = { "flatname", "trustPartner",
1676                                       "securityIdentifier", "trustDirection",
1677                                       "trustType", "trustAttributes", NULL };
1678         int i, n;
1679         int ret;
1680
1681         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
1682                              NETR_TRUST_FLAG_OUTBOUND))) {
1683                 return WERR_INVALID_FLAGS;
1684         }
1685
1686         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
1687                                     ldb_get_default_basedn(sam_ctx),
1688                                     "(&(objectClass=container)(cn=System))");
1689         if (!system_dn) {
1690                 return WERR_GENERAL_FAILURE;
1691         }
1692
1693         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
1694                            &dom_res, trust_attrs,
1695                            "(objectclass=trustedDomain)");
1696
1697         for (i = 0; i < ret; i++) {
1698                 unsigned int trust_dir;
1699                 uint32_t flags = 0;
1700
1701                 trust_dir = samdb_result_uint(dom_res[i],
1702                                               "trustDirection", 0);
1703
1704                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
1705                         flags |= NETR_TRUST_FLAG_INBOUND;
1706                 }
1707                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
1708                         flags |= NETR_TRUST_FLAG_OUTBOUND;
1709                 }
1710
1711                 if (!(flags & trust_flags)) {
1712                         /* this trust direction was not requested */
1713                         continue;
1714                 }
1715
1716                 n = trusts->count;
1717                 trusts->array = talloc_realloc(trusts, trusts->array,
1718                                                struct netr_DomainTrust,
1719                                                n + 1);
1720                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1721
1722                 GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
1723                               dom_res[i], "flatname");
1724                 GET_CHECK_STR(trusts->array[n].dns_name, trusts,
1725                               dom_res[i], "trustPartner");
1726
1727                 trusts->array[n].trust_flags = flags;
1728                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
1729                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
1730                         /* TODO: find if we have parent in the list */
1731                         trusts->array[n].parent_index = 0;
1732                 }
1733
1734                 trusts->array[n].trust_type =
1735                                 samdb_result_uint(dom_res[i],
1736                                                   "trustType", 0);
1737                 trusts->array[n].trust_attributes =
1738                                 samdb_result_uint(dom_res[i],
1739                                                   "trustAttributes", 0);
1740
1741                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
1742                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
1743                         struct dom_sid zero_sid;
1744                         ZERO_STRUCT(zero_sid);
1745                         trusts->array[n].sid =
1746                                 dom_sid_dup(trusts, &zero_sid);
1747                 } else {
1748                         trusts->array[n].sid =
1749                                 samdb_result_dom_sid(trusts, dom_res[i],
1750                                                      "securityIdentifier");
1751                 }
1752                 trusts->array[n].guid = GUID_zero();
1753
1754                 trusts->count = n + 1;
1755         }
1756
1757         talloc_free(dom_res);
1758         return WERR_OK;
1759 }
1760
1761 /*
1762   netr_DsrEnumerateDomainTrusts
1763 */
1764 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
1765                                                    TALLOC_CTX *mem_ctx,
1766                                                    struct netr_DsrEnumerateDomainTrusts *r)
1767 {
1768         struct netr_DomainTrustList *trusts;
1769         struct ldb_context *sam_ctx;
1770         int ret;
1771         struct ldb_message **dom_res;
1772         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1773         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1774         const char *dnsdomain = lp_dnsdomain(lp_ctx);
1775         const char *p;
1776         WERROR werr;
1777
1778         if (r->in.trust_flags & 0xFFFFFE00) {
1779                 return WERR_INVALID_FLAGS;
1780         }
1781
1782         /* TODO: turn to hard check once we are sure this is 100% correct */
1783         if (!r->in.server_name) {
1784                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
1785                           "But received NULL!\n", dnsdomain));
1786         } else {
1787                 p = strchr(r->in.server_name, '.');
1788                 if (!p) {
1789                         DEBUG(3, ("Invalid domain! Expected name in domain "
1790                                   "[%s]. But received [%s]!\n",
1791                                   dnsdomain, r->in.server_name));
1792                         p = r->in.server_name;
1793                 } else {
1794                         p++;
1795                 }
1796                 if (strcasecmp(p, dnsdomain)) {
1797                         DEBUG(3, ("Invalid domain! Expected name in domain "
1798                                   "[%s]. But received [%s]!\n",
1799                                   dnsdomain, r->in.server_name));
1800                 }
1801         }
1802
1803         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1804         W_ERROR_HAVE_NO_MEMORY(trusts);
1805
1806         trusts->count = 0;
1807         r->out.trusts = trusts;
1808
1809         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1810                                 dce_call->conn->auth_state.session_info);
1811         if (sam_ctx == NULL) {
1812                 return WERR_GENERAL_FAILURE;
1813         }
1814
1815         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
1816             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
1817
1818                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
1819                                                   trusts, r->in.trust_flags);
1820                 W_ERROR_NOT_OK_RETURN(werr);
1821         }
1822
1823         /* NOTE: we currently are always the root of the forest */
1824         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1825                 int n = trusts->count;
1826
1827                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1828                                       &dom_res, dom_attrs);
1829                 if (ret != 1) {
1830                         return WERR_GENERAL_FAILURE;
1831                 }
1832
1833                 trusts->count = n + 1;
1834                 trusts->array = talloc_realloc(trusts, trusts->array,
1835                                                struct netr_DomainTrust,
1836                                                trusts->count);
1837                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
1838
1839                 trusts->array[n].netbios_name = lp_workgroup(lp_ctx);
1840                 trusts->array[n].dns_name = lp_dnsdomain(lp_ctx);
1841                 trusts->array[n].trust_flags =
1842                         NETR_TRUST_FLAG_NATIVE |
1843                         NETR_TRUST_FLAG_TREEROOT |
1844                         NETR_TRUST_FLAG_IN_FOREST |
1845                         NETR_TRUST_FLAG_PRIMARY;
1846                 /* we are always the root domain for now */
1847                 trusts->array[n].parent_index = 0;
1848                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
1849                 trusts->array[n].trust_attributes = 0;
1850                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
1851                                                             dom_res[0],
1852                                                             "objectSid");
1853                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
1854                                                           "objectGUID");
1855                 talloc_free(dom_res);
1856         }
1857
1858         return WERR_OK;
1859 }
1860
1861
1862 /*
1863   netr_DsrDeregisterDNSHostRecords
1864 */
1865 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1866                        struct netr_DsrDeregisterDNSHostRecords *r)
1867 {
1868         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1869 }
1870
1871
1872 /*
1873   netr_ServerTrustPasswordsGet
1874 */
1875 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1876                        struct netr_ServerTrustPasswordsGet *r)
1877 {
1878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1879 }
1880
1881
1882 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
1883                                       struct ldb_context *sam_ctx,
1884                                       struct loadparm_context *lp_ctx,
1885                                       struct lsa_ForestTrustInformation *info)
1886 {
1887         struct lsa_ForestTrustDomainInfo *domain_info;
1888         struct lsa_ForestTrustRecord *e;
1889         struct ldb_message **dom_res;
1890         const char * const dom_attrs[] = { "objectSid", NULL };
1891         int ret;
1892
1893         /* we need to provide 2 entries:
1894          * 1. the Root Forest name
1895          * 2. the Domain Information
1896          */
1897
1898         info->count = 2;
1899         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
1900         W_ERROR_HAVE_NO_MEMORY(info->entries);
1901
1902         /* Forest root info */
1903         e = talloc(info, struct lsa_ForestTrustRecord);
1904         W_ERROR_HAVE_NO_MEMORY(e);
1905
1906         e->flags = 0;
1907         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
1908         e->time = 0; /* so far always 0 in trces. */
1909         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
1910                                                                        mem_ctx);
1911         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
1912
1913         info->entries[0] = e;
1914
1915         /* Domain info */
1916         e = talloc(info, struct lsa_ForestTrustRecord);
1917         W_ERROR_HAVE_NO_MEMORY(e);
1918
1919         /* get our own domain info */
1920         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1921         if (ret != 1) {
1922                 return WERR_GENERAL_FAILURE;
1923         }
1924
1925         /* TODO: check if disabled and set flags accordingly */
1926         e->flags = 0;
1927         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
1928         e->time = 0; /* so far always 0 in traces. */
1929
1930         domain_info = &e->forest_trust_data.domain_info;
1931         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
1932                                                        "objectSid");
1933         domain_info->dns_domain_name.string = lp_dnsdomain(lp_ctx);
1934         domain_info->netbios_domain_name.string = lp_workgroup(lp_ctx);
1935
1936         info->entries[1] = e;
1937
1938         talloc_free(dom_res);
1939
1940         return WERR_OK;
1941 }
1942
1943 /*
1944   netr_DsRGetForestTrustInformation
1945 */
1946 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
1947                                                        TALLOC_CTX *mem_ctx,
1948                                                        struct netr_DsRGetForestTrustInformation *r)
1949 {
1950         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1951         struct lsa_ForestTrustInformation *info, **info_ptr;
1952         struct ldb_context *sam_ctx;
1953         WERROR werr;
1954
1955         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
1956                 return WERR_CALL_NOT_IMPLEMENTED;
1957         }
1958
1959         if (r->in.flags & 0xFFFFFFFE) {
1960                 return WERR_INVALID_FLAGS;
1961         }
1962
1963         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1964                                 dce_call->conn->auth_state.session_info);
1965         if (sam_ctx == NULL) {
1966                 return WERR_GENERAL_FAILURE;
1967         }
1968
1969         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
1970                 if (!samdb_is_pdc(sam_ctx)) {
1971                         return WERR_NERR_NOTPRIMARY;
1972                 }
1973
1974                 if (r->in.trusted_domain_name == NULL) {
1975                         return WERR_INVALID_FLAGS;
1976                 }
1977
1978                 /* TODO: establish an schannel connection with
1979                  * r->in.trusted_domain_name and perform a
1980                  * netr_GetForestTrustInformation call against it */
1981
1982                 /* for now return not implementd */
1983                 return WERR_CALL_NOT_IMPLEMENTED;
1984         }
1985
1986         /* TODO: check r->in.server_name is our name */
1987
1988         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
1989         W_ERROR_HAVE_NO_MEMORY(info_ptr);
1990
1991         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
1992         W_ERROR_HAVE_NO_MEMORY(info);
1993
1994         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
1995         W_ERROR_NOT_OK_RETURN(werr);
1996
1997         *info_ptr = info;
1998         r->out.forest_trust_info = info_ptr;
1999
2000         return WERR_OK;
2001 }
2002
2003
2004 /*
2005   netr_GetForestTrustInformation
2006 */
2007 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2008                                                       TALLOC_CTX *mem_ctx,
2009                                                       struct netr_GetForestTrustInformation *r)
2010 {
2011         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2012         struct netlogon_creds_CredentialState *creds;
2013         struct lsa_ForestTrustInformation *info, **info_ptr;
2014         struct ldb_context *sam_ctx;
2015         NTSTATUS status;
2016         WERROR werr;
2017
2018         if (lp_server_role(lp_ctx) != ROLE_DOMAIN_CONTROLLER) {
2019                 return NT_STATUS_NOT_IMPLEMENTED;
2020         }
2021
2022         status = dcesrv_netr_creds_server_step_check(dce_call,
2023                                                      mem_ctx,
2024                                                      r->in.computer_name,
2025                                                      r->in.credential,
2026                                                      r->out.return_authenticator,
2027                                                      &creds);
2028         if (!NT_STATUS_IS_OK(status)) {
2029                 return status;
2030         }
2031
2032         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2033             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2034                 return NT_STATUS_NOT_IMPLEMENTED;
2035         }
2036
2037         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2038                                 dce_call->conn->auth_state.session_info);
2039         if (sam_ctx == NULL) {
2040                 return NT_STATUS_UNSUCCESSFUL;
2041         }
2042
2043         /* TODO: check r->in.server_name is our name */
2044
2045         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2046         if (!info_ptr) {
2047                 return NT_STATUS_NO_MEMORY;
2048         }
2049         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2050         if (!info) {
2051                 return NT_STATUS_NO_MEMORY;
2052         }
2053
2054         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2055         if (!W_ERROR_IS_OK(werr)) {
2056                 return werror_to_ntstatus(werr);
2057         }
2058
2059         *info_ptr = info;
2060         r->out.forest_trust_info = info_ptr;
2061
2062         return NT_STATUS_OK;
2063 }
2064
2065
2066 /*
2067   netr_ServerGetTrustInfo
2068 */
2069 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2070                        struct netr_ServerGetTrustInfo *r)
2071 {
2072         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2073 }
2074
2075
2076 /* include the generated boilerplate */
2077 #include "librpc/gen_ndr/ndr_netlogon_s.c"