Fix include paths to new location of libutil.
[kai/samba-autobuild/.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.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.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.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                 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.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.credentials = r->out.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.credentials = r->out.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                                            false, /* This is not considered a 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         char new_pass[512];
389         bool ret;
390
391         struct samr_CryptPassword password_buf;
392
393         nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
394                                                         r->in.computer_name, mem_ctx, 
395                                                  &r->in.credential, &r->out.return_authenticator,
396                                                  &creds);
397         NT_STATUS_NOT_OK_RETURN(nt_status);
398
399         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));
400         if (sam_ctx == NULL) {
401                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
402         }
403
404         memcpy(password_buf.data, r->in.new_password.data, 512);
405         SIVAL(password_buf.data,512,r->in.new_password.length);
406         creds_arcfour_crypt(creds, password_buf.data, 516);
407
408         ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass),
409                                STR_UNICODE);
410         if (!ret) {
411                 DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n"));
412                 return NT_STATUS_ACCESS_DENIED;
413         }
414
415         /* Using the sid for the account as the key, set the password */
416         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
417                                            creds->sid,
418                                            new_pass, /* we have plaintext */
419                                            NULL, NULL,
420                                            false, /* This is not considered a password change */
421                                            NULL, NULL);
422         return nt_status;
423 }
424
425
426 /* 
427   netr_LogonUasLogon 
428 */
429 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
430                                  struct netr_LogonUasLogon *r)
431 {
432         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
433 }
434
435
436 /* 
437   netr_LogonUasLogoff 
438 */
439 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
440                        struct netr_LogonUasLogoff *r)
441 {
442         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
443 }
444
445
446 /* 
447   netr_LogonSamLogon_base
448
449   This version of the function allows other wrappers to say 'do not check the credentials'
450
451   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
452 */
453 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
454                                         struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds)
455 {
456         struct auth_context *auth_context;
457         struct auth_usersupplied_info *user_info;
458         struct auth_serversupplied_info *server_info;
459         NTSTATUS nt_status;
460         static const char zeros[16];
461         struct netr_SamBaseInfo *sam;
462         struct netr_SamInfo2 *sam2;
463         struct netr_SamInfo3 *sam3;
464         struct netr_SamInfo6 *sam6;
465         
466         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
467         NT_STATUS_HAVE_NO_MEMORY(user_info);
468
469         user_info->flags = 0;
470         user_info->mapped_state = false;
471         user_info->remote_host = NULL;
472
473         switch (r->in.logon_level) {
474         case NetlogonInteractiveInformation:
475         case NetlogonServiceInformation:
476         case NetlogonInteractiveTransitiveInformation:
477         case NetlogonServiceTransitiveInformation:
478                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
479                         creds_arcfour_crypt(creds, 
480                                             r->in.logon.password->lmpassword.hash, 
481                                             sizeof(r->in.logon.password->lmpassword.hash));
482                         creds_arcfour_crypt(creds, 
483                                             r->in.logon.password->ntpassword.hash, 
484                                             sizeof(r->in.logon.password->ntpassword.hash));
485                 } else {
486                         creds_des_decrypt(creds, &r->in.logon.password->lmpassword);
487                         creds_des_decrypt(creds, &r->in.logon.password->ntpassword);
488                 }
489
490                 /* TODO: we need to deny anonymous access here */
491                 nt_status = auth_context_create(mem_ctx, 
492                                                 dce_call->event_ctx, dce_call->msg_ctx,
493                                                 dce_call->conn->dce_ctx->lp_ctx,
494                                                 &auth_context);
495                 NT_STATUS_NOT_OK_RETURN(nt_status);
496
497                 user_info->logon_parameters = r->in.logon.password->identity_info.parameter_control;
498                 user_info->client.account_name = r->in.logon.password->identity_info.account_name.string;
499                 user_info->client.domain_name = r->in.logon.password->identity_info.domain_name.string;
500                 user_info->workstation_name = r->in.logon.password->identity_info.workstation.string;
501                 
502                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
503                 user_info->password_state = AUTH_PASSWORD_HASH;
504
505                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
506                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
507                 *user_info->password.hash.lanman = r->in.logon.password->lmpassword;
508
509                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
510                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
511                 *user_info->password.hash.nt = r->in.logon.password->ntpassword;
512
513                 break;
514         case NetlogonNetworkInformation:
515         case NetlogonNetworkTransitiveInformation:
516
517                 /* TODO: we need to deny anonymous access here */
518                 nt_status = auth_context_create(mem_ctx, 
519                                                 dce_call->event_ctx, dce_call->msg_ctx,
520                                                 dce_call->conn->dce_ctx->lp_ctx,
521                                                 &auth_context);
522                 NT_STATUS_NOT_OK_RETURN(nt_status);
523
524                 nt_status = auth_context_set_challenge(auth_context, r->in.logon.network->challenge, "netr_LogonSamLogonWithFlags");
525                 NT_STATUS_NOT_OK_RETURN(nt_status);
526
527                 user_info->logon_parameters = r->in.logon.network->identity_info.parameter_control;
528                 user_info->client.account_name = r->in.logon.network->identity_info.account_name.string;
529                 user_info->client.domain_name = r->in.logon.network->identity_info.domain_name.string;
530                 user_info->workstation_name = r->in.logon.network->identity_info.workstation.string;
531                 
532                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
533                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length);
534                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length);
535         
536                 break;
537
538                 
539         case NetlogonGenericInformation:
540         {
541                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
542                         creds_arcfour_crypt(creds, 
543                                             r->in.logon.generic->data, r->in.logon.generic->length);
544                 } else {
545                         /* Using DES to verify kerberos tickets makes no sense */
546                         return NT_STATUS_INVALID_PARAMETER;
547                 }
548
549                 if (strcmp(r->in.logon.generic->package_name.string, "Kerberos") == 0) {
550                         NTSTATUS status;
551                         struct server_id *kdc;
552                         struct kdc_check_generic_kerberos check;
553                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
554                         NT_STATUS_HAVE_NO_MEMORY(generic);
555                         r->out.authoritative = 1;
556                         
557                         /* TODO: Describe and deal with these flags */
558                         r->out.flags = 0;
559
560                         r->out.validation.generic = generic;
561         
562                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
563                         if ((kdc == NULL) || (kdc[0].id == 0)) {
564                                 return NT_STATUS_NO_LOGON_SERVERS;
565                         }
566                         
567                         check.in.generic_request = 
568                                 data_blob_const(r->in.logon.generic->data,
569                                                 r->in.logon.generic->length);   
570                         
571                         status = irpc_call(dce_call->msg_ctx, kdc[0],
572                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
573                                            &check, mem_ctx);
574                         if (!NT_STATUS_IS_OK(status)) {
575                                 return status;
576                         }
577                         generic->length = check.out.generic_reply.length;
578                         generic->data = check.out.generic_reply.data;
579                         return NT_STATUS_OK;
580                 }
581
582                 /* Until we get an implemetnation of these other packages */
583                 return NT_STATUS_INVALID_PARAMETER;
584         }
585         default:
586                 return NT_STATUS_INVALID_PARAMETER;
587         }
588         
589         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
590         NT_STATUS_NOT_OK_RETURN(nt_status);
591
592         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
593         NT_STATUS_NOT_OK_RETURN(nt_status);
594
595         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
596         /* It appears that level 6 is not individually encrypted */
597         if ((r->in.validation_level != 6) &&
598             memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) {
599                 /* This key is sent unencrypted without the ARCFOUR flag set */
600                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
601                         creds_arcfour_crypt(creds, 
602                                             sam->key.key, 
603                                             sizeof(sam->key.key));
604                 }
605         }
606
607         /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
608         /* It appears that level 6 is not individually encrypted */
609         if ((r->in.validation_level != 6) &&
610             memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
611                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
612                         creds_arcfour_crypt(creds, 
613                                             sam->LMSessKey.key, 
614                                             sizeof(sam->LMSessKey.key));
615                 } else {
616                         creds_des_encrypt_LMKey(creds, 
617                                                 &sam->LMSessKey);
618                 }
619         }
620
621         switch (r->in.validation_level) {
622         case 2:
623                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
624                 NT_STATUS_HAVE_NO_MEMORY(sam2);
625                 sam2->base = *sam;
626                 r->out.validation.sam2 = sam2;
627                 break;
628
629         case 3:
630                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
631                 NT_STATUS_HAVE_NO_MEMORY(sam3);
632                 sam3->base = *sam;
633                 r->out.validation.sam3 = sam3;
634                 break;
635
636         case 6:
637                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
638                 NT_STATUS_HAVE_NO_MEMORY(sam6);
639                 sam6->base = *sam;
640                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
641                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s", 
642                                                          sam->account_name.string, sam6->forest.string);
643                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
644                 r->out.validation.sam6 = sam6;
645                 break;
646
647         default:
648                 break;
649         }
650
651         r->out.authoritative = 1;
652
653         /* TODO: Describe and deal with these flags */
654         r->out.flags = 0;
655
656         return NT_STATUS_OK;
657 }
658
659 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
660                                      struct netr_LogonSamLogonEx *r) 
661 {
662         NTSTATUS nt_status;
663         struct creds_CredentialState *creds;
664         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);
665         if (!NT_STATUS_IS_OK(nt_status)) {
666                 return nt_status;
667         }
668
669         if (!dce_call->conn->auth_state.auth_info ||
670             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
671                 return NT_STATUS_INTERNAL_ERROR;
672         }
673         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
674 }
675
676 /* 
677   netr_LogonSamLogonWithFlags
678
679 */
680 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681                                             struct netr_LogonSamLogonWithFlags *r)
682 {
683         NTSTATUS nt_status;
684         struct creds_CredentialState *creds;
685         struct netr_LogonSamLogonEx r2;
686
687         struct netr_Authenticator *return_authenticator;
688
689         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
690         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
691
692         nt_status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
693                                                         r->in.computer_name, mem_ctx, 
694                                                  r->in.credential, return_authenticator,
695                                                  &creds);
696         NT_STATUS_NOT_OK_RETURN(nt_status);
697
698         ZERO_STRUCT(r2);
699
700         r2.in.server_name       = r->in.server_name;
701         r2.in.computer_name     = r->in.computer_name;
702         r2.in.logon_level       = r->in.logon_level;
703         r2.in.logon             = r->in.logon;
704         r2.in.validation_level  = r->in.validation_level;
705         r2.in.flags             = r->in.flags;
706
707         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
708
709         r->out.return_authenticator     = return_authenticator;
710         r->out.validation               = r2.out.validation;
711         r->out.authoritative            = r2.out.authoritative;
712         r->out.flags                    = r2.out.flags;
713
714         return nt_status;
715 }
716
717 /* 
718   netr_LogonSamLogon
719 */
720 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
721                                    struct netr_LogonSamLogon *r)
722 {
723         struct netr_LogonSamLogonWithFlags r2;
724         NTSTATUS status;
725
726         ZERO_STRUCT(r2);
727
728         r2.in.server_name = r->in.server_name;
729         r2.in.computer_name = r->in.computer_name;
730         r2.in.credential  = r->in.credential;
731         r2.in.return_authenticator = r->in.return_authenticator;
732         r2.in.logon_level = r->in.logon_level;
733         r2.in.logon = r->in.logon;
734         r2.in.validation_level = r->in.validation_level;
735         r2.in.flags = 0;
736
737         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
738
739         r->out.return_authenticator = r2.out.return_authenticator;
740         r->out.validation = r2.out.validation;
741         r->out.authoritative = r2.out.authoritative;
742
743         return status;
744 }
745
746
747 /* 
748   netr_LogonSamLogoff 
749 */
750 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751                        struct netr_LogonSamLogoff *r)
752 {
753         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
754 }
755
756
757
758 /* 
759   netr_DatabaseDeltas 
760 */
761 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
762                        struct netr_DatabaseDeltas *r)
763 {
764         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
765 }
766
767
768 /* 
769   netr_DatabaseSync 
770 */
771 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
772                        struct netr_DatabaseSync *r)
773 {
774         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
775         return NT_STATUS_NOT_IMPLEMENTED;
776 }
777
778
779 /* 
780   netr_AccountDeltas 
781 */
782 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
783                        struct netr_AccountDeltas *r)
784 {
785         /* w2k3 returns "NOT IMPLEMENTED" for this call */
786         return NT_STATUS_NOT_IMPLEMENTED;
787 }
788
789
790 /* 
791   netr_AccountSync 
792 */
793 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
794                        struct netr_AccountSync *r)
795 {
796         /* w2k3 returns "NOT IMPLEMENTED" for this call */
797         return NT_STATUS_NOT_IMPLEMENTED;
798 }
799
800
801 /* 
802   netr_GetDcName 
803 */
804 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
805                        struct netr_GetDcName *r)
806 {
807         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
808 }
809
810
811 /* 
812   netr_LogonControl 
813 */
814 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
815                        struct netr_LogonControl *r)
816 {
817         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
818 }
819
820
821 /* 
822   netr_GetAnyDCName 
823 */
824 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
825                        struct netr_GetAnyDCName *r)
826 {
827         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
828 }
829
830
831 /* 
832   netr_LogonControl2 
833 */
834 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
835                        struct netr_LogonControl2 *r)
836 {
837         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
838 }
839
840
841 /* 
842   netr_DatabaseSync2 
843 */
844 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845                        struct netr_DatabaseSync2 *r)
846 {
847         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
848         return NT_STATUS_NOT_IMPLEMENTED;
849 }
850
851
852 /* 
853   netr_DatabaseRedo 
854 */
855 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
856                        struct netr_DatabaseRedo *r)
857 {
858         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
859 }
860
861
862 /* 
863   netr_LogonControl2Ex 
864 */
865 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
866                        struct netr_LogonControl2Ex *r)
867 {
868         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
869 }
870
871
872 /* 
873   netr_NetrEnumerateTurstedDomains
874 */
875 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
876                        struct netr_NetrEnumerateTrustedDomains *r)
877 {
878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
879 }
880
881
882 /* 
883   netr_NETRLOGONDUMMYROUTINE1 
884 */
885 static WERROR dcesrv_netr_NETRLOGONDUMMYROUTINE1(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
886                        struct netr_NETRLOGONDUMMYROUTINE1 *r)
887 {
888         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
889 }
890
891
892 /* 
893   netr_NETRLOGONSETSERVICEBITS 
894 */
895 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
896                        struct netr_NETRLOGONSETSERVICEBITS *r)
897 {
898         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
899 }
900
901
902 /*
903   netr_LogonGetTrustRid
904 */
905 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
906                        struct netr_LogonGetTrustRid *r)
907 {
908         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
909 }
910
911
912 /* 
913   netr_NETRLOGONCOMPUTESERVERDIGEST 
914 */
915 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
916                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
917 {
918         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
919 }
920
921
922 /* 
923   netr_NETRLOGONCOMPUTECLIENTDIGEST 
924 */
925 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
926                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
927 {
928         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
929 }
930
931
932
933 /* 
934   netr_DsRGetSiteName
935 */
936 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
937                                   struct netr_DsRGetSiteName *r)
938 {
939         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
940 }
941
942
943 /*
944   fill in a netr_DomainTrustInfo from a ldb search result
945 */
946 static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx,
947                                        struct ldb_message *res,
948                                        struct ldb_message *ref_res,
949                                        struct netr_DomainTrustInfo *info, 
950                                        bool is_local, bool is_trust_list)
951 {
952         ZERO_STRUCTP(info);
953
954         info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
955         info->trust_extension.length = 16;
956         info->trust_extension.info->flags = 
957                 NETR_TRUST_FLAG_TREEROOT | 
958                 NETR_TRUST_FLAG_IN_FOREST | 
959                 NETR_TRUST_FLAG_PRIMARY;
960         info->trust_extension.info->parent_index = 0; /* should be index into array
961                                                          of parent */
962         info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
963         info->trust_extension.info->trust_attributes = LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE; /* needs to be based on ldb search */
964
965         if (is_trust_list) {
966                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
967                 info->forest.string = NULL;
968         } else {
969                 /* TODO: we need a common function for pulling the forest */
970                 info->forest.string = samdb_result_string(ref_res, "dnsRoot", NULL);
971         }
972
973         if (is_local) {
974                 info->domainname.string = samdb_result_string(ref_res, "nETBIOSName", NULL);
975                 info->fulldomainname.string = samdb_result_string(ref_res, "dnsRoot", NULL);
976                 info->guid = samdb_result_guid(res, "objectGUID");
977                 info->sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
978         } else {
979                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
980                 info->fulldomainname.string = samdb_result_string(res, "trustPartner", NULL);
981                 info->guid = samdb_result_guid(res, "objectGUID");
982                 info->sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
983         }
984
985         return NT_STATUS_OK;
986 }
987
988 /* 
989   netr_LogonGetDomainInfo
990   this is called as part of the ADS domain logon procedure.
991
992   It has an important role in convaying details about the client, such
993   as Operating System, Version, Service Pack etc.
994 */
995 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
996                                         struct netr_LogonGetDomainInfo *r)
997 {
998         const char * const attrs[] = { "objectSid", 
999                                        "objectGUID", "flatName", "securityIdentifier",
1000                                        "trustPartner", NULL };
1001         const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
1002         struct ldb_context *sam_ctx;
1003         struct ldb_message **res1, **res2, **ref_res;
1004         struct netr_DomainInfo1 *info1;
1005         int ret, ret1, ret2, i;
1006         NTSTATUS status;
1007         struct ldb_dn *partitions_basedn;
1008
1009         const char *local_domain;
1010
1011         status = dcesrv_netr_creds_server_step_check(dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
1012                                                      r->in.computer_name, mem_ctx, 
1013                                               r->in.credential, 
1014                                               r->out.return_authenticator,
1015                                               NULL);
1016         if (!NT_STATUS_IS_OK(status)) {
1017                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1018         }
1019         NT_STATUS_NOT_OK_RETURN(status);
1020
1021         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1022         if (sam_ctx == NULL) {
1023                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1024         }
1025
1026         partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
1027
1028         /* we need to do two searches. The first will pull our primary
1029            domain and the second will pull any trusted domains. Our
1030            primary domain is also a "trusted" domain, so we need to
1031            put the primary domain into the lists of returned trusts as
1032            well */
1033         ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx), &res1, attrs);
1034         if (ret1 != 1) {
1035                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1036         }
1037
1038         /* try and find the domain */
1039         ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, 
1040                            &ref_res, ref_attrs, 
1041                            "(&(objectClass=crossRef)(ncName=%s))", 
1042                            ldb_dn_get_linearized(res1[0]->dn));
1043         if (ret != 1) {
1044                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1045         }
1046
1047         local_domain = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
1048
1049         ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
1050         if (ret2 == -1) {
1051                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1052         }
1053
1054         info1 = talloc(mem_ctx, struct netr_DomainInfo1);
1055         NT_STATUS_HAVE_NO_MEMORY(info1);
1056
1057         ZERO_STRUCTP(info1);
1058
1059         info1->num_trusts = ret2 + 1;
1060         info1->trusts = talloc_array(mem_ctx, struct netr_DomainTrustInfo, 
1061                                        info1->num_trusts);
1062         NT_STATUS_HAVE_NO_MEMORY(info1->trusts);
1063
1064         status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->domaininfo, 
1065                                         true, false);
1066         NT_STATUS_NOT_OK_RETURN(status);
1067
1068         for (i=0;i<ret2;i++) {
1069                 status = fill_domain_trust_info(mem_ctx, res2[i], NULL, &info1->trusts[i], 
1070                                                 false, true);
1071                 NT_STATUS_NOT_OK_RETURN(status);
1072         }
1073
1074         status = fill_domain_trust_info(mem_ctx, res1[0], ref_res[0], &info1->trusts[i], 
1075                                         true, true);
1076         NT_STATUS_NOT_OK_RETURN(status);
1077
1078         info1->dns_hostname.string = samdb_result_string(ref_res[0], "dnsRoot", NULL);
1079         info1->workstation_flags = 
1080                 NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS | NETR_WS_FLAG_HANDLES_SPN_UPDATE;
1081         info1->supported_enc_types = 0; /* w2008 gives this 0 */
1082
1083         r->out.info.info1 = info1;
1084
1085         return NT_STATUS_OK;
1086 }
1087
1088
1089
1090 /*
1091   netr_ServerPasswordGet
1092 */
1093 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1094                        struct netr_ServerPasswordGet *r)
1095 {
1096         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1097 }
1098
1099
1100 /* 
1101   netr_NETRLOGONSENDTOSAM 
1102 */
1103 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1104                        struct netr_NETRLOGONSENDTOSAM *r)
1105 {
1106         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1107 }
1108
1109
1110 /* 
1111   netr_DsRAddressToSitenamesW 
1112 */
1113 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1114                        struct netr_DsRAddressToSitenamesW *r)
1115 {
1116         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1117 }
1118
1119
1120 /* 
1121   netr_DsRGetDCNameEx2
1122 */
1123 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1124                                    struct netr_DsRGetDCNameEx2 *r)
1125 {
1126         const char * const attrs[] = { "dnsDomain", "objectGUID", NULL };
1127         void *sam_ctx;
1128         struct ldb_message **res;
1129         struct ldb_dn *domain_dn;
1130         int ret;
1131
1132         ZERO_STRUCT(r->out);
1133
1134         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1135         if (sam_ctx == NULL) {
1136                 return WERR_DS_SERVICE_UNAVAILABLE;
1137         }
1138
1139         domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx,
1140                                            r->in.domain_name);   
1141         if (domain_dn == NULL) {
1142                 return WERR_DS_SERVICE_UNAVAILABLE;
1143         }
1144
1145         ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs);
1146         if (ret != 1) {
1147                 return WERR_NO_SUCH_DOMAIN;
1148         }
1149
1150         r->out.info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1151         W_ERROR_HAVE_NO_MEMORY(r->out.info);
1152
1153         /* TODO: - return real IP address
1154          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1155          */
1156         r->out.info->dc_unc             = talloc_asprintf(mem_ctx, "\\\\%s.%s", 
1157                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), 
1158                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
1159         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_unc);
1160         r->out.info->dc_address         = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
1161         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_address);
1162         r->out.info->dc_address_type    = DS_ADDRESS_TYPE_INET;
1163         r->out.info->domain_guid        = samdb_result_guid(res[0], "objectGUID");
1164         r->out.info->domain_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1165         r->out.info->forest_name        = samdb_result_string(res[0], "dnsDomain", NULL);
1166         r->out.info->dc_flags           = DS_DNS_FOREST |
1167                                           DS_DNS_DOMAIN |
1168                                           DS_DNS_CONTROLLER |
1169                                           DS_SERVER_WRITABLE |
1170                                           DS_SERVER_CLOSEST |
1171                                           DS_SERVER_TIMESERV |
1172                                           DS_SERVER_KDC |
1173                                           DS_SERVER_DS |
1174                                           DS_SERVER_LDAP |
1175                                           DS_SERVER_GC |
1176                                           DS_SERVER_PDC;
1177         r->out.info->dc_site_name       = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1178         W_ERROR_HAVE_NO_MEMORY(r->out.info->dc_site_name);
1179         r->out.info->client_site_name   = talloc_strdup(mem_ctx, "Default-First-Site-Name");
1180         W_ERROR_HAVE_NO_MEMORY(r->out.info->client_site_name);
1181
1182         return WERR_OK;
1183 }
1184
1185 /* 
1186   netr_DsRGetDCNameEx
1187 */
1188 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1189                                   struct netr_DsRGetDCNameEx *r)
1190 {
1191         struct netr_DsRGetDCNameEx2 r2;
1192         WERROR werr;
1193
1194         ZERO_STRUCT(r2);
1195
1196         r2.in.server_unc = r->in.server_unc;
1197         r2.in.client_account = NULL;
1198         r2.in.mask = 0;
1199         r2.in.domain_guid = r->in.domain_guid;
1200         r2.in.domain_name = r->in.domain_name;
1201         r2.in.site_name = r->in.site_name;
1202         r2.in.flags = r->in.flags;
1203         r2.out.info = NULL;
1204
1205         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1206         
1207         r->out.info = r2.out.info;
1208         
1209         return werr;
1210 }
1211
1212 /* 
1213   netr_DsRGetDCName
1214 */
1215 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1216                                 struct netr_DsRGetDCName *r)
1217 {
1218         struct netr_DsRGetDCNameEx2 r2;
1219         WERROR werr;
1220
1221         ZERO_STRUCT(r2);
1222
1223         r2.in.server_unc = r->in.server_unc;
1224         r2.in.client_account = NULL;
1225         r2.in.mask = 0;
1226         r2.in.domain_name = r->in.domain_name;
1227         r2.in.domain_guid = r->in.domain_guid;
1228         
1229         r2.in.site_name = NULL; /* should fill in from site GUID */
1230         r2.in.flags = r->in.flags;
1231         r2.out.info = NULL;
1232
1233         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1234         
1235         r->out.info = r2.out.info;
1236         
1237         return werr;
1238 }
1239
1240 /* 
1241   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
1242 */
1243 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1244                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1245 {
1246         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1247 }
1248
1249
1250 /*
1251   netr_NetrEnumerateTrustedDomainsEx
1252 */
1253 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1254                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1255 {
1256         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1257 }
1258
1259
1260 /* 
1261   netr_DsRAddressToSitenamesExW 
1262 */
1263 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1264                        struct netr_DsRAddressToSitenamesExW *r)
1265 {
1266         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1267 }
1268
1269
1270 /* 
1271   netr_DsrGetDcSiteCoverageW
1272 */
1273 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1274                        struct netr_DsrGetDcSiteCoverageW *r)
1275 {
1276         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1277 }
1278
1279
1280 /* 
1281   netr_DsrEnumerateDomainTrusts 
1282 */
1283 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1284                                               struct netr_DsrEnumerateDomainTrusts *r)
1285 {
1286         struct netr_DomainTrust *trusts;
1287         void *sam_ctx;
1288         int ret;
1289         struct ldb_message **dom_res, **ref_res;
1290         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
1291         const char * const ref_attrs[] = { "nETBIOSName", "dnsRoot", NULL };
1292         struct ldb_dn *partitions_basedn;
1293
1294         ZERO_STRUCT(r->out);
1295
1296         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
1297         if (sam_ctx == NULL) {
1298                 return WERR_GENERAL_FAILURE;
1299         }
1300
1301         partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
1302
1303         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
1304         if (ret == -1) {
1305                 return WERR_GENERAL_FAILURE;            
1306         }
1307         if (ret != 1) {
1308                 return WERR_GENERAL_FAILURE;
1309         }
1310
1311         ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
1312                            "(&(objectClass=crossRef)(ncName=%s))",
1313                            ldb_dn_get_linearized(dom_res[0]->dn));
1314         if (ret == -1) {
1315                 return WERR_GENERAL_FAILURE;
1316         }
1317         if (ret != 1) {
1318                 return WERR_GENERAL_FAILURE;
1319         }
1320
1321         trusts = talloc_array(mem_ctx, struct netr_DomainTrust, ret);
1322         W_ERROR_HAVE_NO_MEMORY(trusts);
1323         
1324         r->out.count = 1;
1325         r->out.trusts = trusts;
1326
1327         /* TODO: add filtering by trust_flags, and correct trust_type
1328            and attributes */
1329         trusts[0].netbios_name = samdb_result_string(ref_res[0], "nETBIOSName", NULL);
1330         trusts[0].dns_name     = samdb_result_string(ref_res[0], "dnsRoot", NULL);
1331         trusts[0].trust_flags = 
1332                 NETR_TRUST_FLAG_TREEROOT | 
1333                 NETR_TRUST_FLAG_IN_FOREST | 
1334                 NETR_TRUST_FLAG_PRIMARY;
1335         trusts[0].parent_index = 0;
1336         trusts[0].trust_type = 2;
1337         trusts[0].trust_attributes = 0;
1338         trusts[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
1339         trusts[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
1340
1341         return WERR_OK;
1342 }
1343
1344
1345 /*
1346   netr_DsrDeregisterDNSHostRecords
1347 */
1348 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1349                        struct netr_DsrDeregisterDNSHostRecords *r)
1350 {
1351         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1352 }
1353
1354
1355 /*
1356   netr_ServerTrustPasswordsGet
1357 */
1358 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1359                        struct netr_ServerTrustPasswordsGet *r)
1360 {
1361         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1362 }
1363
1364
1365 /* 
1366   netr_DsRGetForestTrustInformation 
1367 */
1368 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1369                        struct netr_DsRGetForestTrustInformation *r)
1370 {
1371         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1372 }
1373
1374
1375 /*
1376   netr_GetForestTrustInformation
1377 */
1378 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1379                        struct netr_GetForestTrustInformation *r)
1380 {
1381         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1382 }
1383
1384
1385 /* 
1386   netr_NETRSERVERGETTRUSTINFO 
1387 */
1388 static WERROR dcesrv_netr_NETRSERVERGETTRUSTINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1389                        struct netr_NETRSERVERGETTRUSTINFO *r)
1390 {
1391         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1392 }
1393
1394
1395 /* include the generated boilerplate */
1396 #include "librpc/gen_ndr/ndr_netlogon_s.c"