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