Add GenericInfo level for SamLogon calls from the WSPP IDL.
[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                 /* Until we get enough information for an implemetnation */
492                 return NT_STATUS_INVALID_PARAMETER;
493         }
494         default:
495                 return NT_STATUS_INVALID_PARAMETER;
496         }
497         
498         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
499         NT_STATUS_NOT_OK_RETURN(nt_status);
500
501         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
502         NT_STATUS_NOT_OK_RETURN(nt_status);
503
504         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
505         /* It appears that level 6 is not individually encrypted */
506         if ((r->in.validation_level != 6) &&
507             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
508                 /* This key is sent unencrypted without the ARCFOUR flag set */
509                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
510                         creds_arcfour_crypt(creds, 
511                                             sam->key.key, 
512                                             sizeof(sam->key.key));
513                 }
514         }
515
516         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
517         /* It appears that level 6 is not individually encrypted */
518         if ((r->in.validation_level != 6) &&
519             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
520                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
521                         creds_arcfour_crypt(creds, 
522                                             sam->LMSessKey.key, 
523                                             sizeof(sam->LMSessKey.key));
524                 } else {
525                         creds_des_encrypt_LMKey(creds, 
526                                                 &sam->LMSessKey);
527                 }
528         }
529
530         switch (r->in.validation_level) {
531         case 2:
532                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
533                 NT_STATUS_HAVE_NO_MEMORY(sam2);
534                 sam2->base = *sam;
535                 r->out.validation.sam2 = sam2;
536                 break;
537
538         case 3:
539                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
540                 NT_STATUS_HAVE_NO_MEMORY(sam3);
541                 sam3->base = *sam;
542                 r->out.validation.sam3 = sam3;
543                 break;
544
545         case 6:
546                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
547                 NT_STATUS_HAVE_NO_MEMORY(sam6);
548                 sam6->base = *sam;
549                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
550                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
551                                                          sam->account_name.string, sam6->forest.string);
552                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
553                 r->out.validation.sam6 = sam6;
554                 break;
555
556         default:
557                 break;
558         }
559
560         r->out.authoritative = 1;
561
562         /* TODO: Describe and deal with these flags */
563         r->out.flags = 0;
564
565         return NT_STATUS_OK;
566 }
567
568 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
569                                      struct netr_LogonSamLogonEx *r) 
570 {
571         NTSTATUS nt_status;
572         struct creds_CredentialState *creds;
573         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);
574         if (!NT_STATUS_IS_OK(nt_status)) {
575                 return nt_status;
576         }
577
578         if (!dce_call->conn->auth_state.auth_info ||
579             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
580                 return NT_STATUS_INTERNAL_ERROR;
581         }
582         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
583 }
584
585 /* 
586   netr_LogonSamLogonWithFlags
587
588 */
589 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
590                                             struct netr_LogonSamLogonWithFlags *r)
591 {
592         NTSTATUS nt_status;
593         struct creds_CredentialState *creds;
594         struct netr_LogonSamLogonEx r2;
595
596         struct netr_Authenticator *return_authenticator;
597
598         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
599         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
600
601         nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
602                                                         r->in.computer_name, mem_ctx, 
603                                                  r->in.credential, return_authenticator,
604                                                  &creds);
605         NT_STATUS_NOT_OK_RETURN(nt_status);
606
607         ZERO_STRUCT(r2);
608
609         r2.in.server_name       = r->in.server_name;
610         r2.in.computer_name     = r->in.computer_name;
611         r2.in.logon_level       = r->in.logon_level;
612         r2.in.logon             = r->in.logon;
613         r2.in.validation_level  = r->in.validation_level;
614         r2.in.flags             = r->in.flags;
615
616         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
617
618         r->out.return_authenticator     = return_authenticator;
619         r->out.validation               = r2.out.validation;
620         r->out.authoritative            = r2.out.authoritative;
621         r->out.flags                    = r2.out.flags;
622
623         return nt_status;
624 }
625
626 /* 
627   netr_LogonSamLogon
628 */
629 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
630                                    struct netr_LogonSamLogon *r)
631 {
632         struct netr_LogonSamLogonWithFlags r2;
633         NTSTATUS status;
634
635         ZERO_STRUCT(r2);
636
637         r2.in.server_name = r->in.server_name;
638         r2.in.computer_name = r->in.computer_name;
639         r2.in.credential  = r->in.credential;
640         r2.in.return_authenticator = r->in.return_authenticator;
641         r2.in.logon_level = r->in.logon_level;
642         r2.in.logon = r->in.logon;
643         r2.in.validation_level = r->in.validation_level;
644         r2.in.flags = 0;
645
646         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
647
648         r->out.return_authenticator = r2.out.return_authenticator;
649         r->out.validation = r2.out.validation;
650         r->out.authoritative = r2.out.authoritative;
651
652         return status;
653 }
654
655
656 /* 
657   netr_LogonSamLogoff 
658 */
659 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
660                        struct netr_LogonSamLogoff *r)
661 {
662         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
663 }
664
665
666
667 /* 
668   netr_DatabaseDeltas 
669 */
670 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
671                        struct netr_DatabaseDeltas *r)
672 {
673         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
674 }
675
676
677 /* 
678   netr_DatabaseSync 
679 */
680 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681                        struct netr_DatabaseSync *r)
682 {
683         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
684         return NT_STATUS_NOT_IMPLEMENTED;
685 }
686
687
688 /* 
689   netr_AccountDeltas 
690 */
691 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
692                        struct netr_AccountDeltas *r)
693 {
694         /* w2k3 returns "NOT IMPLEMENTED" for this call */
695         return NT_STATUS_NOT_IMPLEMENTED;
696 }
697
698
699 /* 
700   netr_AccountSync 
701 */
702 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
703                        struct netr_AccountSync *r)
704 {
705         /* w2k3 returns "NOT IMPLEMENTED" for this call */
706         return NT_STATUS_NOT_IMPLEMENTED;
707 }
708
709
710 /* 
711   netr_GetDcName 
712 */
713 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
714                        struct netr_GetDcName *r)
715 {
716         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
717 }
718
719
720 /* 
721   netr_LogonControl 
722 */
723 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
724                        struct netr_LogonControl *r)
725 {
726         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
727 }
728
729
730 /* 
731   netr_GetAnyDCName 
732 */
733 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
734                        struct netr_GetAnyDCName *r)
735 {
736         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
737 }
738
739
740 /* 
741   netr_LogonControl2 
742 */
743 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
744                        struct netr_LogonControl2 *r)
745 {
746         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
747 }
748
749
750 /* 
751   netr_DatabaseSync2 
752 */
753 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
754                        struct netr_DatabaseSync2 *r)
755 {
756         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
757         return NT_STATUS_NOT_IMPLEMENTED;
758 }
759
760
761 /* 
762   netr_DatabaseRedo 
763 */
764 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
765                        struct netr_DatabaseRedo *r)
766 {
767         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
768 }
769
770
771 /* 
772   netr_LogonControl2Ex 
773 */
774 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
775                        struct netr_LogonControl2Ex *r)
776 {
777         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
778 }
779
780
781 /* 
782   netr_NetrEnumerateTurstedDomains
783 */
784 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
785                        struct netr_NetrEnumerateTrustedDomains *r)
786 {
787         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
788 }
789
790
791 /* 
792   netr_NETRLOGONDUMMYROUTINE1 
793 */
794 static WERROR dcesrv_netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
795                        struct netr_NETRLOGONDUMMYROUTINE1 *r)
796 {
797         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
798 }
799
800
801 /* 
802   netr_NETRLOGONSETSERVICEBITS 
803 */
804 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
805                        struct netr_NETRLOGONSETSERVICEBITS *r)
806 {
807         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
808 }
809
810
811 /*
812   netr_LogonGetTrustRid
813 */
814 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
815                        struct netr_LogonGetTrustRid *r)
816 {
817         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
818 }
819
820
821 /* 
822   netr_NETRLOGONCOMPUTESERVERDIGEST 
823 */
824 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
825                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
826 {
827         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
828 }
829
830
831 /* 
832   netr_NETRLOGONCOMPUTECLIENTDIGEST 
833 */
834 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
835                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
836 {
837         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
838 }
839
840
841
842 /* 
843   netr_DsRGetSiteName
844 */
845 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
846                                   struct netr_DsRGetSiteName *r)
847 {
848         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
849 }
850
851
852 /*
853   fill in a netr_DomainTrustInfo from a ldb search result
854 */
855 static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
856                                        struct ldb_message *res,
857                                        struct ldb_message *ref_res,
858                                        struct netr_DomainTrustInfo *info, 
859                                        bool is_local)
860 {
861         ZERO_STRUCTP(info);
862
863         if (is_local) {
864                 info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL);
865                 info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL);
866                 info->forest.string = NULL;
867                 info->guid = samdb_result_guid(res, "objectGUID");
868                 info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
869         } else {
870                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
871                 info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
872                 info->forest.string = NULL;
873                 info->guid = samdb_result_guid(res, "objectGUID");
874                 info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
875         }
876
877         return NT_STATUS_OK;
878 }
879
880 /* 
881   netr_LogonGetDomainInfo
882   this is called as part of the ADS domain logon procedure.
883
884   It has an important role in convaying details about the client, such
885   as Operating System, Version, Service Pack etc.
886 */
887 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
888                                         struct netr_LogonGetDomainInfo *r)
889 {
890         const char * const attrs[] = { "objectSid", 
891                                        "objectGUID", "flatName", "securityIdentifier",
892                                        "trustPartner", NULL };
893         const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
894         struct ldb_context *sam_ctx;
895         struct ldb_message **res1, **res2, **ref_res;
896         struct netr_DomainInfo1 *info1;
897         int ret, ret1, ret2, i;
898         NTSTATUS status;
899         struct ldb_dn *partitions_basedn;
900
901         const char *local_domain;
902
903         status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
904                                                      r->in.computer_name, mem_ctx, 
905                                               r->in.credential, 
906                                               r->out.return_authenticator,
907                                               NULL);
908         NT_STATUS_NOT_OK_RETURN(status);
909
910         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
911         if (sam_ctx == NULL) {
912                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
913         }
914
915         partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
916
917         /* we need to do two searches. The first will pull our primary
918            domain and the second will pull any trusted domains. Our
919            primary domain is also a "trusted" domain, so we need to
920            put the primary domain into the lists of returned trusts as
921            well */
922         ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx), &res1, attrs);
923         if (ret1 != 1) {
924                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
925         }
926
927         /* try and find the domain */
928         ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, 
929                            &ref_res, ref_attrs, 
930                            "(&(objectClass=crossRef)(ncName=%s))", 
931                            ldb_dn_get_linearized(res1[0]->dn));
932         if (ret != 1) {
933                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
934         }
935
936         local_domain = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
937
938         ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
939         if (ret2 == -1) {
940                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
941         }
942
943         info1 = talloc(mem_ctx, struct netr_DomainInfo1);
944         NT_STATUS_HAVE_NO_MEMORY(info1);
945
946         ZERO_STRUCTP(info1);
947
948         info1->num_trusts = ret2 + 1;
949         info1->trusts = talloc_array(mem_ctx, struct netr_DomainTrustInfo, 
950                                        info1->num_trusts);
951         NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
952
953         status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, true);
954         NT_STATUS_NOT_OK_RETURN(status);
955
956         for (i=0;i<ret2;i++) {
957                 status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], false);
958                 NT_STATUS_NOT_OK_RETURN(status);
959         }
960
961         status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], true);
962         NT_STATUS_NOT_OK_RETURN(status);
963
964         r->out.info.info1 = info1;
965
966         return NT_STATUS_OK;
967 }
968
969
970
971 /*
972   netr_ServerPasswordGet
973 */
974 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
975                        struct netr_ServerPasswordGet *r)
976 {
977         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
978 }
979
980
981 /* 
982   netr_NETRLOGONSENDTOSAM 
983 */
984 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
985                        struct netr_NETRLOGONSENDTOSAM *r)
986 {
987         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
988 }
989
990
991 /* 
992   netr_DsRAddressToSitenamesW 
993 */
994 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
995                        struct netr_DsRAddressToSitenamesW *r)
996 {
997         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
998 }
999
1000
1001 /* 
1002   netr_DsRGetDCNameEx2
1003 */
1004 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1005                                    struct netr_DsRGetDCNameEx2 *r)
1006 {
1007         const char * const attrs[] = { "dnsDomain", "objectGUID", NULL };
1008         void *sam_ctx;
1009         struct ldb_message **res;
1010         struct ldb_dn *domain_dn;
1011         int ret;
1012
1013         ZERO_STRUCT(r->out);
1014
1015         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1016         if (sam_ctx == NULL) {
1017                 return WERR_DS_SERVICE_UNAVAILABLE;
1018         }
1019
1020         domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx,
1021                                            r->in.domain_name);   
1022         if (domain_dn == NULL) {
1023                 return WERR_DS_SERVICE_UNAVAILABLE;
1024         }
1025
1026         ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs);
1027         if (ret != 1) {
1028                 return WERR_NO_SUCH_DOMAIN;
1029         }
1030
1031         r->out.info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1032         W_ERROR_HAVE_NO_MEMORY(r->out.info);
1033
1034         /* TODO: - return real IP address
1035          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1036          */
1037         r->out.info->dc_unc             = talloc_asprintf(mem_ctx, "\\\\%s.%s", 
1038                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1039                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1040         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_unc);
1041         r->out.info->dc_address         = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1042         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_address);
1043         r->out.info->dc_address_type    = DS_ADDRESS_TYPE_INET;
1044         r->out.info->domain_guid        = samdb_result_guid(res[0], "objectGUID");
1045         r->out.info->domain_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1046         r->out.info->forest_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1047         r->out.info->dc_flags           = DS_DNS_FOREST |
1048                                           DS_DNS_DOMAIN |
1049                                           DS_DNS_CONTROLLER |
1050                                           DS_SERVER_WRITABLE |
1051                                           DS_SERVER_CLOSEST |
1052                                           DS_SERVER_TIMESERV |
1053                                           DS_SERVER_KDC |
1054                                           DS_SERVER_DS |
1055                                           DS_SERVER_LDAP |
1056                                           DS_SERVER_GC |
1057                                           DS_SERVER_PDC;
1058         r->out.info->dc_site_name       = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1059         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_site_name);
1060         r->out.info->client_site_name   = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1061         W_ERROR_HAVE_NO_MEMORY(r->out.info->client_site_name);
1062
1063         return WERR_OK;
1064 }
1065
1066 /* 
1067   netr_DsRGetDCNameEx
1068 */
1069 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1070                                   struct netr_DsRGetDCNameEx *r)
1071 {
1072         struct netr_DsRGetDCNameEx2 r2;
1073         WERROR werr;
1074
1075         ZERO_STRUCT(r2);
1076
1077         r2.in.server_unc = r->in.server_unc;
1078         r2.in.client_account = NULL;
1079         r2.in.mask = 0;
1080         r2.in.domain_guid = r->in.domain_guid;
1081         r2.in.domain_name = r->in.domain_name;
1082         r2.in.site_name = r->in.site_name;
1083         r2.in.flags = r->in.flags;
1084         r2.out.info = NULL;
1085
1086         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1087         
1088         r->out.info = r2.out.info;
1089         
1090         return werr;
1091 }
1092
1093 /* 
1094   netr_DsRGetDCName
1095 */
1096 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1097                                 struct netr_DsRGetDCName *r)
1098 {
1099         struct netr_DsRGetDCNameEx2 r2;
1100         WERROR werr;
1101
1102         ZERO_STRUCT(r2);
1103
1104         r2.in.server_unc = r->in.server_unc;
1105         r2.in.client_account = NULL;
1106         r2.in.mask = 0;
1107         r2.in.domain_name = r->in.domain_name;
1108         r2.in.domain_guid = r->in.domain_guid;
1109         
1110         r2.in.site_name = NULL; /* should fill in from site GUID */
1111         r2.in.flags = r->in.flags;
1112         r2.out.info = NULL;
1113
1114         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1115         
1116         r->out.info = r2.out.info;
1117         
1118         return werr;
1119 }
1120
1121 /* 
1122   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1123 */
1124 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1125                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1126 {
1127         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1128 }
1129
1130
1131 /*
1132   netr_NetrEnumerateTrustedDomainsEx
1133 */
1134 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1135                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1136 {
1137         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1138 }
1139
1140
1141 /* 
1142   netr_DsRAddressToSitenamesExW 
1143 */
1144 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1145                        struct netr_DsRAddressToSitenamesExW *r)
1146 {
1147         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1148 }
1149
1150
1151 /* 
1152   netr_DsrGetDcSiteCoverageW
1153 */
1154 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1155                        struct netr_DsrGetDcSiteCoverageW *r)
1156 {
1157         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1158 }
1159
1160
1161 /* 
1162   netr_DsrEnumerateDomainTrusts 
1163 */
1164 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1165                                               struct netr_DsrEnumerateDomainTrusts *r)
1166 {
1167         struct netr_DomainTrust *trusts;
1168         void *sam_ctx;
1169         int ret;
1170         struct ldb_message **dom_res, **ref_res;
1171         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1172         const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
1173         struct ldb_dn *partitions_basedn;
1174
1175         ZERO_STRUCT(r->out);
1176
1177         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1178         if (sam_ctx == NULL) {
1179                 return WERR_GENERAL_FAILURE;
1180         }
1181
1182         partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
1183
1184         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1185         if (ret == -1) {
1186                 return WERR_GENERAL_FAILURE;            
1187         }
1188         if (ret != 1) {
1189                 return WERR_GENERAL_FAILURE;
1190         }
1191
1192         ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
1193                            "(&(objectClass=crossRef)(ncName=%s))",
1194                            ldb_dn_get_linearized(dom_res[0]->dn));
1195         if (ret == -1) {
1196                 return WERR_GENERAL_FAILURE;
1197         }
1198         if (ret != 1) {
1199                 return WERR_GENERAL_FAILURE;
1200         }
1201
1202         trusts = talloc_array(mem_ctx, struct netr_DomainTrust, ret);
1203         W_ERROR_HAVE_NO_MEMORY(trusts);
1204         
1205         r->out.count = 1;
1206         r->out.trusts = trusts;
1207
1208         /* TODO: add filtering by trust_flags, and correct trust_type
1209            and attributes */
1210         trusts[0].netbios_name = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
1211         trusts[0].dns_name     = samdb_result_string(ref_res[0], "dnsRoot", NULL);
1212         trusts[0].trust_flags = 
1213                 NETR_TRUST_FLAG_TREEROOT | 
1214                 NETR_TRUST_FLAG_IN_FOREST | 
1215                 NETR_TRUST_FLAG_PRIMARY;
1216         trusts[0].parent_index = 0;
1217         trusts[0].trust_type = 2;
1218         trusts[0].trust_attributes = 0;
1219         trusts[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1220         trusts[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1221
1222         return WERR_OK;
1223 }
1224
1225
1226 /*
1227   netr_DsrDeregisterDNSHostRecords
1228 */
1229 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1230                        struct netr_DsrDeregisterDNSHostRecords *r)
1231 {
1232         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1233 }
1234
1235
1236 /*
1237   netr_ServerTrustPasswordsGet
1238 */
1239 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1240                        struct netr_ServerTrustPasswordsGet *r)
1241 {
1242         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1243 }
1244
1245
1246 /* 
1247   netr_DsRGetForestTrustInformation 
1248 */
1249 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1250                        struct netr_DsRGetForestTrustInformation *r)
1251 {
1252         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1253 }
1254
1255
1256 /*
1257   netr_GetForestTrustInformation
1258 */
1259 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1260                        struct netr_GetForestTrustInformation *r)
1261 {
1262         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1263 }
1264
1265
1266 /* 
1267   netr_NETRSERVERGETTRUSTINFO 
1268 */
1269 static WERROR dcesrv_netr_NETRSERVERGETTRUSTINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1270                        struct netr_NETRSERVERGETTRUSTINFO *r)
1271 {
1272         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1273 }
1274
1275
1276 /* include the generated boilerplate */
1277 #include "librpc/gen_ndr/ndr_netlogon_s.c"