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