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