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