r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
[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
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_netlogon.h"
26 #include "rpc_server/dcerpc_server.h"
27 #include "rpc_server/common/common.h"
28 #include "librpc/gen_ndr/ndr_dcom.h"
29 #include "auth/auth.h"
30 #include "lib/ldb/include/ldb.h"
31
32 struct server_pipe_state {
33         struct netr_Credential client_challenge;
34         struct netr_Credential server_challenge;
35         struct creds_CredentialState *creds;
36 };
37
38
39 /*
40   a client has connected to the netlogon server using schannel, so we need
41   to re-establish the credentials state
42 */
43 static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call) 
44 {
45         struct server_pipe_state *state;
46         NTSTATUS status;
47
48         state = talloc(dce_call->conn, struct server_pipe_state);
49         if (state == NULL) {
50                 return NT_STATUS_NO_MEMORY;
51         }
52         ZERO_STRUCTP(state);
53         
54         if (dce_call->conn->auth_state.session_info == NULL) {
55                 talloc_free(state);
56                 smb_panic("No session info provided by schannel level setup!");
57                 return NT_STATUS_NO_USER_SESSION_KEY;
58         }
59         
60         status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security, 
61                                        state, 
62                                        &state->creds);
63
64         if (!NT_STATUS_IS_OK(status)) {
65                 DEBUG(3, ("getting schannel credentials failed with %s\n", nt_errstr(status)));
66                 talloc_free(state);
67                 return status;
68         }
69         
70         dce_call->context->private = state;
71
72         return NT_STATUS_OK;
73 }
74
75 /*
76   a hook for bind on the netlogon pipe
77 */
78 static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di) 
79 {
80         dce_call->context->private = NULL;
81
82         /* if this is a schannel bind then we need to reconstruct the pipe state */
83         if (dce_call->conn->auth_state.auth_info &&
84             dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
85                 NTSTATUS status;
86
87                 DEBUG(5, ("schannel bind on netlogon\n"));
88
89                 status = netlogon_schannel_setup(dce_call);
90                 if (!NT_STATUS_IS_OK(status)) {
91                         DEBUG(3, ("schannel bind on netlogon failed with %s\n", nt_errstr(status)));
92                         return status;
93                 }
94         }
95
96         return NT_STATUS_OK;
97 }
98
99 #define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
100
101 static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
102                                         struct netr_ServerReqChallenge *r)
103 {
104         struct server_pipe_state *pipe_state = dce_call->context->private;
105
106         ZERO_STRUCTP(r->out.credentials);
107
108         /* destroyed on pipe shutdown */
109
110         if (pipe_state) {
111                 talloc_free(pipe_state);
112                 dce_call->context->private = NULL;
113         }
114         
115         pipe_state = talloc(dce_call->context, struct server_pipe_state);
116         if (!pipe_state) {
117                 return NT_STATUS_NO_MEMORY;
118         }
119
120         pipe_state->creds = NULL;
121
122         pipe_state->client_challenge = *r->in.credentials;
123
124         generate_random_buffer(pipe_state->server_challenge.data, 
125                                sizeof(pipe_state->server_challenge.data));
126
127         *r->out.credentials = pipe_state->server_challenge;
128
129         dce_call->context->private = pipe_state;
130
131         return NT_STATUS_OK;
132 }
133
134 static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
135                                          struct netr_ServerAuthenticate3 *r)
136 {
137         struct server_pipe_state *pipe_state = dce_call->context->private;
138         void *sam_ctx;
139         struct samr_Password *mach_pwd;
140         uint16_t acct_flags;
141         int num_records;
142         struct ldb_message **msgs;
143         NTSTATUS nt_status;
144         const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash", "userAccountControl", 
145                                "objectSid", NULL};
146
147         ZERO_STRUCTP(r->out.credentials);
148         *r->out.rid = 0;
149         *r->out.negotiate_flags = *r->in.negotiate_flags;
150
151         if (!pipe_state) {
152                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
153                 return NT_STATUS_ACCESS_DENIED;
154         }
155
156         sam_ctx = samdb_connect(mem_ctx);
157         if (sam_ctx == NULL) {
158                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
159         }
160         /* pull the user attributes */
161         num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
162                                    "(&(sAMAccountName=%s)(objectclass=user))", 
163                                    r->in.account_name);
164
165         if (num_records == 0) {
166                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
167                          r->in.account_name));
168                 return NT_STATUS_NO_SUCH_USER;
169         }
170
171         if (num_records > 1) {
172                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
173                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
174         }
175
176         acct_flags = samdb_result_acct_flags(msgs[0], 
177                                              "userAccountControl");
178
179         if (acct_flags & ACB_DISABLED) {
180                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
181                 return NT_STATUS_ACCESS_DENIED;
182         }
183
184         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
185                 if (!(acct_flags & ACB_WSTRUST)) {
186                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", acct_flags));
187                         return NT_STATUS_ACCESS_DENIED;
188                 }
189         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) {
190                 if (!(acct_flags & ACB_DOMTRUST)) {
191                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", acct_flags));
192                         return NT_STATUS_ACCESS_DENIED;
193                 }
194         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
195                 if (!(acct_flags & ACB_SVRTRUST)) {
196                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", acct_flags));
197                         return NT_STATUS_ACCESS_DENIED;
198                 }
199         } else {
200                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", 
201                           r->in.secure_channel_type));
202                 return NT_STATUS_ACCESS_DENIED;
203         }
204
205
206         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], "objectSid", 0);
207
208         nt_status = samdb_result_passwords(mem_ctx, msgs[0], NULL, &mach_pwd);
209         if (!NT_STATUS_IS_OK(nt_status) || mach_pwd == NULL) {
210                 return NT_STATUS_ACCESS_DENIED;
211         }
212
213         if (pipe_state->creds) {
214                 talloc_free(pipe_state->creds);
215         }
216         pipe_state->creds = talloc(pipe_state, struct creds_CredentialState);
217         if (!pipe_state->creds) {
218                 return NT_STATUS_NO_MEMORY;
219         }
220
221         creds_server_init(pipe_state->creds, &pipe_state->client_challenge, 
222                           &pipe_state->server_challenge, mach_pwd,
223                           r->out.credentials,
224                           *r->in.negotiate_flags);
225         
226         if (!creds_server_check(pipe_state->creds, r->in.credentials)) {
227                 talloc_free(pipe_state->creds);
228                 pipe_state->creds = NULL;
229                 return NT_STATUS_ACCESS_DENIED;
230         }
231
232         pipe_state->creds->account_name = talloc_reference(pipe_state->creds, r->in.account_name);
233         
234         pipe_state->creds->computer_name = talloc_reference(pipe_state->creds, r->in.computer_name);
235
236         pipe_state->creds->secure_channel_type = r->in.secure_channel_type;
237
238         /* remember this session key state */
239         nt_status = schannel_store_session_key(mem_ctx, pipe_state->creds);
240
241         return nt_status;
242 }
243                                                  
244 static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
245                                         struct netr_ServerAuthenticate *r)
246 {
247         struct netr_ServerAuthenticate3 r3;
248         uint32_t rid = 0;
249         /* TODO: 
250          * negotiate_flags is used as an [in] parameter
251          * so it need to be initialised.
252          *
253          * (I think ... = 0; seems wrong here --metze)
254          */
255         uint32 negotiate_flags = 0;  
256
257         r3.in.server_name = r->in.server_name;
258         r3.in.account_name = r->in.account_name;
259         r3.in.secure_channel_type = r->in.secure_channel_type;
260         r3.in.computer_name = r->in.computer_name;
261         r3.in.credentials = r->in.credentials;
262         r3.out.credentials = r->out.credentials;
263         r3.in.negotiate_flags = &negotiate_flags;
264         r3.out.negotiate_flags = &negotiate_flags;
265         r3.out.rid = &rid;
266         
267         return netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
268 }
269
270 static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
271                                          struct netr_ServerAuthenticate2 *r)
272 {
273         struct netr_ServerAuthenticate3 r3;
274         uint32 rid = 0;
275
276         r3.in.server_name = r->in.server_name;
277         r3.in.account_name = r->in.account_name;
278         r3.in.secure_channel_type = r->in.secure_channel_type;
279         r3.in.computer_name = r->in.computer_name;
280         r3.in.credentials = r->in.credentials;
281         r3.out.credentials = r->out.credentials;
282         r3.in.negotiate_flags = r->in.negotiate_flags;
283         r3.out.negotiate_flags = r->out.negotiate_flags;
284         r3.out.rid = &rid;
285         
286         return netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
287 }
288
289
290 static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
291                                              struct netr_Authenticator *received_authenticator,
292                                              struct netr_Authenticator *return_authenticator) 
293 {
294         if (!pipe_state) {
295                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
296                 return NT_STATUS_ACCESS_DENIED;
297         }
298
299         return creds_server_step_check(pipe_state->creds, 
300                                        received_authenticator, 
301                                        return_authenticator);
302 }
303
304
305 static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
306                                        struct netr_ServerPasswordSet *r)
307 {
308         struct server_pipe_state *pipe_state = dce_call->context->private;
309
310         void *sam_ctx;
311         int num_records;
312         int num_records_domain;
313         int ret;
314         struct ldb_message **msgs;
315         struct ldb_message **msgs_domain;
316         NTSTATUS nt_status;
317         struct ldb_message *mod;
318         const char *domain_sid;
319
320         const char *attrs[] = {"objectSid", NULL };
321
322         const char **domain_attrs = attrs;
323
324         nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
325         NT_STATUS_NOT_OK_RETURN(nt_status);
326
327         sam_ctx = samdb_connect(mem_ctx);
328         if (sam_ctx == NULL) {
329                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
330         }
331         /* pull the user attributes */
332         num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
333                                    "(&(sAMAccountName=%s)(objectclass=user))", 
334                                    pipe_state->creds->account_name);
335         if (num_records == -1) {
336                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
337         }
338
339         if (num_records == 0) {
340                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
341                          pipe_state->creds->account_name));
342                 return NT_STATUS_NO_SUCH_USER;
343         }
344
345         if (num_records > 1) {
346                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, 
347                          pipe_state->creds->account_name));
348                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
349         }
350
351         domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
352         if (!domain_sid) {
353                 DEBUG(0,("no objectSid in user record\n"));
354                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
355         }
356
357         /* find the domain's DN */
358         num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL, 
359                                           &msgs_domain, domain_attrs,
360                                           "(&(objectSid=%s)(objectclass=domain))", 
361                                           domain_sid);
362         if (num_records_domain == -1) {
363                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
364         }
365
366         if (num_records_domain == 0) {
367                 DEBUG(3,("Couldn't find domain [%s] in samdb.\n", 
368                          domain_sid));
369                 return NT_STATUS_NO_SUCH_USER;
370         }
371
372         if (num_records_domain > 1) {
373                 DEBUG(0,("Found %d records matching domain [%s]\n", 
374                          num_records_domain, domain_sid));
375                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
376         }
377
378         mod = talloc_zero(mem_ctx, struct ldb_message);
379         NT_STATUS_HAVE_NO_MEMORY(mod);
380         mod->dn = talloc_reference(mod, msgs[0]->dn);
381     
382         creds_des_decrypt(pipe_state->creds, &r->in.new_password);
383
384         /* set the password - samdb needs to know both the domain and user DNs,
385            so the domain password policy can be used */
386         nt_status = samdb_set_password(sam_ctx, mod,
387                                        msgs[0]->dn,
388                                        msgs_domain[0]->dn,
389                                        mod,
390                                        NULL, /* Don't have plaintext */
391                                        NULL, &r->in.new_password,
392                                        False, /* This is not considered a password change */
393                                        False, /* don't restrict this password change (match w2k3) */
394                                        NULL);
395         NT_STATUS_NOT_OK_RETURN(nt_status);
396
397         ret = samdb_replace(sam_ctx, mem_ctx, mod);
398         if (ret != 0) {
399                 /* we really need samdb.c to return NTSTATUS */
400                 return NT_STATUS_UNSUCCESSFUL;
401         }
402
403         return NT_STATUS_OK;
404 }
405
406
407 /* 
408   netr_LogonUasLogon 
409 */
410 static WERROR netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
411                                  struct netr_LogonUasLogon *r)
412 {
413         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
414 }
415
416
417 /* 
418   netr_LogonUasLogoff 
419 */
420 static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
421                        struct netr_LogonUasLogoff *r)
422 {
423         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
424 }
425
426
427 /* 
428   netr_LogonSamLogonWithFlags
429
430   This version of the function allows other wrappers to say 'do not check the credentials'
431 */
432 static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
433                                      struct netr_LogonSamLogonEx *r)
434 {
435         struct server_pipe_state *pipe_state = dce_call->context->private;
436
437         struct auth_context *auth_context;
438         struct auth_usersupplied_info *user_info;
439         struct auth_serversupplied_info *server_info;
440         NTSTATUS nt_status;
441         const uint8_t *chal;
442         static const char zeros[16];
443         struct netr_SamBaseInfo *sam;
444         struct netr_SamInfo2 *sam2;
445         struct netr_SamInfo3 *sam3;
446         struct netr_SamInfo6 *sam6;
447         
448         switch (r->in.logon_level) {
449         case 1:
450         case 3:
451         case 5:
452                 if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
453                         creds_arcfour_crypt(pipe_state->creds, 
454                                             r->in.logon.password->lmpassword.hash, 
455                                             sizeof(r->in.logon.password->lmpassword.hash));
456                         creds_arcfour_crypt(pipe_state->creds, 
457                                             r->in.logon.password->ntpassword.hash, 
458                                             sizeof(r->in.logon.password->ntpassword.hash));
459                 } else {
460                         creds_des_decrypt(pipe_state->creds, &r->in.logon.password->lmpassword);
461                         creds_des_decrypt(pipe_state->creds, &r->in.logon.password->ntpassword);
462                 }
463
464                 /* TODO: we need to deny anonymous access here */
465                 nt_status = auth_context_create(mem_ctx, lp_auth_methods(), &auth_context);
466                 NT_STATUS_NOT_OK_RETURN(nt_status);
467
468                 nt_status = auth_get_challenge(auth_context, &chal);
469                 NT_STATUS_NOT_OK_RETURN(nt_status);
470
471                 nt_status = make_user_info_netlogon_interactive(mem_ctx,
472                                                                 r->in.logon.password->identity_info.account_name.string,
473                                                                 r->in.logon.password->identity_info.domain_name.string,
474                                                                 r->in.logon.password->identity_info.workstation.string,
475                                                                 chal,
476                                                                 &r->in.logon.password->lmpassword,
477                                                                 &r->in.logon.password->ntpassword,
478                                                                 &user_info);
479                 NT_STATUS_NOT_OK_RETURN(nt_status);
480                 break;          
481         case 2:
482         case 6:
483                 /* TODO: we need to deny anonymous access here */
484                 nt_status = auth_context_create(mem_ctx, lp_auth_methods(), &auth_context);
485                 NT_STATUS_NOT_OK_RETURN(nt_status);
486
487                 nt_status = auth_context_set_challenge(auth_context, r->in.logon.network->challenge, "netr_LogonSamLogonWithFlags");
488                 NT_STATUS_NOT_OK_RETURN(nt_status);
489
490                 nt_status = make_user_info_netlogon_network(auth_context,
491                                                             r->in.logon.network->identity_info.account_name.string,
492                                                             r->in.logon.network->identity_info.domain_name.string,
493                                                             r->in.logon.network->identity_info.workstation.string,
494                                                             r->in.logon.network->lm.data, r->in.logon.network->lm.length,
495                                                             r->in.logon.network->nt.data, r->in.logon.network->nt.length,
496                                                             &user_info);
497                 NT_STATUS_NOT_OK_RETURN(nt_status);
498                 break;
499         default:
500                 return NT_STATUS_INVALID_PARAMETER;
501         }
502         
503         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
504         NT_STATUS_NOT_OK_RETURN(nt_status);
505
506         sam = talloc_zero(mem_ctx, struct netr_SamBaseInfo);
507         NT_STATUS_HAVE_NO_MEMORY(sam);
508
509         sam->last_logon = server_info->last_logon;
510         sam->last_logoff = server_info->last_logoff;
511         sam->acct_expiry = server_info->acct_expiry;
512         sam->last_password_change = server_info->last_password_change;
513         sam->allow_password_change = server_info->allow_password_change;
514         sam->force_password_change = server_info->force_password_change;
515
516         sam->account_name.string = server_info->account_name;
517         sam->full_name.string = server_info->full_name;
518         sam->logon_script.string = server_info->logon_script;
519         sam->profile_path.string = server_info->profile_path;
520         sam->home_directory.string = server_info->home_directory;
521         sam->home_drive.string = server_info->home_drive;
522
523         sam->logon_count = server_info->logon_count;
524         sam->bad_password_count = sam->bad_password_count;
525         sam->rid = server_info->account_sid->sub_auths[server_info->account_sid->num_auths-1];
526         sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
527         sam->group_count = 0;
528         sam->groupids = NULL;
529         sam->user_flags = 0; /* TODO: w2k3 uses 0x120 - what is this? */
530         sam->acct_flags = server_info->acct_flags;
531         sam->logon_server.string = lp_netbios_name();
532         sam->domain.string = server_info->domain_name;
533
534         sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
535         NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
536         sam->domain_sid->num_auths--;
537
538         ZERO_ARRAY(sam->unknown);
539
540         ZERO_STRUCT(sam->key);
541         if (server_info->user_session_key.length == sizeof(sam->key.key)) {
542                 memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
543         }
544
545         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
546         /* It appears that level 6 is not individually encrypted */
547         if ((r->in.validation_level != 6) 
548             && memcmp(sam->key.key, zeros,  
549                       sizeof(sam->key.key)) != 0) {
550
551                 /* This key is sent unencrypted without the ARCFOUR flag set */
552                 if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
553                         creds_arcfour_crypt(pipe_state->creds, 
554                                             sam->key.key, 
555                                             sizeof(sam->key.key));
556                 }
557         }
558
559         ZERO_STRUCT(sam->LMSessKey);
560         if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
561                 memcpy(sam->LMSessKey.key, server_info->lm_session_key.data, 
562                        sizeof(sam->LMSessKey.key));
563         }
564         
565         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
566         /* It appears that level 6 is not individually encrypted */
567         if ((r->in.validation_level != 6) 
568             && memcmp(sam->LMSessKey.key, zeros,  
569                       sizeof(sam->LMSessKey.key)) != 0) {
570                 if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
571                         creds_arcfour_crypt(pipe_state->creds, 
572                                             sam->LMSessKey.key, 
573                                             sizeof(sam->LMSessKey.key));
574                 } else {
575                         creds_des_encrypt_LMKey(pipe_state->creds, 
576                                                 &sam->LMSessKey);
577                 }
578         }
579
580         switch (r->in.validation_level) {
581         case 2:
582                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
583                 NT_STATUS_HAVE_NO_MEMORY(sam2);
584                 sam2->base = *sam;
585                 r->out.validation.sam2 = sam2;
586                 break;
587
588         case 3:
589                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
590                 NT_STATUS_HAVE_NO_MEMORY(sam3);
591                 sam3->base = *sam;
592                 r->out.validation.sam3 = sam3;
593                 break;
594
595         case 6:
596                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
597                 NT_STATUS_HAVE_NO_MEMORY(sam6);
598                 sam6->base = *sam;
599                 sam6->forest.string = lp_realm();
600                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
601                                                          sam->account_name.string, sam6->forest.string);
602                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
603                 r->out.validation.sam6 = sam6;
604                 break;
605
606         default:
607                 break;
608         }
609
610         r->out.authoritative = 1;
611
612         /* TODO: Describe and deal with these flags */
613         r->out.flags = 0;
614
615         return NT_STATUS_OK;
616 }
617
618 /* 
619   netr_LogonSamLogonWithFlags
620
621 */
622 static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623                                             struct netr_LogonSamLogonWithFlags *r)
624 {
625         struct server_pipe_state *pipe_state = dce_call->context->private;
626         NTSTATUS nt_status;
627         struct netr_LogonSamLogonEx r2;
628
629         struct netr_Authenticator *return_authenticator;
630
631         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
632         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
633
634         nt_status = netr_creds_server_step_check(pipe_state, r->in.credential, return_authenticator);
635         NT_STATUS_NOT_OK_RETURN(nt_status);
636
637         ZERO_STRUCT(r2);
638
639         r2.in.server_name       = r->in.server_name;
640         r2.in.workstation       = r->in.workstation;
641         r2.in.logon_level       = r->in.logon_level;
642         r2.in.logon             = r->in.logon;
643         r2.in.validation_level  = r->in.validation_level;
644         r2.in.flags             = r->in.flags;
645
646         nt_status = netr_LogonSamLogonEx(dce_call, mem_ctx, &r2);
647
648         r->out.return_authenticator     = return_authenticator;
649         r->out.validation               = r2.out.validation;
650         r->out.authoritative            = r2.out.authoritative;
651         r->out.flags                    = r2.out.flags;
652
653         return nt_status;
654 }
655
656 /* 
657   netr_LogonSamLogon
658 */
659 static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
660                                    struct netr_LogonSamLogon *r)
661 {
662         struct netr_LogonSamLogonWithFlags r2;
663         NTSTATUS status;
664
665         ZERO_STRUCT(r2);
666
667         r2.in.server_name = r->in.server_name;
668         r2.in.workstation = r->in.workstation;
669         r2.in.credential  = r->in.credential;
670         r2.in.return_authenticator = r->in.return_authenticator;
671         r2.in.logon_level = r->in.logon_level;
672         r2.in.logon = r->in.logon;
673         r2.in.validation_level = r->in.validation_level;
674         r2.in.flags = 0;
675
676         status = netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
677
678         r->out.return_authenticator = r2.out.return_authenticator;
679         r->out.validation = r2.out.validation;
680         r->out.authoritative = r2.out.authoritative;
681
682         return status;
683 }
684
685
686 /* 
687   netr_LogonSamLogoff 
688 */
689 static NTSTATUS netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
690                        struct netr_LogonSamLogoff *r)
691 {
692         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
693 }
694
695
696
697 /* 
698   netr_DatabaseDeltas 
699 */
700 static NTSTATUS netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
701                        struct netr_DatabaseDeltas *r)
702 {
703         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
704 }
705
706
707 /* 
708   netr_DatabaseSync 
709 */
710 static NTSTATUS netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
711                        struct netr_DatabaseSync *r)
712 {
713         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
714 }
715
716
717 /* 
718   netr_AccountDeltas 
719 */
720 static NTSTATUS netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
721                        struct netr_AccountDeltas *r)
722 {
723         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
724 }
725
726
727 /* 
728   netr_AccountSync 
729 */
730 static NTSTATUS netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
731                        struct netr_AccountSync *r)
732 {
733         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
734 }
735
736
737 /* 
738   netr_GetDcName 
739 */
740 static NTSTATUS netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
741                        struct netr_GetDcName *r)
742 {
743         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
744 }
745
746
747 /* 
748   netr_LogonControl 
749 */
750 static WERROR netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751                        struct netr_LogonControl *r)
752 {
753         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
754 }
755
756
757 /* 
758   netr_GetAnyDCName 
759 */
760 static WERROR netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
761                        struct netr_GetAnyDCName *r)
762 {
763         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
764 }
765
766
767 /* 
768   netr_LogonControl2 
769 */
770 static WERROR netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
771                        struct netr_LogonControl2 *r)
772 {
773         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
774 }
775
776
777 /* 
778   netr_DatabaseSync2 
779 */
780 static NTSTATUS netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
781                        struct netr_DatabaseSync2 *r)
782 {
783         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
784 }
785
786
787 /* 
788   netr_DatabaseRedo 
789 */
790 static NTSTATUS netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
791                        struct netr_DatabaseRedo *r)
792 {
793         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
794 }
795
796
797 /* 
798   netr_LogonControl2Ex 
799 */
800 static WERROR netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
801                        struct netr_LogonControl2Ex *r)
802 {
803         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
804 }
805
806
807 /* 
808   netr_NETRENUMERATETRUSTEDDOMAINS 
809 */
810 static WERROR netr_NETRENUMERATETRUSTEDDOMAINS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
811                        struct netr_NETRENUMERATETRUSTEDDOMAINS *r)
812 {
813         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
814 }
815
816
817 /* 
818   netr_DSRGETDCNAME 
819 */
820 static WERROR netr_DSRGETDCNAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
821                        struct netr_DSRGETDCNAME *r)
822 {
823         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
824 }
825
826
827 /* 
828   netr_NETRLOGONDUMMYROUTINE1 
829 */
830 static WERROR netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
831                        struct netr_NETRLOGONDUMMYROUTINE1 *r)
832 {
833         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
834 }
835
836
837 /* 
838   netr_NETRLOGONSETSERVICEBITS 
839 */
840 static WERROR netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
841                        struct netr_NETRLOGONSETSERVICEBITS *r)
842 {
843         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
844 }
845
846
847 /* 
848   netr_NETRLOGONGETTRUSTRID 
849 */
850 static WERROR netr_NETRLOGONGETTRUSTRID(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
851                        struct netr_NETRLOGONGETTRUSTRID *r)
852 {
853         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
854 }
855
856
857 /* 
858   netr_NETRLOGONCOMPUTESERVERDIGEST 
859 */
860 static WERROR netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
862 {
863         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
864 }
865
866
867 /* 
868   netr_NETRLOGONCOMPUTECLIENTDIGEST 
869 */
870 static WERROR netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
871                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
872 {
873         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
874 }
875
876
877 /* 
878   netr_DSRGETDCNAMEX 
879 */
880 static WERROR netr_DSRGETDCNAMEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
881                        struct netr_DSRGETDCNAMEX *r)
882 {
883         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
884 }
885
886
887 /* 
888   netr_DSRGETSITENAME 
889 */
890 static WERROR netr_DSRGETSITENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
891                        struct netr_DSRGETSITENAME *r)
892 {
893         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
894 }
895
896
897 /*
898   fill in a netr_DomainTrustInfo from a ldb search result
899 */
900 static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, struct ldb_message *res,
901                                        struct netr_DomainTrustInfo *info, BOOL is_local)
902 {
903         ZERO_STRUCTP(info);
904
905         if (is_local) {
906                 info->domainname.string = samdb_result_string(res, "name", NULL);
907                 info->fulldomainname.string = samdb_result_string(res, "dnsDomain", NULL);
908                 info->guid = samdb_result_guid(res, "objectGUID");
909                 info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
910         } else {
911                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
912                 info->fulldomainname.string = samdb_result_string(res, "name", NULL);
913                 info->guid = samdb_result_guid(res, "objectGUID");
914                 info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
915         }
916
917         /* TODO: we need proper forest support */
918         info->forest.string = info->fulldomainname.string;
919
920         return NT_STATUS_OK;
921 }
922
923 /* 
924   netr_LogonGetDomainInfo
925   this is called as part of the ADS domain logon procedure.
926 */
927 static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
928                                         struct netr_LogonGetDomainInfo *r)
929 {
930         struct server_pipe_state *pipe_state = dce_call->context->private;
931         const char * const attrs[] = { "name", "dnsDomain", "objectSid", 
932                                        "objectGUID", "flatName", "securityIdentifier",
933                                        NULL };
934         void *sam_ctx;
935         struct ldb_message **res1, **res2;
936         struct netr_DomainInfo1 *info1;
937         int ret1, ret2, i;
938         NTSTATUS status;
939
940         status = netr_creds_server_step_check(pipe_state, 
941                                               r->in.credential, r->out.credential);
942         if (!NT_STATUS_IS_OK(status)) {
943                 return status;
944         }
945
946         sam_ctx = samdb_connect(mem_ctx);
947         if (sam_ctx == NULL) {
948                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
949         }
950
951         /* we need to do two searches. The first will pull our primary
952            domain and the second will pull any trusted domains. Our
953            primary domain is also a "trusted" domain, so we need to
954            put the primary domain into the lists of returned trusts as
955            well */
956         ret1 = samdb_search(sam_ctx, mem_ctx, NULL, &res1, attrs, "(objectClass=domainDNS)");
957         if (ret1 != 1) {
958                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
959         }
960
961         ret2 = samdb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
962         if (ret2 == -1) {
963                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
964         }
965
966         info1 = talloc(mem_ctx, struct netr_DomainInfo1);
967         if (info1 == NULL) {
968                 return NT_STATUS_NO_MEMORY;
969         }
970
971         ZERO_STRUCTP(info1);
972
973         info1->num_trusts = ret2 + 1;
974         info1->trusts = talloc_array(mem_ctx, struct netr_DomainTrustInfo, 
975                                        info1->num_trusts);
976         if (info1->trusts == NULL) {
977                 return NT_STATUS_NO_MEMORY;
978         }
979
980         status = fill_domain_trust_info(mem_ctx, res1[0], &info1->domaininfo, True);
981         if (!NT_STATUS_IS_OK(status)) {
982                 return status;
983         }
984
985         status = fill_domain_trust_info(mem_ctx, res1[0], &info1->trusts[0], True);
986         if (!NT_STATUS_IS_OK(status)) {
987                 return status;
988         }
989
990         for (i=0;i<ret2;i++) {
991                 status = fill_domain_trust_info(mem_ctx, res2[i], &info1->trusts[i+1], False);
992                 if (!NT_STATUS_IS_OK(status)) {
993                         return status;
994                 }
995         }
996
997         r->out.info.info1 = info1;
998
999         return NT_STATUS_OK;
1000 }
1001
1002
1003 /* 
1004   netr_ServerPasswordSet2 
1005 */
1006 static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1007                                        struct netr_ServerPasswordSet2 *r)
1008 {
1009         struct server_pipe_state *pipe_state = dce_call->context->private;
1010
1011         void *sam_ctx;
1012         int num_records;
1013         int num_records_domain;
1014         int ret;
1015         struct ldb_message **msgs;
1016         struct ldb_message **msgs_domain;
1017         NTSTATUS nt_status;
1018         struct ldb_message *mod;
1019         const char *domain_sid;
1020         char new_pass[512];
1021         uint32_t new_pass_len;
1022
1023         const char *attrs[] = {"objectSid", NULL };
1024
1025         const char **domain_attrs = attrs;
1026
1027         nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
1028         NT_STATUS_NOT_OK_RETURN(nt_status);
1029
1030         sam_ctx = samdb_connect(mem_ctx);
1031         if (sam_ctx == NULL) {
1032                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1033         }
1034         /* pull the user attributes */
1035         num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
1036                                    "(&(sAMAccountName=%s)(objectclass=user))", 
1037                                    pipe_state->creds->account_name);
1038         if (num_records == -1) {
1039                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1040         }
1041
1042         if (num_records == 0) {
1043                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
1044                          pipe_state->creds->account_name));
1045                 return NT_STATUS_NO_SUCH_USER;
1046         }
1047
1048         if (num_records > 1) {
1049                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, 
1050                          pipe_state->creds->account_name));
1051                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1052         }
1053
1054         domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
1055         if (!domain_sid) {
1056                 DEBUG(0,("no objectSid in user record\n"));
1057                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1058         }
1059
1060         /* find the domain's DN */
1061         num_records_domain = samdb_search(sam_ctx, mem_ctx, NULL, 
1062                                           &msgs_domain, domain_attrs,
1063                                           "(&(objectSid=%s)(objectclass=domain))", 
1064                                           domain_sid);
1065         if (num_records_domain == -1) {
1066                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1067         }
1068
1069         if (num_records_domain == 0) {
1070                 DEBUG(3,("Couldn't find domain [%s] in samdb.\n", 
1071                          domain_sid));
1072                 return NT_STATUS_NO_SUCH_USER;
1073         }
1074
1075         if (num_records_domain > 1) {
1076                 DEBUG(0,("Found %d records matching domain [%s]\n", 
1077                          num_records_domain, domain_sid));
1078                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1079         }
1080
1081         mod = talloc_zero(mem_ctx, struct ldb_message);
1082         NT_STATUS_HAVE_NO_MEMORY(mod);
1083         mod->dn = talloc_reference(mod, msgs[0]->dn);
1084     
1085         creds_arcfour_crypt(pipe_state->creds, r->in.new_password.data, 516);
1086
1087         ret = decode_pw_buffer(r->in.new_password.data, new_pass, sizeof(new_pass),
1088                               &new_pass_len, STR_UNICODE);
1089         if (!ret) {
1090                 DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
1091                 return NT_STATUS_ACCESS_DENIED;
1092         }
1093
1094         /* set the password - samdb needs to know both the domain and user DNs,
1095            so the domain password policy can be used */
1096         nt_status = samdb_set_password(sam_ctx, mod,
1097                                        msgs[0]->dn,
1098                                        msgs_domain[0]->dn,
1099                                        mod, new_pass, /* we have plaintext */
1100                                        NULL, NULL,
1101                                        False, /* This is not considered a password change */
1102                                        False, /* don't restrict this password change (match w2k3) */
1103                                        NULL);
1104         ZERO_ARRAY(new_pass);
1105         NT_STATUS_NOT_OK_RETURN(nt_status);
1106
1107         ret = samdb_replace(sam_ctx, mem_ctx, mod);
1108         if (ret != 0) {
1109                 /* we really need samdb.c to return NTSTATUS */
1110                 return NT_STATUS_UNSUCCESSFUL;
1111         }
1112
1113         return NT_STATUS_OK;
1114 }
1115
1116
1117 /* 
1118   netr_NETRSERVERPASSWORDGET 
1119 */
1120 static WERROR netr_NETRSERVERPASSWORDGET(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1121                        struct netr_NETRSERVERPASSWORDGET *r)
1122 {
1123         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1124 }
1125
1126
1127 /* 
1128   netr_NETRLOGONSENDTOSAM 
1129 */
1130 static WERROR netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1131                        struct netr_NETRLOGONSENDTOSAM *r)
1132 {
1133         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1134 }
1135
1136
1137 /* 
1138   netr_DSRADDRESSTOSITENAMESW 
1139 */
1140 static WERROR netr_DSRADDRESSTOSITENAMESW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1141                        struct netr_DSRADDRESSTOSITENAMESW *r)
1142 {
1143         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1144 }
1145
1146
1147 /* 
1148   netr_DrsGetDCNameEx2
1149 */
1150 static WERROR netr_DrsGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151                        struct netr_DrsGetDCNameEx2 *r)
1152 {
1153         const char * const attrs[] = { "dnsDomain", "objectGUID", NULL };
1154         void *sam_ctx;
1155         struct ldb_message **res;
1156         int ret;
1157
1158         ZERO_STRUCT(r->out);
1159
1160         sam_ctx = samdb_connect(mem_ctx);
1161         if (sam_ctx == NULL) {
1162                 return WERR_DS_SERVICE_UNAVAILABLE;
1163         }
1164
1165         ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
1166                                 "(&(objectClass=domainDNS)(dnsDomain=%s))",
1167                                 r->in.domain_name);
1168         if (ret != 1) {
1169                 return WERR_NO_SUCH_DOMAIN;
1170         }
1171
1172         r->out.info = talloc(mem_ctx, struct netr_DrsGetDCNameEx2Info);
1173         if (!r->out.info) {
1174                 return WERR_NOMEM;
1175         }
1176
1177         /* TODO: - return real IP address
1178          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1179          */
1180         r->out.info->dc_unc             = talloc_asprintf(mem_ctx, "\\\\%s.%s", lp_netbios_name(),lp_realm());
1181         r->out.info->dc_address = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1182         r->out.info->dc_address_type    = 1;
1183         r->out.info->domain_guid        = samdb_result_guid(res[0], "objectGUID");
1184         r->out.info->domain_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1185         r->out.info->forest_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1186         r->out.info->dc_flags           = 0xE00001FD;
1187         r->out.info->dc_site_name       = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1188         r->out.info->client_site_name   = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1189
1190         return WERR_OK;
1191 }
1192
1193
1194 /* 
1195   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1196 */
1197 static WERROR netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1198                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1199 {
1200         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1201 }
1202
1203
1204 /* 
1205   netr_NETRENUMERATETRUSTEDDOMAINSEX 
1206 */
1207 static WERROR netr_NETRENUMERATETRUSTEDDOMAINSEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1208                        struct netr_NETRENUMERATETRUSTEDDOMAINSEX *r)
1209 {
1210         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1211 }
1212
1213
1214 /* 
1215   netr_DSRADDRESSTOSITENAMESEXW 
1216 */
1217 static WERROR netr_DSRADDRESSTOSITENAMESEXW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1218                        struct netr_DSRADDRESSTOSITENAMESEXW *r)
1219 {
1220         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1221 }
1222
1223
1224 /* 
1225   netr_DSRGETDCSITECOVERAGEW 
1226 */
1227 static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1228                        struct netr_DSRGETDCSITECOVERAGEW *r)
1229 {
1230         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1231 }
1232
1233
1234 /* 
1235   netr_DsrEnumerateDomainTrusts 
1236 */
1237 static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1238                                               struct netr_DsrEnumerateDomainTrusts *r)
1239 {
1240         struct netr_DomainTrust *trusts;
1241         void *sam_ctx;
1242         int ret, i;
1243         struct ldb_message **res;
1244         const char * const attrs[] = { "name", "dnsDomain", "objectSid", "objectGUID", NULL };
1245
1246         ZERO_STRUCT(r->out);
1247
1248         sam_ctx = samdb_connect(mem_ctx);
1249         if (sam_ctx == NULL) {
1250                 return WERR_GENERAL_FAILURE;
1251         }
1252
1253         ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(objectClass=domainDNS)");
1254         if (ret == -1) {
1255                 return WERR_GENERAL_FAILURE;            
1256         }
1257
1258         if (ret == 0) {
1259                 return WERR_OK;
1260         }
1261
1262         trusts = talloc_array(mem_ctx, struct netr_DomainTrust, ret);
1263         if (trusts == NULL) {
1264                 return WERR_NOMEM;
1265         }
1266         
1267         r->out.count = ret;
1268         r->out.trusts = trusts;
1269
1270         /* TODO: add filtering by trust_flags, and correct trust_type
1271            and attributes */
1272         for (i=0;i<ret;i++) {
1273                 trusts[i].netbios_name = samdb_result_string(res[i], "name", NULL);
1274                 trusts[i].dns_name     = samdb_result_string(res[i], "dnsDomain", NULL);
1275                 trusts[i].trust_flags = 
1276                         NETR_TRUST_FLAG_TREEROOT | 
1277                         NETR_TRUST_FLAG_IN_FOREST | 
1278                         NETR_TRUST_FLAG_PRIMARY;
1279                 trusts[i].parent_index = 0;
1280                 trusts[i].trust_type = 2;
1281                 trusts[i].trust_attributes = 0;
1282                 trusts[i].sid  = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
1283                 trusts[i].guid = samdb_result_guid(res[i], "objectGUID");
1284         }
1285         
1286
1287         return WERR_OK;
1288 }
1289
1290
1291 /* 
1292   netr_DSRDEREGISTERDNSHOSTRECORDS 
1293 */
1294 static WERROR netr_DSRDEREGISTERDNSHOSTRECORDS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1295                        struct netr_DSRDEREGISTERDNSHOSTRECORDS *r)
1296 {
1297         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1298 }
1299
1300
1301 /* 
1302   netr_NETRSERVERTRUSTPASSWORDSGET 
1303 */
1304 static WERROR netr_NETRSERVERTRUSTPASSWORDSGET(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1305                        struct netr_NETRSERVERTRUSTPASSWORDSGET *r)
1306 {
1307         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1308 }
1309
1310
1311 /* 
1312   netr_DSRGETFORESTTRUSTINFORMATION 
1313 */
1314 static WERROR netr_DSRGETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1315                        struct netr_DSRGETFORESTTRUSTINFORMATION *r)
1316 {
1317         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1318 }
1319
1320
1321 /* 
1322   netr_NETRGETFORESTTRUSTINFORMATION 
1323 */
1324 static WERROR netr_NETRGETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1325                        struct netr_NETRGETFORESTTRUSTINFORMATION *r)
1326 {
1327         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1328 }
1329
1330
1331 /* 
1332   netr_NETRSERVERGETTRUSTINFO 
1333 */
1334 static WERROR netr_NETRSERVERGETTRUSTINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1335                        struct netr_NETRSERVERGETTRUSTINFO *r)
1336 {
1337         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1338 }
1339
1340
1341 /* include the generated boilerplate */
1342 #include "librpc/gen_ndr/ndr_netlogon_s.c"