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