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