Provide a mem_ctx for child requests
[ira/wip.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    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "rpc_server/common/common.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "auth/auth.h"
28 #include "auth/auth_sam_reply.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "../libds/common/flags.h"
31 #include "rpc_server/samr/proto.h"
32 #include "../lib/util/util_ldb.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "auth/gensec/schannel.h"
35 #include "libcli/security/security.h"
36 #include "param/param.h"
37 #include "lib/messaging/irpc.h"
38 #include "librpc/gen_ndr/ndr_irpc.h"
39 #include "librpc/gen_ndr/ndr_netlogon.h"
40
41 struct netlogon_server_pipe_state {
42         struct netr_Credential client_challenge;
43         struct netr_Credential server_challenge;
44 };
45
46
47 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
48                                         struct netr_ServerReqChallenge *r)
49 {
50         struct netlogon_server_pipe_state *pipe_state =
51                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52
53         ZERO_STRUCTP(r->out.return_credentials);
54
55         /* destroyed on pipe shutdown */
56
57         if (pipe_state) {
58                 talloc_free(pipe_state);
59                 dce_call->context->private_data = NULL;
60         }
61         
62         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64
65         pipe_state->client_challenge = *r->in.credentials;
66
67         generate_random_buffer(pipe_state->server_challenge.data, 
68                                sizeof(pipe_state->server_challenge.data));
69
70         *r->out.return_credentials = pipe_state->server_challenge;
71
72         dce_call->context->private_data = pipe_state;
73
74         return NT_STATUS_OK;
75 }
76
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78                                          struct netr_ServerAuthenticate3 *r)
79 {
80         struct netlogon_server_pipe_state *pipe_state =
81                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82         struct netlogon_creds_CredentialState *creds;
83         struct ldb_context *schannel_ldb;
84         struct ldb_context *sam_ctx;
85         struct samr_Password *mach_pwd;
86         uint32_t user_account_control;
87         int num_records;
88         struct ldb_message **msgs;
89         NTSTATUS nt_status;
90         const char *attrs[] = {"unicodePwd", "userAccountControl", 
91                                "objectSid", NULL};
92
93         const char *trust_dom_attrs[] = {"flatname", NULL};
94         const char *account_name;
95
96         ZERO_STRUCTP(r->out.return_credentials);
97         *r->out.rid = 0;
98
99         /*
100          * According to Microsoft (see bugid #6099)
101          * Windows 7 looks at the negotiate_flags
102          * returned in this structure *even if the
103          * call fails with access denied!
104          */
105         *r->out.negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
106                                   NETLOGON_NEG_PERSISTENT_SAMREPL |
107                                   NETLOGON_NEG_ARCFOUR |
108                                   NETLOGON_NEG_PROMOTION_COUNT |
109                                   NETLOGON_NEG_CHANGELOG_BDC |
110                                   NETLOGON_NEG_FULL_SYNC_REPL |
111                                   NETLOGON_NEG_MULTIPLE_SIDS |
112                                   NETLOGON_NEG_REDO |
113                                   NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
114                                   NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
115                                   NETLOGON_NEG_GENERIC_PASSTHROUGH |
116                                   NETLOGON_NEG_CONCURRENT_RPC |
117                                   NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
118                                   NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
119                                   NETLOGON_NEG_STRONG_KEYS |
120                                   NETLOGON_NEG_TRANSITIVE_TRUSTS |
121                                   NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
122                                   NETLOGON_NEG_PASSWORD_SET2 |
123                                   NETLOGON_NEG_GETDOMAININFO |
124                                   NETLOGON_NEG_CROSS_FOREST_TRUSTS |
125                                   NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
126                                   NETLOGON_NEG_RODC_PASSTHROUGH |
127                                   NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
128                                   NETLOGON_NEG_AUTHENTICATED_RPC;
129
130         if (!pipe_state) {
131                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
132                 return NT_STATUS_ACCESS_DENIED;
133         }
134
135         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, 
136                                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
137         if (sam_ctx == NULL) {
138                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
139         }
140
141         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
142                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
143                 const char *flatname;
144                 if (!encoded_account) {
145                         return NT_STATUS_NO_MEMORY;
146                 }
147
148                 /* Kill the trailing dot */
149                 if (encoded_account[strlen(encoded_account)-1] == '.') {
150                         encoded_account[strlen(encoded_account)-1] = '\0';
151                 }
152
153                 /* pull the user attributes */
154                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
155                                            trust_dom_attrs,
156                                            "(&(trustPartner=%s)(objectclass=trustedDomain))", 
157                                            encoded_account);
158                 
159                 if (num_records == 0) {
160                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n", 
161                                  encoded_account));
162                         return NT_STATUS_ACCESS_DENIED;
163                 }
164                 
165                 if (num_records > 1) {
166                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
167                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
168                 }
169                 
170                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
171                 if (!flatname) {
172                         /* No flatname for this trust - we can't proceed */
173                         return NT_STATUS_ACCESS_DENIED;
174                 }
175                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
176
177                 if (!account_name) {
178                         return NT_STATUS_NO_MEMORY;
179                 }
180                 
181         } else {
182                 account_name = r->in.account_name;
183         }
184         
185         /* pull the user attributes */
186         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
187                                    "(&(sAMAccountName=%s)(objectclass=user))", 
188                                    ldb_binary_encode_string(mem_ctx, account_name));
189
190         if (num_records == 0) {
191                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
192                          r->in.account_name));
193                 return NT_STATUS_ACCESS_DENIED;
194         }
195
196         if (num_records > 1) {
197                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
198                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
199         }
200
201         
202         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
203
204         if (user_account_control & UF_ACCOUNTDISABLE) {
205                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
206                 return NT_STATUS_ACCESS_DENIED;
207         }
208
209         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
210                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
211                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
212                         return NT_STATUS_ACCESS_DENIED;
213                 }
214         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || 
215                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
216                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
217                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
218                         
219                         return NT_STATUS_ACCESS_DENIED;
220                 }
221         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
222                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
223                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
224                         return NT_STATUS_ACCESS_DENIED;
225                 }
226         } else {
227                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", 
228                           r->in.secure_channel_type));
229                 return NT_STATUS_ACCESS_DENIED;
230         }
231
232         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], 
233                                                 "objectSid", 0);
234
235         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
236         if (mach_pwd == NULL) {
237                 return NT_STATUS_ACCESS_DENIED;
238         }
239
240         creds = netlogon_creds_server_init(mem_ctx,     
241                                            r->in.account_name,
242                                            r->in.computer_name,
243                                            r->in.secure_channel_type,
244                                            &pipe_state->client_challenge, 
245                                            &pipe_state->server_challenge, 
246                                            mach_pwd,
247                                            r->in.credentials,
248                                            r->out.return_credentials,
249                                            *r->in.negotiate_flags);
250         
251         if (!creds) {
252                 return NT_STATUS_ACCESS_DENIED;
253         }
254
255         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
256
257         schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
258         if (!schannel_ldb) {
259                 return NT_STATUS_ACCESS_DENIED;
260         }
261
262         nt_status = schannel_store_session_key(schannel_ldb, mem_ctx, creds);
263         talloc_free(schannel_ldb);
264
265         return nt_status;
266 }
267                                                  
268 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
269                                         struct netr_ServerAuthenticate *r)
270 {
271         struct netr_ServerAuthenticate3 a;
272         uint32_t rid;
273         /* TODO: 
274          * negotiate_flags is used as an [in] parameter
275          * so it need to be initialised.
276          *
277          * (I think ... = 0; seems wrong here --metze)
278          */
279         uint32_t negotiate_flags_in = 0;
280         uint32_t negotiate_flags_out = 0;
281
282         a.in.server_name                = r->in.server_name;
283         a.in.account_name               = r->in.account_name;
284         a.in.secure_channel_type        = r->in.secure_channel_type;
285         a.in.computer_name              = r->in.computer_name;
286         a.in.credentials                = r->in.credentials;
287         a.in.negotiate_flags            = &negotiate_flags_in;
288
289         a.out.return_credentials        = r->out.return_credentials;
290         a.out.rid                       = &rid;
291         a.out.negotiate_flags           = &negotiate_flags_out;
292
293         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
294 }
295
296 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
297                                          struct netr_ServerAuthenticate2 *r)
298 {
299         struct netr_ServerAuthenticate3 r3;
300         uint32_t rid = 0;
301
302         r3.in.server_name = r->in.server_name;
303         r3.in.account_name = r->in.account_name;
304         r3.in.secure_channel_type = r->in.secure_channel_type;
305         r3.in.computer_name = r->in.computer_name;
306         r3.in.credentials = r->in.credentials;
307         r3.out.return_credentials = r->out.return_credentials;
308         r3.in.negotiate_flags = r->in.negotiate_flags;
309         r3.out.negotiate_flags = r->out.negotiate_flags;
310         r3.out.rid = &rid;
311         
312         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
313 }
314
315 /*
316   Validate an incoming authenticator against the credentials for the remote machine.
317
318   The credentials are (re)read and from the schannel database, and
319   written back after the caclulations are performed.
320
321   The creds_out parameter (if not NULL) returns the credentials, if
322   the caller needs some of that information.
323
324 */
325 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
326                                                     TALLOC_CTX *mem_ctx, 
327                                                     const char *computer_name,
328                                                     struct netr_Authenticator *received_authenticator,
329                                                     struct netr_Authenticator *return_authenticator,
330                                                     struct netlogon_creds_CredentialState **creds_out) 
331 {
332         NTSTATUS nt_status;
333         struct ldb_context *ldb;
334         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
335         bool schannel_in_use = dce_call->conn->auth_state.auth_info
336                 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
337                 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY 
338                     || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
339
340         ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
341         if (!ldb) {
342                 return NT_STATUS_ACCESS_DENIED;
343         }
344         nt_status = schannel_creds_server_step_check(ldb, mem_ctx,
345                                                      computer_name,
346                                                      schannel_global_required,
347                                                      schannel_in_use,
348                                                      received_authenticator, 
349                                                      return_authenticator, creds_out); 
350         talloc_free(ldb);
351         return nt_status;
352 }
353
354 /* 
355   Change the machine account password for the currently connected
356   client.  Supplies only the NT#.
357 */
358
359 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
360                                        struct netr_ServerPasswordSet *r)
361 {
362         struct netlogon_creds_CredentialState *creds;
363         struct ldb_context *sam_ctx;
364         NTSTATUS nt_status;
365
366         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
367                                                         mem_ctx, 
368                                                         r->in.computer_name, 
369                                                         r->in.credential, r->out.return_authenticator,
370                                                         &creds);
371         NT_STATUS_NOT_OK_RETURN(nt_status);
372
373         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));
374         if (sam_ctx == NULL) {
375                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
376         }
377
378         netlogon_creds_des_decrypt(creds, r->in.new_password);
379
380         /* Using the sid for the account as the key, set the password */
381         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, 
382                                            creds->sid,
383                                            NULL, /* Don't have plaintext */
384                                            NULL, r->in.new_password,
385                                            true, /* Password change */
386                                            NULL, NULL);
387         return nt_status;
388 }
389
390 /* 
391   Change the machine account password for the currently connected
392   client.  Supplies new plaintext.
393 */
394 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
395                                        struct netr_ServerPasswordSet2 *r)
396 {
397         struct netlogon_creds_CredentialState *creds;
398         struct ldb_context *sam_ctx;
399         NTSTATUS nt_status;
400         DATA_BLOB new_password;
401
402         struct samr_CryptPassword password_buf;
403
404         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
405                                                         mem_ctx, 
406                                                         r->in.computer_name, 
407                                                         r->in.credential, r->out.return_authenticator,
408                                                         &creds);
409         NT_STATUS_NOT_OK_RETURN(nt_status);
410
411         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));
412         if (sam_ctx == NULL) {
413                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
414         }
415
416         memcpy(password_buf.data, r->in.new_password->data, 512);
417         SIVAL(password_buf.data, 512, r->in.new_password->length);
418         netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
419
420         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
421                 DEBUG(3,("samr: failed to decode password buffer\n"));
422                 return NT_STATUS_WRONG_PASSWORD;
423         }
424                 
425         /* Using the sid for the account as the key, set the password */
426         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
427                                            creds->sid,
428                                            &new_password, /* we have plaintext */
429                                            NULL, NULL,
430                                            true, /* Password change */
431                                            NULL, NULL);
432         return nt_status;
433 }
434
435
436 /* 
437   netr_LogonUasLogon 
438 */
439 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
440                                  struct netr_LogonUasLogon *r)
441 {
442         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
443 }
444
445
446 /* 
447   netr_LogonUasLogoff 
448 */
449 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
450                        struct netr_LogonUasLogoff *r)
451 {
452         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
453 }
454
455
456 /* 
457   netr_LogonSamLogon_base
458
459   This version of the function allows other wrappers to say 'do not check the credentials'
460
461   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
462 */
463 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
464                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
465 {
466         struct auth_context *auth_context;
467         struct auth_usersupplied_info *user_info;
468         struct auth_serversupplied_info *server_info;
469         NTSTATUS nt_status;
470         static const char zeros[16];
471         struct netr_SamBaseInfo *sam;
472         struct netr_SamInfo2 *sam2;
473         struct netr_SamInfo3 *sam3;
474         struct netr_SamInfo6 *sam6;
475         
476         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
477         NT_STATUS_HAVE_NO_MEMORY(user_info);
478
479         user_info->flags = 0;
480         user_info->mapped_state = false;
481         user_info->remote_host = NULL;
482
483         switch (r->in.logon_level) {
484         case NetlogonInteractiveInformation:
485         case NetlogonServiceInformation:
486         case NetlogonInteractiveTransitiveInformation:
487         case NetlogonServiceTransitiveInformation:
488                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
489                         netlogon_creds_arcfour_crypt(creds, 
490                                             r->in.logon->password->lmpassword.hash,
491                                             sizeof(r->in.logon->password->lmpassword.hash));
492                         netlogon_creds_arcfour_crypt(creds, 
493                                             r->in.logon->password->ntpassword.hash,
494                                             sizeof(r->in.logon->password->ntpassword.hash));
495                 } else {
496                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
497                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
498                 }
499
500                 /* TODO: we need to deny anonymous access here */
501                 nt_status = auth_context_create(mem_ctx, 
502                                                 dce_call->event_ctx, dce_call->msg_ctx,
503                                                 dce_call->conn->dce_ctx->lp_ctx,
504                                                 &auth_context);
505                 NT_STATUS_NOT_OK_RETURN(nt_status);
506
507                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
508                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
509                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
510                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
511                 
512                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
513                 user_info->password_state = AUTH_PASSWORD_HASH;
514
515                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
516                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
517                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
518
519                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
520                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
521                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
522
523                 break;
524         case NetlogonNetworkInformation:
525         case NetlogonNetworkTransitiveInformation:
526
527                 /* TODO: we need to deny anonymous access here */
528                 nt_status = auth_context_create(mem_ctx, 
529                                                 dce_call->event_ctx, dce_call->msg_ctx,
530                                                 dce_call->conn->dce_ctx->lp_ctx,
531                                                 &auth_context);
532                 NT_STATUS_NOT_OK_RETURN(nt_status);
533
534                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
535                 NT_STATUS_NOT_OK_RETURN(nt_status);
536
537                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
538                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
539                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
540                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
541                 
542                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
543                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
544                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
545         
546                 break;
547
548                 
549         case NetlogonGenericInformation:
550         {
551                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
552                         netlogon_creds_arcfour_crypt(creds, 
553                                             r->in.logon->generic->data, r->in.logon->generic->length);
554                 } else {
555                         /* Using DES to verify kerberos tickets makes no sense */
556                         return NT_STATUS_INVALID_PARAMETER;
557                 }
558
559                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
560                         NTSTATUS status;
561                         struct server_id *kdc;
562                         struct kdc_check_generic_kerberos check;
563                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
564                         NT_STATUS_HAVE_NO_MEMORY(generic);
565                         *r->out.authoritative = 1;
566                         
567                         /* TODO: Describe and deal with these flags */
568                         *r->out.flags = 0;
569
570                         r->out.validation->generic = generic;
571         
572                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
573                         if ((kdc == NULL) || (kdc[0].id == 0)) {
574                                 return NT_STATUS_NO_LOGON_SERVERS;
575                         }
576                         
577                         check.in.generic_request = 
578                                 data_blob_const(r->in.logon->generic->data,
579                                                 r->in.logon->generic->length);
580                         
581                         status = irpc_call(dce_call->msg_ctx, kdc[0],
582                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
583                                            &check, mem_ctx);
584                         if (!NT_STATUS_IS_OK(status)) {
585                                 return status;
586                         }
587                         generic->length = check.out.generic_reply.length;
588                         generic->data = check.out.generic_reply.data;
589                         return NT_STATUS_OK;
590                 }
591
592                 /* Until we get an implemetnation of these other packages */
593                 return NT_STATUS_INVALID_PARAMETER;
594         }
595         default:
596                 return NT_STATUS_INVALID_PARAMETER;
597         }
598         
599         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
600         NT_STATUS_NOT_OK_RETURN(nt_status);
601
602         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
603         NT_STATUS_NOT_OK_RETURN(nt_status);
604
605         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
606         /* It appears that level 6 is not individually encrypted */
607         if ((r->in.validation_level != 6) &&
608             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
609                 /* This key is sent unencrypted without the ARCFOUR flag set */
610                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
611                         netlogon_creds_arcfour_crypt(creds, 
612                                             sam->key.key, 
613                                             sizeof(sam->key.key));
614                 }
615         }
616
617         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
618         /* It appears that level 6 is not individually encrypted */
619         if ((r->in.validation_level != 6) &&
620             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
621                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
622                         netlogon_creds_arcfour_crypt(creds, 
623                                             sam->LMSessKey.key, 
624                                             sizeof(sam->LMSessKey.key));
625                 } else {
626                         netlogon_creds_des_encrypt_LMKey(creds, 
627                                                 &sam->LMSessKey);
628                 }
629         }
630
631         switch (r->in.validation_level) {
632         case 2:
633                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
634                 NT_STATUS_HAVE_NO_MEMORY(sam2);
635                 sam2->base = *sam;
636                 r->out.validation->sam2 = sam2;
637                 break;
638
639         case 3:
640                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
641                 NT_STATUS_HAVE_NO_MEMORY(sam3);
642                 sam3->base = *sam;
643                 r->out.validation->sam3 = sam3;
644                 break;
645
646         case 6:
647                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
648                 NT_STATUS_HAVE_NO_MEMORY(sam6);
649                 sam6->base = *sam;
650                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
651                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
652                                                          sam->account_name.string, sam6->forest.string);
653                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
654                 r->out.validation->sam6 = sam6;
655                 break;
656
657         default:
658                 break;
659         }
660
661         *r->out.authoritative = 1;
662
663         /* TODO: Describe and deal with these flags */
664         *r->out.flags = 0;
665
666         return NT_STATUS_OK;
667 }
668
669 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
670                                      struct netr_LogonSamLogonEx *r) 
671 {
672         NTSTATUS nt_status;
673         struct netlogon_creds_CredentialState *creds;
674         struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
675         if (!ldb) {
676                 return NT_STATUS_ACCESS_DENIED;
677         }
678         
679         nt_status = schannel_fetch_session_key(ldb, mem_ctx, r->in.computer_name, &creds);
680         if (!NT_STATUS_IS_OK(nt_status)) {
681                 return nt_status;
682         }
683
684         if (!dce_call->conn->auth_state.auth_info ||
685             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
686                 return NT_STATUS_ACCESS_DENIED;
687         }
688         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
689 }
690
691 /* 
692   netr_LogonSamLogonWithFlags
693
694 */
695 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
696                                             struct netr_LogonSamLogonWithFlags *r)
697 {
698         NTSTATUS nt_status;
699         struct netlogon_creds_CredentialState *creds;
700         struct netr_LogonSamLogonEx r2;
701
702         struct netr_Authenticator *return_authenticator;
703
704         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
705         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
706
707         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
708                                                         mem_ctx, 
709                                                         r->in.computer_name, 
710                                                         r->in.credential, return_authenticator,
711                                                         &creds);
712         NT_STATUS_NOT_OK_RETURN(nt_status);
713
714         ZERO_STRUCT(r2);
715
716         r2.in.server_name       = r->in.server_name;
717         r2.in.computer_name     = r->in.computer_name;
718         r2.in.logon_level       = r->in.logon_level;
719         r2.in.logon             = r->in.logon;
720         r2.in.validation_level  = r->in.validation_level;
721         r2.in.flags             = r->in.flags;
722         r2.out.validation       = r->out.validation;
723         r2.out.authoritative    = r->out.authoritative;
724         r2.out.flags            = r->out.flags;
725
726         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
727
728         r->out.return_authenticator     = return_authenticator;
729
730         return nt_status;
731 }
732
733 /* 
734   netr_LogonSamLogon
735 */
736 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
737                                    struct netr_LogonSamLogon *r)
738 {
739         struct netr_LogonSamLogonWithFlags r2;
740         uint32_t flags = 0;
741         NTSTATUS status;
742
743         ZERO_STRUCT(r2);
744
745         r2.in.server_name = r->in.server_name;
746         r2.in.computer_name = r->in.computer_name;
747         r2.in.credential  = r->in.credential;
748         r2.in.return_authenticator = r->in.return_authenticator;
749         r2.in.logon_level = r->in.logon_level;
750         r2.in.logon = r->in.logon;
751         r2.in.validation_level = r->in.validation_level;
752         r2.in.flags = &flags;
753         r2.out.validation = r->out.validation;
754         r2.out.authoritative = r->out.authoritative;
755         r2.out.flags = &flags;
756
757         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
758
759         r->out.return_authenticator = r2.out.return_authenticator;
760
761         return status;
762 }
763
764
765 /* 
766   netr_LogonSamLogoff 
767 */
768 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
769                        struct netr_LogonSamLogoff *r)
770 {
771         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
772 }
773
774
775
776 /* 
777   netr_DatabaseDeltas 
778 */
779 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
780                        struct netr_DatabaseDeltas *r)
781 {
782         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
783 }
784
785
786 /* 
787   netr_DatabaseSync2 
788 */
789 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
790                        struct netr_DatabaseSync2 *r)
791 {
792         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
793         return NT_STATUS_NOT_IMPLEMENTED;
794 }
795
796
797 /* 
798   netr_DatabaseSync 
799 */
800 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
801                        struct netr_DatabaseSync *r)
802 {
803         struct netr_DatabaseSync2 r2;
804         NTSTATUS status;
805
806         ZERO_STRUCT(r2);
807
808         r2.in.logon_server = r->in.logon_server;
809         r2.in.computername = r->in.computername;
810         r2.in.credential = r->in.credential;
811         r2.in.database_id = r->in.database_id;
812         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
813         r2.in.sync_context = r->in.sync_context;
814         r2.out.sync_context = r->out.sync_context;
815         r2.out.delta_enum_array = r->out.delta_enum_array;
816         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
817
818         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
819
820         return status;
821 }
822
823
824 /* 
825   netr_AccountDeltas 
826 */
827 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
828                        struct netr_AccountDeltas *r)
829 {
830         /* w2k3 returns "NOT IMPLEMENTED" for this call */
831         return NT_STATUS_NOT_IMPLEMENTED;
832 }
833
834
835 /* 
836   netr_AccountSync 
837 */
838 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
839                        struct netr_AccountSync *r)
840 {
841         /* w2k3 returns "NOT IMPLEMENTED" for this call */
842         return NT_STATUS_NOT_IMPLEMENTED;
843 }
844
845
846 /* 
847   netr_GetDcName 
848 */
849 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
850                        struct netr_GetDcName *r)
851 {
852         const char * const attrs[] = { NULL };
853         struct ldb_context *sam_ctx;
854         struct ldb_message **res;
855         struct ldb_dn *domain_dn;
856         int ret;
857         const char *dcname;
858
859         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
860                                 dce_call->conn->dce_ctx->lp_ctx,
861                                 dce_call->conn->auth_state.session_info);
862         if (sam_ctx == NULL) {
863                 return WERR_DS_SERVICE_UNAVAILABLE;
864         }
865
866         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
867                                        r->in.domainname);
868         if (domain_dn == NULL) {
869                 return WERR_DS_SERVICE_UNAVAILABLE;
870         }
871
872         ret = gendb_search_dn(sam_ctx, mem_ctx,
873                               domain_dn, &res, attrs);
874         if (ret != 1) {
875                 return WERR_NO_SUCH_DOMAIN;
876         }
877
878         /* TODO: - return real IP address
879          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
880          */
881         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
882                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
883         W_ERROR_HAVE_NO_MEMORY(dcname);
884
885         *r->out.dcname = dcname;
886         return WERR_OK;
887 }
888
889
890 /* 
891   netr_LogonControl2Ex 
892 */
893 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
894                        struct netr_LogonControl2Ex *r)
895 {
896         return WERR_NOT_SUPPORTED;
897 }
898
899
900 /* 
901   netr_LogonControl 
902 */
903 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
904                        struct netr_LogonControl *r)
905 {
906         struct netr_LogonControl2Ex r2;
907         WERROR werr;
908
909         if (r->in.level == 0x00000001) {
910                 ZERO_STRUCT(r2);
911
912                 r2.in.logon_server = r->in.logon_server;
913                 r2.in.function_code = r->in.function_code;
914                 r2.in.level = r->in.level;
915                 r2.in.data = NULL;
916                 r2.out.query = r->out.query;
917
918                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
919         } else if (r->in.level == 0x00000002) {
920                 werr = WERR_NOT_SUPPORTED;
921         } else {
922                 werr = WERR_UNKNOWN_LEVEL;
923         }
924
925         return werr;
926 }
927
928
929 /* 
930   netr_LogonControl2 
931 */
932 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
933                        struct netr_LogonControl2 *r)
934 {
935         struct netr_LogonControl2Ex r2;
936         WERROR werr;
937
938         ZERO_STRUCT(r2);
939
940         r2.in.logon_server = r->in.logon_server;
941         r2.in.function_code = r->in.function_code;
942         r2.in.level = r->in.level;
943         r2.in.data = r->in.data;
944         r2.out.query = r->out.query;
945
946         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
947
948         return werr;
949 }
950
951
952 /* 
953   netr_GetAnyDCName 
954 */
955 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
956                        struct netr_GetAnyDCName *r)
957 {
958         struct netr_GetDcName r2;
959         WERROR werr;
960
961         ZERO_STRUCT(r2);
962
963         r2.in.logon_server      = r->in.logon_server;
964         r2.in.domainname        = r->in.domainname;
965         r2.out.dcname           = r->out.dcname;
966
967         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
968
969         return werr;
970 }
971
972
973 /* 
974   netr_DatabaseRedo 
975 */
976 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
977                        struct netr_DatabaseRedo *r)
978 {
979         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
980 }
981
982
983 /* 
984   netr_NetrEnumerateTurstedDomains
985 */
986 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
987                        struct netr_NetrEnumerateTrustedDomains *r)
988 {
989         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
990 }
991
992
993 /* 
994   netr_LogonGetCapabilities
995 */
996 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
997                        struct netr_LogonGetCapabilities *r)
998 {
999         /* we don't support AES yet */
1000         return NT_STATUS_NOT_IMPLEMENTED;
1001 }
1002
1003
1004 /* 
1005   netr_NETRLOGONSETSERVICEBITS 
1006 */
1007 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1008                        struct netr_NETRLOGONSETSERVICEBITS *r)
1009 {
1010         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1011 }
1012
1013
1014 /*
1015   netr_LogonGetTrustRid
1016 */
1017 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1018                        struct netr_LogonGetTrustRid *r)
1019 {
1020         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1021 }
1022
1023
1024 /* 
1025   netr_NETRLOGONCOMPUTESERVERDIGEST 
1026 */
1027 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1028                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1029 {
1030         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1031 }
1032
1033
1034 /* 
1035   netr_NETRLOGONCOMPUTECLIENTDIGEST 
1036 */
1037 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1038                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1039 {
1040         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1041 }
1042
1043
1044
1045 /* 
1046   netr_DsRGetSiteName
1047 */
1048 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1049                                   struct netr_DsRGetSiteName *r)
1050 {
1051         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1052 }
1053
1054
1055 /*
1056   fill in a netr_DomainTrustInfo from a ldb search result
1057 */
1058 static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
1059                                        struct loadparm_context *lp_ctx,
1060                                        struct ldb_context *sam_ctx,
1061                                        struct ldb_message *res,
1062                                        struct netr_DomainTrustInfo *info, 
1063                                        bool is_local, bool is_trust_list)
1064 {
1065         ZERO_STRUCTP(info);
1066
1067         info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1068         info->trust_extension.length = 16;
1069         info->trust_extension.info->flags = 
1070                 NETR_TRUST_FLAG_TREEROOT |
1071                 NETR_TRUST_FLAG_IN_FOREST | 
1072                 NETR_TRUST_FLAG_PRIMARY;
1073
1074         info->trust_extension.info->parent_index = 0; /* should be index into array
1075                                                          of parent */
1076         info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1077         info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
1078
1079         if (is_trust_list) {
1080                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1081                 info->forest.string = NULL;
1082         } else {
1083                 char *p;
1084                 /* TODO: we need a common function for pulling the forest */
1085                 info->forest.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
1086                 if (!info->forest.string) {
1087                         return NT_STATUS_NO_SUCH_DOMAIN;                
1088                 }
1089                 p = strchr(info->forest.string, '/');
1090                 if (p) {
1091                         *p = '\0';
1092                 }
1093         }
1094
1095         if (is_local) {
1096                 info->domainname.string = lp_sam_name(lp_ctx);
1097                 info->fulldomainname.string = lp_realm(lp_ctx);
1098                 info->guid = samdb_result_guid(res, "objectGUID");
1099                 info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1100         } else {
1101                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
1102                 info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
1103                 info->guid = samdb_result_guid(res, "objectGUID");
1104                 info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1105         }
1106
1107         return NT_STATUS_OK;
1108 }
1109
1110 /* 
1111   netr_LogonGetDomainInfo
1112   this is called as part of the ADS domain logon procedure.
1113
1114   It has an important role in convaying details about the client, such
1115   as Operating System, Version, Service Pack etc.
1116 */
1117 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1118                                         struct netr_LogonGetDomainInfo *r)
1119 {
1120         const char * const attrs[] = { "objectSid", 
1121                                        "objectGUID", "flatName", "securityIdentifier",
1122                                        "trustPartner", NULL };
1123         struct ldb_context *sam_ctx;
1124         struct ldb_message **res1, **res2;
1125         struct netr_DomainInfo1 *info1;
1126         int ret1, ret2, i;
1127         NTSTATUS status;
1128
1129         const char *local_domain;
1130
1131         status = dcesrv_netr_creds_server_step_check(dce_call,
1132                                                      mem_ctx, 
1133                                                      r->in.computer_name, 
1134                                                      r->in.credential, 
1135                                                      r->out.return_authenticator,
1136                                                      NULL);
1137         if (!NT_STATUS_IS_OK(status)) {
1138                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1139         }
1140         NT_STATUS_NOT_OK_RETURN(status);
1141
1142         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1143         if (sam_ctx == NULL) {
1144                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1145         }
1146
1147         /* we need to do two searches. The first will pull our primary
1148            domain and the second will pull any trusted domains. Our
1149            primary domain is also a "trusted" domain, so we need to
1150            put the primary domain into the lists of returned trusts as
1151            well */
1152         ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx), &res1, attrs);
1153         if (ret1 != 1) {
1154                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1155         }
1156
1157         /* try and find the domain */
1158         local_domain = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1159
1160         ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
1161         if (ret2 == -1) {
1162                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1163         }
1164
1165         info1 = talloc(mem_ctx, struct netr_DomainInfo1);
1166         NT_STATUS_HAVE_NO_MEMORY(info1);
1167
1168         ZERO_STRUCTP(info1);
1169
1170         info1->num_trusts = ret2 + 1;
1171         info1->trusts = talloc_array(mem_ctx, struct netr_DomainTrustInfo, 
1172                                        info1->num_trusts);
1173         NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
1174
1175         status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0], &info1->domaininfo, 
1176                                         true, false);
1177         NT_STATUS_NOT_OK_RETURN(status);
1178
1179         for (i=0;i<ret2;i++) {
1180                 status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[i], &info1->trusts[i], 
1181                                                 false, true);
1182                 NT_STATUS_NOT_OK_RETURN(status);
1183         }
1184
1185         status = fill_domain_trust_info(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0], &info1->trusts[i], 
1186                                         true, true);
1187         NT_STATUS_NOT_OK_RETURN(status);
1188
1189         info1->dns_hostname.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1190         info1->workstation_flags = 
1191                 NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE;
1192         info1->supported_enc_types = 0; /* w2008 gives this 0 */
1193
1194         r->out.info->info1 = info1;
1195
1196         return NT_STATUS_OK;
1197 }
1198
1199
1200
1201 /*
1202   netr_ServerPasswordGet
1203 */
1204 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1205                        struct netr_ServerPasswordGet *r)
1206 {
1207         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1208 }
1209
1210
1211 /* 
1212   netr_NETRLOGONSENDTOSAM 
1213 */
1214 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1215                        struct netr_NETRLOGONSENDTOSAM *r)
1216 {
1217         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1218 }
1219
1220
1221 /* 
1222   netr_DsRAddressToSitenamesW 
1223 */
1224 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1225                        struct netr_DsRAddressToSitenamesW *r)
1226 {
1227         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1228 }
1229
1230
1231 /* 
1232   netr_DsRGetDCNameEx2
1233 */
1234 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1235                                    struct netr_DsRGetDCNameEx2 *r)
1236 {
1237         const char * const attrs[] = { "objectGUID", NULL };
1238         struct ldb_context *sam_ctx;
1239         struct ldb_message **res;
1240         struct ldb_dn *domain_dn;
1241         int ret;
1242         struct netr_DsRGetDCNameInfo *info;
1243
1244         ZERO_STRUCTP(r->out.info);
1245
1246         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1247         if (sam_ctx == NULL) {
1248                 return WERR_DS_SERVICE_UNAVAILABLE;
1249         }
1250
1251         /* Win7-beta will send the domain name in the form the user typed, so we have to cope
1252            with both the short and long form here */
1253         if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx, 
1254                                                                 r->in.domain_name)) {
1255                 return WERR_NO_SUCH_DOMAIN;
1256         }
1257
1258         domain_dn = ldb_get_default_basedn(sam_ctx);
1259         if (domain_dn == NULL) {
1260                 return WERR_DS_SERVICE_UNAVAILABLE;
1261         }
1262
1263         ret = gendb_search_dn(sam_ctx, mem_ctx,
1264                               domain_dn, &res, attrs);
1265         if (ret != 1) {
1266         }
1267
1268         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1269         W_ERROR_HAVE_NO_MEMORY(info);
1270
1271         /* TODO: - return real IP address
1272          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1273          */
1274         info->dc_unc                    = talloc_asprintf(mem_ctx, "\\\\%s.%s",
1275                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1276                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1277         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1278         info->dc_address                = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1279         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1280         info->dc_address_type           = DS_ADDRESS_TYPE_INET;
1281         info->domain_guid               = samdb_result_guid(res[0], "objectGUID");
1282         info->domain_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1283         info->forest_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1284         info->dc_flags                  = DS_DNS_FOREST |
1285                                           DS_DNS_DOMAIN |
1286                                           DS_DNS_CONTROLLER |
1287                                           DS_SERVER_WRITABLE |
1288                                           DS_SERVER_CLOSEST |
1289                                           DS_SERVER_TIMESERV |
1290                                           DS_SERVER_KDC |
1291                                           DS_SERVER_DS |
1292                                           DS_SERVER_LDAP |
1293                                           DS_SERVER_GC |
1294                                           DS_SERVER_PDC;
1295         info->dc_site_name      = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1296         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
1297         info->client_site_name  = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1298         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
1299
1300         *r->out.info = info;
1301
1302         return WERR_OK;
1303 }
1304
1305 /* 
1306   netr_DsRGetDCNameEx
1307 */
1308 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1309                                   struct netr_DsRGetDCNameEx *r)
1310 {
1311         struct netr_DsRGetDCNameEx2 r2;
1312         WERROR werr;
1313
1314         ZERO_STRUCT(r2);
1315
1316         r2.in.server_unc = r->in.server_unc;
1317         r2.in.client_account = NULL;
1318         r2.in.mask = 0;
1319         r2.in.domain_guid = r->in.domain_guid;
1320         r2.in.domain_name = r->in.domain_name;
1321         r2.in.site_name = r->in.site_name;
1322         r2.in.flags = r->in.flags;
1323         r2.out.info = r->out.info;
1324
1325         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1326
1327         return werr;
1328 }
1329
1330 /* 
1331   netr_DsRGetDCName
1332 */
1333 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1334                                 struct netr_DsRGetDCName *r)
1335 {
1336         struct netr_DsRGetDCNameEx2 r2;
1337         WERROR werr;
1338
1339         ZERO_STRUCT(r2);
1340
1341         r2.in.server_unc = r->in.server_unc;
1342         r2.in.client_account = NULL;
1343         r2.in.mask = 0;
1344         r2.in.domain_name = r->in.domain_name;
1345         r2.in.domain_guid = r->in.domain_guid;
1346         
1347         r2.in.site_name = NULL; /* should fill in from site GUID */
1348         r2.in.flags = r->in.flags;
1349         r2.out.info = r->out.info;
1350
1351         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1352
1353         return werr;
1354 }
1355 /* 
1356   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1357 */
1358 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1359                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1360 {
1361         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1362 }
1363
1364
1365 /*
1366   netr_NetrEnumerateTrustedDomainsEx
1367 */
1368 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1369                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1370 {
1371         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1372 }
1373
1374
1375 /* 
1376   netr_DsRAddressToSitenamesExW 
1377 */
1378 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1379                        struct netr_DsRAddressToSitenamesExW *r)
1380 {
1381         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1382 }
1383
1384
1385 /* 
1386   netr_DsrGetDcSiteCoverageW
1387 */
1388 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1389                        struct netr_DsrGetDcSiteCoverageW *r)
1390 {
1391         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1392 }
1393
1394
1395 /* 
1396   netr_DsrEnumerateDomainTrusts 
1397 */
1398 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1399                                               struct netr_DsrEnumerateDomainTrusts *r)
1400 {
1401         struct netr_DomainTrustList *trusts;
1402         struct ldb_context *sam_ctx;
1403         int ret;
1404         struct ldb_message **dom_res;
1405         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1406
1407         ZERO_STRUCT(r->out);
1408
1409         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1410         if (sam_ctx == NULL) {
1411                 return WERR_GENERAL_FAILURE;
1412         }
1413
1414         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
1415                               &dom_res, dom_attrs);
1416         if (ret == -1) {
1417                 return WERR_GENERAL_FAILURE;            
1418         }
1419         if (ret != 1) {
1420                 return WERR_GENERAL_FAILURE;
1421         }
1422
1423         trusts = talloc(mem_ctx, struct netr_DomainTrustList);
1424         W_ERROR_HAVE_NO_MEMORY(trusts);
1425
1426         trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
1427         W_ERROR_HAVE_NO_MEMORY(trusts->array);
1428
1429         trusts->count = 1; /* ?? */
1430
1431         r->out.trusts = trusts;
1432
1433         /* TODO: add filtering by trust_flags, and correct trust_type
1434            and attributes */
1435         trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
1436         trusts->array[0].dns_name     = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
1437         trusts->array[0].trust_flags =
1438                 NETR_TRUST_FLAG_TREEROOT | 
1439                 NETR_TRUST_FLAG_IN_FOREST | 
1440                 NETR_TRUST_FLAG_PRIMARY;
1441         trusts->array[0].parent_index = 0;
1442         trusts->array[0].trust_type = 2;
1443         trusts->array[0].trust_attributes = 0;
1444         trusts->array[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1445         trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1446
1447         return WERR_OK;
1448 }
1449
1450
1451 /*
1452   netr_DsrDeregisterDNSHostRecords
1453 */
1454 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1455                        struct netr_DsrDeregisterDNSHostRecords *r)
1456 {
1457         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1458 }
1459
1460
1461 /*
1462   netr_ServerTrustPasswordsGet
1463 */
1464 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1465                        struct netr_ServerTrustPasswordsGet *r)
1466 {
1467         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1468 }
1469
1470
1471 /* 
1472   netr_DsRGetForestTrustInformation 
1473 */
1474 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1475                        struct netr_DsRGetForestTrustInformation *r)
1476 {
1477         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1478 }
1479
1480
1481 /*
1482   netr_GetForestTrustInformation
1483 */
1484 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1485                        struct netr_GetForestTrustInformation *r)
1486 {
1487         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1488 }
1489
1490
1491 /*
1492   netr_ServerGetTrustInfo
1493 */
1494 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1495                        struct netr_ServerGetTrustInfo *r)
1496 {
1497         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1498 }
1499
1500
1501 /* include the generated boilerplate */
1502 #include "librpc/gen_ndr/ndr_netlogon_s.c"