s4-rpc_server: use netlogon_creds_encrypt_samlogon().
[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    Copyright (C) Matthias Dieter Wallnöfer            2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "rpc_server/dcerpc_server.h"
26 #include "auth/auth.h"
27 #include "auth/auth_sam_reply.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "../lib/util/util_ldb.h"
30 #include "../libcli/auth/schannel.h"
31 #include "libcli/security/security.h"
32 #include "param/param.h"
33 #include "lib/messaging/irpc.h"
34 #include "librpc/gen_ndr/ndr_irpc_c.h"
35 #include "../libcli/ldap/ldap_ndr.h"
36 #include "cldap_server/cldap_server.h"
37 #include "lib/tsocket/tsocket.h"
38 #include "librpc/gen_ndr/ndr_netlogon.h"
39 #include "librpc/gen_ndr/ndr_irpc.h"
40 #include "lib/socket/netif.h"
41
42 struct netlogon_server_pipe_state {
43         struct netr_Credential client_challenge;
44         struct netr_Credential server_challenge;
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 netlogon_server_pipe_state *pipe_state =
51                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
52
53         ZERO_STRUCTP(r->out.return_credentials);
54
55         /* destroyed on pipe shutdown */
56
57         if (pipe_state) {
58                 talloc_free(pipe_state);
59                 dce_call->context->private_data = NULL;
60         }
61
62         pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
63         NT_STATUS_HAVE_NO_MEMORY(pipe_state);
64
65         pipe_state->client_challenge = *r->in.credentials;
66
67         generate_random_buffer(pipe_state->server_challenge.data,
68                                sizeof(pipe_state->server_challenge.data));
69
70         *r->out.return_credentials = pipe_state->server_challenge;
71
72         dce_call->context->private_data = pipe_state;
73
74         return NT_STATUS_OK;
75 }
76
77 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
78                                          struct netr_ServerAuthenticate3 *r)
79 {
80         struct netlogon_server_pipe_state *pipe_state =
81                 talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
82         struct netlogon_creds_CredentialState *creds;
83         struct ldb_context *sam_ctx;
84         struct samr_Password *mach_pwd;
85         uint32_t user_account_control;
86         int num_records;
87         struct ldb_message **msgs;
88         NTSTATUS nt_status;
89         const char *attrs[] = {"unicodePwd", "userAccountControl",
90                                "objectSid", NULL};
91
92         const char *trust_dom_attrs[] = {"flatname", NULL};
93         const char *account_name;
94         uint32_t negotiate_flags = 0;
95
96         ZERO_STRUCTP(r->out.return_credentials);
97         *r->out.rid = 0;
98
99         negotiate_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
100                           NETLOGON_NEG_PERSISTENT_SAMREPL |
101                           NETLOGON_NEG_ARCFOUR |
102                           NETLOGON_NEG_PROMOTION_COUNT |
103                           NETLOGON_NEG_CHANGELOG_BDC |
104                           NETLOGON_NEG_FULL_SYNC_REPL |
105                           NETLOGON_NEG_MULTIPLE_SIDS |
106                           NETLOGON_NEG_REDO |
107                           NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
108                           NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
109                           NETLOGON_NEG_GENERIC_PASSTHROUGH |
110                           NETLOGON_NEG_CONCURRENT_RPC |
111                           NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
112                           NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
113                           NETLOGON_NEG_TRANSITIVE_TRUSTS |
114                           NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
115                           NETLOGON_NEG_PASSWORD_SET2 |
116                           NETLOGON_NEG_GETDOMAININFO |
117                           NETLOGON_NEG_CROSS_FOREST_TRUSTS |
118                           NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
119                           NETLOGON_NEG_RODC_PASSTHROUGH |
120                           NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
121                           NETLOGON_NEG_AUTHENTICATED_RPC;
122
123         if (*r->in.negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
124                 negotiate_flags |= NETLOGON_NEG_STRONG_KEYS;
125         }
126
127         if (*r->in.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
128                 negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
129         }
130
131         /*
132          * According to Microsoft (see bugid #6099)
133          * Windows 7 looks at the negotiate_flags
134          * returned in this structure *even if the
135          * call fails with access denied!
136          */
137         *r->out.negotiate_flags = negotiate_flags;
138
139         switch (r->in.secure_channel_type) {
140         case SEC_CHAN_WKSTA:
141         case SEC_CHAN_DNS_DOMAIN:
142         case SEC_CHAN_DOMAIN:
143         case SEC_CHAN_BDC:
144         case SEC_CHAN_RODC:
145                 break;
146         default:
147                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
148                           r->in.secure_channel_type));
149                 return NT_STATUS_INVALID_PARAMETER;
150         }
151
152         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
153                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
154         if (sam_ctx == NULL) {
155                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
156         }
157
158         if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
159                 char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name);
160                 const char *flatname;
161                 if (!encoded_account) {
162                         return NT_STATUS_NO_MEMORY;
163                 }
164
165                 /* Kill the trailing dot */
166                 if (encoded_account[strlen(encoded_account)-1] == '.') {
167                         encoded_account[strlen(encoded_account)-1] = '\0';
168                 }
169
170                 /* pull the user attributes */
171                 num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
172                                            trust_dom_attrs,
173                                            "(&(trustPartner=%s)(objectclass=trustedDomain))",
174                                            encoded_account);
175
176                 if (num_records == 0) {
177                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
178                                  encoded_account));
179                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
180                 }
181
182                 if (num_records > 1) {
183                         DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
184                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
185                 }
186
187                 flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
188                 if (!flatname) {
189                         /* No flatname for this trust - we can't proceed */
190                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
191                 }
192                 account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
193
194                 if (!account_name) {
195                         return NT_STATUS_NO_MEMORY;
196                 }
197
198         } else {
199                 account_name = r->in.account_name;
200         }
201
202         /* pull the user attributes */
203         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
204                                    "(&(sAMAccountName=%s)(objectclass=user))",
205                                    ldb_binary_encode_string(mem_ctx, account_name));
206
207         if (num_records == 0) {
208                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
209                          r->in.account_name));
210                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
211         }
212
213         if (num_records > 1) {
214                 DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
215                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
216         }
217
218         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
219
220         if (user_account_control & UF_ACCOUNTDISABLE) {
221                 DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
222                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
223         }
224
225         if (r->in.secure_channel_type == SEC_CHAN_WKSTA) {
226                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
227                         DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
228                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
229                 }
230         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
231                    r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
232                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
233                         DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
234
235                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
236                 }
237         } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
238                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
239                         DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
240                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
241                 }
242         } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
243                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
244                         DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
245                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
246                 }
247         } else {
248                 /* we should never reach this */
249                 return NT_STATUS_INTERNAL_ERROR;
250         }
251
252         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
253                                                 "objectSid", 0);
254
255         mach_pwd = samdb_result_hash(mem_ctx, msgs[0], "unicodePwd");
256         if (mach_pwd == NULL) {
257                 return NT_STATUS_ACCESS_DENIED;
258         }
259
260         if (!pipe_state) {
261                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
262                 return NT_STATUS_ACCESS_DENIED;
263         }
264
265         creds = netlogon_creds_server_init(mem_ctx,
266                                            r->in.account_name,
267                                            r->in.computer_name,
268                                            r->in.secure_channel_type,
269                                            &pipe_state->client_challenge,
270                                            &pipe_state->server_challenge,
271                                            mach_pwd,
272                                            r->in.credentials,
273                                            r->out.return_credentials,
274                                            negotiate_flags);
275         if (!creds) {
276                 return NT_STATUS_ACCESS_DENIED;
277         }
278
279         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
280
281         nt_status = schannel_save_creds_state(mem_ctx,
282                                               dce_call->conn->dce_ctx->lp_ctx,
283                                               creds);
284
285         return nt_status;
286 }
287
288 static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289                                         struct netr_ServerAuthenticate *r)
290 {
291         struct netr_ServerAuthenticate3 a;
292         uint32_t rid;
293         /* TODO:
294          * negotiate_flags is used as an [in] parameter
295          * so it need to be initialised.
296          *
297          * (I think ... = 0; seems wrong here --metze)
298          */
299         uint32_t negotiate_flags_in = 0;
300         uint32_t negotiate_flags_out = 0;
301
302         a.in.server_name                = r->in.server_name;
303         a.in.account_name               = r->in.account_name;
304         a.in.secure_channel_type        = r->in.secure_channel_type;
305         a.in.computer_name              = r->in.computer_name;
306         a.in.credentials                = r->in.credentials;
307         a.in.negotiate_flags            = &negotiate_flags_in;
308
309         a.out.return_credentials        = r->out.return_credentials;
310         a.out.rid                       = &rid;
311         a.out.negotiate_flags           = &negotiate_flags_out;
312
313         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
314 }
315
316 static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
317                                          struct netr_ServerAuthenticate2 *r)
318 {
319         struct netr_ServerAuthenticate3 r3;
320         uint32_t rid = 0;
321
322         r3.in.server_name = r->in.server_name;
323         r3.in.account_name = r->in.account_name;
324         r3.in.secure_channel_type = r->in.secure_channel_type;
325         r3.in.computer_name = r->in.computer_name;
326         r3.in.credentials = r->in.credentials;
327         r3.out.return_credentials = r->out.return_credentials;
328         r3.in.negotiate_flags = r->in.negotiate_flags;
329         r3.out.negotiate_flags = r->out.negotiate_flags;
330         r3.out.rid = &rid;
331
332         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
333 }
334
335 /*
336  * NOTE: The following functions are nearly identical to the ones available in
337  * source3/rpc_server/srv_nelog_nt.c
338  * The reason we keep 2 copies is that they use different structures to
339  * represent the auth_info and the decrpc pipes.
340  */
341
342 /*
343  * If schannel is required for this call test that it actually is available.
344  */
345 static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
346                                         const char *computer_name,
347                                         bool integrity, bool privacy)
348 {
349
350         if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
351                 if (!privacy && !integrity) {
352                         return NT_STATUS_OK;
353                 }
354
355                 if ((!privacy && integrity) &&
356                     auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
357                         return NT_STATUS_OK;
358                 }
359
360                 if ((privacy || integrity) &&
361                     auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
362                         return NT_STATUS_OK;
363                 }
364         }
365
366         /* test didn't pass */
367         DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
368                   computer_name));
369
370         return NT_STATUS_ACCESS_DENIED;
371 }
372
373 static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
374                                                     TALLOC_CTX *mem_ctx,
375                                                     const char *computer_name,
376                                                     struct netr_Authenticator *received_authenticator,
377                                                     struct netr_Authenticator *return_authenticator,
378                                                     struct netlogon_creds_CredentialState **creds_out)
379 {
380         NTSTATUS nt_status;
381         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
382         bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
383
384         if (schannel_global_required) {
385                 nt_status = schannel_check_required(auth_info,
386                                                     computer_name,
387                                                     true, false);
388                 if (!NT_STATUS_IS_OK(nt_status)) {
389                         return nt_status;
390                 }
391         }
392
393         nt_status = schannel_check_creds_state(mem_ctx,
394                                                dce_call->conn->dce_ctx->lp_ctx,
395                                                computer_name,
396                                                received_authenticator,
397                                                return_authenticator,
398                                                creds_out);
399         return nt_status;
400 }
401
402 /*
403   Change the machine account password for the currently connected
404   client.  Supplies only the NT#.
405 */
406
407 static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
408                                        struct netr_ServerPasswordSet *r)
409 {
410         struct netlogon_creds_CredentialState *creds;
411         struct ldb_context *sam_ctx;
412         const char * const attrs[] = { "unicodePwd", NULL };
413         struct ldb_message **res;
414         struct samr_Password *oldNtHash;
415         NTSTATUS nt_status;
416         int ret;
417
418         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
419                                                         mem_ctx,
420                                                         r->in.computer_name,
421                                                         r->in.credential, r->out.return_authenticator,
422                                                         &creds);
423         NT_STATUS_NOT_OK_RETURN(nt_status);
424
425         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
426         if (sam_ctx == NULL) {
427                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
428         }
429
430         netlogon_creds_des_decrypt(creds, r->in.new_password);
431
432         /* fetch the old password hashes (the NT hash has to exist) */
433
434         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
435                            "(&(objectClass=user)(objectSid=%s))",
436                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
437         if (ret != 1) {
438                 return NT_STATUS_WRONG_PASSWORD;
439         }
440
441         nt_status = samdb_result_passwords(mem_ctx,
442                                            dce_call->conn->dce_ctx->lp_ctx,
443                                            res[0], NULL, &oldNtHash);
444         if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
445                 return NT_STATUS_WRONG_PASSWORD;
446         }
447
448         /* Using the sid for the account as the key, set the password */
449         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
450                                            creds->sid,
451                                            NULL, /* Don't have plaintext */
452                                            NULL, r->in.new_password,
453                                            NULL, oldNtHash, /* Password change */
454                                            NULL, NULL);
455         return nt_status;
456 }
457
458 /*
459   Change the machine account password for the currently connected
460   client.  Supplies new plaintext.
461 */
462 static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
463                                        struct netr_ServerPasswordSet2 *r)
464 {
465         struct netlogon_creds_CredentialState *creds;
466         struct ldb_context *sam_ctx;
467         const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
468         struct ldb_message **res;
469         struct samr_Password *oldLmHash, *oldNtHash;
470         NTSTATUS nt_status;
471         DATA_BLOB new_password;
472         int ret;
473
474         struct samr_CryptPassword password_buf;
475
476         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
477                                                         mem_ctx,
478                                                         r->in.computer_name,
479                                                         r->in.credential, r->out.return_authenticator,
480                                                         &creds);
481         NT_STATUS_NOT_OK_RETURN(nt_status);
482
483         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
484         if (sam_ctx == NULL) {
485                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
486         }
487
488         memcpy(password_buf.data, r->in.new_password->data, 512);
489         SIVAL(password_buf.data, 512, r->in.new_password->length);
490
491         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
492                 netlogon_creds_aes_decrypt(creds, password_buf.data, 516);
493         } else {
494                 netlogon_creds_arcfour_crypt(creds, password_buf.data, 516);
495         }
496
497         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
498                 DEBUG(3,("samr: failed to decode password buffer\n"));
499                 return NT_STATUS_WRONG_PASSWORD;
500         }
501
502         /* fetch the old password hashes (at least one of both has to exist) */
503
504         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
505                            "(&(objectClass=user)(objectSid=%s))",
506                            ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
507         if (ret != 1) {
508                 return NT_STATUS_WRONG_PASSWORD;
509         }
510
511         nt_status = samdb_result_passwords(mem_ctx,
512                                            dce_call->conn->dce_ctx->lp_ctx,
513                                            res[0], &oldLmHash, &oldNtHash);
514         if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
515                 return NT_STATUS_WRONG_PASSWORD;
516         }
517
518         /* Using the sid for the account as the key, set the password */
519         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
520                                            creds->sid,
521                                            &new_password, /* we have plaintext */
522                                            NULL, NULL,
523                                            oldLmHash, oldNtHash, /* Password change */
524                                            NULL, NULL);
525         return nt_status;
526 }
527
528
529 /*
530   netr_LogonUasLogon
531 */
532 static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
533                                  struct netr_LogonUasLogon *r)
534 {
535         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
536 }
537
538
539 /*
540   netr_LogonUasLogoff
541 */
542 static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
543                        struct netr_LogonUasLogoff *r)
544 {
545         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
546 }
547
548
549 static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
550 {
551         switch (r->in.logon_level) {
552         case NetlogonInteractiveInformation:
553         case NetlogonServiceInformation:
554         case NetlogonInteractiveTransitiveInformation:
555         case NetlogonServiceTransitiveInformation:
556                 if (r->in.logon->password == NULL) {
557                         return NT_STATUS_INVALID_PARAMETER;
558                 }
559
560                 switch (r->in.validation_level) {
561                 case NetlogonValidationSamInfo:  /* 2 */
562                 case NetlogonValidationSamInfo2: /* 3 */
563                 case NetlogonValidationSamInfo4: /* 6 */
564                         break;
565                 default:
566                         return NT_STATUS_INVALID_INFO_CLASS;
567                 }
568
569                 break;
570         case NetlogonNetworkInformation:
571         case NetlogonNetworkTransitiveInformation:
572                 if (r->in.logon->network == NULL) {
573                         return NT_STATUS_INVALID_PARAMETER;
574                 }
575
576                 switch (r->in.validation_level) {
577                 case NetlogonValidationSamInfo:  /* 2 */
578                 case NetlogonValidationSamInfo2: /* 3 */
579                 case NetlogonValidationSamInfo4: /* 6 */
580                         break;
581                 default:
582                         return NT_STATUS_INVALID_INFO_CLASS;
583                 }
584
585                 break;
586
587         case NetlogonGenericInformation:
588                 if (r->in.logon->generic == NULL) {
589                         return NT_STATUS_INVALID_PARAMETER;
590                 }
591
592                 switch (r->in.validation_level) {
593                 /* TODO: case NetlogonValidationGenericInfo: 4 */
594                 case NetlogonValidationGenericInfo2: /* 5 */
595                         break;
596                 default:
597                         return NT_STATUS_INVALID_INFO_CLASS;
598                 }
599
600                 break;
601         default:
602                 return NT_STATUS_INVALID_PARAMETER;
603         }
604
605         return NT_STATUS_OK;
606 }
607
608 /*
609   netr_LogonSamLogon_base
610
611   This version of the function allows other wrappers to say 'do not check the credentials'
612
613   We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
614 */
615 static NTSTATUS dcesrv_netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
616                                         struct netr_LogonSamLogonEx *r, struct netlogon_creds_CredentialState *creds)
617 {
618         struct auth4_context *auth_context;
619         struct auth_usersupplied_info *user_info;
620         struct auth_user_info_dc *user_info_dc;
621         NTSTATUS nt_status;
622         struct netr_SamBaseInfo *sam;
623         struct netr_SamInfo2 *sam2;
624         struct netr_SamInfo3 *sam3;
625         struct netr_SamInfo6 *sam6;
626
627         *r->out.authoritative = 1;
628
629         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
630         NT_STATUS_HAVE_NO_MEMORY(user_info);
631
632         switch (r->in.logon_level) {
633         case NetlogonInteractiveInformation:
634         case NetlogonServiceInformation:
635         case NetlogonInteractiveTransitiveInformation:
636         case NetlogonServiceTransitiveInformation:
637                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
638                         netlogon_creds_aes_decrypt(creds,
639                                                    r->in.logon->password->lmpassword.hash,
640                                                    sizeof(r->in.logon->password->lmpassword.hash));
641                         netlogon_creds_aes_decrypt(creds,
642                                                    r->in.logon->password->ntpassword.hash,
643                                                    sizeof(r->in.logon->password->ntpassword.hash));
644                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
645                         netlogon_creds_arcfour_crypt(creds,
646                                             r->in.logon->password->lmpassword.hash,
647                                             sizeof(r->in.logon->password->lmpassword.hash));
648                         netlogon_creds_arcfour_crypt(creds,
649                                             r->in.logon->password->ntpassword.hash,
650                                             sizeof(r->in.logon->password->ntpassword.hash));
651                 } else {
652                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->lmpassword);
653                         netlogon_creds_des_decrypt(creds, &r->in.logon->password->ntpassword);
654                 }
655
656                 /* TODO: we need to deny anonymous access here */
657                 nt_status = auth_context_create(mem_ctx,
658                                                 dce_call->event_ctx, dce_call->msg_ctx,
659                                                 dce_call->conn->dce_ctx->lp_ctx,
660                                                 &auth_context);
661                 NT_STATUS_NOT_OK_RETURN(nt_status);
662
663                 user_info->logon_parameters = r->in.logon->password->identity_info.parameter_control;
664                 user_info->client.account_name = r->in.logon->password->identity_info.account_name.string;
665                 user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
666                 user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
667
668                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
669                 user_info->password_state = AUTH_PASSWORD_HASH;
670
671                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
672                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
673                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
674
675                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
676                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
677                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
678
679                 break;
680         case NetlogonNetworkInformation:
681         case NetlogonNetworkTransitiveInformation:
682
683                 /* TODO: we need to deny anonymous access here */
684                 nt_status = auth_context_create(mem_ctx,
685                                                 dce_call->event_ctx, dce_call->msg_ctx,
686                                                 dce_call->conn->dce_ctx->lp_ctx,
687                                                 &auth_context);
688                 NT_STATUS_NOT_OK_RETURN(nt_status);
689
690                 nt_status = auth_context_set_challenge(auth_context, r->in.logon->network->challenge, "netr_LogonSamLogonWithFlags");
691                 NT_STATUS_NOT_OK_RETURN(nt_status);
692
693                 user_info->logon_parameters = r->in.logon->network->identity_info.parameter_control;
694                 user_info->client.account_name = r->in.logon->network->identity_info.account_name.string;
695                 user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
696                 user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
697
698                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
699                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
700                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
701
702                 break;
703
704
705         case NetlogonGenericInformation:
706         {
707                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
708                         netlogon_creds_aes_decrypt(creds,
709                                             r->in.logon->generic->data, r->in.logon->generic->length);
710                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
711                         netlogon_creds_arcfour_crypt(creds,
712                                             r->in.logon->generic->data, r->in.logon->generic->length);
713                 } else {
714                         /* Using DES to verify kerberos tickets makes no sense */
715                         return NT_STATUS_INVALID_PARAMETER;
716                 }
717
718                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
719                         NTSTATUS status;
720                         struct dcerpc_binding_handle *irpc_handle;
721                         struct kdc_check_generic_kerberos check;
722                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
723                         NT_STATUS_HAVE_NO_MEMORY(generic);
724                         *r->out.authoritative = 1;
725
726                         /* TODO: Describe and deal with these flags */
727                         *r->out.flags = 0;
728
729                         r->out.validation->generic = generic;
730
731                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
732                                                                   dce_call->msg_ctx,
733                                                                   "kdc_server",
734                                                                   &ndr_table_irpc);
735                         if (irpc_handle == NULL) {
736                                 return NT_STATUS_NO_LOGON_SERVERS;
737                         }
738
739                         check.in.generic_request =
740                                 data_blob_const(r->in.logon->generic->data,
741                                                 r->in.logon->generic->length);
742
743                         status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
744                                                                      mem_ctx,
745                                                                      &check);
746                         if (!NT_STATUS_IS_OK(status)) {
747                                 return status;
748                         }
749                         generic->length = check.out.generic_reply.length;
750                         generic->data = check.out.generic_reply.data;
751                         return NT_STATUS_OK;
752                 }
753
754                 /* Until we get an implemetnation of these other packages */
755                 return NT_STATUS_INVALID_PARAMETER;
756         }
757         default:
758                 return NT_STATUS_INVALID_PARAMETER;
759         }
760
761         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
762         /* TODO: set *r->out.authoritative = 0 on specific errors */
763         NT_STATUS_NOT_OK_RETURN(nt_status);
764
765         switch (r->in.validation_level) {
766         case 2:
767                 nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
768                 NT_STATUS_NOT_OK_RETURN(nt_status);
769
770                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
771                 NT_STATUS_HAVE_NO_MEMORY(sam2);
772                 sam2->base = *sam;
773
774                 /* And put into the talloc tree */
775                 talloc_steal(sam2, sam);
776                 r->out.validation->sam2 = sam2;
777
778                 sam = &sam2->base;
779                 break;
780
781         case 3:
782                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
783                                                               user_info_dc,
784                                                               &sam3);
785                 NT_STATUS_NOT_OK_RETURN(nt_status);
786
787                 r->out.validation->sam3 = sam3;
788
789                 sam = &sam3->base;
790                 break;
791
792         case 6:
793                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
794                                                            user_info_dc,
795                                                            &sam3);
796                 NT_STATUS_NOT_OK_RETURN(nt_status);
797
798                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
799                 NT_STATUS_HAVE_NO_MEMORY(sam6);
800                 sam6->base = sam3->base;
801                 sam = &sam6->base;
802                 sam6->sidcount = sam3->sidcount;
803                 sam6->sids = sam3->sids;
804
805                 sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
806                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
807                                                          sam->account_name.string, sam6->dns_domainname.string);
808                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
809                 /* And put into the talloc tree */
810                 talloc_steal(sam6, sam3);
811
812                 r->out.validation->sam6 = sam6;
813                 break;
814
815         default:
816                 return NT_STATUS_INVALID_INFO_CLASS;
817         }
818
819         netlogon_creds_encrypt_samlogon_validation(creds,
820                                                    r->in.validation_level,
821                                                    r->out.validation);
822
823         /* TODO: Describe and deal with these flags */
824         *r->out.flags = 0;
825
826         return NT_STATUS_OK;
827 }
828
829 static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
830                                      struct netr_LogonSamLogonEx *r)
831 {
832         NTSTATUS nt_status;
833         struct netlogon_creds_CredentialState *creds;
834
835         *r->out.authoritative = 1;
836
837         nt_status = dcesrv_netr_LogonSamLogon_check(r);
838         if (!NT_STATUS_IS_OK(nt_status)) {
839                 return nt_status;
840         }
841
842         nt_status = schannel_get_creds_state(mem_ctx,
843                                              dce_call->conn->dce_ctx->lp_ctx,
844                                              r->in.computer_name, &creds);
845         if (!NT_STATUS_IS_OK(nt_status)) {
846                 return nt_status;
847         }
848
849         if (!dce_call->conn->auth_state.auth_info ||
850             dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
851                 return NT_STATUS_ACCESS_DENIED;
852         }
853         return dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
854 }
855
856 /*
857   netr_LogonSamLogonWithFlags
858
859 */
860 static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
861                                             struct netr_LogonSamLogonWithFlags *r)
862 {
863         NTSTATUS nt_status;
864         struct netlogon_creds_CredentialState *creds;
865         struct netr_LogonSamLogonEx r2;
866
867         struct netr_Authenticator *return_authenticator;
868
869         ZERO_STRUCT(r2);
870
871         r2.in.server_name       = r->in.server_name;
872         r2.in.computer_name     = r->in.computer_name;
873         r2.in.logon_level       = r->in.logon_level;
874         r2.in.logon             = r->in.logon;
875         r2.in.validation_level  = r->in.validation_level;
876         r2.in.flags             = r->in.flags;
877         r2.out.validation       = r->out.validation;
878         r2.out.authoritative    = r->out.authoritative;
879         r2.out.flags            = r->out.flags;
880
881         *r->out.authoritative = 1;
882
883         nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
884         if (!NT_STATUS_IS_OK(nt_status)) {
885                 return nt_status;
886         }
887
888         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
889         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
890
891         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
892                                                         mem_ctx,
893                                                         r->in.computer_name,
894                                                         r->in.credential, return_authenticator,
895                                                         &creds);
896         NT_STATUS_NOT_OK_RETURN(nt_status);
897
898         nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
899
900         r->out.return_authenticator     = return_authenticator;
901
902         return nt_status;
903 }
904
905 /*
906   netr_LogonSamLogon
907 */
908 static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
909                                    struct netr_LogonSamLogon *r)
910 {
911         struct netr_LogonSamLogonWithFlags r2;
912         uint32_t flags = 0;
913         NTSTATUS status;
914
915         ZERO_STRUCT(r2);
916
917         r2.in.server_name = r->in.server_name;
918         r2.in.computer_name = r->in.computer_name;
919         r2.in.credential  = r->in.credential;
920         r2.in.return_authenticator = r->in.return_authenticator;
921         r2.in.logon_level = r->in.logon_level;
922         r2.in.logon = r->in.logon;
923         r2.in.validation_level = r->in.validation_level;
924         r2.in.flags = &flags;
925         r2.out.validation = r->out.validation;
926         r2.out.authoritative = r->out.authoritative;
927         r2.out.flags = &flags;
928
929         status = dcesrv_netr_LogonSamLogonWithFlags(dce_call, mem_ctx, &r2);
930
931         r->out.return_authenticator = r2.out.return_authenticator;
932
933         return status;
934 }
935
936
937 /*
938   netr_LogonSamLogoff
939 */
940 static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
941                        struct netr_LogonSamLogoff *r)
942 {
943         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
944 }
945
946
947
948 /*
949   netr_DatabaseDeltas
950 */
951 static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
952                        struct netr_DatabaseDeltas *r)
953 {
954         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
955 }
956
957
958 /*
959   netr_DatabaseSync2
960 */
961 static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
962                        struct netr_DatabaseSync2 *r)
963 {
964         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
965         return NT_STATUS_NOT_IMPLEMENTED;
966 }
967
968
969 /*
970   netr_DatabaseSync
971 */
972 static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
973                        struct netr_DatabaseSync *r)
974 {
975         struct netr_DatabaseSync2 r2;
976         NTSTATUS status;
977
978         ZERO_STRUCT(r2);
979
980         r2.in.logon_server = r->in.logon_server;
981         r2.in.computername = r->in.computername;
982         r2.in.credential = r->in.credential;
983         r2.in.database_id = r->in.database_id;
984         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
985         r2.in.sync_context = r->in.sync_context;
986         r2.out.sync_context = r->out.sync_context;
987         r2.out.delta_enum_array = r->out.delta_enum_array;
988         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
989
990         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
991
992         return status;
993 }
994
995
996 /*
997   netr_AccountDeltas
998 */
999 static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1000                        struct netr_AccountDeltas *r)
1001 {
1002         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1003         return NT_STATUS_NOT_IMPLEMENTED;
1004 }
1005
1006
1007 /*
1008   netr_AccountSync
1009 */
1010 static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1011                        struct netr_AccountSync *r)
1012 {
1013         /* w2k3 returns "NOT IMPLEMENTED" for this call */
1014         return NT_STATUS_NOT_IMPLEMENTED;
1015 }
1016
1017
1018 /*
1019   netr_GetDcName
1020 */
1021 static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1022                        struct netr_GetDcName *r)
1023 {
1024         const char * const attrs[] = { NULL };
1025         struct ldb_context *sam_ctx;
1026         struct ldb_message **res;
1027         struct ldb_dn *domain_dn;
1028         int ret;
1029         const char *dcname;
1030
1031         /*
1032          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
1033          * that the domainname needs to be a valid netbios domain
1034          * name, if it is not NULL.
1035          */
1036         if (r->in.domainname) {
1037                 const char *dot = strchr(r->in.domainname, '.');
1038                 size_t len = strlen(r->in.domainname);
1039
1040                 if (dot || len > 15) {
1041                         return WERR_DCNOTFOUND;
1042                 }
1043
1044                 /*
1045                  * TODO: Should we also varify that only valid
1046                  *       netbios name characters are used?
1047                  */
1048         }
1049
1050         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1051                                 dce_call->conn->dce_ctx->lp_ctx,
1052                                 dce_call->conn->auth_state.session_info, 0);
1053         if (sam_ctx == NULL) {
1054                 return WERR_DS_UNAVAILABLE;
1055         }
1056
1057         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
1058                                        r->in.domainname);
1059         if (domain_dn == NULL) {
1060                 return WERR_NO_SUCH_DOMAIN;
1061         }
1062
1063         ret = gendb_search_dn(sam_ctx, mem_ctx,
1064                               domain_dn, &res, attrs);
1065         if (ret != 1) {
1066                 return WERR_NO_SUCH_DOMAIN;
1067         }
1068
1069         /* TODO: - return real IP address
1070          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
1071          */
1072         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
1073                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
1074         W_ERROR_HAVE_NO_MEMORY(dcname);
1075
1076         *r->out.dcname = dcname;
1077         return WERR_OK;
1078 }
1079
1080
1081 /*
1082   netr_LogonControl2Ex
1083 */
1084 static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1085                        struct netr_LogonControl2Ex *r)
1086 {
1087         return WERR_NOT_SUPPORTED;
1088 }
1089
1090
1091 /*
1092   netr_LogonControl
1093 */
1094 static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1095                        struct netr_LogonControl *r)
1096 {
1097         struct netr_LogonControl2Ex r2;
1098         WERROR werr;
1099
1100         if (r->in.level == 0x00000001) {
1101                 ZERO_STRUCT(r2);
1102
1103                 r2.in.logon_server = r->in.logon_server;
1104                 r2.in.function_code = r->in.function_code;
1105                 r2.in.level = r->in.level;
1106                 r2.in.data = NULL;
1107                 r2.out.query = r->out.query;
1108
1109                 werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1110         } else if (r->in.level == 0x00000002) {
1111                 werr = WERR_NOT_SUPPORTED;
1112         } else {
1113                 werr = WERR_UNKNOWN_LEVEL;
1114         }
1115
1116         return werr;
1117 }
1118
1119
1120 /*
1121   netr_LogonControl2
1122 */
1123 static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1124                        struct netr_LogonControl2 *r)
1125 {
1126         struct netr_LogonControl2Ex r2;
1127         WERROR werr;
1128
1129         ZERO_STRUCT(r2);
1130
1131         r2.in.logon_server = r->in.logon_server;
1132         r2.in.function_code = r->in.function_code;
1133         r2.in.level = r->in.level;
1134         r2.in.data = r->in.data;
1135         r2.out.query = r->out.query;
1136
1137         werr = dcesrv_netr_LogonControl2Ex(dce_call, mem_ctx, &r2);
1138
1139         return werr;
1140 }
1141
1142 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
1143                                          struct ldb_context *sam_ctx,
1144                                          struct netr_DomainTrustList *trusts,
1145                                          uint32_t trust_flags);
1146
1147 /*
1148   netr_GetAnyDCName
1149 */
1150 static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1151                        struct netr_GetAnyDCName *r)
1152 {
1153         struct netr_DomainTrustList *trusts;
1154         struct ldb_context *sam_ctx;
1155         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1156         uint32_t i;
1157         WERROR werr;
1158
1159         *r->out.dcname = NULL;
1160
1161         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
1162                 /* if the domainname parameter wasn't set assume our domain */
1163                 r->in.domainname = lpcfg_workgroup(lp_ctx);
1164         }
1165
1166         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1167                                 dce_call->conn->auth_state.session_info, 0);
1168         if (sam_ctx == NULL) {
1169                 return WERR_DS_UNAVAILABLE;
1170         }
1171
1172         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
1173                 /* well we asked for a DC of our own domain */
1174                 if (samdb_is_pdc(sam_ctx)) {
1175                         /* we are the PDC of the specified domain */
1176                         return WERR_NO_SUCH_DOMAIN;
1177                 }
1178
1179                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
1180                                                 lpcfg_netbios_name(lp_ctx));
1181                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
1182
1183                 return WERR_OK;
1184         }
1185
1186         /* Okay, now we have to consider the trusted domains */
1187
1188         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
1189         W_ERROR_HAVE_NO_MEMORY(trusts);
1190
1191         trusts->count = 0;
1192
1193         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
1194                                           NETR_TRUST_FLAG_INBOUND
1195                                           | NETR_TRUST_FLAG_OUTBOUND);
1196         W_ERROR_NOT_OK_RETURN(werr);
1197
1198         for (i = 0; i < trusts->count; i++) {
1199                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
1200                         /* FIXME: Here we need to find a DC for the specified
1201                          * trusted domain. */
1202
1203                         /* return WERR_OK; */
1204                         return WERR_NO_SUCH_DOMAIN;
1205                 }
1206         }
1207
1208         return WERR_NO_SUCH_DOMAIN;
1209 }
1210
1211
1212 /*
1213   netr_DatabaseRedo
1214 */
1215 static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1216                        struct netr_DatabaseRedo *r)
1217 {
1218         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1219 }
1220
1221
1222 /*
1223   netr_NetrEnumerateTrustedDomains
1224 */
1225 static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1226                        struct netr_NetrEnumerateTrustedDomains *r)
1227 {
1228         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1229 }
1230
1231
1232 /*
1233   netr_LogonGetCapabilities
1234 */
1235 static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1236                        struct netr_LogonGetCapabilities *r)
1237 {
1238         struct netlogon_creds_CredentialState *creds;
1239         NTSTATUS status;
1240
1241         status = dcesrv_netr_creds_server_step_check(dce_call,
1242                                                      mem_ctx,
1243                                                      r->in.computer_name,
1244                                                      r->in.credential,
1245                                                      r->out.return_authenticator,
1246                                                      &creds);
1247         if (!NT_STATUS_IS_OK(status)) {
1248                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1249         }
1250         NT_STATUS_NOT_OK_RETURN(status);
1251
1252         if (r->in.query_level != 1) {
1253                 return NT_STATUS_NOT_SUPPORTED;
1254         }
1255
1256         r->out.capabilities->server_capabilities = creds->negotiate_flags;
1257
1258         return NT_STATUS_OK;
1259 }
1260
1261
1262 /*
1263   netr_NETRLOGONSETSERVICEBITS
1264 */
1265 static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1266                        struct netr_NETRLOGONSETSERVICEBITS *r)
1267 {
1268         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1269 }
1270
1271
1272 /*
1273   netr_LogonGetTrustRid
1274 */
1275 static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1276                        struct netr_LogonGetTrustRid *r)
1277 {
1278         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1279 }
1280
1281
1282 /*
1283   netr_NETRLOGONCOMPUTESERVERDIGEST
1284 */
1285 static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1286                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
1287 {
1288         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1289 }
1290
1291
1292 /*
1293   netr_NETRLOGONCOMPUTECLIENTDIGEST
1294 */
1295 static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1296                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
1297 {
1298         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1299 }
1300
1301
1302
1303 /*
1304   netr_DsRGetSiteName
1305 */
1306 static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1307                                   struct netr_DsRGetSiteName *r)
1308 {
1309         struct ldb_context *sam_ctx;
1310         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1311
1312         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1313                                 dce_call->conn->auth_state.session_info, 0);
1314         if (sam_ctx == NULL) {
1315                 return WERR_DS_UNAVAILABLE;
1316         }
1317
1318         /*
1319          * We assume to be a DC when we get called over NETLOGON. Hence we
1320          * get our site name always by using "samdb_server_site_name()"
1321          * and not "samdb_client_site_name()".
1322          */
1323         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
1324         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
1325
1326         return WERR_OK;
1327 }
1328
1329
1330 /*
1331   fill in a netr_OneDomainInfo from a ldb search result
1332 */
1333 static NTSTATUS fill_one_domain_info(TALLOC_CTX *mem_ctx,
1334                                      struct loadparm_context *lp_ctx,
1335                                      struct ldb_context *sam_ctx,
1336                                      struct ldb_message *res,
1337                                      struct netr_OneDomainInfo *info,
1338                                      bool is_local, bool is_trust_list)
1339 {
1340         ZERO_STRUCTP(info);
1341
1342         if (is_trust_list) {
1343                 /* w2k8 only fills this on trusted domains */
1344                 info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
1345                 info->trust_extension.length = 16;
1346                 info->trust_extension.info->flags =
1347                         NETR_TRUST_FLAG_TREEROOT |
1348                         NETR_TRUST_FLAG_IN_FOREST |
1349                         NETR_TRUST_FLAG_PRIMARY |
1350                         NETR_TRUST_FLAG_NATIVE;
1351
1352                 info->trust_extension.info->parent_index = 0; /* should be index into array
1353                                                                  of parent */
1354                 info->trust_extension.info->trust_type = LSA_TRUST_TYPE_UPLEVEL; /* should be based on ldb search for trusts */
1355                 info->trust_extension.info->trust_attributes = 0; /*    TODO: base on ldb search? */
1356         }
1357
1358         if (is_trust_list) {
1359                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
1360                 info->dns_forestname.string = NULL;
1361         } else {
1362                 info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
1363                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1364                 info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
1365                 NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
1366         }
1367
1368         if (is_local) {
1369                 info->domainname.string = lpcfg_workgroup(lp_ctx);
1370                 info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
1371                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1372                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
1373         } else {
1374                 info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
1375                 info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
1376                 info->domain_guid = samdb_result_guid(res, "objectGUID");
1377                 info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
1378         }
1379         if (!is_trust_list) {
1380                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_domainname.string);
1381         }
1382
1383         return NT_STATUS_OK;
1384 }
1385
1386 /*
1387   netr_LogonGetDomainInfo
1388   this is called as part of the ADS domain logon procedure.
1389
1390   It has an important role in convaying details about the client, such
1391   as Operating System, Version, Service Pack etc.
1392 */
1393 static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
1394         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
1395 {
1396         struct netlogon_creds_CredentialState *creds;
1397         const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
1398                 "securityIdentifier", "trustPartner", NULL };
1399         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
1400                 "msDS-SupportedEncryptionTypes", NULL };
1401         const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
1402         struct ldb_context *sam_ctx;
1403         struct ldb_message **res1, **res2, **res3, *new_msg;
1404         struct ldb_dn *workstation_dn;
1405         struct netr_DomainInformation *domain_info;
1406         struct netr_LsaPolicyInformation *lsa_policy_info;
1407         uint32_t default_supported_enc_types = 0xFFFFFFFF;
1408         bool update_dns_hostname = true;
1409         int ret, ret3, i;
1410         NTSTATUS status;
1411
1412         status = dcesrv_netr_creds_server_step_check(dce_call,
1413                                                      mem_ctx,
1414                                                      r->in.computer_name,
1415                                                      r->in.credential,
1416                                                      r->out.return_authenticator,
1417                                                      &creds);
1418         if (!NT_STATUS_IS_OK(status)) {
1419                 DEBUG(0,(__location__ " Bad credentials - error\n"));
1420         }
1421         NT_STATUS_NOT_OK_RETURN(status);
1422
1423         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
1424                                 dce_call->conn->dce_ctx->lp_ctx,
1425                                 system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
1426         if (sam_ctx == NULL) {
1427                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
1428         }
1429
1430         switch (r->in.level) {
1431         case 1: /* Domain information */
1432
1433                 if (r->in.query->workstation_info == NULL) {
1434                         return NT_STATUS_INVALID_PARAMETER;
1435                 }
1436
1437                 /* Prepares the workstation DN */
1438                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
1439                                                 dom_sid_string(mem_ctx, creds->sid));
1440                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
1441
1442                 /* Lookup for attributes in workstation object */
1443                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
1444                                       attrs2);
1445                 if (ret != 1) {
1446                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1447                 }
1448
1449                 /* Gets the sam account name which is checked against the DNS
1450                  * hostname parameter. */
1451                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
1452                                                                "sAMAccountName",
1453                                                                NULL);
1454                 if (sam_account_name == NULL) {
1455                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1456                 }
1457
1458                 /*
1459                  * Checks that the sam account name without a possible "$"
1460                  * matches as prefix with the DNS hostname in the workstation
1461                  * info structure.
1462                  */
1463                 prefix1 = talloc_strndup(mem_ctx, sam_account_name,
1464                                          strcspn(sam_account_name, "$"));
1465                 NT_STATUS_HAVE_NO_MEMORY(prefix1);
1466                 if (r->in.query->workstation_info->dns_hostname != NULL) {
1467                         prefix2 = talloc_strndup(mem_ctx,
1468                                                  r->in.query->workstation_info->dns_hostname,
1469                                                  strcspn(r->in.query->workstation_info->dns_hostname, "."));
1470                         NT_STATUS_HAVE_NO_MEMORY(prefix2);
1471
1472                         if (strcasecmp(prefix1, prefix2) != 0) {
1473                                 update_dns_hostname = false;
1474                         }
1475                 } else {
1476                         update_dns_hostname = false;
1477                 }
1478
1479                 /* Gets the old DNS hostname */
1480                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
1481                                                                "dNSHostName",
1482                                                                NULL);
1483
1484                 /*
1485                  * Updates the DNS hostname when the client wishes that the
1486                  * server should handle this for him
1487                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
1488                  * obviously only checked when we do already have a
1489                  * "dNSHostName".
1490                  * See MS-NRPC section 3.5.4.3.9
1491                  */
1492                 if ((old_dns_hostname != NULL) &&
1493                     (r->in.query->workstation_info->workstation_flags
1494                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1495                         update_dns_hostname = false;
1496                 }
1497
1498                 /* Gets host information and put them into our directory */
1499
1500                 new_msg = ldb_msg_new(mem_ctx);
1501                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
1502
1503                 new_msg->dn = workstation_dn;
1504
1505                 /* Sets the OS name */
1506
1507                 if (r->in.query->workstation_info->os_name.string == NULL) {
1508                         return NT_STATUS_INVALID_PARAMETER;
1509                 }
1510
1511                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
1512                                          r->in.query->workstation_info->os_name.string);
1513                 if (ret != LDB_SUCCESS) {
1514                         return NT_STATUS_NO_MEMORY;
1515                 }
1516
1517                 /*
1518                  * Sets information from "os_version". On an empty structure
1519                  * the values are cleared.
1520                  */
1521                 if (r->in.query->workstation_info->os_version.os != NULL) {
1522                         struct netr_OsVersionInfoEx *os_version;
1523                         const char *os_version_str;
1524
1525                         os_version = &r->in.query->workstation_info->os_version.os->os;
1526
1527                         if (os_version->CSDVersion == NULL) {
1528                                 return NT_STATUS_INVALID_PARAMETER;
1529                         }
1530
1531                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
1532                                                          os_version->MajorVersion,
1533                                                          os_version->MinorVersion,
1534                                                          os_version->BuildNumber);
1535                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
1536
1537                         ret = ldb_msg_add_string(new_msg,
1538                                                  "operatingSystemServicePack",
1539                                                  os_version->CSDVersion);
1540                         if (ret != LDB_SUCCESS) {
1541                                 return NT_STATUS_NO_MEMORY;
1542                         }
1543
1544                         ret = ldb_msg_add_string(new_msg,
1545                                                  "operatingSystemVersion",
1546                                                  os_version_str);
1547                         if (ret != LDB_SUCCESS) {
1548                                 return NT_STATUS_NO_MEMORY;
1549                         }
1550                 } else {
1551                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1552                                                    "operatingSystemServicePack");
1553                         if (ret != LDB_SUCCESS) {
1554                                 return NT_STATUS_NO_MEMORY;
1555                         }
1556
1557                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
1558                                                    "operatingSystemVersion");
1559                         if (ret != LDB_SUCCESS) {
1560                                 return NT_STATUS_NO_MEMORY;
1561                         }
1562                 }
1563
1564                 /*
1565                  * If the boolean "update_dns_hostname" remained true, then we
1566                  * are fine to start the update.
1567                  */
1568                 if (update_dns_hostname) {
1569                         ret = ldb_msg_add_string(new_msg,
1570                                                  "dNSHostname",
1571                                                  r->in.query->workstation_info->dns_hostname);
1572                         if (ret != LDB_SUCCESS) {
1573                                 return NT_STATUS_NO_MEMORY;
1574                         }
1575
1576                         /* This manual "servicePrincipalName" generation is
1577                          * still needed! Since the update in the samldb LDB
1578                          * module does only work if the entries already exist
1579                          * which isn't always the case. */
1580                         ret = ldb_msg_add_string(new_msg,
1581                                                  "servicePrincipalName",
1582                                                  talloc_asprintf(new_msg, "HOST/%s",
1583                                                  r->in.computer_name));
1584                         if (ret != LDB_SUCCESS) {
1585                                 return NT_STATUS_NO_MEMORY;
1586                         }
1587
1588                         ret = ldb_msg_add_string(new_msg,
1589                                                  "servicePrincipalName",
1590                                                  talloc_asprintf(new_msg, "HOST/%s",
1591                                                  r->in.query->workstation_info->dns_hostname));
1592                         if (ret != LDB_SUCCESS) {
1593                                 return NT_STATUS_NO_MEMORY;
1594                         }
1595                 }
1596
1597                 if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
1598                         DEBUG(3,("Impossible to update samdb: %s\n",
1599                                 ldb_errstring(sam_ctx)));
1600                 }
1601
1602                 talloc_free(new_msg);
1603
1604                 /* Writes back the domain information */
1605
1606                 /* We need to do two searches. The first will pull our primary
1607                    domain and the second will pull any trusted domains. Our
1608                    primary domain is also a "trusted" domain, so we need to
1609                    put the primary domain into the lists of returned trusts as
1610                    well. */
1611                 ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
1612                         &res2, attrs);
1613                 if (ret != 1) {
1614                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1615                 }
1616
1617                 ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
1618                         "(objectClass=trustedDomain)");
1619                 if (ret3 == -1) {
1620                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1621                 }
1622
1623                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
1624                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
1625
1626                 ZERO_STRUCTP(domain_info);
1627
1628                 /* Informations about the local and trusted domains */
1629
1630                 status = fill_one_domain_info(mem_ctx,
1631                         dce_call->conn->dce_ctx->lp_ctx,
1632                         sam_ctx, res2[0], &domain_info->primary_domain,
1633                         true, false);
1634                 NT_STATUS_NOT_OK_RETURN(status);
1635
1636                 domain_info->trusted_domain_count = ret3 + 1;
1637                 domain_info->trusted_domains = talloc_array(mem_ctx,
1638                         struct netr_OneDomainInfo,
1639                         domain_info->trusted_domain_count);
1640                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
1641
1642                 for (i=0;i<ret3;i++) {
1643                         status = fill_one_domain_info(mem_ctx,
1644                                 dce_call->conn->dce_ctx->lp_ctx,
1645                                 sam_ctx, res3[i],
1646                                 &domain_info->trusted_domains[i],
1647                                 false, true);
1648                         NT_STATUS_NOT_OK_RETURN(status);
1649                 }
1650
1651                 status = fill_one_domain_info(mem_ctx,
1652                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
1653                         &domain_info->trusted_domains[i], true, true);
1654                 NT_STATUS_NOT_OK_RETURN(status);
1655
1656                 /* Sets the supported encryption types */
1657                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
1658                         "msDS-SupportedEncryptionTypes",
1659                         default_supported_enc_types);
1660
1661                 /* Other host domain information */
1662
1663                 lsa_policy_info = talloc(mem_ctx,
1664                         struct netr_LsaPolicyInformation);
1665                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1666                 ZERO_STRUCTP(lsa_policy_info);
1667
1668                 domain_info->lsa_policy = *lsa_policy_info;
1669
1670                 /* The DNS hostname is only returned back when there is a chance
1671                  * for a change. */
1672                 if ((r->in.query->workstation_info->workstation_flags
1673                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
1674                         domain_info->dns_hostname.string = old_dns_hostname;
1675                 } else {
1676                         domain_info->dns_hostname.string = NULL;
1677                 }
1678
1679                 domain_info->workstation_flags =
1680                         r->in.query->workstation_info->workstation_flags & (
1681                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
1682
1683                 r->out.info->domain_info = domain_info;
1684         break;
1685         case 2: /* LSA policy information - not used at the moment */
1686                 lsa_policy_info = talloc(mem_ctx,
1687                         struct netr_LsaPolicyInformation);
1688                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
1689                 ZERO_STRUCTP(lsa_policy_info);
1690
1691                 r->out.info->lsa_policy_info = lsa_policy_info;
1692         break;
1693         default:
1694                 return NT_STATUS_INVALID_LEVEL;
1695         break;
1696         }
1697
1698         return NT_STATUS_OK;
1699 }
1700
1701
1702 /*
1703   netr_ServerPasswordGet
1704 */
1705 static WERROR dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1706                        struct netr_ServerPasswordGet *r)
1707 {
1708         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1709 }
1710
1711
1712 /*
1713   netr_NETRLOGONSENDTOSAM
1714 */
1715 static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1716                        struct netr_NETRLOGONSENDTOSAM *r)
1717 {
1718         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1719 }
1720
1721
1722 /*
1723   netr_DsRGetDCNameEx2
1724 */
1725 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
1726                                           TALLOC_CTX *mem_ctx,
1727                                           struct netr_DsRGetDCNameEx2 *r)
1728 {
1729         struct ldb_context *sam_ctx;
1730         struct netr_DsRGetDCNameInfo *info;
1731         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1732         const struct tsocket_address *remote_address;
1733         char *addr = NULL;
1734         const char *server_site_name;
1735         char *guid_str;
1736         struct netlogon_samlogon_response response;
1737         NTSTATUS status;
1738         const char *dc_name = NULL;
1739         const char *domain_name = NULL;
1740         struct interface *ifaces;
1741         const char *pdc_ip;
1742
1743         ZERO_STRUCTP(r->out.info);
1744
1745         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1746                                 dce_call->conn->auth_state.session_info, 0);
1747         if (sam_ctx == NULL) {
1748                 return WERR_DS_UNAVAILABLE;
1749         }
1750
1751         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
1752         if (tsocket_address_is_inet(remote_address, "ip")) {
1753                 addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1754                 W_ERROR_HAVE_NO_MEMORY(addr);
1755         }
1756
1757         /* "server_unc" is ignored by w2k3 */
1758
1759         if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
1760                 return WERR_INVALID_FLAGS;
1761         }
1762
1763         if (r->in.flags & DS_GC_SERVER_REQUIRED &&
1764             r->in.flags & DS_PDC_REQUIRED &&
1765             r->in.flags & DS_KDC_REQUIRED) {
1766                 return WERR_INVALID_FLAGS;
1767         }
1768         if (r->in.flags & DS_IS_FLAT_NAME &&
1769             r->in.flags & DS_IS_DNS_NAME) {
1770                 return WERR_INVALID_FLAGS;
1771         }
1772         if (r->in.flags & DS_RETURN_DNS_NAME &&
1773             r->in.flags & DS_RETURN_FLAT_NAME) {
1774                 return WERR_INVALID_FLAGS;
1775         }
1776         if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
1777             r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
1778                 return WERR_INVALID_FLAGS;
1779         }
1780
1781         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
1782             r->in.flags &
1783             (DS_DIRECTORY_SERVICE_REQUIRED |
1784              DS_DIRECTORY_SERVICE_PREFERRED |
1785              DS_GC_SERVER_REQUIRED |
1786              DS_PDC_REQUIRED |
1787              DS_KDC_REQUIRED)) {
1788                 return WERR_INVALID_FLAGS;
1789         }
1790
1791         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
1792             r->in.site_name) {
1793                 return WERR_INVALID_FLAGS;
1794         }
1795
1796         /* Proof server site parameter "site_name" if it was specified */
1797         server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
1798         W_ERROR_HAVE_NO_MEMORY(server_site_name);
1799         if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
1800                                                      server_site_name) != 0)) {
1801                 return WERR_NO_SUCH_DOMAIN;
1802         }
1803
1804         guid_str = r->in.domain_guid != NULL ?
1805                  GUID_string(mem_ctx, r->in.domain_guid) : NULL;
1806
1807         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
1808                                                  r->in.domain_name,
1809                                                  r->in.domain_name,
1810                                                  NULL, guid_str,
1811                                                  r->in.client_account,
1812                                                  r->in.mask, addr,
1813                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
1814                                                  lp_ctx, &response, true);
1815         if (!NT_STATUS_IS_OK(status)) {
1816                 return ntstatus_to_werror(status);
1817         }
1818
1819         /*
1820          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
1821          * (O) flag when the returned forest name is in DNS format. This is here
1822          * always the case (see below).
1823          */
1824         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
1825
1826         if (r->in.flags & DS_RETURN_DNS_NAME) {
1827                 dc_name = response.data.nt5_ex.pdc_dns_name;
1828                 domain_name = response.data.nt5_ex.dns_domain;
1829                 /*
1830                  * According to MS-NRPC 2.2.1.2.1 we should set the
1831                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
1832                  * the returned information is in DNS form.
1833                  */
1834                 response.data.nt5_ex.server_type |=
1835                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
1836         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
1837                 dc_name = response.data.nt5_ex.pdc_name;
1838                 domain_name = response.data.nt5_ex.domain_name;
1839         } else {
1840
1841                 /*
1842                  * TODO: autodetect what we need to return
1843                  * based on the given arguments
1844                  */
1845                 dc_name = response.data.nt5_ex.pdc_name;
1846                 domain_name = response.data.nt5_ex.domain_name;
1847         }
1848
1849         if (!dc_name || !dc_name[0]) {
1850                 return WERR_NO_SUCH_DOMAIN;
1851         }
1852
1853         if (!domain_name || !domain_name[0]) {
1854                 return WERR_NO_SUCH_DOMAIN;
1855         }
1856
1857         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
1858         W_ERROR_HAVE_NO_MEMORY(info);
1859         info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
1860         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
1861
1862         load_interface_list(mem_ctx, lp_ctx, &ifaces);
1863         pdc_ip = iface_list_best_ip(ifaces, addr);
1864         if (pdc_ip == NULL) {
1865                 pdc_ip = "127.0.0.1";
1866         }
1867         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
1868         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
1869         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
1870         info->domain_guid      = response.data.nt5_ex.domain_uuid;
1871         info->domain_name      = domain_name;
1872         info->forest_name      = response.data.nt5_ex.forest;
1873         info->dc_flags         = response.data.nt5_ex.server_type;
1874         info->dc_site_name     = response.data.nt5_ex.server_site;
1875         info->client_site_name = response.data.nt5_ex.client_site;
1876
1877         *r->out.info = info;
1878
1879         return WERR_OK;
1880 }
1881
1882 /*
1883   netr_DsRGetDCNameEx
1884 */
1885 static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1886                                   struct netr_DsRGetDCNameEx *r)
1887 {
1888         struct netr_DsRGetDCNameEx2 r2;
1889         WERROR werr;
1890
1891         ZERO_STRUCT(r2);
1892
1893         r2.in.server_unc = r->in.server_unc;
1894         r2.in.client_account = NULL;
1895         r2.in.mask = 0;
1896         r2.in.domain_guid = r->in.domain_guid;
1897         r2.in.domain_name = r->in.domain_name;
1898         r2.in.site_name = r->in.site_name;
1899         r2.in.flags = r->in.flags;
1900         r2.out.info = r->out.info;
1901
1902         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1903
1904         return werr;
1905 }
1906
1907 /*
1908   netr_DsRGetDCName
1909 */
1910 static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1911                                 struct netr_DsRGetDCName *r)
1912 {
1913         struct netr_DsRGetDCNameEx2 r2;
1914         WERROR werr;
1915
1916         ZERO_STRUCT(r2);
1917
1918         r2.in.server_unc = r->in.server_unc;
1919         r2.in.client_account = NULL;
1920         r2.in.mask = 0;
1921         r2.in.domain_name = r->in.domain_name;
1922         r2.in.domain_guid = r->in.domain_guid;
1923
1924         r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
1925         r2.in.flags = r->in.flags;
1926         r2.out.info = r->out.info;
1927
1928         werr = dcesrv_netr_DsRGetDCNameEx2(dce_call, mem_ctx, &r2);
1929
1930         return werr;
1931 }
1932 /*
1933   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
1934 */
1935 static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1936                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
1937 {
1938         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1939 }
1940
1941
1942 /*
1943   netr_NetrEnumerateTrustedDomainsEx
1944 */
1945 static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946                        struct netr_NetrEnumerateTrustedDomainsEx *r)
1947 {
1948         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1949 }
1950
1951
1952 /*
1953   netr_DsRAddressToSitenamesExW
1954 */
1955 static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1956                                                    struct netr_DsRAddressToSitenamesExW *r)
1957 {
1958         struct ldb_context *sam_ctx;
1959         struct netr_DsRAddressToSitenamesExWCtr *ctr;
1960         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1961         sa_family_t sin_family;
1962         struct sockaddr_in *addr;
1963 #ifdef HAVE_IPV6
1964         struct sockaddr_in6 *addr6;
1965         char addr_str[INET6_ADDRSTRLEN];
1966 #else
1967         char addr_str[INET_ADDRSTRLEN];
1968 #endif
1969         char *subnet_name;
1970         const char *res;
1971         uint32_t i;
1972
1973         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
1974                                 dce_call->conn->auth_state.session_info, 0);
1975         if (sam_ctx == NULL) {
1976                 return WERR_DS_UNAVAILABLE;
1977         }
1978
1979         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
1980         W_ERROR_HAVE_NO_MEMORY(ctr);
1981
1982         *r->out.ctr = ctr;
1983
1984         ctr->count = r->in.count;
1985         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
1986         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
1987         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
1988         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
1989
1990         for (i=0; i<ctr->count; i++) {
1991                 ctr->sitename[i].string = NULL;
1992                 ctr->subnetname[i].string = NULL;
1993
1994                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
1995                         continue;
1996                 }
1997                 /* The first two byte of the buffer are reserved for the
1998                  * "sin_family" but for now only the first one is used. */
1999                 sin_family = r->in.addresses[i].buffer[0];
2000
2001                 switch (sin_family) {
2002                 case AF_INET:
2003                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
2004                                 continue;
2005                         }
2006                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
2007                         res = inet_ntop(AF_INET, &addr->sin_addr,
2008                                         addr_str, sizeof(addr_str));
2009                         break;
2010 #ifdef HAVE_IPV6
2011                 case AF_INET6:
2012                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
2013                                 continue;
2014                         }
2015                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
2016                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
2017                                         addr_str, sizeof(addr_str));
2018                         break;
2019 #endif
2020                 default:
2021                         continue;
2022                 }
2023
2024                 if (res == NULL) {
2025                         continue;
2026                 }
2027
2028                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
2029                                                                    mem_ctx,
2030                                                                    addr_str,
2031                                                                    &subnet_name);
2032                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
2033                 ctr->subnetname[i].string = subnet_name;
2034         }
2035
2036         return WERR_OK;
2037 }
2038
2039
2040 /*
2041   netr_DsRAddressToSitenamesW
2042 */
2043 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2044                        struct netr_DsRAddressToSitenamesW *r)
2045 {
2046         struct netr_DsRAddressToSitenamesExW r2;
2047         struct netr_DsRAddressToSitenamesWCtr *ctr;
2048         uint32_t i;
2049         WERROR werr;
2050
2051         ZERO_STRUCT(r2);
2052
2053         r2.in.server_name = r->in.server_name;
2054         r2.in.count = r->in.count;
2055         r2.in.addresses = r->in.addresses;
2056
2057         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
2058         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
2059
2060         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
2061         W_ERROR_HAVE_NO_MEMORY(ctr);
2062
2063         *r->out.ctr = ctr;
2064
2065         ctr->count = r->in.count;
2066         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
2067         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
2068
2069         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
2070
2071         for (i=0; i<ctr->count; i++) {
2072                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
2073         }
2074
2075         return werr;
2076 }
2077
2078
2079 /*
2080   netr_DsrGetDcSiteCoverageW
2081 */
2082 static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2083                        struct netr_DsrGetDcSiteCoverageW *r)
2084 {
2085         struct ldb_context *sam_ctx;
2086         struct DcSitesCtr *ctr;
2087         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2088
2089         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2090                                 dce_call->conn->auth_state.session_info, 0);
2091         if (sam_ctx == NULL) {
2092                 return WERR_DS_UNAVAILABLE;
2093         }
2094
2095         ctr = talloc(mem_ctx, struct DcSitesCtr);
2096         W_ERROR_HAVE_NO_MEMORY(ctr);
2097
2098         *r->out.ctr = ctr;
2099
2100         /* For now only return our default site */
2101         ctr->num_sites = 1;
2102         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
2103         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
2104         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
2105         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
2106
2107         return WERR_OK;
2108 }
2109
2110
2111 static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
2112                                          struct ldb_context *sam_ctx,
2113                                          struct netr_DomainTrustList *trusts,
2114                                          uint32_t trust_flags)
2115 {
2116         struct ldb_dn *system_dn;
2117         struct ldb_message **dom_res = NULL;
2118         const char *trust_attrs[] = { "flatname", "trustPartner",
2119                                       "securityIdentifier", "trustDirection",
2120                                       "trustType", "trustAttributes", NULL };
2121         uint32_t n;
2122         int i;
2123         int ret;
2124
2125         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
2126                              NETR_TRUST_FLAG_OUTBOUND))) {
2127                 return WERR_INVALID_FLAGS;
2128         }
2129
2130         system_dn = samdb_search_dn(sam_ctx, mem_ctx,
2131                                     ldb_get_default_basedn(sam_ctx),
2132                                     "(&(objectClass=container)(cn=System))");
2133         if (!system_dn) {
2134                 return WERR_GENERAL_FAILURE;
2135         }
2136
2137         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
2138                            &dom_res, trust_attrs,
2139                            "(objectclass=trustedDomain)");
2140
2141         for (i = 0; i < ret; i++) {
2142                 unsigned int trust_dir;
2143                 uint32_t flags = 0;
2144
2145                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
2146                                                       "trustDirection", 0);
2147
2148                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
2149                         flags |= NETR_TRUST_FLAG_INBOUND;
2150                 }
2151                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
2152                         flags |= NETR_TRUST_FLAG_OUTBOUND;
2153                 }
2154
2155                 if (!(flags & trust_flags)) {
2156                         /* this trust direction was not requested */
2157                         continue;
2158                 }
2159
2160                 n = trusts->count;
2161                 trusts->array = talloc_realloc(trusts, trusts->array,
2162                                                struct netr_DomainTrust,
2163                                                n + 1);
2164                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2165
2166                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
2167                 if (!trusts->array[n].netbios_name) {
2168                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
2169                                   "without flatname\n", 
2170                                   ldb_dn_get_linearized(dom_res[i]->dn)));
2171                 }
2172
2173                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
2174
2175                 trusts->array[n].trust_flags = flags;
2176                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
2177                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
2178                         /* TODO: find if we have parent in the list */
2179                         trusts->array[n].parent_index = 0;
2180                 }
2181
2182                 trusts->array[n].trust_type =
2183                                 ldb_msg_find_attr_as_uint(dom_res[i],
2184                                                   "trustType", 0);
2185                 trusts->array[n].trust_attributes =
2186                                 ldb_msg_find_attr_as_uint(dom_res[i],
2187                                                   "trustAttributes", 0);
2188
2189                 if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
2190                     (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
2191                         struct dom_sid zero_sid;
2192                         ZERO_STRUCT(zero_sid);
2193                         trusts->array[n].sid =
2194                                 dom_sid_dup(trusts, &zero_sid);
2195                 } else {
2196                         trusts->array[n].sid =
2197                                 samdb_result_dom_sid(trusts, dom_res[i],
2198                                                      "securityIdentifier");
2199                 }
2200                 trusts->array[n].guid = GUID_zero();
2201
2202                 trusts->count = n + 1;
2203         }
2204
2205         talloc_free(dom_res);
2206         return WERR_OK;
2207 }
2208
2209 /*
2210   netr_DsrEnumerateDomainTrusts
2211 */
2212 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
2213                                                    TALLOC_CTX *mem_ctx,
2214                                                    struct netr_DsrEnumerateDomainTrusts *r)
2215 {
2216         struct netr_DomainTrustList *trusts;
2217         struct ldb_context *sam_ctx;
2218         int ret;
2219         struct ldb_message **dom_res;
2220         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
2221         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2222         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
2223         const char *p;
2224         WERROR werr;
2225
2226         if (r->in.trust_flags & 0xFFFFFE00) {
2227                 return WERR_INVALID_FLAGS;
2228         }
2229
2230         /* TODO: turn to hard check once we are sure this is 100% correct */
2231         if (!r->in.server_name) {
2232                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
2233                           "But received NULL!\n", dnsdomain));
2234         } else {
2235                 p = strchr(r->in.server_name, '.');
2236                 if (!p) {
2237                         DEBUG(3, ("Invalid domain! Expected name in domain "
2238                                   "[%s]. But received [%s]!\n",
2239                                   dnsdomain, r->in.server_name));
2240                         p = r->in.server_name;
2241                 } else {
2242                         p++;
2243                 }
2244                 if (strcasecmp(p, dnsdomain)) {
2245                         DEBUG(3, ("Invalid domain! Expected name in domain "
2246                                   "[%s]. But received [%s]!\n",
2247                                   dnsdomain, r->in.server_name));
2248                 }
2249         }
2250
2251         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
2252         W_ERROR_HAVE_NO_MEMORY(trusts);
2253
2254         trusts->count = 0;
2255         r->out.trusts = trusts;
2256
2257         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2258                                 dce_call->conn->auth_state.session_info, 0);
2259         if (sam_ctx == NULL) {
2260                 return WERR_GENERAL_FAILURE;
2261         }
2262
2263         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
2264             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
2265
2266                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
2267                                                   trusts, r->in.trust_flags);
2268                 W_ERROR_NOT_OK_RETURN(werr);
2269         }
2270
2271         /* NOTE: we currently are always the root of the forest */
2272         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
2273                 uint32_t n = trusts->count;
2274
2275                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
2276                                       &dom_res, dom_attrs);
2277                 if (ret != 1) {
2278                         return WERR_GENERAL_FAILURE;
2279                 }
2280
2281                 trusts->count = n + 1;
2282                 trusts->array = talloc_realloc(trusts, trusts->array,
2283                                                struct netr_DomainTrust,
2284                                                trusts->count);
2285                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
2286
2287                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
2288                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
2289                 trusts->array[n].trust_flags =
2290                         NETR_TRUST_FLAG_NATIVE |
2291                         NETR_TRUST_FLAG_TREEROOT |
2292                         NETR_TRUST_FLAG_IN_FOREST |
2293                         NETR_TRUST_FLAG_PRIMARY;
2294                 /* we are always the root domain for now */
2295                 trusts->array[n].parent_index = 0;
2296                 trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
2297                 trusts->array[n].trust_attributes = 0;
2298                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
2299                                                             dom_res[0],
2300                                                             "objectSid");
2301                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
2302                                                           "objectGUID");
2303                 talloc_free(dom_res);
2304         }
2305
2306         return WERR_OK;
2307 }
2308
2309
2310 /*
2311   netr_DsrDeregisterDNSHostRecords
2312 */
2313 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314                        struct netr_DsrDeregisterDNSHostRecords *r)
2315 {
2316         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2317 }
2318
2319
2320 /*
2321   netr_ServerTrustPasswordsGet
2322 */
2323 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2324                        struct netr_ServerTrustPasswordsGet *r)
2325 {
2326         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2327 }
2328
2329
2330 static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
2331                                       struct ldb_context *sam_ctx,
2332                                       struct loadparm_context *lp_ctx,
2333                                       struct lsa_ForestTrustInformation *info)
2334 {
2335         struct lsa_ForestTrustDomainInfo *domain_info;
2336         struct lsa_ForestTrustRecord *e;
2337         struct ldb_message **dom_res;
2338         const char * const dom_attrs[] = { "objectSid", NULL };
2339         int ret;
2340
2341         /* we need to provide 2 entries:
2342          * 1. the Root Forest name
2343          * 2. the Domain Information
2344          */
2345
2346         info->count = 2;
2347         info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
2348         W_ERROR_HAVE_NO_MEMORY(info->entries);
2349
2350         /* Forest root info */
2351         e = talloc(info, struct lsa_ForestTrustRecord);
2352         W_ERROR_HAVE_NO_MEMORY(e);
2353
2354         e->flags = 0;
2355         e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
2356         e->time = 0; /* so far always 0 in trces. */
2357         e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
2358                                                                        mem_ctx);
2359         W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
2360
2361         info->entries[0] = e;
2362
2363         /* Domain info */
2364         e = talloc(info, struct lsa_ForestTrustRecord);
2365         W_ERROR_HAVE_NO_MEMORY(e);
2366
2367         /* get our own domain info */
2368         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
2369         if (ret != 1) {
2370                 return WERR_GENERAL_FAILURE;
2371         }
2372
2373         /* TODO: check if disabled and set flags accordingly */
2374         e->flags = 0;
2375         e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
2376         e->time = 0; /* so far always 0 in traces. */
2377
2378         domain_info = &e->forest_trust_data.domain_info;
2379         domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
2380                                                        "objectSid");
2381         domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
2382         domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
2383
2384         info->entries[1] = e;
2385
2386         talloc_free(dom_res);
2387
2388         return WERR_OK;
2389 }
2390
2391 /*
2392   netr_DsRGetForestTrustInformation
2393 */
2394 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
2395                                                        TALLOC_CTX *mem_ctx,
2396                                                        struct netr_DsRGetForestTrustInformation *r)
2397 {
2398         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2399         struct lsa_ForestTrustInformation *info, **info_ptr;
2400         struct ldb_context *sam_ctx;
2401         WERROR werr;
2402
2403         if (r->in.flags & 0xFFFFFFFE) {
2404                 return WERR_INVALID_FLAGS;
2405         }
2406
2407         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2408                                 dce_call->conn->auth_state.session_info, 0);
2409         if (sam_ctx == NULL) {
2410                 return WERR_GENERAL_FAILURE;
2411         }
2412
2413         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
2414                 if (!samdb_is_pdc(sam_ctx)) {
2415                         return WERR_NERR_NOTPRIMARY;
2416                 }
2417
2418                 if (r->in.trusted_domain_name == NULL) {
2419                         return WERR_INVALID_FLAGS;
2420                 }
2421
2422                 /* TODO: establish an schannel connection with
2423                  * r->in.trusted_domain_name and perform a
2424                  * netr_GetForestTrustInformation call against it */
2425
2426                 /* for now return not implementd */
2427                 return WERR_CALL_NOT_IMPLEMENTED;
2428         }
2429
2430         /* TODO: check r->in.server_name is our name */
2431
2432         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2433         W_ERROR_HAVE_NO_MEMORY(info_ptr);
2434
2435         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2436         W_ERROR_HAVE_NO_MEMORY(info);
2437
2438         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2439         W_ERROR_NOT_OK_RETURN(werr);
2440
2441         *info_ptr = info;
2442         r->out.forest_trust_info = info_ptr;
2443
2444         return WERR_OK;
2445 }
2446
2447
2448 /*
2449   netr_GetForestTrustInformation
2450 */
2451 static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
2452                                                       TALLOC_CTX *mem_ctx,
2453                                                       struct netr_GetForestTrustInformation *r)
2454 {
2455         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
2456         struct netlogon_creds_CredentialState *creds;
2457         struct lsa_ForestTrustInformation *info, **info_ptr;
2458         struct ldb_context *sam_ctx;
2459         NTSTATUS status;
2460         WERROR werr;
2461
2462         status = dcesrv_netr_creds_server_step_check(dce_call,
2463                                                      mem_ctx,
2464                                                      r->in.computer_name,
2465                                                      r->in.credential,
2466                                                      r->out.return_authenticator,
2467                                                      &creds);
2468         if (!NT_STATUS_IS_OK(status)) {
2469                 return status;
2470         }
2471
2472         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
2473             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
2474                 return NT_STATUS_NOT_IMPLEMENTED;
2475         }
2476
2477         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
2478                                 dce_call->conn->auth_state.session_info, 0);
2479         if (sam_ctx == NULL) {
2480                 return NT_STATUS_INTERNAL_ERROR;
2481         }
2482
2483         /* TODO: check r->in.server_name is our name */
2484
2485         info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
2486         if (!info_ptr) {
2487                 return NT_STATUS_NO_MEMORY;
2488         }
2489         info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
2490         if (!info) {
2491                 return NT_STATUS_NO_MEMORY;
2492         }
2493
2494         werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
2495         if (!W_ERROR_IS_OK(werr)) {
2496                 return werror_to_ntstatus(werr);
2497         }
2498
2499         *info_ptr = info;
2500         r->out.forest_trust_info = info_ptr;
2501
2502         return NT_STATUS_OK;
2503 }
2504
2505
2506 /*
2507   netr_ServerGetTrustInfo
2508 */
2509 static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2510                        struct netr_ServerGetTrustInfo *r)
2511 {
2512         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2513 }
2514
2515 /*
2516   netr_Unused47
2517 */
2518 static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2519                                      struct netr_Unused47 *r)
2520 {
2521         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2522 }
2523
2524
2525 struct netr_dnsupdate_RODC_state {
2526         struct dcesrv_call_state *dce_call;
2527         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
2528         struct dnsupdate_RODC *r2;
2529 };
2530
2531 /*
2532   called when the forwarded RODC dns update request is finished
2533  */
2534 static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
2535 {
2536         struct netr_dnsupdate_RODC_state *st =
2537                 tevent_req_callback_data(subreq,
2538                                          struct netr_dnsupdate_RODC_state);
2539         NTSTATUS status;
2540
2541         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
2542         TALLOC_FREE(subreq);
2543         if (!NT_STATUS_IS_OK(status)) {
2544                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
2545                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2546         }
2547
2548         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
2549
2550         status = dcesrv_reply(st->dce_call);
2551         if (!NT_STATUS_IS_OK(status)) {
2552                 DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
2553         }
2554 }
2555
2556 /*
2557   netr_DsrUpdateReadOnlyServerDnsRecords
2558 */
2559 static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
2560                                                               TALLOC_CTX *mem_ctx,
2561                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
2562 {
2563         struct netlogon_creds_CredentialState *creds;
2564         NTSTATUS nt_status;
2565         struct dcerpc_binding_handle *binding_handle;
2566         struct netr_dnsupdate_RODC_state *st;
2567         struct tevent_req *subreq;
2568
2569         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
2570                                                         mem_ctx,
2571                                                         r->in.computer_name,
2572                                                         r->in.credential,
2573                                                         r->out.return_authenticator,
2574                                                         &creds);
2575         NT_STATUS_NOT_OK_RETURN(nt_status);
2576
2577         if (creds->secure_channel_type != SEC_CHAN_RODC) {
2578                 return NT_STATUS_ACCESS_DENIED;
2579         }
2580
2581         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
2582         NT_STATUS_HAVE_NO_MEMORY(st);
2583
2584         st->dce_call = dce_call;
2585         st->r = r;
2586         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
2587         NT_STATUS_HAVE_NO_MEMORY(st->r2);
2588
2589         st->r2->in.dom_sid = creds->sid;
2590         st->r2->in.site_name = r->in.site_name;
2591         st->r2->in.dns_ttl = r->in.dns_ttl;
2592         st->r2->in.dns_names = r->in.dns_names;
2593         st->r2->out.dns_names = r->out.dns_names;
2594
2595         binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
2596                                                      "dnsupdate", &ndr_table_irpc);
2597         if (binding_handle == NULL) {
2598                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
2599                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
2600                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2601         }
2602
2603         /* forward the call */
2604         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
2605                                               binding_handle, st->r2);
2606         NT_STATUS_HAVE_NO_MEMORY(subreq);
2607
2608         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
2609
2610         /* setup the callback */
2611         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
2612
2613         return NT_STATUS_OK;
2614 }
2615
2616
2617 /* include the generated boilerplate */
2618 #include "librpc/gen_ndr/ndr_netlogon_s.c"